[mutter] events: Only pass key events to Wayland if focus is on the stage



commit 89f6fdce5dbb4c4aa0b4efa5fc3deeee460f69d0
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Mar 10 17:51:46 2016 +0100

    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

 src/core/events.c |   34 ++++++++++++++++++++++++++--------
 src/core/window.c |    7 +++++++
 2 files changed, 33 insertions(+), 8 deletions(-)
---
diff --git a/src/core/events.c b/src/core/events.c
index a99b99d..a6f4a50 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -47,6 +47,18 @@
                              (e)->type == CLUTTER_TOUCH_END || \
                              (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 *
 get_window_for_event (MetaDisplay        *display,
                       const ClutterEvent *event)
@@ -58,14 +70,8 @@ get_window_for_event (MetaDisplay        *display,
         ClutterActor *source;
 
         /* Always use the key focused window for key events. */
-        switch (event->type)
-          {
-          case CLUTTER_KEY_PRESS:
-          case CLUTTER_KEY_RELEASE:
-            return display->focus_window;
-          default:
-            break;
-          }
+        if (IS_KEY_EVENT (event))
+            return stage_has_key_focus () ? display->focus_window : NULL;
 
         source = clutter_event_get_source (event);
         if (META_IS_SURFACE_ACTOR (source))
@@ -299,6 +305,18 @@ meta_display_handle_event (MetaDisplay        *display,
       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)
     {
       bypass_wayland = TRUE;
diff --git a/src/core/window.c b/src/core/window.c
index 61f0a60..2f72ca2 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4300,6 +4300,13 @@ meta_window_focus (MetaWindow  *window,
 
   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)
     meta_window_unset_demands_attention(window);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]