wayland: Move MetaWindow ownership to window owning roles

There are two surface roles owning a MetaWindow: MetaWaylandShellSurface
(basis of MetaWaylandXdgToplevel, MetaWaylandXdgPopup,
MetaWaylandWlShellSurface, etc), and MetaXwaylandSurface.

With these two role types, the MetaWindow has two different types of
life times. With MetaWaylandShellSurface, the window is owned and
managed by the role itself, while with MetaXwaylandSurface, the
MetaWindow is tied to the X11 window, while the Wayland surface and its
role plays more the role of the backing rendering surface.

Before, for historical reasons, MetaWindow was part of
MetaWaylandSurface, even though just some roles used it, and before
'wayland: Untie MetaWindowXwayland lifetime from the wl_surface' had
equivalent life times as well. But since that commit, the management
changed. To not have the same fied in MetaWaylandSurface being managed
in such drastically different ways, rearrange it so that the roles that
has a MetaWindow themself manages it in the way it is meant to; meaning
MetaWaylandShellSurface practically owns it, while with Xwayland, the
existance of a MetaWindow is tracked via X11.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/835
This commit is contained in:
Jonas Ådahl 2019-10-09 09:57:40 +02:00 committed by Robert Mader
parent df642eb150
commit 44ae38599f
5 changed files with 265 additions and 127 deletions

View File

