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
This commit is contained in:
Owen W. Taylor 2009-08-12 00:22:46 -04:00
parent af9ab5dbb6
commit 799f56fe87
7 changed files with 32 additions and 57 deletions

View File

@ -144,8 +144,6 @@ AltTabPopup.prototype = {
show : function(initialSelection) { show : function(initialSelection) {
let global = Shell.Global.get(); let global = Shell.Global.get();
Main.startModal();
global.window_group.add_actor(this._overlay); global.window_group.add_actor(this._overlay);
this._overlay.raise_top(); this._overlay.raise_top();
this._overlay.show(); this._overlay.show();
@ -164,8 +162,6 @@ AltTabPopup.prototype = {
destroy : function() { destroy : function() {
this.actor.destroy(); this.actor.destroy();
this._overlay.destroy(); this._overlay.destroy();
Main.endModal();
}, },
select : function(n) { select : function(n) {

View File

@ -555,7 +555,7 @@ LookingGlass.prototype = {
Tweener.removeTweens(this.actor); Tweener.removeTweens(this.actor);
if (!Main.startModal()) if (!Main.beginModal())
return; return;
let global = Shell.Global.get(); let global = Shell.Global.get();

View File

@ -137,10 +137,11 @@ function _removeUnusedWorkspaces() {
// Used to go into a mode where all keyboard and mouse input goes to // 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 // the stage. Returns true if we successfully grabbed the keyboard and
// went modal, false otherwise // went modal, false otherwise
function startModal() { function beginModal() {
let global = Shell.Global.get(); 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; return false;
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN); global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
@ -151,8 +152,9 @@ function startModal() {
function endModal() { function endModal() {
let global = Shell.Global.get(); 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); global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
inModal = false; inModal = false;
} }

View File

@ -271,7 +271,7 @@ Overview.prototype = {
show : function() { show : function() {
if (this.visible) if (this.visible)
return; return;
if (!Main.startModal()) if (!Main.beginModal())
return; return;
this.visible = true; this.visible = true;

View File

@ -124,7 +124,7 @@ RunDialog.prototype = {
if (this._isOpen) // Already shown if (this._isOpen) // Already shown
return; return;
if (!Main.startModal()) if (!Main.beginModal())
return; return;
this._isOpen = true; this._isOpen = true;

View File

@ -40,7 +40,6 @@ struct _ShellGlobal {
MutterPlugin *plugin; MutterPlugin *plugin;
ShellWM *wm; ShellWM *wm;
gboolean keyboard_grabbed;
const char *imagedir; const char *imagedir;
const char *configdir; const char *configdir;
@ -475,66 +474,42 @@ _shell_global_set_plugin (ShellGlobal *global,
} }
/** /**
* shell_global_grab_keyboard: * shell_global_begin_modal:
* @global: a #ShellGlobal * @global: a #ShellGlobal
* *
* Grab the keyboard to the stage window. The stage will receive * Grabs the keyboard and mouse to the stage window. The stage will
* all keyboard events until shell_global_ungrab_keyboard() is called. * receive all keyboard and mouse events until shell_global_end_modal()
* This is appropriate to do when the desktop goes into a special * is called. This is used to implement "modes" for the shell, such as the
* mode where no normal global key shortcuts or application keyboard * overview mode or the "looking glass" debug overlay, that block
* processing should happen. * 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 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)); ClutterStage *stage = CLUTTER_STAGE (mutter_plugin_get_stage (global->plugin));
Window stagewin = clutter_x11_get_stage_window (stage); Window stagewin = clutter_x11_get_stage_window (stage);
/* FIXME: we need to coordinate with the rest of Metacity or we return mutter_plugin_begin_modal (global->plugin, stagewin, None, 0, timestamp);
* 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;
} }
/** /**
* shell_global_ungrab_keyboard: * shell_global_end_modal:
* @global: a #ShellGlobal * @global: a #ShellGlobal
* *
* Undoes the effect of shell_global_grab_keyboard * Undoes the effect of shell_global_begin_modal().
*/ */
void void
shell_global_ungrab_keyboard (ShellGlobal *global) shell_global_end_modal (ShellGlobal *global,
guint32 timestamp)
{ {
MetaScreen *screen; mutter_plugin_end_modal (global->plugin, timestamp);
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;
} }
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib. /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.

View File

@ -64,8 +64,10 @@ GList *shell_global_get_windows (ShellGlobal *global);
void _shell_global_set_plugin (ShellGlobal *global, void _shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin); MutterPlugin *plugin);
gboolean shell_global_grab_keyboard (ShellGlobal *global); gboolean shell_global_begin_modal (ShellGlobal *global,
void shell_global_ungrab_keyboard (ShellGlobal *global); guint32 timestamp);
void shell_global_end_modal (ShellGlobal *global,
guint32 timestamp);
void shell_global_reexec_self (ShellGlobal *global); void shell_global_reexec_self (ShellGlobal *global);