wayland/subsurface: Hook up sub-surface placement ops in callers

wl_subsurface_place_above/below need to hook it up to the parent
surface's pending state, so that it gets picked up next time the parent
is committed.

v2:
* Adapt to wl_subsurface_destructor not resetting sub-surface position

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3364>
This commit is contained in:
Michel Dänzer 2023-11-03 16:10:19 +01:00 committed by Marge Bot
parent 6718e267fb
commit a2863fc1ea

View File

@ -306,24 +306,16 @@ is_valid_sibling (MetaWaylandSurface *surface,
return FALSE; return FALSE;
} }
static void static MetaWaylandSubsurfacePlacementOp *
queue_subsurface_placement (MetaWaylandSurface *surface, get_subsurface_placement_op (MetaWaylandSurface *surface,
MetaWaylandSurface *sibling, MetaWaylandSurface *sibling,
MetaWaylandSubsurfacePlacement placement) MetaWaylandSubsurfacePlacement placement)
{ {
MetaWaylandSurface *parent = surface->protocol_state.parent; MetaWaylandSurface *parent = surface->protocol_state.parent;
gboolean have_synced_parent;
MetaWaylandTransaction *transaction;
MetaWaylandSubsurfacePlacementOp *op = MetaWaylandSubsurfacePlacementOp *op =
g_new0 (MetaWaylandSubsurfacePlacementOp, 1); g_new0 (MetaWaylandSubsurfacePlacementOp, 1);
GNode *sibling_node; GNode *sibling_node;
have_synced_parent = sibling && meta_wayland_surface_is_synchronized (parent);
if (have_synced_parent)
transaction = meta_wayland_surface_ensure_transaction (parent);
else
transaction = meta_wayland_transaction_new (surface->compositor);
op->placement = placement; op->placement = placement;
op->sibling = sibling; op->sibling = sibling;
op->surface = surface; op->surface = surface;
@ -331,7 +323,7 @@ queue_subsurface_placement (MetaWaylandSurface *surface,
g_node_unlink (surface->protocol_state.subsurface_branch_node); g_node_unlink (surface->protocol_state.subsurface_branch_node);
if (!sibling) if (!sibling)
goto out; return op;
if (sibling == parent) if (sibling == parent)
sibling_node = parent->protocol_state.subsurface_leaf_node; sibling_node = parent->protocol_state.subsurface_leaf_node;
@ -352,11 +344,39 @@ queue_subsurface_placement (MetaWaylandSurface *surface,
break; break;
} }
out: return op;
meta_wayland_transaction_add_placement_op (transaction, parent, op); }
if (!have_synced_parent) static void
meta_wayland_transaction_commit (transaction); subsurface_place (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *sibling_resource,
MetaWaylandSubsurfacePlacement placement)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
MetaWaylandSurfaceState *pending_state;
MetaWaylandSubsurfacePlacementOp *op;
if (!is_valid_sibling (surface, sibling))
{
wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE,
"wl_subsurface::place_%s: wl_surface@%d is "
"not a valid parent or sibling",
placement == META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE ?
"above" : "below",
wl_resource_get_id (sibling->resource));
return;
}
op = get_subsurface_placement_op (surface,
sibling,
placement);
pending_state =
meta_wayland_surface_get_pending_state (surface->protocol_state.parent);
pending_state->subsurface_placement_ops =
g_slist_append (pending_state->subsurface_placement_ops, op);
} }
static void static void
@ -364,20 +384,7 @@ wl_subsurface_place_above (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *sibling_resource) struct wl_resource *sibling_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); subsurface_place (client, resource, sibling_resource,
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
{
wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE,
"wl_subsurface::place_above: wl_surface@%d is "
"not a valid parent or sibling",
wl_resource_get_id (sibling->resource));
return;
}
queue_subsurface_placement (surface,
sibling,
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE); META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE);
} }
@ -386,20 +393,7 @@ wl_subsurface_place_below (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *sibling_resource) struct wl_resource *sibling_resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); subsurface_place (client, resource, sibling_resource,
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
{
wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE,
"wl_subsurface::place_below: wl_surface@%d is "
"not a valid parent or sibling",
wl_resource_get_id (sibling->resource));
return;
}
queue_subsurface_placement (surface,
sibling,
META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW);
} }
@ -407,11 +401,20 @@ static void
wl_subsurface_destructor (struct wl_resource *resource) wl_subsurface_destructor (struct wl_resource *resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *parent = surface->protocol_state.parent;
if (surface->protocol_state.parent) if (parent)
{ {
queue_subsurface_placement (surface, NULL, MetaWaylandSubsurfacePlacementOp *op;
MetaWaylandTransaction *transaction;
op = get_subsurface_placement_op (surface, NULL,
META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW);
transaction = meta_wayland_transaction_new (surface->compositor);
meta_wayland_transaction_add_placement_op (transaction, parent, op);
meta_wayland_transaction_commit (transaction);
surface->protocol_state.parent = NULL; surface->protocol_state.parent = NULL;
} }
else else
@ -481,8 +484,16 @@ wl_subcompositor_destroy (struct wl_client *client,
void void
meta_wayland_subsurface_parent_destroyed (MetaWaylandSurface *surface) meta_wayland_subsurface_parent_destroyed (MetaWaylandSurface *surface)
{ {
queue_subsurface_placement (surface, NULL, MetaWaylandSurface *parent = surface->protocol_state.parent;
MetaWaylandTransaction *transaction;
MetaWaylandSubsurfacePlacementOp *op;
transaction = meta_wayland_transaction_new (surface->compositor);
op = get_subsurface_placement_op (surface, NULL,
META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW);
meta_wayland_transaction_add_placement_op (transaction, parent, op);
meta_wayland_transaction_commit (transaction);
surface->protocol_state.parent = NULL; surface->protocol_state.parent = NULL;
} }
@ -506,6 +517,8 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
MetaWaylandSurfaceState *pending_state;
MetaWaylandSubsurfacePlacementOp *op;
MetaWaylandSurface *reference; MetaWaylandSurface *reference;
MetaWindow *toplevel_window; MetaWindow *toplevel_window;
@ -559,8 +572,12 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
reference = reference =
g_node_last_child (parent->protocol_state.subsurface_branch_node)->data; g_node_last_child (parent->protocol_state.subsurface_branch_node)->data;
queue_subsurface_placement (surface, reference, op = get_subsurface_placement_op (surface, reference,
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE); META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE);
pending_state = meta_wayland_surface_get_pending_state (parent);
pending_state->subsurface_placement_ops =
g_slist_append (pending_state->subsurface_placement_ops, op);
} }
static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = { static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = {