mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 18:09:49 +01:00
subcompositor: use wlr_surface_synced
This commit is contained in:
parent
1c3c24825f
commit
96aec06b0a
3 changed files with 84 additions and 20 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue