[mutter] wayland: GObject:ify surface roles



commit 83c17134f1a13f8073816773a357cbc67588bc16
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Jul 8 16:14:00 2015 +0800

    wayland: GObject:ify surface roles
    
    Make a surface roles into objects with vfuncs for things where there
    before was a big switch statement. The declaration and definition
    boilerplate is hidden behind C macros.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744932

 src/wayland/meta-wayland-data-device.c |    2 +-
 src/wayland/meta-wayland-pointer.c     |   16 +-
 src/wayland/meta-wayland-surface.c     |  430 ++++++++++++++++++++++++-------
 src/wayland/meta-wayland-surface.h     |   81 +++++--
 src/wayland/meta-window-wayland.c      |    2 +-
 src/wayland/meta-xwayland.c            |   70 +++++-
 6 files changed, 475 insertions(+), 126 deletions(-)
---
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 3771d19..d7a1525 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -538,7 +538,7 @@ data_device_start_drag (struct wl_client *client,
 
   if (icon_resource &&
       !meta_wayland_surface_assign_role (icon_surface,
-                                         META_WAYLAND_SURFACE_ROLE_DND))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_DND))
     {
       wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE,
                               "wl_surface %d already has a different role",
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index f1e4d2f..f4297e3 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -774,16 +774,14 @@ pointer_set_cursor (struct wl_client *client,
   if (pointer->focus_serial - serial > G_MAXUINT32 / 2)
     return;
 
-  if (surface)
+  if (surface &&
+      !meta_wayland_surface_assign_role (surface,
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
     {
-      if (!meta_wayland_surface_assign_role (surface,
-                                             META_WAYLAND_SURFACE_ROLE_CURSOR))
-        {
-          wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
-                                  "wl_surface %d already has a different role",
-                                  wl_resource_get_id (surface_resource));
-          return;
-        }
+      wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
+                              "wl_surface %d already has a different role",
+                              wl_resource_get_id (surface_resource));
+      return;
     }
 
   pointer->hotspot_x = x;
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index ac4de2d..5277e71 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -55,6 +55,11 @@
 #include "meta-surface-actor-wayland.h"
 #include "meta-xwayland-private.h"
 
+typedef struct _MetaWaylandSurfaceRolePrivate
+{
+  MetaWaylandSurface *surface;
+} MetaWaylandSurfaceRolePrivate;
+
 typedef enum
 {
   META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
@@ -72,47 +77,107 @@ GType meta_wayland_surface_get_type (void) G_GNUC_CONST;
 
 G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
 
-gboolean
-meta_wayland_surface_assign_role (MetaWaylandSurface    *surface,
-                                  MetaWaylandSurfaceRole role)
+GType meta_wayland_surface_role_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
+                            meta_wayland_surface_role,
+                            G_TYPE_OBJECT);
+
+struct _MetaWaylandSurfaceRoleSubsurface
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_subsurface_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleSubsurface,
+               meta_wayland_surface_role_subsurface,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
+struct _MetaWaylandSurfaceRoleXdgSurface
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_xdg_surface_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgSurface,
+               meta_wayland_surface_role_xdg_surface,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
+struct _MetaWaylandSurfaceRoleXdgPopup
 {
-  MetaSurfaceActorWayland *surface_actor;
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_xdg_popup_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleXdgPopup,
+               meta_wayland_surface_role_xdg_popup,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
+struct _MetaWaylandSurfaceRoleWlShellSurface
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_wl_shell_surface_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleWlShellSurface,
+               meta_wayland_surface_role_wl_shell_surface,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
 
-  if (surface->role == META_WAYLAND_SURFACE_ROLE_NONE ||
-      surface->role == role)
+struct _MetaWaylandSurfaceRoleCursor
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_cursor_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
+               meta_wayland_surface_role_cursor,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
+struct _MetaWaylandSurfaceRoleDND
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_dnd_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND,
+               meta_wayland_surface_role_dnd,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
+static void
+meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role);
+
+static void
+meta_wayland_surface_role_commit (MetaWaylandSurfaceRole  *surface_role,
+                                  MetaWaylandPendingState *pending);
+
+static gboolean
+meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role,
+                                        MetaMonitorInfo *info);
+
+gboolean
+meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
+                                  GType               role_type)
+{
+  if (!surface->role)
     {
-      surface->role = role;
+      MetaWaylandSurfaceRolePrivate *role_priv;
 
-      switch (surface->role)
-        {
-        case META_WAYLAND_SURFACE_ROLE_NONE:
-          g_assert_not_reached();
-          break;
-        case META_WAYLAND_SURFACE_ROLE_XWAYLAND:
-          /* See apply_pending_state for explanation why Xwayland is special here. */
-        case META_WAYLAND_SURFACE_ROLE_CURSOR:
-        case META_WAYLAND_SURFACE_ROLE_DND:
-          wl_list_insert_list (&surface->compositor->frame_callbacks,
-                               &surface->pending_frame_callback_list);
-          wl_list_init (&surface->pending_frame_callback_list);
-          break;
-        case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
-        case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
-        case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
-        case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
-          surface_actor = META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-          meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
-                                                          &surface->pending_frame_callback_list);
-          wl_list_init (&surface->pending_frame_callback_list);
-          break;
-        }
+      surface->role = g_object_new (role_type, NULL);
+      role_priv =
+        meta_wayland_surface_role_get_instance_private (surface->role);
+      role_priv->surface = surface;
+
+      meta_wayland_surface_role_assigned (surface->role);
 
       return TRUE;
     }
