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 { - MetaSurfaceActorWayland *surface_actor; + MetaWaylandSurfaceRole parent; +}; - if (surface->role == META_WAYLAND_SURFACE_ROLE_NONE || - surface->role == role) +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 +{ + 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); + +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 #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; +#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); -typedef struct +#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 #include +#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; +}