diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 3b87f0139..78f5266d4 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -197,7 +197,7 @@ meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor) meta_window_actor_get_surface (actor); MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface ( META_SURFACE_ACTOR_WAYLAND (surface_actor)); - GNode *root_node = surface->subsurface_branch_node; + GNode *root_node = surface->output_state.subsurface_branch_node; g_autoptr (GList) surface_actors = NULL; g_autoptr (GList) children = NULL; GList *l; diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index 362785c89..71ef652a8 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -273,7 +273,8 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor meta_shaped_texture_ensure_size_valid (stex); - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface_surface) { MetaWaylandActorSurface *actor_surface; @@ -417,7 +418,8 @@ meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface) meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (actor_surface)); MetaWaylandSurface *subsurface_surface; - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface_surface) { MetaWaylandActorSurface *actor_surface; diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index d000ccfd8..314adec27 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -1369,7 +1369,8 @@ pointer_can_grab_surface (MetaWaylandPointer *pointer, if (pointer->focus_surface == surface) return TRUE; - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface) { if (pointer_can_grab_surface (pointer, subsurface)) return TRUE; diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c index c2e8c5fc7..a98101a59 100644 --- a/src/wayland/meta-wayland-shell-surface.c +++ b/src/wayland/meta-wayland-shell-surface.c @@ -59,7 +59,8 @@ meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_su .height = meta_wayland_surface_get_height (surface), }; - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface_surface) { MetaWaylandSubsurface *subsurface; diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 23168bce1..d86e66ab0 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -50,7 +50,7 @@ transform_subsurface_position (MetaWaylandSurface *surface, *x += surface->sub.x; *y += surface->sub.y; - surface = surface->sub.parent; + surface = surface->output_state.parent; } while (surface); } @@ -60,8 +60,8 @@ should_show (MetaWaylandSurface *surface) { if (!surface->buffer_ref->buffer) return FALSE; - else if (surface->sub.parent) - return should_show (surface->sub.parent); + else if (surface->output_state.parent) + return should_show (surface->output_state.parent); else return TRUE; } @@ -96,14 +96,15 @@ static gboolean is_child (MetaWaylandSurface *surface, MetaWaylandSurface *sibling) { - return surface->sub.parent == sibling; + return surface->protocol_state.parent == sibling; } static gboolean is_sibling (MetaWaylandSurface *surface, MetaWaylandSurface *sibling) { - return surface != sibling && surface->sub.parent == sibling->sub.parent; + return surface != sibling && + surface->protocol_state.parent == sibling->protocol_state.parent; } void @@ -128,7 +129,8 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, if (surface->buffer_ref->buffer) meta_rectangle_union (out_geometry, &geometry, out_geometry); - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface_surface) { MetaWaylandSubsurface *subsurface; @@ -158,7 +160,7 @@ meta_wayland_subsurface_get_toplevel (MetaWaylandSurfaceRole *surface_role) { MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; + MetaWaylandSurface *parent = surface->output_state.parent; if (parent) return meta_wayland_surface_get_toplevel (parent); @@ -176,7 +178,7 @@ meta_wayland_subsurface_is_synchronized (MetaWaylandSurfaceRole *surface_role) if (surface->sub.synchronous) return TRUE; - parent = surface->sub.parent; + parent = surface->protocol_state.parent; if (parent) return meta_wayland_surface_is_synchronized (parent); @@ -188,7 +190,7 @@ meta_wayland_subsurface_notify_subsurface_state_changed (MetaWaylandSurfaceRole { MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; + MetaWaylandSurface *parent = surface->output_state.parent; if (parent) return meta_wayland_surface_notify_subsurface_state_changed (parent); @@ -201,13 +203,14 @@ meta_wayland_subsurface_get_geometry_scale (MetaWaylandActorSurface *actor_surfa META_WAYLAND_SURFACE_ROLE (actor_surface); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; + MetaWaylandSurface *parent = surface->output_state.parent; if (parent) { MetaWaylandActorSurface *parent_actor; - parent_actor = META_WAYLAND_ACTOR_SURFACE (surface->sub.parent->role); + parent_actor = + META_WAYLAND_ACTOR_SURFACE (surface->output_state.parent->role); return meta_wayland_actor_surface_get_geometry_scale (parent_actor); } else @@ -259,23 +262,6 @@ meta_wayland_subsurface_class_init (MetaWaylandSubsurfaceClass *klass) meta_wayland_subsurface_sync_actor_state; } -static void -wl_subsurface_destructor (struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - - g_node_unlink (surface->subsurface_branch_node); - - if (surface->sub.parent) - { - meta_wayland_surface_notify_subsurface_state_changed (surface->sub.parent); - wl_list_remove (&surface->sub.parent_destroy_listener.link); - surface->sub.parent = NULL; - } - - surface->wl_subsurface = NULL; -} - static void wl_subsurface_destroy (struct wl_client *client, struct wl_resource *resource) @@ -307,61 +293,57 @@ is_valid_sibling (MetaWaylandSurface *surface, return FALSE; } -static void -subsurface_handle_pending_subsurface_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandSubsurfacePlacementOp *op = - wl_container_of (listener, op, subsurface_destroy_listener); - - op->surface = NULL; - wl_list_remove (&op->subsurface_destroy_listener.link); -} - -static void -subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandSubsurfacePlacementOp *op = - wl_container_of (listener, op, sibling_destroy_listener); - - op->sibling = NULL; - wl_list_remove (&op->sibling_destroy_listener.link); -} - -void -meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op) -{ - if (op->surface) - wl_list_remove (&op->subsurface_destroy_listener.link); - if (op->sibling) - wl_list_remove (&op->sibling_destroy_listener.link); - g_free (op); -} - static void queue_subsurface_placement (MetaWaylandSurface *surface, MetaWaylandSurface *sibling, MetaWaylandSubsurfacePlacement placement) { - MetaWaylandSurface *parent = surface->sub.parent; + MetaWaylandSurface *parent = surface->protocol_state.parent; + gboolean have_synced_parent; + MetaWaylandTransaction *transaction; MetaWaylandSubsurfacePlacementOp *op = g_new0 (MetaWaylandSubsurfacePlacementOp, 1); + 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->surface = surface; op->sibling = sibling; - op->subsurface_destroy_listener.notify = - subsurface_handle_pending_subsurface_destroyed; - op->sibling_destroy_listener.notify = - subsurface_handle_pending_sibling_destroyed; - wl_resource_add_destroy_listener (surface->wl_subsurface, - &op->subsurface_destroy_listener); - wl_resource_add_destroy_listener (sibling->resource, - &op->sibling_destroy_listener); + op->surface = surface; - parent->pending_state->subsurface_placement_ops = - g_slist_append (parent->pending_state->subsurface_placement_ops, op); + g_node_unlink (surface->protocol_state.subsurface_branch_node); + + if (!sibling) + goto out; + + if (sibling == parent) + sibling_node = parent->protocol_state.subsurface_leaf_node; + else + sibling_node = sibling->protocol_state.subsurface_branch_node; + + switch (placement) + { + case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: + g_node_insert_after (parent->protocol_state.subsurface_branch_node, + sibling_node, + surface->protocol_state.subsurface_branch_node); + break; + case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: + g_node_insert_before (parent->protocol_state.subsurface_branch_node, + sibling_node, + surface->protocol_state.subsurface_branch_node); + break; + } + +out: + meta_wayland_transaction_add_placement_op (transaction, parent, op); + + if (!have_synced_parent) + meta_wayland_transaction_commit (transaction); } static void @@ -408,6 +390,25 @@ wl_subsurface_place_below (struct wl_client *client, META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); } +static void +wl_subsurface_destructor (struct wl_resource *resource) +{ + MetaWaylandSurface *surface = wl_resource_get_user_data (resource); + + if (surface->protocol_state.parent) + { + queue_subsurface_placement (surface, NULL, + META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); + surface->protocol_state.parent = NULL; + } + else + { + g_node_unlink (surface->protocol_state.subsurface_branch_node); + } + + surface->wl_subsurface = NULL; +} + static void wl_subsurface_set_sync (struct wl_client *client, struct wl_resource *resource) @@ -428,7 +429,8 @@ meta_wayland_subsurface_parent_desynced (MetaWaylandSurface *surface) if (surface->sub.transaction) meta_wayland_transaction_commit (g_steal_pointer (&surface->sub.transaction)); - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->protocol_state, + subsurface_surface) meta_wayland_subsurface_parent_desynced (subsurface_surface); } @@ -463,17 +465,12 @@ wl_subcompositor_destroy (struct wl_client *client, wl_resource_destroy (resource); } -static void -surface_handle_parent_surface_destroyed (struct wl_listener *listener, - void *data) +void +meta_wayland_subsurface_parent_destroyed (MetaWaylandSurface *surface) { - MetaWaylandSurface *surface = wl_container_of (listener, - surface, - sub.parent_destroy_listener); - - g_node_unlink (surface->subsurface_branch_node); - surface->sub.parent = NULL; - wl_list_remove (&surface->sub.parent_destroy_listener.link); + queue_subsurface_placement (surface, NULL, + META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); + surface->protocol_state.parent = NULL; } static gboolean @@ -482,8 +479,8 @@ is_same_or_ancestor (MetaWaylandSurface *surface, { if (surface == other_surface) return TRUE; - if (other_surface->sub.parent) - return is_same_or_ancestor (surface, other_surface->sub.parent); + if (other_surface->protocol_state.parent) + return is_same_or_ancestor (surface, other_surface->protocol_state.parent); return FALSE; } @@ -496,6 +493,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client, { MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); + MetaWaylandSurface *reference; MetaWindow *toplevel_window; if (surface->wl_subsurface) @@ -542,16 +540,12 @@ wl_subcompositor_get_subsurface (struct wl_client *client, wl_subsurface_destructor); surface->sub.synchronous = TRUE; - surface->sub.parent = parent; - surface->sub.parent_destroy_listener.notify = - surface_handle_parent_surface_destroyed; - wl_resource_add_destroy_listener (parent->resource, - &surface->sub.parent_destroy_listener); + surface->protocol_state.parent = parent; - g_node_append (parent->subsurface_branch_node, - surface->subsurface_branch_node); - - meta_wayland_surface_notify_subsurface_state_changed (parent); + reference = + g_node_last_child (parent->protocol_state.subsurface_branch_node)->data; + queue_subsurface_placement (surface, reference, + META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE); } static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = { diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h index 5fa2999db..61338e921 100644 --- a/src/wayland/meta-wayland-subsurface.h +++ b/src/wayland/meta-wayland-subsurface.h @@ -40,8 +40,6 @@ typedef struct MetaWaylandSubsurfacePlacement placement; MetaWaylandSurface *surface; MetaWaylandSurface *sibling; - struct wl_listener subsurface_destroy_listener; - struct wl_listener sibling_destroy_listener; } MetaWaylandSubsurfacePlacementOp; void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, @@ -49,7 +47,7 @@ void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, int parent_y, MetaRectangle *out_geometry); -void meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op); +void meta_wayland_subsurface_parent_destroyed (MetaWaylandSurface *surface); void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 1752cde8f..f5487936d 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -526,11 +526,7 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) wl_resource_destroy (cb->resource); if (state->subsurface_placement_ops) - { - g_slist_free_full ( - state->subsurface_placement_ops, - (GDestroyNotify) meta_wayland_subsurface_placement_op_free); - } + g_slist_free_full (state->subsurface_placement_ops, g_free); meta_wayland_surface_state_discard_presentation_feedback (state); } @@ -714,6 +710,49 @@ meta_wayland_surface_discard_presentation_feedback (MetaWaylandSurface *surface) } } +void +meta_wayland_surface_apply_placement_ops (MetaWaylandSurface *parent, + MetaWaylandSurfaceState *state) +{ + GSList *l; + + for (l = state->subsurface_placement_ops; l; l = l->next) + { + MetaWaylandSubsurfacePlacementOp *op = l->data; + MetaWaylandSurface *surface = op->surface; + GNode *sibling_node; + + g_node_unlink (surface->output_state.subsurface_branch_node); + + if (!op->sibling) + { + surface->output_state.parent = NULL; + continue; + } + + surface->output_state.parent = parent; + + if (op->sibling == parent) + sibling_node = parent->output_state.subsurface_leaf_node; + else + sibling_node = op->sibling->output_state.subsurface_branch_node; + + switch (op->placement) + { + case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: + g_node_insert_after (parent->output_state.subsurface_branch_node, + sibling_node, + surface->output_state.subsurface_branch_node); + break; + case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: + g_node_insert_before (parent->output_state.subsurface_branch_node, + sibling_node, + surface->output_state.subsurface_branch_node); + break; + } + } +} + void meta_wayland_surface_apply_state (MetaWaylandSurface *surface, MetaWaylandSurfaceState *state) @@ -908,41 +947,7 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, } if (state->subsurface_placement_ops) - { - GSList *l; - - for (l = state->subsurface_placement_ops; l; l = l->next) - { - MetaWaylandSubsurfacePlacementOp *op = l->data; - GNode *sibling_node; - - if (!op->surface || !op->sibling) - continue; - - if (op->sibling == surface) - sibling_node = surface->subsurface_leaf_node; - else - sibling_node = op->sibling->subsurface_branch_node; - - g_node_unlink (op->surface->subsurface_branch_node); - - switch (op->placement) - { - case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: - g_node_insert_after (surface->subsurface_branch_node, - sibling_node, - op->surface->subsurface_branch_node); - break; - case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: - g_node_insert_before (surface->subsurface_branch_node, - sibling_node, - op->surface->subsurface_branch_node); - break; - } - } - - meta_wayland_surface_notify_subsurface_state_changed (surface); - } + meta_wayland_surface_notify_subsurface_state_changed (surface); cleanup: /* If we have a buffer that we are not using, decrease the use count so it may @@ -1012,7 +1017,8 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) meta_wayland_transaction_merge_pending_state (transaction, surface); - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->protocol_state, + subsurface_surface) { if (!subsurface_surface->sub.transaction) continue; @@ -1501,7 +1507,7 @@ meta_wayland_surface_finalize (GObject *object) meta_wayland_surface_discard_presentation_feedback (surface); - g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy); + g_clear_pointer (&surface->output_state.subsurface_branch_node, g_node_destroy); g_hash_table_destroy (surface->shortcut_inhibited_seats); @@ -1512,6 +1518,7 @@ static void wl_surface_destructor (struct wl_resource *resource) { MetaWaylandSurface *surface = wl_resource_get_user_data (resource); + MetaWaylandSurface *subsurface_surface; g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0); @@ -1521,7 +1528,12 @@ wl_surface_destructor (struct wl_resource *resource) if (surface->resource) wl_resource_set_user_data (g_steal_pointer (&surface->resource), NULL); + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->protocol_state, + subsurface_surface) + meta_wayland_subsurface_parent_destroyed (subsurface_surface); + g_clear_pointer (&surface->wl_subsurface, wl_resource_destroy); + g_clear_pointer (&surface->protocol_state.subsurface_branch_node, g_node_destroy); /* * Any transactions referencing this surface will keep it alive until they get @@ -1758,9 +1770,13 @@ meta_wayland_surface_init (MetaWaylandSurface *surface) surface->buffer_ref = meta_wayland_buffer_ref_new (); - surface->subsurface_branch_node = g_node_new (surface); - surface->subsurface_leaf_node = - g_node_prepend_data (surface->subsurface_branch_node, surface); + surface->output_state.subsurface_branch_node = g_node_new (surface); + surface->output_state.subsurface_leaf_node = + g_node_prepend_data (surface->output_state.subsurface_branch_node, surface); + + surface->protocol_state.subsurface_branch_node = g_node_new (surface); + surface->protocol_state.subsurface_leaf_node = + g_node_prepend_data (surface->protocol_state.subsurface_branch_node, surface); } static void diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 1f5eb4f63..7aab3f2c7 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -166,8 +166,6 @@ struct _MetaWaylandSurface cairo_region_t *opaque_region; int scale; int32_t offset_x, offset_y; - GNode *subsurface_branch_node; - GNode *subsurface_leaf_node; GHashTable *outputs; MetaMonitorTransform buffer_transform; @@ -192,14 +190,17 @@ struct _MetaWaylandSurface /* All the pending state that wl_surface.commit will apply. */ MetaWaylandSurfaceState *pending_state; + struct MetaWaylandSurfaceSubState { + MetaWaylandSurface *parent; + GNode *subsurface_branch_node; + GNode *subsurface_leaf_node; + } output_state, protocol_state; + /* Extension resources. */ struct wl_resource *wl_subsurface; /* wl_subsurface stuff. */ struct { - MetaWaylandSurface *parent; - struct wl_listener parent_destroy_listener; - int x; int y; @@ -274,6 +275,9 @@ void meta_wayland_surface_state_reset (MetaWaylandSurfaceState *s void meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, MetaWaylandSurfaceState *to); +void meta_wayland_surface_apply_placement_ops (MetaWaylandSurface *surface, + MetaWaylandSurfaceState *state); + void meta_wayland_surface_apply_state (MetaWaylandSurface *surface, MetaWaylandSurfaceState *state); @@ -415,11 +419,11 @@ meta_get_next_subsurface_sibling (GNode *n) } static inline GNode * -meta_get_first_subsurface_node (MetaWaylandSurface *surface) +meta_get_first_subsurface_node (struct MetaWaylandSurfaceSubState *sub) { GNode *n; - n = g_node_first_child (surface->subsurface_branch_node); + n = g_node_first_child (sub->subsurface_branch_node); if (!n) return NULL; else if (!G_NODE_IS_LEAF (n)) @@ -428,9 +432,11 @@ meta_get_first_subsurface_node (MetaWaylandSurface *surface) return meta_get_next_subsurface_sibling (n); } -#define META_WAYLAND_SURFACE_FOREACH_SUBSURFACE(surface, subsurface) \ - for (GNode *G_PASTE(__n, __LINE__) = meta_get_first_subsurface_node ((surface)); \ +#define META_WAYLAND_SURFACE_FOREACH_SUBSURFACE(state, subsurface) \ + for (GNode *G_PASTE(__n, __LINE__) = meta_get_first_subsurface_node (state), \ + *G_PASTE(__next, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__)); \ (subsurface = (G_PASTE (__n, __LINE__) ? G_PASTE (__n, __LINE__)->data : NULL)); \ - G_PASTE (__n, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__))) + G_PASTE (__n, __LINE__) = G_PASTE (__next, __LINE__), \ + G_PASTE (__next, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__))) #endif diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c index 27d31a5b2..ef5358947 100644 --- a/src/wayland/meta-wayland-tablet-tool.c +++ b/src/wayland/meta-wayland-tablet-tool.c @@ -899,7 +899,8 @@ tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, if (tool->focus_surface == surface) return TRUE; - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, + subsurface) { if (tablet_tool_can_grab_surface (tool, subsurface)) return TRUE; diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c index fdc3cad12..56aaf3923 100644 --- a/src/wayland/meta-wayland-transaction.c +++ b/src/wayland/meta-wayland-transaction.c @@ -24,7 +24,6 @@ #include "wayland/meta-wayland-transaction.h" #include "wayland/meta-wayland.h" -#include "wayland/meta-wayland-subsurface.h" #define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE) @@ -67,7 +66,7 @@ meta_wayland_transaction_sync_child_states (MetaWaylandSurface *surface) { MetaWaylandSurface *subsurface_surface; - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) + META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->output_state, subsurface_surface) { MetaWaylandSubsurface *subsurface; MetaWaylandActorSurface *actor_surface; @@ -95,7 +94,9 @@ is_ancestor (MetaWaylandSurface *candidate, { MetaWaylandSurface *ancestor; - for (ancestor = reference->sub.parent; ancestor; ancestor = ancestor->sub.parent) + for (ancestor = reference->output_state.parent; + ancestor; + ancestor = ancestor->output_state.parent) { if (ancestor == candidate) return TRUE; @@ -112,7 +113,7 @@ meta_wayland_transaction_compare (const void *key1, MetaWaylandSurface *surface2 = *(MetaWaylandSurface **) key2; /* Order of siblings doesn't matter */ - if (surface1->sub.parent == surface2->sub.parent) + if (surface1->output_state.parent == surface2->output_state.parent) return 0; /* Ancestor surfaces come before descendant surfaces */ @@ -156,12 +157,25 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction, g_autofree MetaWaylandSurface **surfaces = NULL; g_autofree MetaWaylandSurfaceState **states = NULL; unsigned int num_surfaces; + MetaWaylandSurface *surface; + MetaWaylandTransactionEntry *entry; int i; surfaces = (MetaWaylandSurface **) g_hash_table_get_keys_as_array (transaction->entries, &num_surfaces); states = g_new (MetaWaylandSurfaceState *, num_surfaces); + /* Apply sub-surface states to ensure output surface hierarchy is up to date */ + for (i = 0; i < num_surfaces; i++) + { + surface = surfaces[i]; + entry = meta_wayland_transaction_get_entry (transaction, surface); + meta_wayland_transaction_apply_subsurface_position (surface, entry); + + if (entry->state && entry->state->subsurface_placement_ops) + meta_wayland_surface_apply_placement_ops (surface, entry->state); + } + /* Sort surfaces from ancestors to descendants */ qsort (surfaces, num_surfaces, sizeof (MetaWaylandSurface *), meta_wayland_transaction_compare); @@ -169,12 +183,10 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction, /* Apply states from ancestors to descendants */ for (i = 0; i < num_surfaces; i++) { - MetaWaylandSurface *surface = surfaces[i]; - MetaWaylandTransactionEntry *entry; - + surface = surfaces[i]; entry = meta_wayland_transaction_get_entry (transaction, surface); + states[i] = entry->state; - meta_wayland_transaction_apply_subsurface_position (surface, entry); if (entry->state) meta_wayland_surface_apply_state (surface, entry->state); @@ -314,7 +326,6 @@ meta_wayland_transaction_entry_free (MetaWaylandTransactionEntry *entry) static void meta_wayland_transaction_add_placement_surfaces (MetaWaylandTransaction *transaction, - MetaWaylandSurface *surface, MetaWaylandSurfaceState *state) { GSList *l; @@ -323,8 +334,7 @@ meta_wayland_transaction_add_placement_surfaces (MetaWaylandTransaction *transa { MetaWaylandSubsurfacePlacementOp *op = l->data; - if (op->surface) - meta_wayland_transaction_ensure_entry (transaction, op->surface); + meta_wayland_transaction_ensure_entry (transaction, op->surface); if (op->sibling) meta_wayland_transaction_ensure_entry (transaction, op->sibling); @@ -339,10 +349,27 @@ meta_wayland_transaction_add_entry (MetaWaylandTransaction *transaction, g_hash_table_insert (transaction->entries, g_object_ref (surface), entry); if (entry->state) - { - meta_wayland_transaction_add_placement_surfaces (transaction, surface, - entry->state); - } + meta_wayland_transaction_add_placement_surfaces (transaction, entry->state); +} + +void +meta_wayland_transaction_add_placement_op (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + MetaWaylandSubsurfacePlacementOp *op) +{ + MetaWaylandTransactionEntry *entry; + MetaWaylandSurfaceState *state; + + entry = meta_wayland_transaction_ensure_entry (transaction, surface); + + if (!entry->state) + entry->state = meta_wayland_surface_state_new (); + + state = entry->state; + state->subsurface_placement_ops = + g_slist_append (state->subsurface_placement_ops, op); + + meta_wayland_transaction_add_placement_surfaces (transaction, state); } void @@ -402,10 +429,7 @@ meta_wayland_transaction_merge_into (MetaWaylandTransaction *from, } if (from_entry->state) - { - meta_wayland_transaction_add_placement_surfaces (to, surface, - from_entry->state); - } + meta_wayland_transaction_add_placement_surfaces (to, from_entry->state); meta_wayland_transaction_entry_merge_into (from_entry, to_entry); g_hash_table_iter_remove (&iter); diff --git a/src/wayland/meta-wayland-transaction.h b/src/wayland/meta-wayland-transaction.h index 720af1f56..e05ff001a 100644 --- a/src/wayland/meta-wayland-transaction.h +++ b/src/wayland/meta-wayland-transaction.h @@ -21,9 +21,14 @@ #define META_WAYLAND_TRANSACTION_H #include "wayland/meta-wayland-types.h" +#include "wayland/meta-wayland-subsurface.h" void meta_wayland_transaction_commit (MetaWaylandTransaction *transaction); +void meta_wayland_transaction_add_placement_op (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + MetaWaylandSubsurfacePlacementOp *op); + void meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transaction, MetaWaylandSurface *surface, int x,