1
0
Fork 0

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 &&
!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",

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
#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

View file

@ -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;

View file

@ -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;
}