From 6b40e0814844a805760a53c3c5054899e67fdaee Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 4 Mar 2023 22:13:52 +0300 Subject: [PATCH] compositor: introduce unified map logic --- include/wlr/types/wlr_compositor.h | 31 ++++++++++++++++++++++++++++++ types/wlr_compositor.c | 27 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 3c4f5a4b..11379ab4 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -76,6 +76,7 @@ struct wlr_surface_role { void (*commit)(struct wlr_surface *surface); void (*precommit)(struct wlr_surface *surface, const struct wlr_surface_state *state); + void (*unmap)(struct wlr_surface *surface); void (*destroy)(struct wlr_surface *surface); }; @@ -135,6 +136,8 @@ struct wlr_surface { struct wl_list cached; // wlr_surface_state.cached_link + bool mapped; + const struct wlr_surface_role *role; // the lifetime-bound role or NULL void *role_data; // role-specific data @@ -142,6 +145,20 @@ struct wlr_surface { struct wl_signal client_commit; struct wl_signal precommit; // const struct wlr_surface_state * struct wl_signal commit; + + /** + * The `map` event signals that the surface has a non-null buffer + * committed and is ready to be displayed. + */ + struct wl_signal map; + /** + * The `unmap` event signals that the surface shouldn't be displayed + * anymore. This can happen when a null buffer is committed, + * the associated role object is destroyed, or when the role-specific + * conditions for the surface to be mapped no longer apply. + */ + struct wl_signal unmap; + struct wl_signal new_subsurface; struct wl_signal destroy; } events; @@ -200,6 +217,20 @@ bool wlr_surface_set_role(struct wlr_surface *surface, */ void wlr_surface_destroy_role_object(struct wlr_surface *surface); +/** + * Map the surface. If the surface is already mapped, this is no-op. + * + * This function must only be used by surface role implementations. + */ +void wlr_surface_map(struct wlr_surface *surface); + +/** + * Unmap the surface. If the surface is already unmapped, this is no-op. + * + * This function must only be used by surface role implementations. + */ +void wlr_surface_unmap(struct wlr_surface *surface); + /** * Whether or not this surface currently has an attached buffer. A surface has * an attached buffer when it commits with a non-null buffer in its pending diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 0236c40f..0411f547 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -442,6 +442,10 @@ static void surface_commit_state(struct wlr_surface *surface, bool invalid_buffer = next->committed & WLR_SURFACE_STATE_BUFFER; + if (invalid_buffer && next->buffer == NULL) { + wlr_surface_unmap(surface); + } + surface_update_damage(&surface->buffer_damage, &surface->current, next); pixman_region32_clear(&surface->external_damage); @@ -696,6 +700,8 @@ static struct wlr_surface *surface_create(struct wl_client *client, wl_signal_init(&surface->events.client_commit); wl_signal_init(&surface->events.precommit); wl_signal_init(&surface->events.commit); + wl_signal_init(&surface->events.map); + wl_signal_init(&surface->events.unmap); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.new_subsurface); wl_list_init(&surface->current_outputs); @@ -727,6 +733,26 @@ bool wlr_surface_has_buffer(struct wlr_surface *surface) { return surface->has_buffer; } +void wlr_surface_map(struct wlr_surface *surface) { + if (surface->mapped) { + return; + } + assert(wlr_surface_has_buffer(surface)); + surface->mapped = true; + wl_signal_emit_mutable(&surface->events.map, NULL); +} + +void wlr_surface_unmap(struct wlr_surface *surface) { + if (!surface->mapped) { + return; + } + surface->mapped = false; + wl_signal_emit_mutable(&surface->events.unmap, NULL); + if (surface->role != NULL && surface->role->unmap != NULL) { + surface->role->unmap(surface); + } +} + bool wlr_surface_set_role(struct wlr_surface *surface, const struct wlr_surface_role *role, void *role_data, struct wl_resource *error_resource, uint32_t error_code) { @@ -758,6 +784,7 @@ void wlr_surface_destroy_role_object(struct wlr_surface *surface) { if (surface->role_data == NULL) { return; } + wlr_surface_unmap(surface); if (surface->role->destroy != NULL) { surface->role->destroy(surface); }