void accel_group_test(GtkWindow* toplevel, GtkAccelGroup* accel) { guint n_entries; gtk_accel_group_query(accel, '4', (GdkModifierType)0, &n_entries); globalOutputStream() << "grid4: " << n_entries << "\n"; globalOutputStream() << "toplevel accelgroups: " << g_slist_length(gtk_accel_groups_from_object(G_OBJECT(toplevel))) << "\n"; }
/* Send keyboard accelerators to the parent window, if necessary. * This code is heavily based on gtk_menu_key_press () */ static gboolean hildon_app_menu_key_press (GtkWidget *widget, GdkEventKey *event) { GtkWindow *parent_window; HildonAppMenuPrivate *priv; g_return_val_if_fail (HILDON_IS_APP_MENU (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->key_press_event (widget, event)) return TRUE; priv = HILDON_APP_MENU_GET_PRIVATE (widget); parent_window = priv->parent_window; if (parent_window) { guint accel_key, accel_mods; GdkModifierType consumed_modifiers; GdkDisplay *display; GSList *accel_groups; GSList *list; display = gtk_widget_get_display (widget); /* Figure out what modifiers went into determining the key symbol */ gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display), event->hardware_keycode, event->state, event->group, NULL, NULL, NULL, &consumed_modifiers); accel_key = gdk_keyval_to_lower (event->keyval); accel_mods = event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_modifiers; /* If lowercasing affects the keysym, then we need to include SHIFT in the modifiers, * We re-upper case when we match against the keyval, but display and save in caseless form. */ if (accel_key != event->keyval) accel_mods |= GDK_SHIFT_MASK; accel_groups = gtk_accel_groups_from_object (G_OBJECT (parent_window)); for (list = accel_groups; list; list = list->next) { GtkAccelGroup *accel_group = list->data; if (gtk_accel_group_query (accel_group, accel_key, accel_mods, NULL)) { gtk_window_activate_key (parent_window, event); priv->hide_idle_id = gdk_threads_add_idle (hildon_app_menu_hide_idle, widget); break; } } } return TRUE; }
GClosure* global_accel_group_find( Accelerator accelerator ){ guint numEntries = 0; GtkAccelGroupEntry* entry = gtk_accel_group_query( global_accel, accelerator.key, accelerator.modifiers, &numEntries ); if ( numEntries != 0 ) { if ( numEntries != 1 ) { char* name = gtk_accelerator_name( accelerator.key, accelerator.modifiers ); globalErrorStream() << "accelerator already in-use: " << name << "\n"; g_free( name ); } return entry->closure; } return 0; }
int clip_GTK_ACCELGROUPQUERY(ClipMachine * ClipMachineMemory) { C_widget *caccelg = _fetch_cw_arg(ClipMachineMemory); guint accel_key = _clip_parni(ClipMachineMemory, 2); GdkModifierType mods = _clip_parni(ClipMachineMemory, 3); guint n_entries; GtkAccelGroupEntry *entry; CHECKCWID(caccelg, GTK_IS_ACCEL_GROUP); CHECKOPT2(1, MAP_type_of_ClipVarType, NUMERIC_type_of_ClipVarType); CHECKARG(2, NUMERIC_type_of_ClipVarType); CHECKARG(3, NUMERIC_type_of_ClipVarType); entry = gtk_accel_group_query(GTK_ACCEL_GROUP(caccelg->widget), accel_key, mods, &n_entries); if (entry) { ClipVar *cv = RETPTR(ClipMachineMemory); long n; n = n_entries; _clip_array(ClipMachineMemory, cv, 1, &n); for (n = 0; n < n_entries; n++) { C_object *centry; centry = _register_object(ClipMachineMemory, &entry[n], GTK_TYPE_ACCEL_GROUP_ENTRY, NULL, NULL); if (centry) _clip_aset(ClipMachineMemory, cv, ¢ry->obj, 1, &n); } _clip_storni(ClipMachineMemory, n_entries, 4, 0); } return 0; err: return 1; }
static void accel_edited_callback (GtkCellRendererAccel *cell, gchar *path_string, guint keyval, GdkModifierType mask, guint hardware_keycode, GtkTreeView *view) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; KeyEntry *ke; GtkAccelGroupEntry *entries; guint n_entries; char *str; model = gtk_tree_view_get_model (view); path = gtk_tree_path_new_from_string (path_string); if (!path) return; if (!gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_path_free (path); return; } gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1); /* sanity check */ if (ke == NULL) return; /* Check if we already have an entry using this accel */ entries = gtk_accel_group_query (notification_group, keyval, mask, &n_entries); if (n_entries > 0) { if (entries[0].accel_path_quark != g_quark_from_string (ke->accel_path)) { GtkWidget *dialog; char *name; KeyEntry *other_key; name = gtk_accelerator_get_label (keyval, mask); other_key = entries[0].closure->data; g_assert (other_key); dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The shortcut key “%s” is already bound to the “%s” action"), name, other_key->user_visible_name ? _(other_key->user_visible_name) : other_key->gsettings_key); g_free (name); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_window_present (GTK_WINDOW (dialog)); } return; } str = binding_name (keyval, mask); _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "Edited path %s keyval %s, setting GSettings to %s\n", ke->accel_path, gdk_keyval_name (keyval) ? gdk_keyval_name (keyval) : "null", str); #ifdef MATE_ENABLE_DEBUG _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS) { GtkAccelKey old_key; if (gtk_accel_map_lookup_entry (ke->accel_path, &old_key)) { _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " Old entry of path %s is keyval %s mask %x\n", ke->accel_path, gdk_keyval_name (old_key.accel_key), old_key.accel_mods); } else { _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " Failed to look up the old entry of path %s\n", ke->accel_path); } } #endif g_settings_set_string (settings_keybindings, ke->gsettings_key, str); g_free (str); }
/* if simulate==TRUE, return whether accel_path can be changed to * accel_key && accel_mods. otherwise, return whether accel_path * was actually changed. */ static gboolean internal_change_entry (const gchar *accel_path, guint accel_key, GdkModifierType accel_mods, gboolean replace, gboolean simulate) { GSList *node, *slist, *win_list, *group_list, *replace_list = NULL; GHashTable *group_hm, *window_hm; gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE; GQuark entry_quark; AccelEntry *entry = accel_path_lookup (accel_path); /* not much todo if there's no entry yet */ if (!entry) { if (!simulate) { gtk_accel_map_add_entry (accel_path, 0, 0); entry = accel_path_lookup (accel_path); entry->accel_key = accel_key; entry->accel_mods = accel_mods; entry->changed = TRUE; do_accel_map_changed (entry); } return TRUE; } /* if there's nothing to change, not much todo either */ if (entry->accel_key == accel_key && entry->accel_mods == accel_mods) { if (!simulate) entry->changed = TRUE; return simulate ? TRUE : FALSE; } /* The no-change case has already been handled, so * simulate doesn't make a difference here. */ if (entry->lock_count > 0) return FALSE; /* nobody's interested, easy going */ if (!entry->groups) { if (!simulate) { entry->accel_key = accel_key; entry->accel_mods = accel_mods; entry->changed = TRUE; do_accel_map_changed (entry); } return TRUE; } /* 1) fetch all accel groups affected by this entry */ entry_quark = g_quark_try_string (entry->accel_path); group_hm = g_hash_table_new (NULL, NULL); window_hm = g_hash_table_new (NULL, NULL); for (slist = entry->groups; slist; slist = slist->next) g_hash_table_insert (group_hm, slist->data, slist->data); /* 2) collect acceleratables affected */ group_list = g_hash_table_slist_values (group_hm); for (slist = group_list; slist; slist = slist->next) { GtkAccelGroup *group = slist->data; for (node = _gtk_accel_group_get_accelerables (group); node; node = node->next) g_hash_table_insert (window_hm, node->data, node->data); } g_slist_free (group_list); /* 3) include all accel groups used by acceleratables */ win_list = g_hash_table_slist_values (window_hm); g_hash_table_destroy (window_hm); for (slist = win_list; slist; slist = slist->next) for (node = gtk_accel_groups_from_object (slist->data); node; node = node->next) g_hash_table_insert (group_hm, node->data, node->data); group_list = g_hash_table_slist_values (group_hm); g_hash_table_destroy (group_hm); /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */ if (accel_key) for (slist = win_list; slist; slist = slist->next) if (GTK_IS_WINDOW (slist->data)) /* bad kludge in lack of a GtkAcceleratable */ if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods)) { seen_accel = TRUE; break; } removable = !seen_accel; /* 5) walk all accel groups and search for locks */ if (removable) for (slist = group_list; slist; slist = slist->next) { GtkAccelGroup *group = slist->data; GtkAccelGroupEntry *ag_entry; guint i, n; n = 0; ag_entry = entry->accel_key ? gtk_accel_group_query (group, entry->accel_key, entry->accel_mods, &n) : NULL; for (i = 0; i < n; i++) if (ag_entry[i].accel_path_quark == entry_quark) { can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED); if (!can_change) goto break_loop_step5; } n = 0; ag_entry = accel_key ? gtk_accel_group_query (group, accel_key, accel_mods, &n) : NULL; for (i = 0; i < n; i++) { seen_accel = TRUE; removable = !gtk_accel_group_get_is_locked (group) && !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED); if (!removable) goto break_loop_step5; if (ag_entry[i].accel_path_quark) replace_list = g_slist_prepend (replace_list, GUINT_TO_POINTER (ag_entry[i].accel_path_quark)); } } break_loop_step5: /* 6) check whether we can remove existing accelerators */ if (removable && can_change) for (slist = replace_list; slist; slist = slist->next) if (!internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, TRUE)) { removable = FALSE; break; } /* 7) check conditions and proceed if possible */ change_accel = can_change && (!seen_accel || (removable && replace)); if (change_accel && !simulate) { /* ref accel groups */ for (slist = group_list; slist; slist = slist->next) g_object_ref (slist->data); /* 8) remove existing accelerators */ for (slist = replace_list; slist; slist = slist->next) internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, FALSE); /* 9) install new accelerator */ entry->accel_key = accel_key; entry->accel_mods = accel_mods; entry->changed = TRUE; for (slist = group_list; slist; slist = slist->next) _gtk_accel_group_reconnect (slist->data, g_quark_from_string (entry->accel_path)); /* unref accel groups */ for (slist = group_list; slist; slist = slist->next) g_object_unref (slist->data); do_accel_map_changed (entry); } g_slist_free (replace_list); g_slist_free (group_list); g_slist_free (win_list); return change_accel; }