diff --git a/js/ui/main.js b/js/ui/main.js index 638a85777..db7698bd3 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -167,8 +167,6 @@ function start() { _startDate = new Date(); - global.stage.connect('captured-event', _globalKeyPressHandler); - log('GNOME Shell started at ' + _startDate); let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); @@ -465,86 +463,6 @@ function getWindowActorsForWorkspace(workspaceIndex) { }); } -// This function encapsulates hacks to make certain global keybindings -// work even when we are in one of our modes where global keybindings -// are disabled with a global grab. (When there is a global grab, then -// all key events will be delivered to the stage, so ::captured-event -// on the stage can be used for global keybindings.) -function _globalKeyPressHandler(actor, event) { - if (modalCount == 0) - return false; - if (event.type() != Clutter.EventType.KEY_PRESS && event.type() != Clutter.EventType.KEY_RELEASE) - return false; - - if (!sessionMode.allowKeybindingsWhenModal) { - if (modalCount > (overview.visible ? 1 : 0)) - return false; - } - - let symbol = event.get_key_symbol(); - let keyCode = event.get_key_code(); - let ignoredModifiers = global.display.get_ignored_modifier_mask(); - let modifierState = event.get_state() & ~ignoredModifiers; - - // This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType - let action = global.display.get_keybinding_action(keyCode, modifierState); - - if (event.type() == Clutter.EventType.KEY_PRESS) { - if (action == Meta.KeyBindingAction.SWITCH_PANELS) { - ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK, - modifierState); - return true; - } - - switch (action) { - // left/right would effectively act as synonyms for up/down if we enabled them; - // but that could be considered confusing; we also disable them in the main view. - // - // case Meta.KeyBindingAction.WORKSPACE_LEFT: - // if (!sessionMode.hasWorkspaces) - // return false; - // - // wm.actionMoveWorkspaceLeft(); - // return true; - // case Meta.KeyBindingAction.WORKSPACE_RIGHT: - // if (!sessionMode.hasWorkspaces) - // return false; - // - // wm.actionMoveWorkspaceRight(); - // return true; - case Meta.KeyBindingAction.WORKSPACE_UP: - if (!sessionMode.hasWorkspaces) - return false; - - wm.actionMoveWorkspace(Meta.MotionDirection.UP); - return true; - case Meta.KeyBindingAction.WORKSPACE_DOWN: - if (!sessionMode.hasWorkspaces) - return false; - - wm.actionMoveWorkspace(Meta.MotionDirection.DOWN); - return true; - case Meta.KeyBindingAction.PANEL_RUN_DIALOG: - case Meta.KeyBindingAction.COMMAND_2: - if (!sessionMode.hasRunDialog) - return false; - - openRunDialog(); - return true; - case Meta.KeyBindingAction.PANEL_MAIN_MENU: - overview.hide(); - return true; - } - } else if (event.type() == Clutter.EventType.KEY_RELEASE) { - if (action == Meta.KeyBindingAction.OVERLAY_KEY) { - overview.hide(); - return true; - } - } - - return false; -} - function _findModal(actor) { for (let i = 0; i < modalActorFocusStack.length; i++) { if (modalActorFocusStack[i].actor == actor) diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js index 6a52037d7..eb7570f48 100644 --- a/js/ui/windowManager.js +++ b/js/ui/windowManager.js @@ -99,6 +99,7 @@ const WindowManager = new Lang.Class({ this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow)); this._shellwm.connect('map', Lang.bind(this, this._mapWindow)); this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow)); + this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding)); this._workspaceSwitcherPopup = null; Meta.keybindings_set_custom_handler('switch-to-workspace-left', @@ -424,6 +425,36 @@ const WindowManager = new Lang.Class({ } }, + _filterKeybinding: function(shellwm, binding) { + if (!Main.sessionMode.allowKeybindingsWhenModal) { + if (Main.modalCount > (Main.overview.visible ? 1 : 0)) + return true; + } + let action = Meta.prefs_get_keybinding_action(binding.get_name()); + switch (action) { + // left/right would effectively act as synonyms for up/down if we enabled them; + // but that could be considered confusing; we also disable them in the main view. + // + // case Meta.KeyBindingAction.WORKSPACE_LEFT: + // case Meta.KeyBindingAction.WORKSPACE_RIGHT: + case Meta.KeyBindingAction.WORKSPACE_UP: + case Meta.KeyBindingAction.WORKSPACE_DOWN: + return !Main.sessionMode.hasWorkspaces; + + case Meta.KeyBindingAction.PANEL_RUN_DIALOG: + case Meta.KeyBindingAction.COMMAND_2: + case Meta.KeyBindingAction.PANEL_MAIN_MENU: + case Meta.KeyBindingAction.OVERLAY_KEY: + case Meta.KeyBindingAction.SWITCH_PANELS: + return false; + } + + if (Main.modalCount == 0 && binding.is_builtin()) + return false; + + return true; + }, + _switchWorkspace : function(shellwm, from, to, direction) { if (!this._shouldAnimate()) { shellwm.completed_switch_workspace(); diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c index 737c19067..03ae79a39 100644 --- a/src/gnome-shell-plugin.c +++ b/src/gnome-shell-plugin.c @@ -72,6 +72,9 @@ static void gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin); static gboolean gnome_shell_plugin_xevent_filter (MetaPlugin *plugin, XEvent *event); + +static gboolean gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin, + MetaKeyBinding *binding); static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin); @@ -126,8 +129,9 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass) plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects; plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace; - plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter; - plugin_class->plugin_info = gnome_shell_plugin_plugin_info; + plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter; + plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter; + plugin_class->plugin_info = gnome_shell_plugin_plugin_info; } static void @@ -337,6 +341,13 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin, return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; } +static gboolean +gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin, + MetaKeyBinding *binding) +{ + return _shell_wm_filter_keybinding (get_shell_wm (), binding); +} + static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin) { diff --git a/src/shell-wm-private.h b/src/shell-wm-private.h index c0cd84d23..6fc9348ce 100644 --- a/src/shell-wm-private.h +++ b/src/shell-wm-private.h @@ -35,6 +35,9 @@ void _shell_wm_kill_window_effects (ShellWM *wm, MetaWindowActor *actor); void _shell_wm_kill_switch_workspace (ShellWM *wm); +gboolean _shell_wm_filter_keybinding (ShellWM *wm, + MetaKeyBinding *binding); + G_END_DECLS #endif /* __SHELL_WM_PRIVATE_H__ */ diff --git a/src/shell-wm.c b/src/shell-wm.c index 835c970cd..08aceb7f2 100644 --- a/src/shell-wm.c +++ b/src/shell-wm.c @@ -26,6 +26,7 @@ enum SWITCH_WORKSPACE, KILL_SWITCH_WORKSPACE, KILL_WINDOW_EFFECTS, + FILTER_KEYBINDING, LAST_SIGNAL }; @@ -115,6 +116,14 @@ shell_wm_class_init (ShellWMClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 1, META_TYPE_WINDOW_ACTOR); + shell_wm_signals[FILTER_KEYBINDING] = + g_signal_new ("filter-keybinding", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, NULL, NULL, + G_TYPE_BOOLEAN, 1, + META_TYPE_KEY_BINDING); } void @@ -267,6 +276,17 @@ _shell_wm_destroy (ShellWM *wm, g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor); } +gboolean +_shell_wm_filter_keybinding (ShellWM *wm, + MetaKeyBinding *binding) +{ + gboolean rv; + + g_signal_emit (wm, shell_wm_signals[FILTER_KEYBINDING], 0, binding, &rv); + + return rv; +} + /** * shell_wm_new: * @plugin: the #MetaPlugin