-  else
+  else if (G_OBJECT_TYPE (surface->role) != role_type)
     {
       return FALSE;
     }
+  else
+    {
+      return TRUE;
+    }
 }
 
 static void
@@ -193,18 +258,37 @@ surface_process_damage (MetaWaylandSurface *surface,
   cairo_region_destroy (scaled_region);
 }
 
+void
+meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface      *surface,
+                                                          MetaWaylandPendingState *pending)
+{
+  wl_list_insert_list (&surface->compositor->frame_callbacks,
+                       &pending->frame_callback_list);
+  wl_list_init (&pending->frame_callback_list);
+}
+
 static void
-cursor_surface_commit (MetaWaylandSurface      *surface,
+cursor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                        MetaWaylandPendingState *pending)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
+
   if (pending->newly_attached)
     meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
 }
 
 static void
-dnd_surface_commit (MetaWaylandSurface      *surface,
+dnd_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                     MetaWaylandPendingState *pending)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
+
   meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device);
 }
 
@@ -261,12 +345,28 @@ destroy_window (MetaWaylandSurface *surface)
 }
 
 static void
-toplevel_surface_commit (MetaWaylandSurface      *surface,
+queue_surface_actor_frame_callbacks (MetaWaylandSurface      *surface,
+                                     MetaWaylandPendingState *pending)
+{
+  MetaSurfaceActorWayland *surface_actor =
+    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
+
+  meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
+                                                  &pending->frame_callback_list);
+  wl_list_init (&pending->frame_callback_list);
+}
+
+static void
+toplevel_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                          MetaWaylandPendingState *pending)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
   MetaWindow *window = surface->window;
 
