aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Primak <vyivel@eclair.cafe>2023-03-04 22:13:52 +0300
committerIsaac Freund <mail@isaacfreund.com>2023-06-02 17:26:18 +0000
commit6b40e0814844a805760a53c3c5054899e67fdaee (patch)
treeb6040bb2ea9a458427ffea458dd835c812b81a80
parent6668c822b3bf58ca5af5d370ef03b075be3e4d27 (diff)
compositor: introduce unified map logic
-rw-r--r--include/wlr/types/wlr_compositor.h31
-rw-r--r--types/wlr_compositor.c27
2 files changed, 58 insertions, 0 deletions
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;
@@ -201,6 +218,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
* state. A surface will not have a buffer if it has never committed one, has
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);
}