From 799f56fe877ca8e66bdf97a702f78e1298aed691 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Wed, 12 Aug 2009 00:22:46 -0400 Subject: [PATCH] Use new plugin-modality functionality in Mutter We now have functionality in Mutter to grab the keyboard on behalf of a plugin. This avoids interactions with the key handling code in Mutter that could leave the user with an inconsistent state and no way to get out of it. src/shell-global.[ch]: Change shell_global_grab_keyboard() and shell_global_grab_keyboard() to shell_global_begin_modal() shell_global_end_modal() and call mutter_plugin_begin_modal() mutter_plugin_end_modal() rather than directly grabbing the keyboard. main.js: Call global.begin_modal/end_modal from Main.startModal() and Main.endModal() altTab.js; Remove call to Main.startModal() - we're letting Mutter handle modality for Alt-Tab. main.js lookingGlass.js overview.js runDialog.js: Rename Main.startModal() to Main.beginModal() for consistency with naming in mutter and ShellGlobal. http://bugzilla.gnome.org/show_bug.cgi?id=590686 --- js/ui/altTab.js | 4 --- js/ui/lookingGlass.js | 2 +- js/ui/main.js | 8 ++++-- js/ui/overview.js | 2 +- js/ui/runDialog.js | 2 +- src/shell-global.c | 65 +++++++++++++------------------------------ src/shell-global.h | 6 ++-- 7 files changed, 32 insertions(+), 57 deletions(-) diff --git a/js/ui/altTab.js b/js/ui/altTab.js index f8470f198..d2a2711ca 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -144,8 +144,6 @@ AltTabPopup.prototype = { show : function(initialSelection) { let global = Shell.Global.get(); - Main.startModal(); - global.window_group.add_actor(this._overlay); this._overlay.raise_top(); this._overlay.show(); @@ -164,8 +162,6 @@ AltTabPopup.prototype = { destroy : function() { this.actor.destroy(); this._overlay.destroy(); - - Main.endModal(); }, select : function(n) { diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js index 5091fda48..57f2a23d6 100644 --- a/js/ui/lookingGlass.js +++ b/js/ui/lookingGlass.js @@ -555,7 +555,7 @@ LookingGlass.prototype = { Tweener.removeTweens(this.actor); - if (!Main.startModal()) + if (!Main.beginModal()) return; let global = Shell.Global.get(); diff --git a/js/ui/main.js b/js/ui/main.js index 4bae93269..484bddc8f 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -137,10 +137,11 @@ function _removeUnusedWorkspaces() { // Used to go into a mode where all keyboard and mouse input goes to // the stage. Returns true if we successfully grabbed the keyboard and // went modal, false otherwise -function startModal() { +function beginModal() { let global = Shell.Global.get(); + let timestamp = global.screen.get_display().get_current_time(); - if (!global.grab_keyboard()) + if (!global.begin_modal(timestamp)) return false; global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN); @@ -151,8 +152,9 @@ function startModal() { function endModal() { let global = Shell.Global.get(); + let timestamp = global.screen.get_display().get_current_time(); - global.ungrab_keyboard(); + global.end_modal(timestamp); global.set_stage_input_mode(Shell.StageInputMode.NORMAL); inModal = false; } diff --git a/js/ui/overview.js b/js/ui/overview.js index 94b4cbdc4..bdfea25f0 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -271,7 +271,7 @@ Overview.prototype = { show : function() { if (this.visible) return; - if (!Main.startModal()) + if (!Main.beginModal()) return; this.visible = true; diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js index 5d68bb832..53a56e95a 100644 --- a/js/ui/runDialog.js +++ b/js/ui/runDialog.js @@ -124,7 +124,7 @@ RunDialog.prototype = { if (this._isOpen) // Already shown return; - if (!Main.startModal()) + if (!Main.beginModal()) return; this._isOpen = true; diff --git a/src/shell-global.c b/src/shell-global.c index e192b34e5..6193e0eb6 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -40,7 +40,6 @@ struct _ShellGlobal { MutterPlugin *plugin; ShellWM *wm; - gboolean keyboard_grabbed; const char *imagedir; const char *configdir; @@ -475,66 +474,42 @@ _shell_global_set_plugin (ShellGlobal *global, } /** - * shell_global_grab_keyboard: + * shell_global_begin_modal: * @global: a #ShellGlobal * - * Grab the keyboard to the stage window. The stage will receive - * all keyboard events until shell_global_ungrab_keyboard() is called. - * This is appropriate to do when the desktop goes into a special - * mode where no normal global key shortcuts or application keyboard - * processing should happen. + * Grabs the keyboard and mouse to the stage window. The stage will + * receive all keyboard and mouse events until shell_global_end_modal() + * is called. This is used to implement "modes" for the shell, such as the + * overview mode or the "looking glass" debug overlay, that block + * application and normal key shortcuts. + * + * Returns value: %TRUE if we succesfully entered the mode. %FALSE if we couldn't + * enter the mode. Failure may occur because an application has the pointer + * or keyboard grabbed, because Mutter is in a mode itself like moving a + * window or alt-Tab window selection, or because shell_global_begin_modal() + * was previouly called. */ gboolean -shell_global_grab_keyboard (ShellGlobal *global) +shell_global_begin_modal (ShellGlobal *global, + guint32 timestamp) { - MetaScreen *screen = mutter_plugin_get_screen (global->plugin); - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); ClutterStage *stage = CLUTTER_STAGE (mutter_plugin_get_stage (global->plugin)); Window stagewin = clutter_x11_get_stage_window (stage); - /* FIXME: we need to coordinate with the rest of Metacity or we - * may grab the keyboard away from other portions of Metacity - * and leave Metacity in a confused state. An X client is allowed - * to overgrab itself, though not allowed to grab they keyboard - * away from another applications. - */ - if (global->keyboard_grabbed) - return FALSE; - - if (XGrabKeyboard (xdisplay, stagewin, - False, /* owner_events - steal events from the rest of metacity */ - GrabModeAsync, GrabModeAsync, - CurrentTime) != Success) - return FALSE; /* probably AlreadyGrabbed, some other app has a keyboard grab */ - - global->keyboard_grabbed = TRUE; - - return TRUE; + return mutter_plugin_begin_modal (global->plugin, stagewin, None, 0, timestamp); } /** - * shell_global_ungrab_keyboard: + * shell_global_end_modal: * @global: a #ShellGlobal * - * Undoes the effect of shell_global_grab_keyboard + * Undoes the effect of shell_global_begin_modal(). */ void -shell_global_ungrab_keyboard (ShellGlobal *global) +shell_global_end_modal (ShellGlobal *global, + guint32 timestamp) { - MetaScreen *screen; - MetaDisplay *display; - Display *xdisplay; - - g_return_if_fail (global->keyboard_grabbed); - - screen = mutter_plugin_get_screen (global->plugin); - display = meta_screen_get_display (screen); - xdisplay = meta_display_get_xdisplay (display); - - XUngrabKeyboard (xdisplay, CurrentTime); - - global->keyboard_grabbed = FALSE; + mutter_plugin_end_modal (global->plugin, timestamp); } /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib. diff --git a/src/shell-global.h b/src/shell-global.h index 52d818d85..a3ad26397 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -64,8 +64,10 @@ GList *shell_global_get_windows (ShellGlobal *global); void _shell_global_set_plugin (ShellGlobal *global, MutterPlugin *plugin); -gboolean shell_global_grab_keyboard (ShellGlobal *global); -void shell_global_ungrab_keyboard (ShellGlobal *global); +gboolean shell_global_begin_modal (ShellGlobal *global, + guint32 timestamp); +void shell_global_end_modal (ShellGlobal *global, + guint32 timestamp); void shell_global_reexec_self (ShellGlobal *global);