-  if (surface->role == META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE)
+  queue_surface_actor_frame_callbacks (surface, pending);
+
+  if (META_IS_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE (surface->role))
     {
       /* For wl_shell, it's equivalent to an unmap. Semantics
        * are poorly defined, so we can choose some that are
@@ -282,7 +382,7 @@ toplevel_surface_commit (MetaWaylandSurface      *surface,
           return;
         }
     }
-  else if (surface->role == META_WAYLAND_SURFACE_ROLE_XDG_POPUP)
+  else if (META_IS_WAYLAND_SURFACE_ROLE_XDG_POPUP (surface->role))
     {
       /* Ignore commits if we couldn't grab the pointer */
       if (!window)
@@ -418,12 +518,16 @@ move_pending_state (MetaWaylandPendingState *from,
 }
 
 static void
-subsurface_surface_commit (MetaWaylandSurface      *surface,
+subsurface_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                            MetaWaylandPendingState *pending)
 {
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
   MetaSurfaceActorWayland *surface_actor =
     META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
 
+  queue_surface_actor_frame_callbacks (surface, pending);
+
   if (surface->buffer != NULL)
     clutter_actor_show (CLUTTER_ACTOR (surface_actor));
   else
@@ -521,9 +625,6 @@ static void
 apply_pending_state (MetaWaylandSurface      *surface,
                      MetaWaylandPendingState *pending)
 {
-  MetaWaylandCompositor *compositor = surface->compositor;
-  MetaSurfaceActorWayland *surface_actor;
-
   if (pending->newly_attached)
     {
       if (!surface->buffer && surface->window)
@@ -567,63 +668,20 @@ apply_pending_state (MetaWaylandSurface      *surface,
         surface->input_region = NULL;
     }
 
-  /* wl_surface.frame */
-  switch (surface->role)
+  if (surface->role)
+    {
+      meta_wayland_surface_role_commit (surface->role, pending);
+      g_assert (wl_list_empty (&pending->frame_callback_list));
+    }
+  else
     {
-    case META_WAYLAND_SURFACE_ROLE_NONE:
       /* Since there is no role assigned to the surface yet, keep frame
        * callbacks queued until a role is assigned and we know how
        * the surface will be drawn.
        */
       wl_list_insert_list (&surface->pending_frame_callback_list,
                            &pending->frame_callback_list);
-      break;
-    case META_WAYLAND_SURFACE_ROLE_XWAYLAND:
-      /* For Xwayland windows, throttling frames when the window isn't actually
-       * drawn is less useful, because Xwayland still has to do the drawing
-       * sent from the application - the throttling would only be of sending us
-       * damage messages, so we simplify and send frame callbacks after the
-       * next paint of the screen, whether the window was drawn or not.
-       *
-       * Currently it may take a few frames before we draw the window, for not
-       * completely understood reasons, and in that case, not thottling frame
-       * callbacks to drawing has the happy side effect that we avoid showing
-       * the user the initial black frame from when the window is mapped empty.
-       */
-    case META_WAYLAND_SURFACE_ROLE_CURSOR:
-    case META_WAYLAND_SURFACE_ROLE_DND:
-      wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
-      break;
-    case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
-    case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
-    case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
-    case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
-      surface_actor = META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-      meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
-                                                      &pending->frame_callback_list);
-    break;
-    }
-  wl_list_init (&pending->frame_callback_list);
-
-  switch (surface->role)
-    {
-    case META_WAYLAND_SURFACE_ROLE_NONE:
-    case META_WAYLAND_SURFACE_ROLE_XWAYLAND:
-      break;
-    case META_WAYLAND_SURFACE_ROLE_CURSOR:
-      cursor_surface_commit (surface, pending);
-      break;
-    case META_WAYLAND_SURFACE_ROLE_DND:
-      dnd_surface_commit (surface, pending);
-      break;
-    case META_WAYLAND_SURFACE_ROLE_XDG_SURFACE:
-    case META_WAYLAND_SURFACE_ROLE_XDG_POPUP:
-    case META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE:
-      toplevel_surface_commit (surface, pending);
-      break;
-    case META_WAYLAND_SURFACE_ROLE_SUBSURFACE:
-      subsurface_surface_commit (surface, pending);
-      break;
+      wl_list_init (&pending->frame_callback_list);
     }
 
   meta_surface_actor_wayland_sync_state (
@@ -932,16 +990,28 @@ set_surface_is_on_output (MetaWaylandSurface *surface,
     }
 }
 
+static gboolean
+actor_surface_is_on_output (MetaWaylandSurfaceRole *surface_role,
+                            MetaMonitorInfo        *monitor)
+{
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaSurfaceActorWayland *actor =
+    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
+
+  return meta_surface_actor_wayland_is_on_monitor (actor, monitor);
+}
+
 static void
 update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
 {
   MetaWaylandOutput *wayland_output = value;
   MetaWaylandSurface *surface = user_data;
-  MetaSurfaceActorWayland *actor =
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
   MetaMonitorInfo *monitor;
   gboolean is_on_output;
 
+  g_assert (surface->role);
+
   monitor = wayland_output->monitor_info;
   if (!monitor)
     {
@@ -949,7 +1019,7 @@ update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
       return;
     }
 
-  is_on_output = meta_surface_actor_wayland_is_on_monitor (actor, monitor);
+  is_on_output = meta_wayland_surface_role_is_on_output (surface->role, monitor);
   set_surface_is_on_output (surface, wayland_output, is_on_output);
 }
 
@@ -980,6 +1050,8 @@ wl_surface_destructor (struct wl_resource *resource)
   MetaWaylandCompositor *compositor = surface->compositor;
   MetaWaylandFrameCallback *cb, *next;
 
+  g_clear_object (&surface->role);
+
   /* If we still have a window at the time of destruction, that means that
    * the client is disconnecting, as the resources are destroyed in a random
    * order. Simply destroy the window in this case. */
@@ -1334,7 +1406,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
     }
 
   if (!meta_wayland_surface_assign_role (surface,
-                                         META_WAYLAND_SURFACE_ROLE_XDG_SURFACE))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_XDG_SURFACE))
     {
       wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
                               "wl_surface %d already has a different role",
@@ -1445,7 +1517,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
     }
 
   if (!meta_wayland_surface_assign_role (surface,
-                                         META_WAYLAND_SURFACE_ROLE_XDG_POPUP))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_XDG_POPUP))
     {
       wl_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
                               "wl_surface %d already has a different role",
@@ -1788,7 +1860,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
     }
 
   if (!meta_wayland_surface_assign_role (surface,
-                                         META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE))
     {
       wl_resource_post_error (resource, WL_SHELL_ERROR_ROLE,
                               "wl_surface %d already has a different role",
@@ -2140,7 +2212,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
     }
 
   if (!meta_wayland_surface_assign_role (surface,
-                                         META_WAYLAND_SURFACE_ROLE_SUBSURFACE))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE))
     {
       /* FIXME: There is no subcompositor "role" error yet, so lets just use something
        * similar until there is.
@@ -2369,3 +2441,167 @@ static void
 meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
 {
 }
+
+static void
+meta_wayland_surface_role_init (MetaWaylandSurfaceRole *role)
+{
+}
+
+static void
+meta_wayland_surface_role_class_init (MetaWaylandSurfaceRoleClass *klass)
+{
+}
+
+static void
+meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
+{
+  META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->assigned (surface_role);
+}
+
+static void
+meta_wayland_surface_role_commit (MetaWaylandSurfaceRole  *surface_role,
+                                  MetaWaylandPendingState *pending)
+{
+  META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->commit (surface_role,
+                                                              pending);
+}
+
+static gboolean
+meta_wayland_surface_role_is_on_output (MetaWaylandSurfaceRole *surface_role,
+                                        MetaMonitorInfo        *monitor)
+{
+  MetaWaylandSurfaceRoleClass *klass;
+
+  klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
+  if (klass->is_on_output)
+    return klass->is_on_output (surface_role, monitor);
+  else
+    return FALSE;
+}
+
+MetaWaylandSurface *
+meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role)
+{
+  MetaWaylandSurfaceRolePrivate *priv =
+    meta_wayland_surface_role_get_instance_private (role);
+
+  return priv->surface;
+}
+
+static void
+default_role_assigned (MetaWaylandSurfaceRole *surface_role)
+{
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  wl_list_insert_list (&surface->compositor->frame_callbacks,
+                       &surface->pending_frame_callback_list);
+  wl_list_init (&surface->pending_frame_callback_list);
+}
+
+static void
+actor_surface_assigned (MetaWaylandSurfaceRole *surface_role)
+{
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaSurfaceActorWayland *surface_actor =
+    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
+
+  meta_surface_actor_wayland_add_frame_callbacks (surface_actor,
+                                                  &surface->pending_frame_callback_list);
+  wl_list_init (&surface->pending_frame_callback_list);
+}
+
+static void
+meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role)
+{
+}
+
+static void
+meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = default_role_assigned;
+  surface_role_class->commit = cursor_surface_commit;
+}
+
+static void
+meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role)
+{
+}
+
+static void
+meta_wayland_surface_role_dnd_class_init (MetaWaylandSurfaceRoleDNDClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = default_role_assigned;
+  surface_role_class->commit = dnd_surface_commit;
+}
+
+static void
+meta_wayland_surface_role_xdg_surface_init (MetaWaylandSurfaceRoleXdgSurface *role)
+{
+}
+
+static void
+meta_wayland_surface_role_xdg_surface_class_init (MetaWaylandSurfaceRoleXdgSurfaceClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = actor_surface_assigned;
+  surface_role_class->commit = toplevel_surface_commit;
+  surface_role_class->is_on_output = actor_surface_is_on_output;
+}
+
+static void
+meta_wayland_surface_role_xdg_popup_init (MetaWaylandSurfaceRoleXdgPopup *role)
+{
+}
+
+static void
+meta_wayland_surface_role_xdg_popup_class_init (MetaWaylandSurfaceRoleXdgPopupClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = actor_surface_assigned;
+  surface_role_class->commit = toplevel_surface_commit;
+  surface_role_class->is_on_output = actor_surface_is_on_output;
+}
+
+static void
+meta_wayland_surface_role_wl_shell_surface_init (MetaWaylandSurfaceRoleWlShellSurface *role)
+{
+}
+
+static void
+meta_wayland_surface_role_wl_shell_surface_class_init (MetaWaylandSurfaceRoleWlShellSurfaceClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = actor_surface_assigned;
+  surface_role_class->commit = toplevel_surface_commit;
+  surface_role_class->is_on_output = actor_surface_is_on_output;
+}
+
+static void
+meta_wayland_surface_role_subsurface_init (MetaWaylandSurfaceRoleSubsurface *role)
+{
+}
+
+static void
+meta_wayland_surface_role_subsurface_class_init (MetaWaylandSurfaceRoleSubsurfaceClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = actor_surface_assigned;
+  surface_role_class->commit = subsurface_surface_commit;
+  surface_role_class->is_on_output = actor_surface_is_on_output;
+}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 74f3759..4962239 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -30,6 +30,9 @@
 #include <meta/meta-cursor-tracker.h>
 #include "meta-wayland-types.h"
 #include "meta-surface-actor.h"
+#include "backends/meta-monitor-manager-private.h"
+
+typedef struct _MetaWaylandPendingState MetaWaylandPendingState;
 
 #define META_TYPE_WAYLAND_SURFACE (meta_wayland_surface_get_type ())
 G_DECLARE_FINAL_TYPE (MetaWaylandSurface,
@@ -37,24 +40,63 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSurface,
                       META, WAYLAND_SURFACE,
                       GObject);
 
+#define META_TYPE_WAYLAND_SURFACE_ROLE (meta_wayland_surface_role_get_type ())
+G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRole, meta_wayland_surface_role,
+                          META, WAYLAND_SURFACE_ROLE, GObject);
+
+struct _MetaWaylandSurfaceRoleClass
+{
+  GObjectClass parent_class;
+
+  void (*assigned) (MetaWaylandSurfaceRole *surface_role);
+  void (*commit) (MetaWaylandSurfaceRole  *surface_role,
+                  MetaWaylandPendingState *pending);
+  gboolean (*is_on_output) (MetaWaylandSurfaceRole *surface_role,
+                            MetaMonitorInfo        *monitor);
+};
+
 struct _MetaWaylandSerial {
   gboolean set;
   uint32_t value;
 };
 
-typedef enum
-{
-  META_WAYLAND_SURFACE_ROLE_NONE,
-  META_WAYLAND_SURFACE_ROLE_SUBSURFACE,
-  META_WAYLAND_SURFACE_ROLE_XDG_SURFACE,
-  META_WAYLAND_SURFACE_ROLE_XDG_POPUP,
-  META_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE,
-  META_WAYLAND_SURFACE_ROLE_CURSOR,
-  META_WAYLAND_SURFACE_ROLE_DND,
-  META_WAYLAND_SURFACE_ROLE_XWAYLAND,
-} MetaWaylandSurfaceRole;
-
-typedef struct
+#define META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE (meta_wayland_surface_role_subsurface_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleSubsurface,
+                      meta_wayland_surface_role_subsurface,
+                      META, WAYLAND_SURFACE_ROLE_SUBSURFACE,
+                      MetaWaylandSurfaceRole);
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_XDG_SURFACE (meta_wayland_surface_role_xdg_surface_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXdgSurface,
+                      meta_wayland_surface_role_xdg_surface,
+                      META, WAYLAND_SURFACE_ROLE_XDG_SURFACE,
+                      MetaWaylandSurfaceRole);
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_XDG_POPUP (meta_wayland_surface_role_xdg_popup_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXdgPopup,
+                      meta_wayland_surface_role_xdg_popup,
+                      META, WAYLAND_SURFACE_ROLE_XDG_POPUP,
+                      MetaWaylandSurfaceRole);
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE (meta_wayland_surface_role_wl_shell_surface_get_type 
())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleWlShellSurface,
+                      meta_wayland_surface_role_wl_shell_surface,
+                      META, WAYLAND_SURFACE_ROLE_WL_SHELL_SURFACE,
+                      MetaWaylandSurfaceRole);
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR (meta_wayland_surface_role_cursor_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleCursor,
+                      meta_wayland_surface_role_cursor,
+                      META, WAYLAND_SURFACE_ROLE_CURSOR,
+                      MetaWaylandSurfaceRole);
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_DND (meta_wayland_surface_role_dnd_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleDND,
+                      meta_wayland_surface_role_dnd,
+                      META, WAYLAND_SURFACE_ROLE_DND,
+                      MetaWaylandSurfaceRole);
+
+struct _MetaWaylandPendingState
 {
   /* wl_surface.attach */
   gboolean newly_attached;
@@ -78,7 +120,7 @@ typedef struct
 
   MetaRectangle new_geometry;
   gboolean has_new_geometry;
-} MetaWaylandPendingState;
+};
 
 struct _MetaWaylandDragDestFuncs
 {
@@ -102,7 +144,7 @@ struct _MetaWaylandSurface
   struct wl_resource *resource;
   MetaWaylandCompositor *compositor;
   MetaSurfaceActor *surface_actor;
-  MetaWaylandSurfaceRole role;
+  MetaWaylandSurfaceRole *role;
   MetaWindow *window;
   MetaWaylandBuffer *buffer;
   struct wl_listener buffer_destroy_listener;
@@ -180,8 +222,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
                                                  struct wl_resource    *compositor_resource,
                                                  guint32                id);
 
