Add a concept of "going modal" by grabbing the keyboard
shell-global.[ch]: Replace shell_global_focus_stage() with shell_global_grab_keyboard()/shell_global_ungrab_keyboard() main.js: Add startModal()/endModal() functions to go modal and undo that. run_dialog.js overlay.js main.js: Use startModal() for the overlay and for the run dialog. http://bugzilla.gnome.org/show_bug.cgi?id=561880 svn path=/trunk/; revision=83
This commit is contained in:
parent
8a9b138c2e
commit
c12de59864
@ -103,13 +103,14 @@ function start() {
|
|||||||
// Make sure not more than one run dialog is shown.
|
// Make sure not more than one run dialog is shown.
|
||||||
if (!run_dialog) {
|
if (!run_dialog) {
|
||||||
run_dialog = new RunDialog.RunDialog();
|
run_dialog = new RunDialog.RunDialog();
|
||||||
let handler = function() {
|
let end_handler = function() {
|
||||||
run_dialog.destroy();
|
run_dialog.destroy();
|
||||||
run_dialog = null;
|
run_dialog = null;
|
||||||
};
|
};
|
||||||
run_dialog.connect('run', handler);
|
run_dialog.connect('run', end_handler);
|
||||||
run_dialog.connect('cancel', handler);
|
run_dialog.connect('cancel', end_handler);
|
||||||
run_dialog.show();
|
if (!run_dialog.show())
|
||||||
|
end_handler();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -120,17 +121,33 @@ function start() {
|
|||||||
wm = new WindowManager.WindowManager();
|
wm = new WindowManager.WindowManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
function show_overlay() {
|
// 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() {
|
||||||
let global = Shell.global_get();
|
let global = Shell.global_get();
|
||||||
|
|
||||||
overlay.show();
|
if (!global.grab_keyboard())
|
||||||
|
return false;
|
||||||
|
|
||||||
global.set_stage_input_area(0, 0, global.screen_width, global.screen_height);
|
global.set_stage_input_area(0, 0, global.screen_width, global.screen_height);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function endModal() {
|
||||||
|
let global = Shell.global_get();
|
||||||
|
|
||||||
|
global.ungrab_keyboard();
|
||||||
|
global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_overlay() {
|
||||||
|
if (startModal())
|
||||||
|
overlay.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide_overlay() {
|
function hide_overlay() {
|
||||||
let global = Shell.global_get();
|
|
||||||
|
|
||||||
overlay.hide();
|
overlay.hide();
|
||||||
panel.overlayHidden();
|
endModal();
|
||||||
global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT);
|
|
||||||
}
|
}
|
||||||
|
@ -178,8 +178,6 @@ Overlay.prototype = {
|
|||||||
|
|
||||||
let global = Shell.global_get();
|
let global = Shell.global_get();
|
||||||
|
|
||||||
global.focus_stage();
|
|
||||||
|
|
||||||
let windows = global.get_windows();
|
let windows = global.get_windows();
|
||||||
let desktopWindow = null;
|
let desktopWindow = null;
|
||||||
|
|
||||||
|
@ -26,8 +26,9 @@ RunDialog.prototype = {
|
|||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.global_get();
|
let global = Shell.global_get();
|
||||||
|
|
||||||
// All actors are inside _group.
|
// All actors are inside _group. We create it initially
|
||||||
this._group = new Clutter.Group();
|
// hidden then show it in show()
|
||||||
|
this._group = new Clutter.Group({ visible: false });
|
||||||
global.stage.add_actor(this._group);
|
global.stage.add_actor(this._group);
|
||||||
|
|
||||||
this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
||||||
@ -74,19 +75,6 @@ RunDialog.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Detect escape key and make it cancel the operation.
|
|
||||||
// Use me.on_cancel() if it exists. Something like this:
|
|
||||||
// this._entry.connect('key-press-event', function(o, e) {
|
|
||||||
// if (the pressed key is the escape key) {
|
|
||||||
// me.hide();
|
|
||||||
// me.emit('cancel');
|
|
||||||
// return false;
|
|
||||||
// } else
|
|
||||||
// return true;
|
|
||||||
// });
|
|
||||||
|
|
||||||
global.focus_stage();
|
|
||||||
global.stage.set_key_focus(this._entry);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_run : function(command) {
|
_run : function(command) {
|
||||||
@ -104,14 +92,41 @@ RunDialog.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
show : function() {
|
show : function() {
|
||||||
|
if (this._group.visible) // Already shown
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Main.startModal())
|
||||||
|
return false;
|
||||||
|
|
||||||
this._group.show_all();
|
this._group.show_all();
|
||||||
|
|
||||||
|
// TODO: Detect escape key and make it cancel the operation.
|
||||||
|
// Use me.on_cancel() if it exists. Something like this:
|
||||||
|
// this._entry.connect('key-press-event', function(o, e) {
|
||||||
|
// if (the pressed key is the escape key) {
|
||||||
|
// me.hide();
|
||||||
|
// me.emit('cancel');
|
||||||
|
// return false;
|
||||||
|
// } else
|
||||||
|
// return true;
|
||||||
|
// });
|
||||||
|
|
||||||
|
let global = Shell.global_get();
|
||||||
|
global.stage.set_key_focus(this._entry);
|
||||||
|
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
hide : function() {
|
hide : function() {
|
||||||
|
if (!this._group.visible)
|
||||||
|
return;
|
||||||
|
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
|
Main.endModal();
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy : function(){
|
destroy : function(){
|
||||||
|
this.hide();
|
||||||
this._group.destroy();
|
this._group.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ struct _ShellGlobal {
|
|||||||
|
|
||||||
MutterPlugin *plugin;
|
MutterPlugin *plugin;
|
||||||
ShellWM *wm;
|
ShellWM *wm;
|
||||||
|
gboolean keyboard_grabbed;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -273,19 +274,64 @@ _shell_global_set_plugin (ShellGlobal *global,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_global_focus_stage:
|
* shell_global_grab_keyboard:
|
||||||
|
* @global: a #ShellGlobal
|
||||||
*
|
*
|
||||||
* Set the keyboard focus to the Clutter stage window. This function
|
* Grab the keyboard to the stage window. The stage will receive
|
||||||
* is best used in combination with some sort of visual notification
|
* all keyboard events until shell_global_ungrab_keyboard() is called.
|
||||||
* that the shell has taken over input.
|
* 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.
|
||||||
*/
|
*/
|
||||||
void
|
gboolean
|
||||||
shell_global_focus_stage (ShellGlobal *global)
|
shell_global_grab_keyboard (ShellGlobal *global)
|
||||||
{
|
{
|
||||||
MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
|
MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
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);
|
||||||
XSetInputFocus (xdisplay, stagewin, RevertToParent, CurrentTime);
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_global_ungrab_keyboard:
|
||||||
|
* @global: a #ShellGlobal
|
||||||
|
*
|
||||||
|
* Undoes the effect of shell_global_grab_keyboard
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_global_ungrab_keyboard (ShellGlobal *global)
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,8 @@ void _shell_global_set_plugin (ShellGlobal *global,
|
|||||||
|
|
||||||
MetaScreen * shell_global_get_screen (ShellGlobal *global);
|
MetaScreen * shell_global_get_screen (ShellGlobal *global);
|
||||||
|
|
||||||
void shell_global_focus_stage (ShellGlobal *global);
|
gboolean shell_global_grab_keyboard (ShellGlobal *global);
|
||||||
|
void shell_global_ungrab_keyboard (ShellGlobal *global);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user