[mutter/wip/wayland] Start to integrate wayland client support into core



commit b8a06aeae159650288b60b03b2920451a982abbd
Author: Robert Bragg <robert linux intel com>
Date:   Mon Jan 23 15:34:43 2012 +0000

    Start to integrate wayland client support into core
    
    Instead of wayland clients being handled in a totally side-band way,
    this patch enables us to create a MetaWindow for client wayland surfaces
    as well as corresponding MetaWindowActors and MetaShapeTexture actors.

 src/compositor/meta-shaped-texture.c |   13 ++-
 src/compositor/meta-shaped-texture.h |    6 +-
 src/compositor/meta-window-actor.c   |   26 +++++--
 src/core/window-private.h            |   24 ++++++
 src/core/window.c                    |  149 ++++++++++++++++++++++++++--------
 src/wayland/meta-wayland-private.h   |    9 ++-
 src/wayland/meta-wayland.c           |  100 ++++++++++++++++-------
 7 files changed, 249 insertions(+), 78 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index f17312c..ab12eba 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -704,16 +704,14 @@ meta_shaped_texture_queue_damage_redraw (ClutterWaylandSurface *surface,
 #endif /* HAVE_WAYLAND */
 
 ClutterActor *
-meta_shaped_texture_new (Window xwindow)
+meta_shaped_texture_new_with_surface (MetaWaylandSurface *surface)
 {
-  MetaWaylandSurface *surface = meta_wayland_lookup_surface_for_xid (xwindow);
-
   if (surface)
     {
       ClutterWaylandSurface *wayland_surface;
       ClutterActor *actor =
         g_object_new (META_TYPE_SHAPED_TEXTURE,
-                      "surface", surface->wayland_surface, NULL);
+                      "surface", &surface->wayland_surface, NULL);
 
       /* XXX: This is a bit messy but meta-wayland.c wants a reference
        * to the corresponding surface actor so that it can pass on
@@ -736,6 +734,13 @@ meta_shaped_texture_new (Window xwindow)
     return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
 }
 
+ClutterActor *
+meta_shaped_texture_new_with_xwindow (Window xwindow)
+{
+  MetaWaylandSurface *surface = meta_wayland_lookup_surface_for_xid (xwindow);
+  return meta_shaped_texture_new_with_surface (surface);
+}
+
 void
 meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
 					gboolean           create_mipmaps)
diff --git a/src/compositor/meta-shaped-texture.h b/src/compositor/meta-shaped-texture.h
index 3152154..ed8a8c0 100644
--- a/src/compositor/meta-shaped-texture.h
+++ b/src/compositor/meta-shaped-texture.h
@@ -33,6 +33,7 @@
 
 #ifdef HAVE_WAYLAND
 #include <wayland-server.h>
+#include "meta-wayland-private.h"
 #endif
 
 G_BEGIN_DECLS
@@ -62,7 +63,10 @@ struct _MetaShapedTexture
 
 GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
 
-ClutterActor *meta_shaped_texture_new (Window xwindow);
+ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
+#ifdef HAVE_WAYLAND
+ClutterActor *meta_shaped_texture_new_with_surface (MetaWaylandSurface *surface);
+#endif
 
 void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
 					     gboolean           create_mipmaps);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 1c615f7..7c2b46a 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -376,7 +376,10 @@ meta_window_actor_constructed (GObject *object)
 
   if (!priv->actor)
     {
-      priv->actor = meta_shaped_texture_new (xwindow);
+      if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+        priv->actor = meta_shaped_texture_new_with_xwindow (xwindow);
+      else
+        priv->actor = meta_shaped_texture_new_with_surface (window->surface);
 
       clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->actor);
 
@@ -1576,13 +1579,22 @@ meta_window_actor_new (MetaWindow *window)
   MetaFrame		 *frame;
   Window		  top_window;
 
-  frame = meta_window_get_frame (window);
-  if (frame)
-    top_window = meta_frame_get_xwindow (frame);
-  else
-    top_window = meta_window_get_xwindow (window);
+  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+    {
+      frame = meta_window_get_frame (window);
+      if (frame)
+        top_window = meta_frame_get_xwindow (frame);
+      else
+        top_window = meta_window_get_xwindow (window);
 
-  meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
+      meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
+    }
+  else
+    {
+      meta_verbose ("add window: Meta %p, wayland surface %p\n",
+                    window, window->surface);
+      top_window = None;
+    }
 
   self = g_object_new (META_TYPE_WINDOW_ACTOR,
                        "meta-window",         window,
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 6d23086..4c1d62a 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -44,6 +44,17 @@
 #include <X11/Xutil.h>
 #include <cairo.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#ifdef HAVE_WAYLAND
+#include "meta-wayland-private.h"
+#endif
+
+/* XXX: We should find a nicer approach to deal with the
+ * circular dependency we have with the current headers
+ * (meta-wayland-private.h which typedefs MetaWaylandSurface
+ *  also includes window-private.h) */
+#ifndef HAVE_META_WAYLAND_SURFACE_TYPE
+typedef struct _MetaWaylandSurface MetaWaylandSurface;
+#endif
 
 typedef struct _MetaWindowQueue MetaWindowQueue;
 
@@ -62,6 +73,11 @@ typedef enum {
 
 #define NUMBER_OF_QUEUES 3
 
+typedef enum {
+  META_WINDOW_CLIENT_TYPE_WAYLAND,
+  META_WINDOW_CLIENT_TYPE_X11
+} MetaWindowClientType;
+
 struct _MetaWindow
 {
   GObject parent_instance;
@@ -70,6 +86,10 @@ struct _MetaWindow
   MetaScreen *screen;
   const MetaMonitorInfo *monitor;
   MetaWorkspace *workspace;
+#ifdef HAVE_WAYLAND
+  MetaWindowClientType client_type;
+  MetaWaylandSurface *surface;
+#endif
   Window xwindow;
   /* may be NULL! not all windows get decorated */
   MetaFrame *frame;
@@ -454,6 +474,10 @@ MetaWindow* meta_window_new_with_attrs     (MetaDisplay       *display,
                                             gboolean           must_be_viewable,
                                             MetaCompEffect     effect,
                                             XWindowAttributes *attrs);
+MetaWindow *meta_window_new_for_wayland    (MetaDisplay        *display,
+                                            int                 width,
+                                            int                 height,
+                                            MetaWaylandSurface *surface);
 void        meta_window_unmanage           (MetaWindow  *window,
                                             guint32      timestamp);
 void        meta_window_calc_showing       (MetaWindow  *window);
diff --git a/src/core/window.c b/src/core/window.c
index 74594fa..4e94e9b 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -749,12 +749,14 @@ meta_window_should_attach_to_parent (MetaWindow *window)
     }
 }
 
-MetaWindow*
-meta_window_new_with_attrs (MetaDisplay       *display,
-                            Window             xwindow,
-                            gboolean           must_be_viewable,
-                            MetaCompEffect     effect,
-                            XWindowAttributes *attrs)
+static MetaWindow*
+meta_window_new_full (MetaDisplay         *display,
+                      MetaWindowClientType client_type,
+                      MetaWaylandSurface  *surface,
+                      Window               xwindow,
+                      gboolean             must_be_viewable,
+                      MetaCompEffect       effect,
+                      XWindowAttributes   *attrs)
 {
   MetaWindow *window;
   GSList *tmp;
@@ -770,7 +772,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
 
-  if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
+  if (client_type == META_WINDOW_CLIENT_TYPE_X11 &&
+      meta_display_xwindow_is_a_no_focus_window (display, xwindow))
     {
       meta_verbose ("Not managing no_focus_window 0x%lx\n",
                     xwindow);
@@ -861,34 +864,40 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   meta_error_trap_push_with_return (display);
 
-  /*
-   * XAddToSaveSet can only be called on windows created by a different client.
-   * with Mutter we want to be able to create manageable windows from within
-   * the process (such as a dummy desktop window), so we do not want this
-   * call failing to prevent the window from being managed -- wrap it in its
-   * own error trap (we use the _with_return() version here to ensure that
-   * XSync() is done on the pop, otherwise the error will not get caught).
-   */
-  meta_error_trap_push_with_return (display);
-  XAddToSaveSet (display->xdisplay, xwindow);
-  meta_error_trap_pop_with_return (display);
-
-  event_mask =
-    PropertyChangeMask | EnterWindowMask | LeaveWindowMask |
-    FocusChangeMask | ColormapChangeMask;
-  if (attrs->override_redirect)
-    event_mask |= StructureNotifyMask;
-
-  /* If the window is from this client (a menu, say) we need to augment
-   * the event mask, not replace it. For windows from other clients,
-   * attrs->your_event_mask will be empty at this point.
-   */
-  XSelectInput (display->xdisplay, xwindow, attrs->your_event_mask | event_mask);
+  if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+    {
+      /*
+       * XAddToSaveSet can only be called on windows created by a different
+       * client.  with Mutter we want to be able to create manageable windows
+       * from within the process (such as a dummy desktop window), so we do not
+       * want this call failing to prevent the window from being managed --
+       * wrap it in its own error trap (we use the _with_return() version here
+       * to ensure that XSync() is done on the pop, otherwise the error will
+       * not get caught).
+       */
+      meta_error_trap_push_with_return (display);
+      XAddToSaveSet (display->xdisplay, xwindow);
+      meta_error_trap_pop_with_return (display);
+
+      event_mask =
+        PropertyChangeMask | EnterWindowMask | LeaveWindowMask |
+        FocusChangeMask | ColormapChangeMask;
+      if (attrs->override_redirect)
+        event_mask |= StructureNotifyMask;
+
+      /* If the window is from this client (a menu, say) we need to augment the
+       * event mask, not replace it. For windows from other clients,
+       * attrs->your_event_mask will be empty at this point.
+       */
+      XSelectInput (display->xdisplay, xwindow,
+                    attrs->your_event_mask | event_mask);
+    }
 
   has_shape = FALSE;
   has_input_shape = FALSE;
 #ifdef HAVE_SHAPE
-  if (META_DISPLAY_HAS_SHAPE (display))
+  if (META_DISPLAY_HAS_SHAPE (display) &&
+      client_type == META_WINDOW_CLIENT_TYPE_X11)
     {
       int x_bounding, y_bounding, x_clip, y_clip;
       unsigned w_bounding, h_bounding, w_clip, h_clip;
@@ -967,6 +976,10 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   window->dialog_pid = -1;
 
+#ifdef HAVE_WAYLAND
+  window->client_type = client_type;
+  window->surface = surface;
+#endif
   window->xwindow = xwindow;
 
   /* this is in window->screen->display, but that's too annoying to
@@ -1093,7 +1106,11 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   window->mwm_has_move_func = TRUE;
   window->mwm_has_resize_func = TRUE;
 
-  window->decorated = TRUE;
+  if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+    window->decorated = TRUE;
+  else
+    window->decorated = FALSE;
+
   window->has_close_func = TRUE;
   window->has_minimize_func = TRUE;
   window->has_maximize_func = TRUE;
@@ -1159,7 +1176,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
       window->has_resize_func = FALSE;
     }
 
-  meta_display_register_x_window (display, &window->xwindow, window);
+  if (client_type == META_WINDOW_CLIENT_TYPE_X11)
+    meta_display_register_x_window (display, &window->xwindow, window);
 
   /* Assign this #MetaWindow a sequence number which can be used
    * for sorting.
@@ -1174,7 +1192,8 @@ meta_window_new_with_attrs (MetaDisplay       *display,
 
   meta_window_load_initial_properties (window);
 
-  if (!window->override_redirect)
+  if (!window->override_redirect &&
+      client_type == META_WINDOW_CLIENT_TYPE_X11)
     {
       update_sm_hints (window); /* must come after transient_for */
 
@@ -1461,6 +1480,68 @@ meta_window_new_with_attrs (MetaDisplay       *display,
   return window;
 }
 
+#ifdef HAVE_WAYLAND
+MetaWindow *
+meta_window_new_for_wayland (MetaDisplay        *display,
+                             int                 width,
+                             int                 height,
+                             MetaWaylandSurface *surface)
+{
+  XWindowAttributes attrs;
+  MetaScreen *scr = display->screens->data;
+  MetaWindow *window;
+
+  attrs.x = 0;
+  attrs.y = 0;
+  attrs.width = width;
+  attrs.height = height;
+  attrs.border_width = 0;
+  attrs.depth = 24;
+  attrs.visual = NULL;
+  attrs.root = scr->xroot;
+  attrs.class = InputOutput;
+  attrs.bit_gravity = NorthWestGravity;
+  attrs.win_gravity = NorthWestGravity;
+  attrs.backing_store = 0;
+  attrs.backing_planes = ~0;
+  attrs.backing_pixel = 0;
+  attrs.save_under = 0;
+  attrs.colormap = 0;
+  attrs.map_installed = 1;
+  attrs.map_state = IsViewable;
+  attrs.all_event_masks = ~0;
+  attrs.your_event_mask = 0;
+  attrs.do_not_propagate_mask = 0;
+  attrs.override_redirect = 0;
+  attrs.screen = scr->xscreen;
+
+  window = meta_window_new_full (display,
+                                 META_WINDOW_CLIENT_TYPE_WAYLAND,
+                                 surface,
+                                 None,
+                                 TRUE,
+                                 META_COMP_EFFECT_NONE,
+                                 &attrs);
+  return window;
+}
+#endif
+
+MetaWindow*
+meta_window_new_with_attrs (MetaDisplay       *display,
+                            Window             xwindow,
+                            gboolean           must_be_viewable,
+                            MetaCompEffect     effect,
+                            XWindowAttributes *attrs)
+{
+  return meta_window_new_full (display,
+                               META_WINDOW_CLIENT_TYPE_X11,
+                               NULL,
+                               xwindow,
+                               must_be_viewable,
+                               effect,
+                               attrs);
+}
+
 /* This function should only be called from the end of meta_window_new_with_attrs () */
 static void
 meta_window_apply_session_info (MetaWindow *window,
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 840e1ab..24576b8 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -38,7 +38,7 @@ typedef struct
   struct wl_listener buffer_destroy_listener;
 } MetaWaylandBuffer;
 
-typedef struct
+struct _MetaWaylandSurface
 {
   struct wl_surface wayland_surface;
   MetaWaylandCompositor *compositor;
@@ -46,10 +46,15 @@ typedef struct
   int x;
   int y;
   MetaWaylandBuffer *buffer;
+  MetaWindow *window;
   ClutterActor *actor;
   gboolean has_shell_surface;
   struct wl_listener surface_destroy_listener;
-} MetaWaylandSurface;
+};
+
+#ifndef HAVE_META_WAYLAND_SURFACE_TYPE
+typedef struct _MetaWaylandSurface MetaWaylandSurface;
+#endif
 
 typedef struct
 {
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 1cbaaa9..00cb5f3 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -239,7 +239,7 @@ meta_wayland_surface_attach_buffer (struct wl_client *wayland_client,
   struct wl_buffer *wayland_buffer = wayland_buffer_resource->data;
   MetaWaylandBuffer *buffer = wayland_buffer->user_data;
   MetaWaylandSurface *surface = wayland_surface_resource->data;
-  MetaWaylandCompositor *compositor = surface->compositor;
+  //MetaWaylandCompositor *compositor = surface->compositor;
   ClutterWaylandSurface *surface_actor;
 
   /* XXX: in the case where we are reattaching the same buffer we can
@@ -262,18 +262,6 @@ meta_wayland_surface_attach_buffer (struct wl_client *wayland_client,
   buffer->surfaces_attached_to = g_list_prepend (buffer->surfaces_attached_to,
                                                  surface);
 
-  /* NB: Surfaces from xwayland are dealt with via MetaShapedTexture
-   * actors */
-  if (wayland_client != compositor->xwayland_client)
-    {
-      if (!surface->actor)
-        {
-          surface->actor = clutter_wayland_surface_new (&surface->wayland_surface);
-          clutter_container_add_actor (CLUTTER_CONTAINER (compositor->stage),
-                                       surface->actor);
-        }
-    }
-
   /* XXX: Its a bit messy but even though xwayland surfaces are
    * handled separately we still set surface->actor to the
    * MetaShapedTexture actor thats created for a MetaWindowActor.
@@ -390,28 +378,37 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
 }
 
 static void
+surface_actor_destroyed_cb (void *user_data,
+                            GObject *old_object)
+{
+  MetaWaylandSurface *surface = user_data;
+
+  surface->actor = NULL;
+  surface->window = NULL;
+}
+
+static void
 meta_wayland_surface_free (MetaWaylandSurface *surface)
 {
   MetaWaylandCompositor *compositor = surface->compositor;
   compositor->surfaces = g_list_remove (compositor->surfaces, surface);
   meta_wayland_surface_detach_buffer (surface);
 
-  /* XXX: This is a bit messy, but we only own surface->actor if
-   * its a ClutterWaylandSurface. Surfaces that correspond to X
-   * applications will have MetaShapedTexture actors and those are
-   * owned by a MetaWindowActor.
-   *
-   * TODO: find a neater way of separating things.
-   */
-  if (surface->actor && CLUTTER_WAYLAND_IS_SURFACE (surface->actor))
+  if (surface->actor)
+    g_object_weak_unref (G_OBJECT (surface->actor),
+                         surface_actor_destroyed_cb,
+                         surface);
+
+  /* NB: If the surface corresponds to an X window then we will be
+   * sure to free the MetaWindow according to some X event. */
+  if (surface->window &&
+      surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
     {
-      clutter_actor_destroy (surface->actor);
+      MetaDisplay *display = meta_get_display ();
+      guint32 timestamp = meta_display_get_current_time_roundtrip (display);
+      meta_window_unmanage (surface->window, timestamp);
     }
 
-  if (surface->actor)
-    g_object_remove_weak_pointer (G_OBJECT (surface->actor),
-                                  (void **)&surface->actor);
-
   g_slice_free (MetaWaylandSurface, surface);
 
   meta_wayland_compositor_repick (compositor);
@@ -588,6 +585,46 @@ static void
 shell_surface_set_toplevel (struct wl_client *client,
                             struct wl_resource *resource)
 {
+  MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
+  MetaWaylandShellSurface *shell_surface = resource->data;
+  MetaWaylandSurface *surface = shell_surface->surface;
+  MetaDisplay *display = meta_get_display ();
+
+  /* NB: Surfaces from xwayland become managed based on X events. */
+  if (client == compositor->xwayland_client)
+    return;
+
+  if (!surface->window)
+    {
+      int width, height;
+
+      if (surface->buffer && surface->buffer->wayland_buffer)
+        {
+          struct wl_buffer *buffer = surface->buffer->wayland_buffer;
+          width = buffer->width;
+          height = buffer->width;
+        }
+      else
+        {
+          width = 0;
+          height = 0;
+        }
+
+      surface->window =
+        meta_window_new_for_wayland (display, width, height, surface);
+
+      /* The new MetaWindow should always result in us creating a corresponding
+       * MetaWindowActor which will be immediately associated with the given
+       * surface... */
+      g_assert (surface->actor);
+
+      /* If the MetaWindow becomes unmanaged (surface->actor will be freed in
+       * this case) we need to make sure to clear our ->actor and ->window
+       * pointers. */
+      g_object_weak_ref (G_OBJECT (surface->actor),
+                         surface_actor_destroyed_cb,
+                         surface);
+    }
 }
 
 static void
@@ -999,12 +1036,15 @@ xserver_set_window_id (struct wl_client *client,
                                                surface->buffer->wayland_buffer,
                                                NULL);
 
+      surface->window = window;
       surface->actor = surface_actor;
 
-      /* If the MetaWindow becomes unmanaged (surface->actor will be freed
-       * in this case) we need to make sure to clear our pointer. */
-      g_object_add_weak_pointer (G_OBJECT (surface->actor),
-                                 (void **)&surface->actor);
+      /* If the MetaWindow becomes unmanaged (surface->actor will be freed in
+       * this case) we need to make sure to clear our ->actor and ->window
+       * pointers in this case. */
+      g_object_weak_ref (G_OBJECT (surface->actor),
+                         surface_actor_destroyed_cb,
+                         surface);
 
 #if 0
       if (window->visible_to_compositor)



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