-gboolean            meta_wayland_surface_assign_role (MetaWaylandSurface    *surface,
-                                                      MetaWaylandSurfaceRole role);
+gboolean            meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
+                                                      GType               role_type);
 
 void                meta_wayland_surface_set_window (MetaWaylandSurface *surface,
                                                      MetaWindow         *window);
@@ -209,4 +251,9 @@ void                meta_wayland_surface_update_outputs (MetaWaylandSurface *sur
 
 MetaWindow *        meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface);
 
+void                meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface      
*surface,
+                                                                              MetaWaylandPendingState 
*pending);
+
+MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role);
+
 #endif
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index e332341..b103359 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -66,7 +66,7 @@ meta_window_wayland_manage (MetaWindow *window)
                                    0);
   }
 
-  if (window->surface->role == META_WAYLAND_SURFACE_ROLE_XDG_POPUP)
+  if (META_IS_WAYLAND_SURFACE_ROLE_XDG_POPUP (window->surface->role))
     {
       MetaWaylandSurface *parent = window->surface->popup.parent;
 
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index ba2c191..1e7cb34 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -32,6 +32,24 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "compositor/meta-surface-actor-wayland.h"
+
+#define META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND (meta_wayland_surface_role_xwayland_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleXWayland,
+                      meta_wayland_surface_role_xwayland,
+                      META, WAYLAND_SURFACE_ROLE_XWAYLAND,
+                      MetaWaylandSurfaceRole);
+
+struct _MetaWaylandSurfaceRoleXWayland
+{
+  MetaWaylandSurfaceRole parent;
+};
+
+GType meta_wayland_surface_role_xwayland_get_type (void) G_GNUC_CONST;
+G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
+               meta_wayland_surface_role_xwayland,
+               META_TYPE_WAYLAND_SURFACE_ROLE);
+
 static void
 associate_window_with_surface (MetaWindow         *window,
                                MetaWaylandSurface *surface)
@@ -46,7 +64,7 @@ associate_window_with_surface (MetaWindow         *window,
     window->surface->window = NULL;
 
   if (!meta_wayland_surface_assign_role (surface,
-                                         META_WAYLAND_SURFACE_ROLE_XWAYLAND))
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_XWAYLAND))
     {
       wl_resource_post_error (surface->resource,
                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -553,3 +571,53 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
       g_clear_pointer (&manager->lock_file, g_free);
     }
 }
+
+static void
+xwayland_surface_assigned (MetaWaylandSurfaceRole *surface_role)
+{
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  /* See comment in xwayland_surface_commit for why we reply even though the
+   * surface may not be drawn the next frame.
+   */
+  wl_list_insert_list (&surface->compositor->frame_callbacks,
+                       &surface->pending_frame_callback_list);
+  wl_list_init (&surface->pending_frame_callback_list);
+}
+
+static void
+xwayland_surface_commit (MetaWaylandSurfaceRole  *surface_role,
+                         MetaWaylandPendingState *pending)
+{
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+
+  /* For Xwayland windows, throttling frames when the window isn't actually
+   * drawn is less useful, because Xwayland still has to do the drawing sent
+   * from the application - the throttling would only be of sending us damage
+   * messages, so we simplify and send frame callbacks after the next paint of
+   * the screen, whether the window was drawn or not.
+   *
+   * Currently it may take a few frames before we draw the window, for not
+   * completely understood reasons, and in that case, not thottling frame
+   * callbacks to drawing has the happy side effect that we avoid showing the
+   * user the initial black frame from when the window is mapped empty.
+   */
+  meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
+}
+
+static void
+meta_wayland_surface_role_xwayland_init (MetaWaylandSurfaceRoleXWayland *role)
+{
+}
+
+static void
+meta_wayland_surface_role_xwayland_class_init (MetaWaylandSurfaceRoleXWaylandClass *klass)
+{
+  MetaWaylandSurfaceRoleClass *surface_role_class =
+    META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+
+  surface_role_class->assigned = xwayland_surface_assigned;
+  surface_role_class->commit = xwayland_surface_commit;
+}


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