static gboolean do_ungrab_key (Binding *binding) { GdkWindow *rootwin = gdk_get_default_root_window (); TRACE (g_print ("Removing grab for '%s'\n", binding->keystring)); grab_ungrab_with_ignorable_modifiers (rootwin, binding, FALSE /* ungrab */); return TRUE; }
/* Grab or ungrab the keycode+modifiers combination, first plainly, and then * including each ignorable modifier in turn. */ static gboolean grab_ungrab_with_ignorable_modifiers (GdkWindow *rootwin, uint keycode, uint modifiers, gboolean grab) { guint i; gboolean success = FALSE; /* Ignorable modifiers */ guint mod_masks [] = { 0, /* modifier only */ GDK_MOD2_MASK, GDK_LOCK_MASK, GDK_MOD2_MASK | GDK_LOCK_MASK, }; gdk_error_trap_push (); for (i = 0; i < G_N_ELEMENTS (mod_masks); i++) { if (grab) { XGrabKey (GDK_WINDOW_XDISPLAY (rootwin), keycode, modifiers | mod_masks [i], GDK_WINDOW_XID (rootwin), False, GrabModeAsync, GrabModeAsync); } else { XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin), keycode, modifiers | mod_masks [i], GDK_WINDOW_XID (rootwin)); } } gdk_flush(); if (gdk_error_trap_pop()) { TRACE (g_warning ("Failed grab/ungrab")); if (grab) { /* On error, immediately release keys again */ grab_ungrab_with_ignorable_modifiers(rootwin, keycode, modifiers, FALSE); } } else { success = TRUE; } return success; }
static gboolean do_grab_key (Binding *binding) { GdkKeymap *keymap = gdk_keymap_get_default (); GdkWindow *rootwin = gdk_get_default_root_window (); EggVirtualModifierType virtual_mods = 0; guint keysym = 0; if (keymap == NULL || rootwin == NULL) return FALSE; if (!egg_accelerator_parse_virtual (binding->keystring, &keysym, &virtual_mods)) return FALSE; TRACE (g_print ("Got accel %d, %d\n", keysym, virtual_mods)); binding->keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin), keysym); if (binding->keycode == 0) return FALSE; TRACE (g_print ("Got keycode %d\n", binding->keycode)); egg_keymap_resolve_virtual_modifiers (keymap, virtual_mods, &binding->modifiers); if (binding->modifiers == 0) return FALSE; TRACE (g_print ("Got modmask %d\n", binding->modifiers)); gdk_error_trap_push (); grab_ungrab_with_ignorable_modifiers (rootwin, binding, TRUE /* grab */); gdk_flush (); if (gdk_error_trap_pop ()) { g_warning ("Binding '%s' failed!\n", binding->keystring); return FALSE; } return TRUE; }
static void accel_cleared_callback (GtkCellRendererText *cell, const char *path_string, gpointer data) { GtkTreeView *view = (GtkTreeView *) data; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); GtkAccelKey *key_entry = NULL; GtkTreeIter iter = {0}; GtkTreeModel *model = NULL; model = gtk_tree_view_get_model (view); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, HOTKEY_COLUMN, &key_entry, -1); g_assert(key_entry); /* unregister what's previously registered */ grab_ungrab_with_ignorable_modifiers(key_entry, FALSE); key_entry->accel_key = key_entry->accel_mods = key_entry->accel_flags = 0; }
static void accel_edited_callback(GtkCellRendererText *cell, const char *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer data) { GtkTreeView *view = (GtkTreeView *)data; GtkTreeModel *model = NULL; GtkTreeIter iter = {0}; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); GtkAccelKey *key_entry = NULL, temp_key = {0}; GtkWidget *msg_dialog = NULL; gchar *temp_str = NULL; model = gtk_tree_view_get_model (view); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, HOTKEY_COLUMN, &key_entry, -1); /* sanity check and check to see if the same key combo was pressed again */ if (key_entry == NULL || (key_entry->accel_key == accel_key && key_entry->accel_mods == accel_mods && key_entry->accel_flags == hardware_keycode)) return; /* CapsLock isn't supported as a keybinding modifier, so keep it from confusing us */ accel_mods &= ~GDK_LOCK_MASK; temp_key.accel_key = accel_key; temp_key.accel_flags = hardware_keycode; temp_key.accel_mods = accel_mods; /* Check for unmodified keys */ if (temp_key.accel_mods == 0 && temp_key.accel_key != 0) { if ((temp_key.accel_key >= GDK_a && temp_key.accel_key <= GDK_z) || (temp_key.accel_key >= GDK_A && temp_key.accel_key <= GDK_Z) || (temp_key.accel_key >= GDK_0 && temp_key.accel_key <= GDK_9) || (temp_key.accel_key >= GDK_kana_fullstop && temp_key.accel_key <= GDK_semivoicedsound) || (temp_key.accel_key >= GDK_Arabic_comma && temp_key.accel_key <= GDK_Arabic_sukun) || (temp_key.accel_key >= GDK_Serbian_dje && temp_key.accel_key <= GDK_Cyrillic_HARDSIGN) || (temp_key.accel_key >= GDK_Greek_ALPHAaccent && temp_key.accel_key <= GDK_Greek_omega) || (temp_key.accel_key >= GDK_hebrew_doublelowline && temp_key.accel_key <= GDK_hebrew_taf) || (temp_key.accel_key >= GDK_Thai_kokai && temp_key.accel_key <= GDK_Thai_lekkao) || (temp_key.accel_key >= GDK_Hangul && temp_key.accel_key <= GDK_Hangul_Special) || (temp_key.accel_key >= GDK_Hangul_Kiyeog && temp_key.accel_key <= GDK_Hangul_J_YeorinHieuh) || keyval_is_forbidden (temp_key.accel_key)) { temp_str = gtk_accelerator_get_label (accel_key, accel_mods); msg_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, STR_INVALID_HOTKEY, temp_str); g_object_set(msg_dialog, "title", STR_INVALID_HOTKEY_TITLE, NULL); g_free (temp_str); temp_str = NULL; gtk_dialog_run (GTK_DIALOG (msg_dialog)); gtk_widget_destroy (msg_dialog); msg_dialog = NULL; return; } } /* try registering the new key combo */ if(grab_ungrab_with_ignorable_modifiers(&temp_key, TRUE)) { /* unregistering previous hotkey is not necessary on Win32 since the same prev. hotkey is modified to the new one */ #ifndef G_OS_WIN32 /* unregister the previous hotkey */ grab_ungrab_with_ignorable_modifiers(key_entry, FALSE); #endif /* set the value in the list store to the newly set key combo so that it gets reflected in the Accel Cell Renderer */ key_entry->accel_key = accel_key; key_entry->accel_flags = hardware_keycode; key_entry->accel_mods = accel_mods; } else { temp_str = gtk_accelerator_get_label (accel_key, accel_mods); msg_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, STR_DUPLICATE_HOTKEY, temp_str); g_object_set(msg_dialog, "title", STR_INVALID_HOTKEY_TITLE, NULL); g_free (temp_str); temp_str = NULL; gtk_dialog_run (GTK_DIALOG (msg_dialog)); gtk_widget_destroy (msg_dialog); return; } }
/* Grab or ungrab then keyval and modifiers combination, grabbing all key * combinations yielding the same key values. * Includes ignorable modifiers using grab_ungrab_with_ignorable_modifiers. */ static gboolean grab_ungrab (GdkWindow *rootwin, uint keyval, uint modifiers, gboolean grab) { int k; GdkKeymap *map; GdkKeymapKey *keys; gint n_keys; GdkModifierType add_modifiers; XkbDescPtr xmap; gboolean success = FALSE; xmap = XkbGetMap(GDK_WINDOW_XDISPLAY(rootwin), XkbAllClientInfoMask, XkbUseCoreKbd); map = gdk_keymap_get_default(); gdk_keymap_get_entries_for_keyval(map, keyval, &keys, &n_keys); if (n_keys == 0) return FALSE; for (k = 0; k < n_keys; k++) { /* NOTE: We only bind for the first group, * so regardless of current keyboard layout, it will * grab the key from the default Layout. */ if (keys[k].group != WE_ONLY_USE_ONE_GROUP) { continue; } add_modifiers = FinallyGetModifiersForKeycode(xmap, keys[k].keycode, keys[k].group, keys[k].level); if (add_modifiers == MODIFIERS_ERROR) { continue; } TRACE (g_print("grab/ungrab keycode: %d, lev: %d, grp: %d, ", keys[k].keycode, keys[k].level, keys[k].group)); TRACE (g_print("modifiers: 0x%x (consumed: 0x%x)\n", add_modifiers | modifiers, add_modifiers)); if (grab_ungrab_with_ignorable_modifiers(rootwin, keys[k].keycode, add_modifiers | modifiers, grab)) { success = TRUE; } else { /* When grabbing, break on error */ if (grab && !success) { break; } } } g_free(keys); XkbFreeClientMap(xmap, 0, TRUE); return success; }