cursor: add wlr_cursor_set_buffer()

A saner replacement for wlr_cursor_set_image():

- Takes a wlr_buffer instead of numerous parameters and a hardcoded
  format.
- The scale is not used to filter outputs.
- A ref to the buffer is kept to apply it to new outputs.
This commit is contained in:
Simon Ser 2023-06-23 20:03:58 +02:00 committed by Alexander Orzechowski
parent bb91787b5f
commit 71c87ff4b8
2 changed files with 64 additions and 2 deletions

View file

@ -147,6 +147,15 @@ void wlr_cursor_set_image(struct wlr_cursor *cur, const uint8_t *pixels,
int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x,
int32_t hotspot_y, float scale); int32_t hotspot_y, float scale);
/**
* Set the cursor buffer.
*
* The buffer is used on all outputs and is scaled accordingly. The hotspot is
* expressed in logical coordinates. A NULL buffer hides the cursor.
*/
void wlr_cursor_set_buffer(struct wlr_cursor *cur, struct wlr_buffer *buffer,
int32_t hotspot_x, int32_t hotspot_y, float scale);
/** /**
* Hide the cursor image. * Hide the cursor image.
*/ */

View file

@ -81,6 +81,13 @@ struct wlr_cursor_state {
struct wl_listener layout_change; struct wl_listener layout_change;
struct wl_listener layout_destroy; struct wl_listener layout_destroy;
// only when using a buffer as the cursor image
struct wlr_buffer *buffer;
struct {
int32_t x, y;
} buffer_hotspot;
float buffer_scale;
// only when using a surface as the cursor image // only when using a surface as the cursor image
struct wlr_surface *surface; struct wlr_surface *surface;
struct { struct {
@ -207,6 +214,9 @@ static void cursor_device_destroy(struct wlr_cursor_device *c_device) {
} }
static void cursor_reset_image(struct wlr_cursor *cur) { static void cursor_reset_image(struct wlr_cursor *cur) {
wlr_buffer_unlock(cur->state->buffer);
cur->state->buffer = NULL;
if (cur->state->surface != NULL) { if (cur->state->surface != NULL) {
struct wlr_cursor_output_cursor *output_cursor; struct wlr_cursor_output_cursor *output_cursor;
wl_list_for_each(output_cursor, &cur->state->output_cursors, link) { wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
@ -430,6 +440,27 @@ void wlr_cursor_set_image(struct wlr_cursor *cur, const uint8_t *pixels,
static void cursor_update_outputs(struct wlr_cursor *cur); static void cursor_update_outputs(struct wlr_cursor *cur);
void wlr_cursor_set_buffer(struct wlr_cursor *cur, struct wlr_buffer *buffer,
int32_t hotspot_x, int32_t hotspot_y, float scale) {
if (buffer == cur->state->buffer &&
hotspot_x == cur->state->buffer_hotspot.x &&
hotspot_y == cur->state->buffer_hotspot.y &&
scale == cur->state->buffer_scale) {
return;
}
cursor_reset_image(cur);
if (buffer != NULL) {
cur->state->buffer = wlr_buffer_lock(buffer);
cur->state->buffer_hotspot.x = hotspot_x;
cur->state->buffer_hotspot.y = hotspot_y;
cur->state->buffer_scale = scale;
}
cursor_update_outputs(cur);
}
void wlr_cursor_unset_image(struct wlr_cursor *cur) { void wlr_cursor_unset_image(struct wlr_cursor *cur) {
cursor_reset_image(cur); cursor_reset_image(cur);
cursor_update_outputs(cur); cursor_update_outputs(cur);
@ -489,8 +520,30 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_
cursor_output_cursor_reset_image(output_cursor); cursor_output_cursor_reset_image(output_cursor);
struct wlr_surface *surface = cur->state->surface; if (cur->state->buffer != NULL) {
if (surface != NULL) { struct wlr_renderer *renderer = output_cursor->output_cursor->output->renderer;
if (!renderer) {
return;
}
struct wlr_buffer *buffer = cur->state->buffer;
int32_t hotspot_x = cur->state->buffer_hotspot.x;
int32_t hotspot_y = cur->state->buffer_hotspot.y;
float scale = cur->state->buffer_scale;
struct wlr_texture *texture = NULL;
if (buffer != NULL) {
texture = wlr_texture_from_buffer(renderer, buffer);
if (texture == NULL) {
return;
}
}
output_cursor_set_texture(output_cursor->output_cursor, texture, true,
scale, WL_OUTPUT_TRANSFORM_NORMAL, hotspot_x, hotspot_y);
} else if (cur->state->surface != NULL) {
struct wlr_surface *surface = cur->state->surface;
wl_signal_add(&output_cursor->output_cursor->output->events.commit, wl_signal_add(&output_cursor->output_cursor->output->events.commit,
&output_cursor->output_commit); &output_cursor->output_commit);
output_cursor->output_commit.notify = output_cursor_output_handle_output_commit; output_cursor->output_commit.notify = output_cursor_output_handle_output_commit;