diff --git a/include/wlr/types/wlr_xdg_decoration_v1.h b/include/wlr/types/wlr_xdg_decoration_v1.h index b36515595..df11616ef 100644 --- a/include/wlr/types/wlr_xdg_decoration_v1.h +++ b/include/wlr/types/wlr_xdg_decoration_v1.h @@ -2,6 +2,7 @@ #define WLR_TYPES_WLR_XDG_DECORATION_V1 #include +#include #include enum wlr_xdg_toplevel_decoration_v1_mode { @@ -32,6 +33,8 @@ struct wlr_xdg_toplevel_decoration_v1_configure { struct wlr_xdg_toplevel_decoration_v1_state { enum wlr_xdg_toplevel_decoration_v1_mode mode; + + struct wlr_surface_synced_state synced_state; }; struct wlr_xdg_toplevel_decoration_v1 { @@ -49,16 +52,17 @@ struct wlr_xdg_toplevel_decoration_v1 { struct wl_list configure_list; // wlr_xdg_toplevel_decoration_v1_configure::link + struct wlr_surface_synced synced; + + struct wl_listener surface_configure; + struct wl_listener surface_ack_configure; + struct wl_listener surface_commit; + struct { struct wl_signal destroy; struct wl_signal request_mode; } events; - struct wl_listener surface_destroy; - struct wl_listener surface_configure; - struct wl_listener surface_ack_configure; - struct wl_listener surface_commit; - void *data; }; diff --git a/types/wlr_xdg_decoration_v1.c b/types/wlr_xdg_decoration_v1.c index d0f969f45..feb200b5f 100644 --- a/types/wlr_xdg_decoration_v1.c +++ b/types/wlr_xdg_decoration_v1.c @@ -63,8 +63,8 @@ static void toplevel_decoration_handle_resource_destroy( struct wlr_xdg_toplevel_decoration_v1 *decoration = toplevel_decoration_from_resource(resource); wlr_signal_emit_safe(&decoration->events.destroy, decoration); + wlr_surface_synced_finish(&decoration->synced); wl_list_remove(&decoration->surface_commit.link); - wl_list_remove(&decoration->surface_destroy.link); wl_list_remove(&decoration->surface_configure.link); wl_list_remove(&decoration->surface_ack_configure.link); struct wlr_xdg_toplevel_decoration_v1_configure *configure, *tmp; @@ -75,13 +75,6 @@ static void toplevel_decoration_handle_resource_destroy( free(decoration); } -static void toplevel_decoration_handle_surface_destroy( - struct wl_listener *listener, void *data) { - struct wlr_xdg_toplevel_decoration_v1 *decoration = - wl_container_of(listener, decoration, surface_destroy); - wl_resource_destroy(decoration->resource); -} - static void toplevel_decoration_handle_surface_configure( struct wl_listener *listener, void *data) { struct wlr_xdg_toplevel_decoration_v1 *decoration = @@ -144,8 +137,6 @@ static void toplevel_decoration_handle_surface_commit( wl_container_of(listener, decoration, surface_commit); struct wlr_xdg_decoration_manager_v1 *manager = decoration->manager; - decoration->current = decoration->pending; - if (decoration->surface->added && !decoration->added) { decoration->added = true; wlr_signal_emit_safe(&manager->events.new_toplevel_decoration, @@ -153,6 +144,47 @@ static void toplevel_decoration_handle_surface_commit( } } +static void xdg_toplevel_decoration_synced_destroy(struct wlr_surface_synced *synced) { + struct wlr_xdg_toplevel_decoration_v1 *decoration = + wl_container_of(synced, decoration, synced); + wl_resource_destroy(decoration->resource); +} + +static void xdg_toplevel_decoration_synced_squash_state( + struct wlr_surface_synced_state *synced_dst, + struct wlr_surface_synced_state *synced_src) { + struct wlr_xdg_toplevel_decoration_v1_state *dst = + wl_container_of(synced_dst, dst, synced_state); + struct wlr_xdg_toplevel_decoration_v1_state *src = + wl_container_of(synced_src, src, synced_state); + + dst->mode = src->mode; +} + +static struct wlr_surface_synced_state *xdg_toplevel_decoration_synced_create_state(void) { + struct wlr_xdg_toplevel_decoration_v1_state *state = + calloc(1, sizeof(*state)); + if (!state) { + return NULL; + } + return &state->synced_state; +} + +static void xdg_toplevel_decoration_synced_destroy_state( + struct wlr_surface_synced_state *synced_state) { + struct wlr_xdg_toplevel_decoration_v1_state *state = + wl_container_of(synced_state, state, synced_state); + free(state); +} + +static const struct wlr_surface_synced_interface xdg_toplevel_decoration_synced_impl = { + .name = "wlr_xdg_toplevel_decoration", + .destroy = xdg_toplevel_decoration_synced_destroy, + .squash_state = xdg_toplevel_decoration_synced_squash_state, + .create_state = xdg_toplevel_decoration_synced_create_state, + .destroy_state = xdg_toplevel_decoration_synced_destroy_state, +}; + static const struct zxdg_decoration_manager_v1_interface decoration_manager_impl; static struct wlr_xdg_decoration_manager_v1 * @@ -192,10 +224,21 @@ static void decoration_manager_handle_get_toplevel_decoration( decoration->manager = manager; decoration->surface = toplevel->base; + if (!wlr_surface_synced_init(&decoration->synced, + &xdg_toplevel_decoration_synced_impl, + toplevel->base->surface, + &decoration->current.synced_state, + &decoration->pending.synced_state)) { + free(decoration); + wl_client_post_no_memory(client); + return; + } + uint32_t version = wl_resource_get_version(manager_resource); decoration->resource = wl_resource_create(client, &zxdg_toplevel_decoration_v1_interface, version, id); if (decoration->resource == NULL) { + wlr_surface_synced_finish(&decoration->synced); free(decoration); wl_client_post_no_memory(client); return; @@ -211,10 +254,6 @@ static void decoration_manager_handle_get_toplevel_decoration( wl_signal_init(&decoration->events.destroy); wl_signal_init(&decoration->events.request_mode); - wl_signal_add(&toplevel->base->events.destroy, - &decoration->surface_destroy); - decoration->surface_destroy.notify = - toplevel_decoration_handle_surface_destroy; wl_signal_add(&toplevel->base->events.configure, &decoration->surface_configure); decoration->surface_configure.notify =