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.
|
||||
if (!run_dialog) {
|
||||
run_dialog = new RunDialog.RunDialog();
|
||||
let handler = function() {
|
||||
let end_handler = function() {
|
||||
run_dialog.destroy();
|
||||
run_dialog = null;
|
||||
};
|
||||
run_dialog.connect('run', handler);
|
||||
run_dialog.connect('cancel', handler);
|
||||
run_dialog.show();
|
||||
run_dialog.connect('run', end_handler);
|
||||
run_dialog.connect('cancel', end_handler);
|
||||
if (!run_dialog.show())
|
||||
end_handler();
|
||||
}
|
||||
});
|
||||
|
||||
@ -120,17 +121,33 @@ function start() {
|
||||
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();
|
||||
|
||||
overlay.show();
|
||||
if (!global.grab_keyboard())
|
||||
return false;
|
||||
|
||||
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() {
|
||||
let global = Shell.global_get();
|
||||
|
||||
overlay.hide();
|
||||
panel.overlayHidden();
|
||||
global.set_stage_input_area(0, 0, global.screen_width, Panel.PANEL_HEIGHT);
|
||||
endModal();
|
||||
}
|
||||
|
@ -178,8 +178,6 @@ Overlay.prototype = {
|
||||
|
||||
let global = Shell.global_get();
|
||||
|
||||
global.focus_stage();
|
||||
|
||||
let windows = global.get_windows();
|
||||
let desktopWindow = null;
|
||||
|
||||
|
@ -26,8 +26,9 @@ RunDialog.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.global_get();
|
||||
|
||||
// All actors are inside _group.
|
||||
this._group = new Clutter.Group();
|
||||
// All actors are inside _group. We create it initially
|
||||
// hidden then show it in show()
|
||||
this._group = new Clutter.Group({ visible: false });
|
||||
global.stage.add_actor(this._group);
|
||||
|
||||
this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
||||
@ -74,19 +75,6 @@ RunDialog.prototype = {
|
||||
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) {
|
||||
@ -104,14 +92,41 @@ RunDialog.prototype = {
|
||||
},
|
||||
|
||||
show : function() {
|
||||
if (this._group.visible) // Already shown
|
||||
return false;
|
||||
|
||||
if (!Main.startModal())
|
||||
return false;
|
||||
|
||||
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() {
|
||||
if (!this._group.visible)
|
||||
return;
|
||||
|
||||
this._group.hide();
|
||||
Main.endModal();
|
||||
},
|
||||
|
||||
destroy : function(){
|
||||
this.hide();
|
||||
this._group.destroy();
|
||||
}
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ struct _ShellGlobal {
|
||||
|
||||
MutterPlugin *plugin;
|
||||
ShellWM *wm;
|
||||
gboolean keyboard_grabbed;
|
||||
};
|
||||
|
||||
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
|
||||
* is best used in combination with some sort of visual notification
|
||||
* that the shell has taken over input.
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
shell_global_focus_stage (ShellGlobal *global)
|
||||
gboolean
|
||||
shell_global_grab_keyboard (ShellGlobal *global)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
void shell_global_focus_stage (ShellGlobal *global);
|
||||
gboolean shell_global_grab_keyboard (ShellGlobal *global);
|
||||
void shell_global_ungrab_keyboard (ShellGlobal *global);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user