@ -223,6 +223,7 @@ enum
WORKSPACE_CHANGED,
FOCUS,
RAISED,
UNMANAGING,
UNMANAGED,
SIZE_CHANGED,
POSITION_CHANGED,
@ -649,6 +650,14 @@ meta_window_class_init (MetaWindowClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
window_signals[UNMANAGING] =
g_signal_new ("unmanaging",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
window_signals[UNMANAGED] =
g_signal_new ("unmanaged",
G_TYPE_FROM_CLASS (object_class),
@ -1435,17 +1444,9 @@ meta_window_unmanage (MetaWindow *window,
g_clear_handle_id (&window->unmanage_idle_id, g_source_remove);
meta_window_free_delete_dialog (window);
g_signal_emit (window, window_signals[UNMANAGING], 0);
#ifdef HAVE_WAYLAND
/* This needs to happen for both Wayland and XWayland clients,
* so it can't be in MetaWindowWayland. */
if (window->surface)
{
meta_wayland_surface_set_window (window->surface, NULL);
window->surface = NULL;
}
#endif
meta_window_free_delete_dialog (window);
if (window->visible_to_compositor)
{

View File

@ -24,6 +24,7 @@
#include "wayland/meta-wayland-shell-surface.h"
#include "compositor/meta-surface-actor-wayland.h"
#include "compositor/meta-window-actor-private.h"
#include "compositor/meta-window-actor-wayland.h"
#include "wayland/meta-wayland-actor-surface.h"
#include "wayland/meta-wayland-buffer.h"
@ -31,9 +32,18 @@
#include "wayland/meta-wayland-surface.h"
#include "wayland/meta-window-wayland.h"
G_DEFINE_ABSTRACT_TYPE (MetaWaylandShellSurface,
meta_wayland_shell_surface,
META_TYPE_WAYLAND_ACTOR_SURFACE)
typedef struct _MetaWaylandShellSurfacePrivate
{
MetaWindow *window;
gulong unmanaging_handler_id;
gulong position_changed_handler_id;
gulong effects_completed_handler_id;
} MetaWaylandShellSurfacePrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandShellSurface,
meta_wayland_shell_surface,
META_TYPE_WAYLAND_ACTOR_SURFACE)
void
meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
@ -81,16 +91,93 @@ meta_wayland_shell_surface_determine_geometry (MetaWaylandShellSurface *shell_su
*out_geometry = intersected_geometry;
}
void
meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface,
MetaWindow *window)
static void
clear_window (MetaWaylandShellSurface *shell_surface)
{
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (shell_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActor *surface_actor;
if (!priv->window)
return;
g_clear_signal_handler (&priv->unmanaging_handler_id,
priv->window);
g_clear_signal_handler (&priv->position_changed_handler_id,
priv->window);
g_clear_signal_handler (&priv->effects_completed_handler_id,
meta_window_actor_from_window (priv->window));
priv->window = NULL;
surface_actor = meta_wayland_surface_get_actor (surface);
if (surface_actor)
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE);
meta_wayland_surface_notify_unmapped (surface);
}
static void
window_unmanaging (MetaWindow *window,
MetaWaylandShellSurface *shell_surface)
{
clear_window (shell_surface);
}
static void
window_position_changed (MetaWindow *window,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
}
static void
window_actor_effects_completed (MetaWindowActor *window_actor,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
meta_wayland_compositor_repick (surface->compositor);
}
void
meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface,
MetaWindow *window)
{
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (shell_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActor *surface_actor;
g_assert (!priv->window);
priv->window = window;
surface_actor = meta_wayland_surface_get_actor (surface);
if (surface_actor)
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
priv->unmanaging_handler_id =
g_signal_connect (window,
"unmanaging",
G_CALLBACK (window_unmanaging),
shell_surface);
priv->position_changed_handler_id =
g_signal_connect (window,
"position-changed",
G_CALLBACK (window_position_changed),
surface);
priv->effects_completed_handler_id =
g_signal_connect (meta_window_actor_from_window (window),
"effects-completed",
G_CALLBACK (window_actor_effects_completed),
surface);
meta_wayland_surface_set_window (surface, window);
meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
}
@ -150,21 +237,27 @@ static void
meta_wayland_shell_surface_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
MetaWaylandSurfaceState *pending)
{
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (surface_role);
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *window;
window = meta_wayland_surface_get_window (surface);
if (pending->newly_attached &&
!surface->buffer_ref.buffer &&
window)
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
priv->window)
meta_window_queue (priv->window, META_QUEUE_CALC_SHOWING);
}
static void
meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
MetaWaylandSurfaceState *pending)
{
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (surface_role);
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (surface_role);
MetaWaylandSurface *surface =
@ -182,7 +275,7 @@ meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface
if (!buffer)
return;
window = meta_wayland_surface_get_window (surface);
window = priv->window;
if (!window)
return;
@ -194,15 +287,28 @@ meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface
meta_wayland_surface_get_height (surface) * geometry_scale;
}
static MetaWindow *
meta_wayland_shell_surface_get_window (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (surface_role);
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
return priv->window;
}
static void
meta_wayland_shell_surface_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandShellSurface *shell_surface =
META_WAYLAND_SHELL_SURFACE (surface_role);
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWindow *window;
MetaWindowActor *window_actor;
window = meta_wayland_surface_get_window (surface);
window = priv->window;
if (!window)
return;
@ -247,22 +353,20 @@ meta_wayland_shell_surface_sync_actor_state (MetaWaylandActorSurface *actor_surf
void
meta_wayland_shell_surface_destroy_window (MetaWaylandShellSurface *shell_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (shell_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandShellSurfacePrivate *priv =
meta_wayland_shell_surface_get_instance_private (shell_surface);
MetaWindow *window;
MetaDisplay *display;
uint32_t timestamp;
window = meta_wayland_surface_get_window (surface);
window = priv->window;
if (!window)
return;
display = meta_window_get_display (window);
timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_unmanage (window, timestamp);
g_assert (!meta_wayland_surface_get_window (surface));
g_assert (!priv->window);
}
static void
@ -298,6 +402,7 @@ meta_wayland_shell_surface_class_init (MetaWaylandShellSurfaceClass *klass)
meta_wayland_shell_surface_surface_apply_state;
surface_role_class->notify_subsurface_state_changed =
meta_wayland_shell_surface_notify_subsurface_state_changed;
surface_role_class->get_window = meta_wayland_shell_surface_get_window;
actor_surface_class->get_geometry_scale =
meta_wayland_shell_surface_get_geometry_scale;

View File

@ -120,13 +120,6 @@ meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface
static MetaWaylandSurface *
meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role);
static void
window_position_changed (MetaWindow *window,
MetaWaylandSurface *surface);
static void
window_actor_effects_completed (MetaWindowActor *window_actor,
MetaWaylandSurface *surface);
static void
role_assignment_valist_to_properties (GType role_type,
const char *first_property_name,
@ -1241,7 +1234,7 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
surface);
}
static void
void
meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface)
{
MetaWaylandSurface *subsurface_surface;
@ -1253,45 +1246,9 @@ meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface)
}
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface)
{
gboolean was_unmapped = surface->window && !window;
ClutterActor *actor;
if (surface->window == window)
return;
if (surface->window)
{
g_signal_handlers_disconnect_by_func (surface->window,
window_position_changed,
surface);
g_signal_handlers_disconnect_by_func (meta_window_actor_from_window (surface->window),
window_actor_effects_completed,
surface);
}
surface->window = window;
actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
if (actor)
clutter_actor_set_reactive (actor, !!window);
if (was_unmapped)
g_signal_emit (surface, surface_signals[SURFACE_UNMAPPED], 0);
if (window)
{
g_signal_connect_object (window,
"position-changed",
G_CALLBACK (window_position_changed),
surface, 0);
g_signal_connect_object (meta_window_actor_from_window (window),
"effects-completed",
G_CALLBACK (window_actor_effects_completed),
surface, 0);
}
g_signal_emit (surface, surface_signals[SURFACE_UNMAPPED], 0);
}
static void
@ -1363,21 +1320,6 @@ wl_surface_destructor (struct wl_resource *resource)
meta_wayland_compositor_repick (compositor);
}
static void
window_position_changed (MetaWindow *window,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
}
static void
window_actor_effects_completed (MetaWindowActor *window_actor,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
meta_wayland_compositor_repick (surface->compositor);
}
MetaWaylandSurface *
meta_wayland_surface_create (MetaWaylandCompositor *compositor,
struct wl_client *client,
@ -1787,10 +1729,23 @@ meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role)
return NULL;
}
static MetaWindow *
meta_wayland_surface_role_get_window (MetaWaylandSurfaceRole *surface_role)
{
MetaWaylandSurfaceRoleClass *klass;
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
if (klass->get_window)
return klass->get_window (surface_role);
else
return NULL;
}
MetaWindow *
meta_wayland_surface_get_window (MetaWaylandSurface *surface)
{
return surface->window;
return meta_wayland_surface_role_get_window (surface->role);
}
static gboolean

