events: Only pass key events to Wayland if focus is on the stage
Even without a compositor grab, key events may still be expected to be processed by the compositor and not applications, for instance when using ctrl-alt-tab to keynav in the top bar. On X11, focus is moved to the stage window in that case, so that events are processed before they are dispatched by the window manager. On wayland, we need to handle this case ourselves, so make sure to not pass key events to wayland in that case, and move the key focus back to the stage when appropriate. https://bugzilla.gnome.org/show_bug.cgi?id=758167
This commit is contained in:
parent
7d9af9585d
commit
89f6fdce5d
2 changed files with 33 additions and 8 deletions
|
@ -47,6 +47,18 @@
|
||||||
(e)->type == CLUTTER_TOUCH_END || \
|
(e)->type == CLUTTER_TOUCH_END || \
|
||||||
(e)->type == CLUTTER_TOUCH_CANCEL)
|
(e)->type == CLUTTER_TOUCH_CANCEL)
|
||||||
|
|
||||||
|
#define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \
|
||||||
|
(e)->type == CLUTTER_KEY_RELEASE)
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
stage_has_key_focus (void)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||||
|
|
||||||
|
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == stage;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaWindow *
|
static MetaWindow *
|
||||||
get_window_for_event (MetaDisplay *display,
|
get_window_for_event (MetaDisplay *display,
|
||||||
const ClutterEvent *event)
|
const ClutterEvent *event)
|
||||||
|
@ -58,14 +70,8 @@ get_window_for_event (MetaDisplay *display,
|
||||||
ClutterActor *source;
|
ClutterActor *source;
|
||||||
|
|
||||||
/* Always use the key focused window for key events. */
|
/* Always use the key focused window for key events. */
|
||||||
switch (event->type)
|
if (IS_KEY_EVENT (event))
|
||||||
{
|
return stage_has_key_focus () ? display->focus_window : NULL;
|
||||||
case CLUTTER_KEY_PRESS:
|
|
||||||
case CLUTTER_KEY_RELEASE:
|
|
||||||
return display->focus_window;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
source = clutter_event_get_source (event);
|
source = clutter_event_get_source (event);
|
||||||
if (META_IS_SURFACE_ACTOR (source))
|
if (META_IS_SURFACE_ACTOR (source))
|
||||||
|
@ -299,6 +305,18 @@ meta_display_handle_event (MetaDisplay *display,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do not pass keyboard events to Wayland if key focus is not on the
|
||||||
|
* stage in normal mode (e.g. during keynav in the panel)
|
||||||
|
*/
|
||||||
|
if (display->event_route == META_EVENT_ROUTE_NORMAL)
|
||||||
|
{
|
||||||
|
if (IS_KEY_EVENT (event) && !stage_has_key_focus ())
|
||||||
|
{
|
||||||
|
bypass_wayland = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (display->current_pad_osd)
|
if (display->current_pad_osd)
|
||||||
{
|
{
|
||||||
bypass_wayland = TRUE;
|
bypass_wayland = TRUE;
|
||||||
|
|
|
@ -4300,6 +4300,13 @@ meta_window_focus (MetaWindow *window,
|
||||||
|
|
||||||
META_WINDOW_GET_CLASS (window)->focus (window, timestamp);
|
META_WINDOW_GET_CLASS (window)->focus (window, timestamp);
|
||||||
|
|
||||||
|
if (window->display->event_route == META_EVENT_ROUTE_NORMAL)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||||
|
clutter_stage_set_key_focus (stage, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (window->wm_state_demands_attention)
|
if (window->wm_state_demands_attention)
|
||||||
meta_window_unset_demands_attention(window);
|
meta_window_unset_demands_attention(window);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue