summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2015-07-08 16:14:00 +0800
committerJonas Ådahl <jadahl@gmail.com>2015-09-13 21:24:58 +0800
commit83c17134f1a13f8073816773a357cbc67588bc16 (patch)
treec13eacdde8f7f2cbf210a0228e5cb1c47cc4f4a5
parent8e5fb036112749c16b5496b018ae5b66765efba6 (diff)
downloadmutter-83c17134f1a13f8073816773a357cbc67588bc16.tar.gz
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
-rw-r--r--src/wayland/meta-wayland-data-device.c2
-rw-r--r--src/wayland/meta-wayland-pointer.c16
-rw-r--r--src/wayland/meta-wayland-surface.c430
-rw-r--r--src/wayland/meta-wayland-surface.h81
-rw-r--r--src/wayland/meta-window-wayland.c2
-rw-r--r--src/wayland/meta-xwayland.c70
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 3771d1996..d7a1525f1 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 f1e4d2f05..f4297e3a7 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 ac4de2dcf..5277e7128 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 74f37592e..49622394a 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 e3323419d..b10335913 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 ba2c19192..1e7cb34f7 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;
+}