View File

@ -68,6 +68,7 @@ struct _MetaWaylandSurfaceRoleClass
float abs_y,
float *out_sx,
float *out_sy);
MetaWindow * (*get_window) (MetaWaylandSurfaceRole *surface_role);
};
struct _MetaWaylandSurfaceState
@ -143,7 +144,6 @@ struct _MetaWaylandSurface
struct wl_resource *resource;
MetaWaylandCompositor *compositor;
MetaWaylandSurfaceRole *role;
MetaWindow *window;
cairo_region_t *input_region;
cairo_region_t *opaque_region;
int scale;
@ -335,6 +335,10 @@ void meta_wayland_surface_notify_geometry_changed (MetaWaylandSur
void meta_wayland_surface_notify_subsurface_state_changed (MetaWaylandSurface *surface);
void meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface);
void meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface);
int meta_wayland_surface_get_width (MetaWaylandSurface *surface);
int meta_wayland_surface_get_height (MetaWaylandSurface *surface);

View File

@ -40,12 +40,72 @@ static guint signals[N_SIGNALS];
struct _MetaXwaylandSurface
{
MetaWaylandActorSurface parent;
MetaWindow *window;
gulong unmanaging_handler_id;
gulong position_changed_handler_id;
gulong effects_completed_handler_id;
};
G_DEFINE_TYPE (MetaXwaylandSurface,
meta_xwayland_surface,
META_TYPE_WAYLAND_ACTOR_SURFACE)
static void
clear_window (MetaXwaylandSurface *xwayland_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (xwayland_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWindowActor *window_actor;
MetaSurfaceActor *surface_actor;
if (!xwayland_surface->window)
return;
g_clear_signal_handler (&xwayland_surface->unmanaging_handler_id,
xwayland_surface->window);
g_clear_signal_handler (&xwayland_surface->position_changed_handler_id,
xwayland_surface->window);
window_actor = meta_window_actor_from_window (xwayland_surface->window);
g_clear_signal_handler (&xwayland_surface->effects_completed_handler_id,
window_actor);
xwayland_surface->window->surface = NULL;
xwayland_surface->window = NULL;
surface_actor = meta_wayland_surface_get_actor (surface);
if (surface_actor)
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE);
meta_wayland_surface_notify_unmapped (surface);
}
static void
window_unmanaging (MetaWindow *window,
MetaXwaylandSurface *xwayland_surface)
{
clear_window (xwayland_surface);
}
static void
window_position_changed (MetaWindow *window,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
}
static void
window_actor_effects_completed (MetaWindowActor *window_actor,
MetaWaylandSurface *surface)
{
meta_wayland_surface_update_outputs_recursively (surface);
meta_wayland_compositor_repick (surface->compositor);
}
void
meta_xwayland_surface_associate_with_window (MetaXwaylandSurface *xwayland_surface,
MetaWindow *window)
@ -54,6 +114,7 @@ meta_xwayland_surface_associate_with_window (MetaXwaylandSurface *xwayland_surfa
META_WAYLAND_SURFACE_ROLE (xwayland_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaSurfaceActor *surface_actor;
MetaWindowActor *window_actor;
/*
@ -63,22 +124,40 @@ meta_xwayland_surface_associate_with_window (MetaXwaylandSurface *xwayland_surfa
*/
if (window->surface)
{
meta_wayland_surface_set_window (window->surface, NULL);
window->surface = NULL;
MetaXwaylandSurface *other_xwayland_surface;
other_xwayland_surface = META_XWAYLAND_SURFACE (window->surface->role);
clear_window (other_xwayland_surface);
}
window->surface = surface;
meta_wayland_surface_set_window (surface, window);
xwayland_surface->window = window;
surface_actor = meta_wayland_surface_get_actor (surface);
if (surface_actor)
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
xwayland_surface->unmanaging_handler_id =
g_signal_connect (window,
"unmanaging",
G_CALLBACK (window_unmanaging),
xwayland_surface);
xwayland_surface->position_changed_handler_id =
g_signal_connect (window,
"position-changed",
G_CALLBACK (window_position_changed),
surface);
xwayland_surface->effects_completed_handler_id =
g_signal_connect (meta_window_actor_from_window (window),
"effects-completed",
G_CALLBACK (window_actor_effects_completed),
surface);
g_signal_emit (xwayland_surface, signals[WINDOW_ASSOCIATED], 0);
window_actor = meta_window_actor_from_window (window);
if (window_actor)
{
MetaSurfaceActor *surface_actor;
surface_actor = meta_wayland_surface_get_actor (surface);
meta_window_actor_assign_surface_actor (window_actor, surface_actor);
}
meta_window_actor_assign_surface_actor (window_actor, surface_actor);
}
static void
@ -100,13 +179,12 @@ meta_xwayland_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaWindow *window;
MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role);
window = meta_wayland_surface_get_window (surface);
if (pending->newly_attached &&
surface->buffer_ref.buffer &&
window)
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
xwayland_surface->window)
meta_window_queue (xwayland_surface->window, META_QUEUE_CALC_SHOWING);
}
static void
@ -116,12 +194,10 @@ meta_xwayland_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_
float *out_sx,
float *out_sy)
{
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role);
MetaRectangle window_rect;
meta_window_get_buffer_rect (meta_wayland_surface_get_window (surface),
&window_rect);
meta_window_get_buffer_rect (xwayland_surface->window, &window_rect);
*out_sx = abs_x - window_rect.x;
*out_sy = abs_y - window_rect.y;
}
@ -132,6 +208,14 @@ meta_xwayland_surface_get_toplevel (MetaWaylandSurfaceRole *surface_role)
return meta_wayland_surface_role_get_surface (surface_role);
}
static MetaWindow *
meta_xwayland_surface_get_window (MetaWaylandSurfaceRole *surface_role)
{
MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role);
return xwayland_surface->window;
}
static double
meta_xwayland_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface)
{
@ -141,34 +225,22 @@ meta_xwayland_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface
static void
meta_xwayland_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (actor_surface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (actor_surface);
MetaWaylandActorSurfaceClass *actor_surface_class =
META_WAYLAND_ACTOR_SURFACE_CLASS (meta_xwayland_surface_parent_class);
if (meta_wayland_surface_get_window (surface))
if (xwayland_surface->window)
actor_surface_class->sync_actor_state (actor_surface);
}
static void
meta_xwayland_surface_finalize (GObject *object)
{
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (object);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (object);
GObjectClass *parent_object_class =
G_OBJECT_CLASS (meta_xwayland_surface_parent_class);
MetaWindow *window;
window = meta_wayland_surface_get_window (surface);
if (window)
{
meta_wayland_surface_set_window (surface, NULL);
window->surface = NULL;
}
clear_window (xwayland_surface);
parent_object_class->finalize (object);
}
@ -194,6 +266,7 @@ meta_xwayland_surface_class_init (MetaXwaylandSurfaceClass *klass)
surface_role_class->get_relative_coordinates =
meta_xwayland_surface_get_relative_coordinates;
surface_role_class->get_toplevel = meta_xwayland_surface_get_toplevel;
surface_role_class->get_window = meta_xwayland_surface_get_window;
actor_surface_class->get_geometry_scale =
meta_xwayland_surface_get_geometry_scale;