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
This commit is contained in:
Jonas Ådahl 2015-07-08 16:14:00 +08:00
parent 8e5fb03611
commit 83c17134f1
6 changed files with 474 additions and 125 deletions

View File

@ -538,7 +538,7 @@ data_device_start_drag (struct wl_client *client,
if (icon_resource && if (icon_resource &&
!meta_wayland_surface_assign_role (icon_surface, !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_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE,
"wl_surface@%d already has a different role", "wl_surface@%d already has a different role",

View File

@ -774,17 +774,15 @@ pointer_set_cursor (struct wl_client *client,
if (pointer->focus_serial - serial > G_MAXUINT32 / 2) if (pointer->focus_serial - serial > G_MAXUINT32 / 2)
return; return;
if (surface) if (surface &&
{ !meta_wayland_surface_assign_role (surface,
if (!meta_wayland_surface_assign_role (surface, META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
META_WAYLAND_SURFACE_ROLE_CURSOR))
{ {
wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
"wl_surface@%d already has a different role", "wl_surface@%d already has a different role",
wl_resource_get_id (surface_resource)); wl_resource_get_id (surface_resource));
return; return;
} }
}
pointer->hotspot_x = x; pointer->hotspot_x = x;
pointer->hotspot_y = y; pointer->hotspot_y = y;

View File

@ -55,6 +55,11 @@
#include "meta-surface-actor-wayland.h" #include "meta-surface-actor-wayland.h"
#include "meta-xwayland-private.h" #include "meta-xwayland-private.h"
typedef struct _MetaWaylandSurfaceRolePrivate
{
MetaWaylandSurface *surface;
} MetaWaylandSurfaceRolePrivate;
typedef enum typedef enum
{ {
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, 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); G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
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
{
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 gboolean
meta_wayland_surface_assign_role (MetaWaylandSurface *surface, meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
MetaWaylandSurfaceRole role) GType role_type)
{ {
MetaSurfaceActorWayland *surface_actor; if (!surface->role)
if (surface->role == META_WAYLAND_SURFACE_ROLE_NONE ||
surface->role == role)
{ {
surface->role = role; MetaWaylandSurfaceRolePrivate *role_priv;
switch (surface->role) surface->role = g_object_new (role_type, NULL);
{ role_priv =
case META_WAYLAND_SURFACE_ROLE_NONE: meta_wayland_surface_role_get_instance_private (surface->role);
g_assert_not_reached(); role_priv->surface = surface;
break;
case META_WAYLAND_SURFACE_ROLE_XWAYLAND: meta_wayland_surface_role_assigned (surface->role);
/* 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;
}
return TRUE; return TRUE;
} }
else else if (G_OBJECT_TYPE (surface->role) != role_type)
{ {
return FALSE; return FALSE;
} }
else
{
return TRUE;
}
} }
static void static void
@ -193,18 +258,37 @@ surface_process_damage (MetaWaylandSurface *surface,
cairo_region_destroy (scaled_region); cairo_region_destroy (scaled_region);
} }
static void void
cursor_surface_commit (MetaWaylandSurface *surface, meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending) 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 (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) if (pending->newly_attached)
meta_wayland_seat_update_cursor_surface (surface->compositor->seat); meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
} }
static void static void
dnd_surface_commit (MetaWaylandSurface *surface, dnd_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) 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); meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device);
} }
@ -261,12 +345,28 @@ destroy_window (MetaWaylandSurface *surface)
} }
static void static void
toplevel_surface_commit (MetaWaylandSurface *surface, queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending) 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; 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 /* For wl_shell, it's equivalent to an unmap. Semantics
* are poorly defined, so we can choose some that are * are poorly defined, so we can choose some that are
@ -282,7 +382,7 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
return; 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 */ /* Ignore commits if we couldn't grab the pointer */
if (!window) if (!window)
@ -418,12 +518,16 @@ move_pending_state (MetaWaylandPendingState *from,
} }
static void static void
subsurface_surface_commit (MetaWaylandSurface *surface, subsurface_surface_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActorWayland *surface_actor = MetaSurfaceActorWayland *surface_actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor); META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
queue_surface_actor_frame_callbacks (surface, pending);
if (surface->buffer != NULL) if (surface->buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor)); clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else else
@ -521,9 +625,6 @@ static void
apply_pending_state (MetaWaylandSurface *surface, apply_pending_state (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending) MetaWaylandPendingState *pending)
{ {
MetaWaylandCompositor *compositor = surface->compositor;
MetaSurfaceActorWayland *surface_actor;
if (pending->newly_attached) if (pending->newly_attached)
{ {
if (!surface->buffer && surface->window) if (!surface->buffer && surface->window)
@ -567,63 +668,20 @@ apply_pending_state (MetaWaylandSurface *surface,
surface->input_region = NULL; surface->input_region = NULL;
} }
/* wl_surface.frame */ if (surface->role)
switch (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 /* Since there is no role assigned to the surface yet, keep frame
* callbacks queued until a role is assigned and we know how * callbacks queued until a role is assigned and we know how
* the surface will be drawn. * the surface will be drawn.
*/ */
wl_list_insert_list (&surface->pending_frame_callback_list, wl_list_insert_list (&surface->pending_frame_callback_list,
&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); 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;
} }
meta_surface_actor_wayland_sync_state ( 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 static void
update_surface_output_state (gpointer key, gpointer value, gpointer user_data) update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
{ {
MetaWaylandOutput *wayland_output = value; MetaWaylandOutput *wayland_output = value;
MetaWaylandSurface *surface = user_data; MetaWaylandSurface *surface = user_data;
MetaSurfaceActorWayland *actor =
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
MetaMonitorInfo *monitor; MetaMonitorInfo *monitor;
gboolean is_on_output; gboolean is_on_output;
g_assert (surface->role);
monitor = wayland_output->monitor_info; monitor = wayland_output->monitor_info;
if (!monitor) if (!monitor)
{ {
@ -949,7 +1019,7 @@ update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
return; 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); 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; MetaWaylandCompositor *compositor = surface->compositor;
MetaWaylandFrameCallback *cb, *next; MetaWaylandFrameCallback *cb, *next;
g_clear_object (&surface->role);
/* If we still have a window at the time of destruction, that means that /* 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 * the client is disconnecting, as the resources are destroyed in a random
* order. Simply destroy the window in this case. */ * 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, 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_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different 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, 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_resource_post_error (resource, XDG_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different 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, 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_resource_post_error (resource, WL_SHELL_ERROR_ROLE,
"wl_surface@%d already has a different 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, 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 /* FIXME: There is no subcompositor "role" error yet, so lets just use something
* similar until there is. * similar until there is.
@ -2369,3 +2441,167 @@ static void
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass) 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;
}

View File

@ -30,6 +30,9 @@
#include <meta/meta-cursor-tracker.h> #include <meta/meta-cursor-tracker.h>
#include "meta-wayland-types.h" #include "meta-wayland-types.h"
#include "meta-surface-actor.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 ()) #define META_TYPE_WAYLAND_SURFACE (meta_wayland_surface_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandSurface, G_DECLARE_FINAL_TYPE (MetaWaylandSurface,
@ -37,24 +40,63 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSurface,
META, WAYLAND_SURFACE, META, WAYLAND_SURFACE,
GObject); 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 { struct _MetaWaylandSerial {
gboolean set; gboolean set;
uint32_t value; uint32_t value;
}; };
typedef enum #define META_TYPE_WAYLAND_SURFACE_ROLE_SUBSURFACE (meta_wayland_surface_role_subsurface_get_type ())
{ G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleSubsurface,
META_WAYLAND_SURFACE_ROLE_NONE, meta_wayland_surface_role_subsurface,
META_WAYLAND_SURFACE_ROLE_SUBSURFACE, META, WAYLAND_SURFACE_ROLE_SUBSURFACE,
META_WAYLAND_SURFACE_ROLE_XDG_SURFACE, MetaWaylandSurfaceRole);
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_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 */ /* wl_surface.attach */
gboolean newly_attached; gboolean newly_attached;
@ -78,7 +120,7 @@ typedef struct
MetaRectangle new_geometry; MetaRectangle new_geometry;
gboolean has_new_geometry; gboolean has_new_geometry;
} MetaWaylandPendingState; };
struct _MetaWaylandDragDestFuncs struct _MetaWaylandDragDestFuncs
{ {
@ -102,7 +144,7 @@ struct _MetaWaylandSurface
struct wl_resource *resource; struct wl_resource *resource;
MetaWaylandCompositor *compositor; MetaWaylandCompositor *compositor;
MetaSurfaceActor *surface_actor; MetaSurfaceActor *surface_actor;
MetaWaylandSurfaceRole role; MetaWaylandSurfaceRole *role;
MetaWindow *window; MetaWindow *window;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener; struct wl_listener buffer_destroy_listener;
@ -181,7 +223,7 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
guint32 id); guint32 id);
gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface, gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
MetaWaylandSurfaceRole role); GType role_type);
void meta_wayland_surface_set_window (MetaWaylandSurface *surface, void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window); MetaWindow *window);
@ -209,4 +251,9 @@ void meta_wayland_surface_update_outputs (MetaWaylandSurface *sur
MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface); 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 #endif

View File

@ -66,7 +66,7 @@ meta_window_wayland_manage (MetaWindow *window)
0); 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; MetaWaylandSurface *parent = window->surface->popup.parent;

View File

@ -32,6 +32,24 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.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 static void
associate_window_with_surface (MetaWindow *window, associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface) MetaWaylandSurface *surface)
@ -46,7 +64,7 @@ associate_window_with_surface (MetaWindow *window,
window->surface->window = NULL; window->surface->window = NULL;
if (!meta_wayland_surface_assign_role (surface, 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_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT, WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -553,3 +571,53 @@ meta_xwayland_stop (MetaXWaylandManager *manager)
g_clear_pointer (&manager->lock_file, g_free); 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;
}