diff options
-rw-r--r-- | include/wlr/types/wlr_subcompositor.h | 15 | ||||
-rw-r--r-- | types/wlr_compositor.c | 26 | ||||
-rw-r--r-- | types/wlr_subcompositor.c | 63 |
3 files changed, 84 insertions, 20 deletions
diff --git a/include/wlr/types/wlr_subcompositor.h b/include/wlr/types/wlr_subcompositor.h index d20fef94..63323da6 100644 --- a/include/wlr/types/wlr_subcompositor.h +++ b/include/wlr/types/wlr_subcompositor.h @@ -12,8 +12,7 @@ #include <stdbool.h> #include <stdint.h> #include <wayland-server-core.h> - -struct wlr_surface; +#include <wlr/types/wlr_compositor.h> /** * The sub-surface state describing the sub-surface's relationship with its @@ -23,6 +22,10 @@ struct wlr_surface; struct wlr_subsurface_parent_state { int32_t x, y; struct wl_list link; + + // private state + + struct wlr_surface_synced *synced; }; struct wlr_subsurface { @@ -47,6 +50,14 @@ struct wlr_subsurface { } events; void *data; + + // private state + + struct wlr_surface_synced parent_synced; + + struct { + int32_t x, y; + } previous; }; struct wlr_subcompositor { diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index c3cc59a3..8f188302 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -371,6 +371,19 @@ static void surface_state_move(struct wlr_surface_state *state, state_synced[synced->index], next_synced[synced->index]); } + // commit subsurface order + struct wlr_subsurface_parent_state *sub_state_next, *sub_state; + wl_list_for_each(sub_state_next, &next->subsurfaces_below, link) { + sub_state = wlr_surface_synced_get_state(sub_state_next->synced, state); + wl_list_remove(&sub_state->link); + wl_list_insert(state->subsurfaces_below.prev, &sub_state->link); + } + wl_list_for_each(sub_state_next, &next->subsurfaces_above, link) { + sub_state = wlr_surface_synced_get_state(sub_state_next->synced, state); + wl_list_remove(&sub_state->link); + wl_list_insert(state->subsurfaces_above.prev, &sub_state->link); + } + state->committed = next->committed; next->committed = 0; @@ -523,20 +536,11 @@ static void surface_commit_state(struct wlr_surface *surface, surface_update_opaque_region(surface); surface_update_input_region(surface); - // commit subsurface order struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->pending.subsurfaces_below, pending.link) { - wl_list_remove(&subsurface->current.link); - wl_list_insert(surface->current.subsurfaces_below.prev, - &subsurface->current.link); - + wl_list_for_each(subsurface, &surface->current.subsurfaces_below, current.link) { subsurface_handle_parent_commit(subsurface); } - wl_list_for_each(subsurface, &surface->pending.subsurfaces_above, pending.link) { - wl_list_remove(&subsurface->current.link); - wl_list_insert(surface->current.subsurfaces_above.prev, - &subsurface->current.link); - + wl_list_for_each(subsurface, &surface->current.subsurfaces_above, current.link) { subsurface_handle_parent_commit(subsurface); } diff --git a/types/wlr_subcompositor.c b/types/wlr_subcompositor.c index c66d6f1d..07ff2b27 100644 --- a/types/wlr_subcompositor.c +++ b/types/wlr_subcompositor.c @@ -33,9 +33,9 @@ static void subsurface_destroy(struct wlr_subsurface *subsurface) { wl_signal_emit_mutable(&subsurface->events.destroy, subsurface); + wlr_surface_synced_finish(&subsurface->parent_synced); + wl_list_remove(&subsurface->surface_client_commit.link); - wl_list_remove(&subsurface->current.link); - wl_list_remove(&subsurface->pending.link); wl_list_remove(&subsurface->parent_destroy.link); wl_resource_set_user_data(subsurface->resource, NULL); @@ -225,6 +225,33 @@ const struct wlr_surface_role subsurface_role = { .destroy = subsurface_role_destroy, }; +static void surface_synced_init_state(void *_state) { + struct wlr_subsurface_parent_state *state = _state; + wl_list_init(&state->link); +} + +static void surface_synced_finish_state(void *_state) { + struct wlr_subsurface_parent_state *state = _state; + wl_list_remove(&state->link); +} + +static void surface_synced_move_state(void *_dst, void *_src) { + struct wlr_subsurface_parent_state *dst = _dst, *src = _src; + dst->x = src->x; + dst->y = src->y; + dst->synced = src->synced; + + // For the sake of simplicity, copying the position in list is done by the + // parent itself +} + +static struct wlr_surface_synced_impl surface_synced_impl = { + .state_size = sizeof(struct wlr_subsurface_parent_state), + .init_state = surface_synced_init_state, + .finish_state = surface_synced_finish_state, + .move_state = surface_synced_move_state, +}; + static void subsurface_handle_parent_destroy(struct wl_listener *listener, void *data) { struct wlr_subsurface *subsurface = @@ -267,8 +294,8 @@ static void collect_damage_iter(struct wlr_surface *surface, void subsurface_handle_parent_commit(struct wlr_subsurface *subsurface) { struct wlr_surface *surface = subsurface->surface; - bool moved = subsurface->current.x != subsurface->pending.x || - subsurface->current.y != subsurface->pending.y; + bool moved = subsurface->current.x != subsurface->previous.x || + subsurface->current.y != subsurface->previous.y; if (subsurface->surface->mapped && moved) { wlr_surface_for_each_surface(surface, collect_damage_iter, subsurface); @@ -279,8 +306,6 @@ void subsurface_handle_parent_commit(struct wlr_subsurface *subsurface) { subsurface->has_cache = false; } - subsurface->current.x = subsurface->pending.x; - subsurface->current.y = subsurface->pending.y; if (subsurface->surface->mapped && (moved || subsurface->reordered)) { subsurface->reordered = false; wlr_surface_for_each_surface(surface, @@ -293,6 +318,9 @@ void subsurface_handle_parent_commit(struct wlr_subsurface *subsurface) { subsurface); subsurface_consider_map(subsurface); } + + subsurface->previous.x = subsurface->current.x; + subsurface->previous.y = subsurface->current.y; } struct wlr_subsurface *wlr_subsurface_try_from_wlr_surface(struct wlr_surface *surface) { @@ -335,11 +363,19 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client, return; } + if (!wlr_surface_synced_init(&subsurface->parent_synced, parent, &surface_synced_impl, + &subsurface->pending, &subsurface->current)) { + free(subsurface); + wl_client_post_no_memory(client); + return; + } + subsurface->synchronized = true; subsurface->surface = surface; subsurface->resource = wl_resource_create(client, &wl_subsurface_interface, wl_resource_get_version(resource), id); if (subsurface->resource == NULL) { + wlr_surface_synced_finish(&subsurface->parent_synced); free(subsurface); wl_client_post_no_memory(client); return; @@ -347,6 +383,19 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client, wl_resource_set_implementation(subsurface->resource, &subsurface_implementation, subsurface, NULL); + // In surface_state_move() we commit sub-surface order. To do so we need to + // iterate over the list of sub-surfaces from a struct wlr_surface_state. + // Store a pointer to struct wlr_surface_synced to facilitate this. + subsurface->pending.synced = &subsurface->parent_synced; + subsurface->current.synced = &subsurface->parent_synced; + + struct wlr_surface_state *cached; + wl_list_for_each(cached, &parent->cached, cached_state_link) { + struct wlr_subsurface_parent_state *sub_state = + wlr_surface_synced_get_state(&subsurface->parent_synced, cached); + sub_state->synced = &subsurface->parent_synced; + } + wlr_surface_set_role_object(surface, subsurface->resource); wl_signal_init(&subsurface->events.destroy); @@ -361,7 +410,7 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client, wl_signal_add(&parent->events.destroy, &subsurface->parent_destroy); subsurface->parent_destroy.notify = subsurface_handle_parent_destroy; - wl_list_init(&subsurface->current.link); + wl_list_remove(&subsurface->pending.link); wl_list_insert(parent->pending.subsurfaces_above.prev, &subsurface->pending.link); } |