[mutter/wayland] compositor: fix focusing the stage window



commit 876f81db12d122ce2be69395c809d9835eebea39
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Tue Aug 13 14:54:55 2013 +0200

    compositor: fix focusing the stage window
    
    We can't use the X11 stage window, if clutter is not using the X11
    backend (and even if it was, it would be bogus when the xwayland
    server is not the one clutter is talking to). Instead, we introduce
    the concept of "focus type", which we use to differentiate the
    various meanings of None in the focus_xwindow field.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706364

 src/compositor/compositor.c |   34 +++++++++++++++----------
 src/core/display-private.h  |   18 ++++++++++---
 src/core/display.c          |   58 +++++++++++++++++++++++++++++++-----------
 3 files changed, 77 insertions(+), 33 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 565cb11..771fa2d 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -391,33 +391,39 @@ meta_focus_stage_window (MetaScreen *screen,
   if (!stage)
     return;
 
-  window = clutter_x11_get_stage_window (stage);
+  if (!meta_is_wayland_compositor ())
+    {
+      window = clutter_x11_get_stage_window (stage);
 
-  if (window == None)
-    return;
+      if (window == None)
+        return;
 
-  meta_display_set_input_focus_xwindow (screen->display,
-                                        screen,
-                                        window,
-                                        timestamp);
+      meta_display_set_input_focus_xwindow (screen->display,
+                                            screen,
+                                            META_FOCUS_STAGE,
+                                            window,
+                                            timestamp);
+    }
+  else
+    {
+      meta_display_set_input_focus_xwindow (screen->display,
+                                            screen,
+                                            META_FOCUS_STAGE,
+                                            None,
+                                            timestamp);
+    }
 }
 
 gboolean
 meta_stage_is_focused (MetaScreen *screen)
 {
   ClutterStage *stage;
-  Window window;
 
   stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
   if (!stage)
     return FALSE;
 
-  window = clutter_x11_get_stage_window (stage);
-
-  if (window == None)
-    return FALSE;
-
-  return (screen->display->focus_xwindow == window);
+  return (screen->display->focus_type == META_FOCUS_STAGE);
 }
 
 gboolean
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 2ca9c67..e9d590d 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -86,6 +86,14 @@ typedef enum {
   META_TILE_MAXIMIZED
 } MetaTileMode;
 
+typedef enum {
+  META_FOCUS_NONE = 0,
+  META_FOCUS_X_CLIENT = 1,
+  META_FOCUS_WAYLAND_CLIENT = 2,
+  META_FOCUS_NO_FOCUS_WINDOW = 3,
+  META_FOCUS_STAGE = 4
+} MetaFocusType;
+
 struct _MetaDisplay
 {
   GObject parent_instance;
@@ -117,6 +125,7 @@ struct _MetaDisplay
    * like the no_focus_window or the stage X window. */
   Window focus_xwindow;
   gulong focus_serial;
+  MetaFocusType focus_type;
 
   /* last timestamp passed to XSetInputFocus */
   guint32 last_focus_time;
@@ -475,9 +484,10 @@ gboolean meta_display_process_barrier_event (MetaDisplay    *display,
                                              XIBarrierEvent *event);
 #endif /* HAVE_XI23 */
 
-void meta_display_set_input_focus_xwindow (MetaDisplay *display,
-                                           MetaScreen  *screen,
-                                           Window       window,
-                                           guint32      timestamp);
+void meta_display_set_input_focus_xwindow (MetaDisplay   *display,
+                                           MetaScreen    *screen,
+                                           MetaFocusType  type,
+                                           Window         window,
+                                           guint32        timestamp);
 
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 316748d..66061c6 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1897,10 +1897,11 @@ get_input_event (MetaDisplay *display,
 }
 
 static void
-update_focus_window (MetaDisplay *display,
-                     MetaWindow  *window,
-                     Window       xwindow,
-                     gulong       serial)
+update_focus_window (MetaDisplay   *display,
+                     MetaFocusType  type,
+                     MetaWindow    *window,
+                     Window         xwindow,
+                     gulong         serial)
 {
 #ifdef HAVE_WAYLAND
   MetaWaylandCompositor *compositor;
@@ -1909,6 +1910,7 @@ update_focus_window (MetaDisplay *display,
   display->focus_serial = serial;
 
   if (display->focus_xwindow == xwindow &&
+      display->focus_type == type &&
       display->focus_window == window)
     return;
 
@@ -1931,6 +1933,7 @@ update_focus_window (MetaDisplay *display,
       meta_window_set_focused_internal (previous, FALSE);
     }
 
+  display->focus_type = type;
   display->focus_window = window;
   display->focus_xwindow = xwindow;
 
@@ -1948,7 +1951,8 @@ update_focus_window (MetaDisplay *display,
     {
       compositor = meta_wayland_compositor_get_default ();
 
-      if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
+      if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW ||
+          display->focus_type == META_FOCUS_STAGE)
         meta_wayland_compositor_set_input_focus (compositor, NULL);
       else if (window && window->surface)
         meta_wayland_compositor_set_input_focus (compositor, window);
@@ -1991,11 +1995,12 @@ timestamp_too_old (MetaDisplay *display,
 }
 
 static void
-request_xserver_input_focus_change (MetaDisplay *display,
-                                    MetaScreen  *screen,
-                                    MetaWindow  *meta_window,
-                                    Window       xwindow,
-                                    guint32      timestamp)
+request_xserver_input_focus_change (MetaDisplay   *display,
+                                    MetaScreen    *screen,
+                                    MetaFocusType  type,
+                                    MetaWindow    *meta_window,
+                                    Window         xwindow,
+                                    guint32        timestamp)
 {
   gulong serial;
 
@@ -2028,6 +2033,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
   meta_display_ungrab (display);
 
   update_focus_window (display,
+                       type,
                        meta_window,
                        xwindow,
                        serial);
@@ -2048,9 +2054,12 @@ handle_window_focus_event (MetaDisplay  *display,
                            unsigned long serial)
 {
   MetaWindow *focus_window;
+  MetaFocusType type;
 #ifdef WITH_VERBOSE_MODE
   const char *window_type;
 
+  type = META_FOCUS_NONE;
+
   /* Note the event can be on either the window or the frame,
    * we focus the frame for shaded windows
    */
@@ -2062,14 +2071,26 @@ handle_window_focus_event (MetaDisplay  *display,
         window_type = "frame window";
       else
         window_type = "unknown client window";
+
+      if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+        type = META_FOCUS_WAYLAND_CLIENT;
+      else
+        type = META_FOCUS_X_CLIENT;
     }
   else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
-    window_type = "no_focus_window";
+    {
+      window_type = "no_focus_window";
+      type = META_FOCUS_NO_FOCUS_WINDOW;
+    }
   else if (meta_display_screen_for_root (display, event->event))
     window_type = "root window";
   else
     window_type = "unknown window";
 
+  /* Don't change type if we don't know the new window */
+  if (type == META_FOCUS_NONE)
+    type = display->focus_type;
+
   meta_topic (META_DEBUG_FOCUS,
               "Focus %s event received on %s 0x%lx (%s) "
               "mode %s detail %s serial %lu\n",
@@ -2147,6 +2168,7 @@ handle_window_focus_event (MetaDisplay  *display,
   if (display->server_focus_serial > display->focus_serial)
     {
       update_focus_window (display,
+                           type,
                            focus_window,
                            focus_window ? focus_window->xwindow : None,
                            display->server_focus_serial);
@@ -2200,6 +2222,7 @@ meta_display_handle_event (MetaDisplay *display,
       meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
                   display->focus_window->desc);
       update_focus_window (display,
+                           META_FOCUS_NONE,
                            meta_display_lookup_x_window (display, display->server_focus_window),
                            display->server_focus_window,
                            display->server_focus_serial);
@@ -5879,6 +5902,8 @@ meta_display_set_input_focus_window (MetaDisplay *display,
 {
   request_xserver_input_focus_change (display,
                                       window->screen,
+                                      window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ?
+                                      META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT,
                                       window,
                                       focus_frame ? window->frame->xwindow : window->xwindow,
                                       timestamp);
@@ -5920,13 +5945,15 @@ meta_display_request_take_focus (MetaDisplay *display,
 }
 
 void
-meta_display_set_input_focus_xwindow (MetaDisplay *display,
-                                      MetaScreen  *screen,
-                                      Window       window,
-                                      guint32      timestamp)
+meta_display_set_input_focus_xwindow (MetaDisplay   *display,
+                                      MetaScreen    *screen,
+                                      MetaFocusType  type,
+                                      Window         window,
+                                      guint32        timestamp)
 {
   request_xserver_input_focus_change (display,
                                       screen,
+                                      type,
                                       NULL,
                                       window,
                                       timestamp);
@@ -5939,6 +5966,7 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
 {
   request_xserver_input_focus_change (display,
                                       screen,
+                                      META_FOCUS_NO_FOCUS_WINDOW,
                                       NULL,
                                       screen->no_focus_window,
                                       timestamp);


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