From c7dc6928a98a985e3832558989baace38720e2d6 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Sun, 31 Mar 2013 19:06:40 +0200 Subject: [PATCH] keybindings: Fix ungrabbing of keys XUngrabKey() doesn't work for XI2 grabs and XI2 doesn't provide API with similar functionality. As such, we have to refactor the code a bit to be able to call XIUngrabKeycode() for each key binding, then reload keybindings and finally grab the new ones. https://bugzilla.gnome.org/show_bug.cgi?id=697003 --- src/core/keybindings.c | 160 ++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index fc9a31ad0..b1681c7ee 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -147,7 +147,8 @@ static gboolean process_workspace_switch_grab (MetaDisplay *display, XIDeviceEvent *event, KeySym keysym); -static void regrab_key_bindings (MetaDisplay *display); +static void grab_key_bindings (MetaDisplay *display); +static void ungrab_key_bindings (MetaDisplay *display); static GHashTable *key_handlers; @@ -531,7 +532,7 @@ rebuild_special_bindings (MetaDisplay *display) } static void -regrab_key_bindings (MetaDisplay *display) +ungrab_key_bindings (MetaDisplay *display) { GSList *tmp; GSList *windows; @@ -544,7 +545,6 @@ regrab_key_bindings (MetaDisplay *display) MetaScreen *screen = tmp->data; meta_screen_ungrab_keys (screen); - meta_screen_grab_keys (screen); tmp = tmp->next; } @@ -556,6 +556,38 @@ regrab_key_bindings (MetaDisplay *display) MetaWindow *w = tmp->data; meta_window_ungrab_keys (w); + + tmp = tmp->next; + } + meta_error_trap_pop (display); + + g_slist_free (windows); +} + +static void +grab_key_bindings (MetaDisplay *display) +{ + GSList *tmp; + GSList *windows; + + meta_error_trap_push (display); /* for efficiency push outer trap */ + + tmp = display->screens; + while (tmp != NULL) + { + MetaScreen *screen = tmp->data; + + meta_screen_grab_keys (screen); + + tmp = tmp->next; + } + + windows = meta_display_list_windows (display, META_LIST_DEFAULT); + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + meta_window_grab_keys (w); tmp = tmp->next; @@ -796,6 +828,8 @@ meta_display_process_mapping_event (MetaDisplay *display, if (keymap_changed || modmap_changed) { + ungrab_key_bindings (display); + if (keymap_changed) reload_keymap (display); @@ -809,7 +843,7 @@ meta_display_process_mapping_event (MetaDisplay *display, reload_modifiers (display); - regrab_key_bindings (display); + grab_key_bindings (display); } } @@ -824,11 +858,12 @@ bindings_changed_callback (MetaPreference pref, switch (pref) { case META_PREF_KEYBINDINGS: + ungrab_key_bindings (display); rebuild_key_binding_table (display); rebuild_special_bindings (display); reload_keycodes (display); reload_modifiers (display); - regrab_key_bindings (display); + grab_key_bindings (display); break; default: break; @@ -947,21 +982,12 @@ meta_change_keygrab (MetaDisplay *display, } static void -meta_grab_key (MetaDisplay *display, - Window xwindow, - int keysym, - unsigned int keycode, - int modmask) -{ - meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask); -} - -static void -grab_keys (MetaKeyBinding *bindings, - int n_bindings, - MetaDisplay *display, - Window xwindow, - gboolean binding_per_window) +change_binding_keygrabs (MetaKeyBinding *bindings, + int n_bindings, + MetaDisplay *display, + Window xwindow, + gboolean binding_per_window, + gboolean grab) { int i; @@ -976,10 +1002,10 @@ grab_keys (MetaKeyBinding *bindings, !!(bindings[i].handler->flags & META_KEY_BINDING_PER_WINDOW) && bindings[i].keycode != 0) { - meta_grab_key (display, xwindow, - bindings[i].keysym, - bindings[i].keycode, - bindings[i].mask); + meta_change_keygrab (display, xwindow, grab, + bindings[i].keysym, + bindings[i].keycode, + bindings[i].mask); } ++i; @@ -989,51 +1015,33 @@ grab_keys (MetaKeyBinding *bindings, } static void -ungrab_all_keys (MetaDisplay *display, - Window xwindow) +meta_screen_change_keygrabs (MetaScreen *screen, + gboolean grab) { - if (meta_is_debugging ()) - meta_error_trap_push_with_return (display); - else - meta_error_trap_push (display); + MetaDisplay *display = screen->display; - XUngrabKey (display->xdisplay, AnyKey, AnyModifier, - xwindow); + if (display->overlay_key_combo.keycode != 0) + meta_change_keygrab (display, screen->xroot, grab, + display->overlay_key_combo.keysym, + display->overlay_key_combo.keycode, + display->overlay_key_combo.modifiers); - if (meta_is_debugging ()) - { - int result; - - result = meta_error_trap_pop_with_return (display); - - if (result != Success) - meta_topic (META_DEBUG_KEYBINDINGS, - "Ungrabbing all keys on 0x%lx failed\n", xwindow); - } - else - meta_error_trap_pop (display); + change_binding_keygrabs (screen->display->key_bindings, + screen->display->n_key_bindings, + screen->display, screen->xroot, + FALSE, grab); } void meta_screen_grab_keys (MetaScreen *screen) { - MetaDisplay *display = screen->display; if (screen->all_keys_grabbed) return; if (screen->keys_grabbed) return; - if (display->overlay_key_combo.keycode != 0) - meta_grab_key (display, screen->xroot, - display->overlay_key_combo.keysym, - display->overlay_key_combo.keycode, - display->overlay_key_combo.modifiers); - - grab_keys (screen->display->key_bindings, - screen->display->n_key_bindings, - screen->display, screen->xroot, - FALSE); + meta_screen_change_keygrabs (screen, TRUE); screen->keys_grabbed = TRUE; } @@ -1041,11 +1049,23 @@ meta_screen_grab_keys (MetaScreen *screen) void meta_screen_ungrab_keys (MetaScreen *screen) { - if (screen->keys_grabbed) - { - ungrab_all_keys (screen->display, screen->xroot); - screen->keys_grabbed = FALSE; - } + if (!screen->keys_grabbed) + return; + + meta_screen_change_keygrabs (screen, FALSE); + + screen->keys_grabbed = FALSE; +} + +static void +meta_window_change_keygrabs (MetaWindow *window, + Window xwindow, + gboolean grab) +{ + change_binding_keygrabs (window->display->key_bindings, + window->display->n_key_bindings, + window->display, xwindow, + TRUE, grab); } void @@ -1058,7 +1078,7 @@ meta_window_grab_keys (MetaWindow *window) || window->override_redirect) { if (window->keys_grabbed) - ungrab_all_keys (window->display, window->xwindow); + meta_window_change_keygrabs (window, window->xwindow, FALSE); window->keys_grabbed = FALSE; return; } @@ -1066,7 +1086,7 @@ meta_window_grab_keys (MetaWindow *window) if (window->keys_grabbed) { if (window->frame && !window->grab_on_frame) - ungrab_all_keys (window->display, window->xwindow); + meta_window_change_keygrabs (window, window->xwindow, FALSE); else if (window->frame == NULL && window->grab_on_frame) ; /* continue to regrab on client window */ @@ -1074,11 +1094,9 @@ meta_window_grab_keys (MetaWindow *window) return; /* already all good */ } - grab_keys (window->display->key_bindings, - window->display->n_key_bindings, - window->display, - window->frame ? window->frame->xwindow : window->xwindow, - TRUE); + meta_window_change_keygrabs (window, + window->frame ? window->frame->xwindow : window->xwindow, + TRUE); window->keys_grabbed = TRUE; window->grab_on_frame = window->frame != NULL; @@ -1091,11 +1109,9 @@ meta_window_ungrab_keys (MetaWindow *window) { if (window->grab_on_frame && window->frame != NULL) - ungrab_all_keys (window->display, - window->frame->xwindow); + meta_window_change_keygrabs (window, window->frame->xwindow, FALSE); else if (!window->grab_on_frame) - ungrab_all_keys (window->display, - window->xwindow); + meta_window_change_keygrabs (window, window->xwindow, FALSE); window->keys_grabbed = FALSE; } @@ -1151,7 +1167,7 @@ meta_display_grab_accelerator (MetaDisplay *display, for (l = display->screens; l; l = l->next) { MetaScreen *screen = l->data; - meta_grab_key (display, screen->xroot, keysym, keycode, mask); + meta_change_keygrab (display, screen->xroot, TRUE, keysym, keycode, mask); } grab = g_new0 (MetaKeyGrab, 1);