From e0a69804ed23cadaba888e3d38bb84d46c419961 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 6 Jun 2023 20:03:26 +0200 Subject: [PATCH] backend/wayland: switch to cursor layers --- backend/wayland/output.c | 102 +++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index e950ce931..4b72bc331 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -19,6 +19,7 @@ #include "backend/wayland.h" #include "render/pixel_format.h" #include "render/wlr_renderer.h" +#include "types/wlr_output.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "presentation-time-client-protocol.h" @@ -270,10 +271,6 @@ static bool test_layer(struct wlr_wl_output *output, struct wlr_output_layer_sta return true; } - if (layer_state->layer->cursor) { - return false; // TODO: add support for cursor layers - } - int x = layer_state->dst_box.x; int y = layer_state->dst_box.y; int width = layer_state->dst_box.width; @@ -294,6 +291,13 @@ static bool test_layer(struct wlr_wl_output *output, struct wlr_output_layer_sta return test_buffer(output->backend, layer_state->buffer); } +static bool test_cursor(struct wlr_wl_output *output, struct wlr_output_layer_state *layer_state) { + if (layer_state->buffer == NULL) { + return true; + } + return !layer_needs_viewport(layer_state) && test_buffer(output->backend, layer_state->buffer); +} + static bool output_test(struct wlr_output *wlr_output, const struct wlr_output_state *state) { struct wlr_wl_output *output = @@ -330,10 +334,17 @@ static bool output_test(struct wlr_output *wlr_output, } if (state->committed & WLR_OUTPUT_STATE_LAYERS) { + size_t layers_len = state->layers_len; + struct wlr_output_layer_state *cursor_state = output_state_get_cursor_layer(state); + if (cursor_state != NULL) { + cursor_state->accepted = test_cursor(output, cursor_state); + layers_len--; + } + // If we can't use a sub-surface for a layer, then we can't use a // sub-surface for any layer underneath bool supported = output->backend->subcompositor != NULL; - for (ssize_t i = state->layers_len - 1; i >= 0; i--) { + for (ssize_t i = layers_len - 1; i >= 0; i--) { struct wlr_output_layer_state *layer_state = &state->layers[i]; supported = supported && test_layer(output, layer_state); layer_state->accepted = supported; @@ -363,6 +374,7 @@ static const struct wlr_addon_interface output_layer_addon_impl = { static struct wlr_wl_output_layer *get_or_create_output_layer( struct wlr_wl_output *output, struct wlr_output_layer *wlr_layer) { assert(output->backend->subcompositor != NULL); + assert(!wlr_layer->cursor); struct wlr_wl_output_layer *layer; struct wlr_addon *addon = wlr_addon_find(&wlr_layer->addons, output, @@ -501,6 +513,10 @@ static bool commit_layers(struct wlr_wl_output *output, struct wlr_wl_output_layer *prev_layer = NULL; for (size_t i = 0; i < layers_len; i++) { + if (layers[i].layer->cursor) { + continue; + } + struct wlr_wl_output_layer *layer = get_or_create_output_layer(output, layers[i].layer); if (layer == NULL) { @@ -525,6 +541,36 @@ static bool commit_layers(struct wlr_wl_output *output, return true; } +static bool commit_cursor(struct wlr_wl_output *output, + const struct wlr_output_layer_state *cursor_state) { + struct wlr_wl_backend *backend = output->backend; + + output->cursor.hotspot_x = cursor_state->cursor_hotspot.x; + output->cursor.hotspot_y = cursor_state->cursor_hotspot.y; + + if (output->cursor.surface == NULL) { + output->cursor.surface = wl_compositor_create_surface(backend->compositor); + } + struct wl_surface *surface = output->cursor.surface; + + if (cursor_state->buffer != NULL) { + struct wlr_wl_buffer *buffer = get_or_create_wl_buffer(backend, cursor_state->buffer); + if (buffer == NULL) { + return false; + } + + wl_surface_attach(surface, buffer->wl_buffer, 0, 0); + wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); + } else { + wl_surface_attach(surface, NULL, 0, 0); + } + + wl_surface_commit(surface); + + update_wl_output_cursor(output); + return true; +} + static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output_state *state) { struct wlr_wl_output *output = @@ -556,6 +602,11 @@ static bool output_commit(struct wlr_output *wlr_output, damage_surface(output->surface, damage); } + struct wlr_output_layer_state *cursor_state = output_state_get_cursor_layer(state); + if (cursor_state != NULL && !commit_cursor(output, cursor_state)) { + return false; + } + if ((state->committed & WLR_OUTPUT_STATE_LAYERS) && !commit_layers(output, state->layers, state->layers_len)) { return false; @@ -604,40 +655,6 @@ static bool output_commit(struct wlr_output *wlr_output, return true; } -static bool output_set_cursor(struct wlr_output *wlr_output, - struct wlr_buffer *wlr_buffer, int hotspot_x, int hotspot_y) { - struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); - struct wlr_wl_backend *backend = output->backend; - - output->cursor.hotspot_x = hotspot_x; - output->cursor.hotspot_y = hotspot_y; - - if (output->cursor.surface == NULL) { - output->cursor.surface = - wl_compositor_create_surface(backend->compositor); - } - struct wl_surface *surface = output->cursor.surface; - - if (wlr_buffer != NULL) { - struct wlr_wl_buffer *buffer = - get_or_create_wl_buffer(output->backend, wlr_buffer); - if (buffer == NULL) { - return false; - } - - wl_surface_attach(surface, buffer->wl_buffer, 0, 0); - wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(surface); - } else { - wl_surface_attach(surface, NULL, 0, 0); - wl_surface_commit(surface); - } - - update_wl_output_cursor(output); - wl_display_flush(backend->remote_display); - return true; -} - static const struct wlr_drm_format_set *output_get_formats( struct wlr_output *wlr_output, uint32_t buffer_caps) { struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); @@ -694,17 +711,10 @@ void update_wl_output_cursor(struct wlr_wl_output *output) { } } -static bool output_move_cursor(struct wlr_output *_output, int x, int y) { - // TODO: only return true if x == current x and y == current y - return true; -} - static const struct wlr_output_impl output_impl = { .destroy = output_destroy, .test = output_test, .commit = output_commit, - .set_cursor = output_set_cursor, - .move_cursor = output_move_cursor, .get_cursor_formats = output_get_formats, .get_primary_formats = output_get_formats, };