shell-global: try to resync the pointer state after grabs
If the pointer moves on or off the stage while another process has a grab, we will lose track of it. One example of this is that if you use a popup menu from a message tray trayicon, the tray will stay up after the menu goes away, because the shell never saw the pointer leave it. Add a new method shell_global_sync_pointer() that causes clutter to recheck what actor is under the pointer and generate leave/enter events if appropriate. Of course, we can't actually tell for sure when another process has a grab, so we need a heuristic of when to call this. Currently we call it from Chrome._windowsRestacked(), which is not really the right thing at all, but does fix the menu-from-trayicon case... https://bugzilla.gnome.org/show_bug.cgi?id=630842
This commit is contained in:
parent
7f17fcfafc
commit
2782011ce8
@ -335,6 +335,11 @@ Chrome.prototype = {
|
|||||||
this._updateVisibility();
|
this._updateVisibility();
|
||||||
this._queueUpdateRegions();
|
this._queueUpdateRegions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Figure out where the pointer is in case we lost track of
|
||||||
|
// it during a grab. (In particular, if a trayicon popup menu
|
||||||
|
// is dismissed, see if we need to close the message tray.)
|
||||||
|
global.sync_pointer();
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateRegions: function() {
|
_updateRegions: function() {
|
||||||
|
@ -1490,6 +1490,48 @@ shell_global_get_pointer (ShellGlobal *global,
|
|||||||
*mods = raw_mods & GDK_MODIFIER_MASK;
|
*mods = raw_mods & GDK_MODIFIER_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_global_sync_pointer:
|
||||||
|
* @global: the #ShellGlobal
|
||||||
|
*
|
||||||
|
* Ensures that clutter is aware of the current pointer position,
|
||||||
|
* causing enter and leave events to be emitted if the pointer moved
|
||||||
|
* behind our back (ie, during a pointer grab).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_global_sync_pointer (ShellGlobal *global)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
GdkModifierType mods;
|
||||||
|
ClutterMotionEvent event;
|
||||||
|
|
||||||
|
gdk_display_get_pointer (gdk_display_get_default (), NULL, &x, &y, &mods);
|
||||||
|
|
||||||
|
event.type = CLUTTER_MOTION;
|
||||||
|
event.time = shell_global_get_current_time (global);
|
||||||
|
event.flags = 0;
|
||||||
|
/* This is wrong: we should be setting event.stage to NULL if the
|
||||||
|
* pointer is not inside the bounds of the stage given the current
|
||||||
|
* stage_input_mode. For our current purposes however, this works.
|
||||||
|
*/
|
||||||
|
event.stage = CLUTTER_STAGE (meta_plugin_get_stage (global->plugin));
|
||||||
|
event.x = x;
|
||||||
|
event.y = y;
|
||||||
|
event.modifier_state = mods;
|
||||||
|
event.axes = NULL;
|
||||||
|
event.device = clutter_device_manager_get_core_device (clutter_device_manager_get_default (),
|
||||||
|
CLUTTER_POINTER_DEVICE);
|
||||||
|
|
||||||
|
/* Leaving event.source NULL will force clutter to look it up, which
|
||||||
|
* will generate enter/leave events as a side effect, if they are
|
||||||
|
* needed. We need a better way to do this though... see
|
||||||
|
* http://bugzilla.clutter-project.org/show_bug.cgi?id=2615.
|
||||||
|
*/
|
||||||
|
event.source = NULL;
|
||||||
|
|
||||||
|
clutter_event_put ((ClutterEvent *)&event);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_get_event_state:
|
* shell_get_event_state:
|
||||||
* @event: a #ClutterEvent
|
* @event: a #ClutterEvent
|
||||||
|
@ -107,6 +107,7 @@ void shell_global_get_pointer (ShellGlobal *global,
|
|||||||
int *x,
|
int *x,
|
||||||
int *y,
|
int *y,
|
||||||
ClutterModifierType *mods);
|
ClutterModifierType *mods);
|
||||||
|
void shell_global_sync_pointer (ShellGlobal *global);
|
||||||
|
|
||||||
GSettings *shell_global_get_settings (ShellGlobal *global);
|
GSettings *shell_global_get_settings (ShellGlobal *global);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user