[mutter] Fix custom-alt-tabs for single-handling of key events
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [mutter] Fix custom-alt-tabs for single-handling of key events
- Date: Wed, 26 Aug 2009 16:40:13 +0000 (UTC)
commit 7b0ba87b24c9faa314d8882e81ed32445dcf70ca
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Tue Aug 25 16:54:54 2009 -0400
Fix custom-alt-tabs for single-handling of key events
The changes to enforce single handling of all key events were breaking
custom-alt-tab keypress handlers, since that code was assuming that
key event would get to process_tab_grab(), and then maybe to
process_event() and then to the plugin's xevent_filter to detect a
key release.
We centeralize all of this handling into process_tab_grab() and either
- Invoke a custom handler for the key press
- Select the current window on modifier release by calling a new
pseudo-binding "tab_popup_select"
- Cancel the grab on an unbound key by calling a new pseudo-binding
"tab_popup_cancel"
http://bugzilla.gnome.org/show_bug.cgi?id=590754
src/core/keybindings.c | 203 +++++++++++++++++++++++++++--------------
src/include/all-keybindings.h | 12 +++
2 files changed, 145 insertions(+), 70 deletions(-)
---
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 957d5e7..9ba062d 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -475,11 +475,11 @@ regrab_key_bindings (MetaDisplay *display)
g_slist_free (windows);
}
-static MetaKeyBindingAction
-display_get_keybinding_action (MetaDisplay *display,
- unsigned int keysym,
- unsigned int keycode,
- unsigned long mask)
+static MetaKeyBinding *
+display_get_keybinding (MetaDisplay *display,
+ unsigned int keysym,
+ unsigned int keycode,
+ unsigned long mask)
{
int i;
@@ -490,13 +490,29 @@ display_get_keybinding_action (MetaDisplay *display,
display->key_bindings[i].keycode == keycode &&
display->key_bindings[i].mask == mask)
{
- return meta_prefs_get_keybinding_action (display->key_bindings[i].name);
+ return &display->key_bindings[i];
}
--i;
}
- return META_KEYBINDING_ACTION_NONE;
+ return NULL;
+}
+
+static MetaKeyBindingAction
+display_get_keybinding_action (MetaDisplay *display,
+ unsigned int keysym,
+ unsigned int keycode,
+ unsigned long mask)
+{
+ MetaKeyBinding *binding;
+
+ binding = display_get_keybinding (display, keysym, keycode, mask);
+
+ if (binding)
+ return meta_prefs_get_keybinding_action (binding->name);
+ else
+ return META_KEYBINDING_ACTION_NONE;
}
void
@@ -1197,6 +1213,45 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
}
+static void
+invoke_handler (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaKeyHandler *handler,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+
+{
+ if (handler->func)
+ (* handler->func) (display, screen,
+ handler->flags & BINDING_PER_WINDOW ?
+ window : NULL,
+ event,
+ binding,
+ handler->user_data);
+ else
+ (* handler->default_func) (display, screen,
+ handler->flags & BINDING_PER_WINDOW ?
+ window: NULL,
+ event,
+ binding,
+ NULL);
+}
+
+static void
+invoke_handler_by_name (MetaDisplay *display,
+ MetaScreen *screen,
+ const char *handler_name,
+ MetaWindow *window,
+ XEvent *event)
+{
+ MetaKeyHandler *handler;
+
+ handler = find_handler (key_handlers, handler_name);
+ if (handler)
+ invoke_handler (display, screen, handler, window, event, NULL);
+}
+
/* now called from only one place, may be worth merging */
static gboolean
process_event (MetaKeyBinding *bindings,
@@ -1253,20 +1308,7 @@ process_event (MetaKeyBinding *bindings,
*/
display->allow_terminal_deactivation = TRUE;
- if (handler->func)
- (* handler->func) (display, screen,
- bindings[i].handler->flags & BINDING_PER_WINDOW ?
- window: NULL,
- event,
- &bindings[i],
- handler->user_data);
- else
- (* handler->default_func) (display, screen,
- bindings[i].handler->flags & BINDING_PER_WINDOW ?
- window: NULL,
- event,
- &bindings[i],
- NULL);
+ invoke_handler (display, screen, handler, window, event, &bindings[i]);
return TRUE;
}
@@ -1985,6 +2027,7 @@ process_tab_grab (MetaDisplay *display,
XEvent *event,
KeySym keysym)
{
+ MetaKeyBinding *binding;
MetaKeyBindingAction action;
gboolean popup_not_showing;
gboolean backward;
@@ -1994,79 +2037,78 @@ process_tab_grab (MetaDisplay *display,
if (screen != display->grab_screen)
return FALSE;
- action = display_get_keybinding_action (display,
- keysym,
- event->xkey.keycode,
- display->grab_mask);
+ binding = display_get_keybinding (display,
+ keysym,
+ event->xkey.keycode,
+ display->grab_mask);
+ if (binding)
+ action = meta_prefs_get_keybinding_action (binding->name);
+ else
+ action = META_KEYBINDING_ACTION_NONE;
/*
- * If there is no tab_pop up object, i.e., there is some custom handler
- * implementing Alt+Tab & Co., we call this custom handler; we do not
- * mess about with the grab, as that is up to the handler to deal with.
+ * There are currently two different ways of customizing Alt-Tab, you can either
+ * provide a replacement AltTabHandler object, or you can hook into the keybindings
+ * meta_keybindings_set_custom_handler() and call meta_display_begin_grab_op()
+ * yourself with one of the "tabbing" grab ops META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
+ * etc. See meta_display_process_key_event() for the complete list. If screen->tab_handler
+ * is NULL, the latter mechanism is being used. We skip most of our normal
+ * processing and just make sure that the right custom handlers get called.
*/
if (!screen->tab_handler)
{
- MetaKeyHandler *handler = NULL;
- const gchar *handler_name = NULL;
+ if (event->type == KeyRelease)
+ {
+ if (end_keyboard_grab (display, event->xkey.keycode))
+ {
+ invoke_handler_by_name (display, screen, "tab_popup_select", NULL, event);
+
+ /* We return FALSE to end the grab; if the handler ended the grab itself
+ * that will be a noop. If the handler didn't end the grab, then it's a
+ * safety measure to prevent a stuck grab.
+ */
+ return FALSE;
+ }
+
+ return TRUE;
+ }
switch (action)
{
case META_KEYBINDING_ACTION_CYCLE_PANELS:
- handler_name = "cycle_group";
- break;
case META_KEYBINDING_ACTION_CYCLE_WINDOWS:
- handler_name = "cycle_windows";
- break;
case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD:
- handler_name = "cycle_panels_backward";
- break;
case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD:
- handler_name = "cycle_windows_backward";
- break;
case META_KEYBINDING_ACTION_SWITCH_PANELS:
- handler_name = "switch_panels";
- break;
case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
- handler_name = "switch_windows";
- break;
case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD:
- handler_name = "switch_panels_backward";
- break;
case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD:
- handler_name = "switch_windows_backward";
- break;
case META_KEYBINDING_ACTION_CYCLE_GROUP:
- handler_name = "cycle_group";
- break;
case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD:
- handler_name = "cycle_group_backward";
- break;
case META_KEYBINDING_ACTION_SWITCH_GROUP:
- handler_name = "switch_group";
- break;
case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD:
- handler_name = "switch_group_backward";
+ /* These are the tab-popup bindings. If a custom Alt-Tab implementation
+ * is in effect, we expect it to want to handle all of these as a group
+ *
+ * If there are some of them that the custom implementation didn't
+ * handle, we treat them as "unbound" for the duration - running the
+ * normal handlers could get us into trouble.
+ */
+ if (binding->handler &&
+ binding->handler->func &&
+ binding->handler->func != binding->handler->default_func)
+ {
+ invoke_handler (display, screen, binding->handler, NULL, event, binding);
+ return TRUE;
+ }
break;
default:
- /*
- * This is the case when the Alt key is released; we preserve
- * the grab, as it is up to the custom implementaiton to free it
- * (a plugin can catch this in their xevent_filter function).
- */
- return TRUE;
+ break;
}
- /*
- * We do not want to actually call the handler, we just want to ensure
- * that if a custom handler is installed, we do not release the grab here.
- * The handler will get called as normal in the process_event() function.
- */
- handler = find_handler (key_handlers, handler_name);
-
- if (!handler || !handler->func || handler->func == handler->default_func)
- return FALSE;
-
- return TRUE;
+ /* Some unhandled key press */
+ invoke_handler_by_name (display, screen, "tab_popup_cancel", NULL, event);
+ return FALSE;
}
if (event->type == KeyRelease &&
@@ -3048,6 +3090,27 @@ handle_cycle (MetaDisplay *display,
backwards, FALSE);
}
+static void
+handle_tab_popup_select (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding,
+ gpointer dummy)
+{
+ /* Stub for custom handlers; no default implementation */
+}
+
+static void
+handle_tab_popup_cancel (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding,
+ gpointer dummy)
+{
+ /* Stub for custom handlers; no default implementation */
+}
static void
handle_toggle_fullscreen (MetaDisplay *display,
diff --git a/src/include/all-keybindings.h b/src/include/all-keybindings.h
index 408b94a..896c0c2 100644
--- a/src/include/all-keybindings.h
+++ b/src/include/all-keybindings.h
@@ -186,6 +186,18 @@ keybind (cycle_panels_backward, handle_cycle, META_TAB_LIST_DOCKS,
_("Move backward between panels and the desktop immediately"))
/***********************************/
+
+/* These two are special pseudo-bindings that are provided for allowing
+ * custom handlers, but will never be bound to a key. While a tab
+ * grab is in effect, they are invoked for releasing the primary modifier
+ * or pressing some unbound key, respectively.
+ */
+keybind (tab_popup_select, handle_tab_popup_select, 0, 0, NULL,
+ "Select window from tab popup")
+keybind (tab_popup_cancel, handle_tab_popup_cancel, 0, 0, NULL,
+ "Cancel tab popup")
+
+/***********************************/
keybind (show_desktop, handle_show_desktop, 0, 0, "<Control><Alt>d",
_("Hide all normal windows and set focus to the desktop"))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]