From ac1573b0e7b0b08413e115bb88682ebedbfbf39a Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 11 Nov 2017 17:27:44 +0100 Subject: [PATCH 1/6] Add scale parameter to wlr_cursor_set_image --- examples/multi-pointer.c | 4 ++-- examples/pointer.c | 4 ++-- include/wlr/types/wlr_cursor.h | 15 ++++++++++++++- rootston/cursor.c | 2 +- rootston/seat.c | 21 ++++++++++----------- types/wlr_cursor.c | 7 ++++++- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index e29a69db..f1bcebc7 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -86,7 +86,7 @@ static void handle_output_add(struct output_state *ostate) { struct wlr_xcursor_image *image = sample->xcursor->images[0]; wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); wlr_cursor_warp(cursor->cursor, NULL, cursor->cursor->x, cursor->cursor->y); @@ -150,7 +150,7 @@ static void handle_input_add(struct compositor_state *state, struct wlr_xcursor_image *image = sample->xcursor->images[0]; wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); wl_list_insert(&sample->cursors, &cursor->link); } diff --git a/examples/pointer.c b/examples/pointer.c index 1bcd7349..476cc617 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -110,7 +110,7 @@ static void handle_output_add(struct output_state *ostate) { struct wlr_xcursor_image *image = sample->xcursor->images[0]; wlr_cursor_set_image(sample->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); wlr_cursor_warp(sample->cursor, NULL, sample->cursor->x, sample->cursor->y); } @@ -321,7 +321,7 @@ int main(int argc, char *argv[]) { struct wlr_xcursor_image *image = state.xcursor->images[0]; wlr_cursor_set_image(state.cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); compositor_init(&compositor); if (!wlr_backend_start(compositor.backend)) { diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 1aac2b94..3df74d28 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -60,9 +60,22 @@ void wlr_cursor_warp_absolute(struct wlr_cursor *cur, void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, double delta_x, double delta_y); +/** + * Set the cursor image. stride is given in bytes. If pixels is NULL, hides the + * cursor. + * + * If scale isn't zero, the image is only set on outputs having the provided + * scale. + */ 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 hotspot_y); + int32_t hotspot_y, uint32_t scale); + +/** + * Set the cursor surface. The surface can be committed to update the cursor + * image. The surface position is substracted from the hotspot. A NULL surface + * commit hides the cursor. + */ void wlr_cursor_set_surface(struct wlr_cursor *cur, struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y); diff --git a/rootston/cursor.c b/rootston/cursor.c index cba9e782..c3982e0e 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -30,7 +30,7 @@ void roots_cursor_destroy(struct roots_cursor *cursor) { static void cursor_set_xcursor_image(struct roots_cursor *cursor, struct wlr_xcursor_image *image) { wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); } static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t time) { diff --git a/rootston/seat.c b/rootston/seat.c index 4602aad5..280443ac 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -176,6 +176,12 @@ void roots_seat_configure_cursor(struct roots_seat *seat) { } } +static void seat_set_xcursor_image(struct roots_seat *seat, struct + wlr_xcursor_image *image) { + wlr_cursor_set_image(seat->cursor->cursor, image->buffer, image->width, + image->width, image->height, image->hotspot_x, image->hotspot_y, 0); +} + static void roots_seat_init_cursor(struct roots_seat *seat) { seat->cursor = roots_cursor_create(seat); if (!seat->cursor) { @@ -204,8 +210,7 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { } struct wlr_xcursor_image *image = xcursor->images[0]; - wlr_cursor_set_image(seat->cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + seat_set_xcursor_image(seat, image); // XXX: xwayland will always have the theme of the last created seat if (seat->input->server->desktop->xwayland != NULL) { @@ -471,10 +476,10 @@ void roots_seat_remove_device(struct roots_seat *seat, } void roots_seat_configure_xcursor(struct roots_seat *seat) { - struct wlr_xcursor *xcursor = get_default_xcursor(seat->cursor->xcursor_theme); + struct wlr_xcursor *xcursor = + get_default_xcursor(seat->cursor->xcursor_theme); struct wlr_xcursor_image *image = xcursor->images[0]; - wlr_cursor_set_image(seat->cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); + seat_set_xcursor_image(seat, image); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); @@ -537,12 +542,6 @@ void roots_seat_focus_view(struct roots_seat *seat, struct roots_view *view) { wlr_seat_keyboard_notify_enter(seat->seat, view->wlr_surface); } -static void seat_set_xcursor_image(struct roots_seat *seat, struct - wlr_xcursor_image *image) { - wlr_cursor_set_image(seat->cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y); -} - void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view) { struct roots_cursor *cursor = seat->cursor; cursor->mode = ROOTS_CURSOR_MOVE; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index dfaccb53..e8965b68 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -299,9 +299,14 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, 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 hotspot_y) { + int32_t hotspot_y, uint32_t scale) { struct wlr_cursor_output_cursor *output_cursor; wl_list_for_each(output_cursor, &cur->state->output_cursors, link) { + if (scale != 0 && + output_cursor->output_cursor->output->scale != scale) { + continue; + } + wlr_output_cursor_set_image(output_cursor->output_cursor, pixels, stride, width, height, hotspot_x, hotspot_y); } From aaf069188319f42bc214f4317c37d533aea64518 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 11 Nov 2017 18:42:14 +0100 Subject: [PATCH 2/6] rootston: add roots_xcursor_theme roots_xcursor_theme loads multiple wlr_xcursor_theme at different scales. --- include/rootston/cursor.h | 1 - include/rootston/desktop.h | 2 + include/rootston/xcursor.h | 39 +++++++++++-- rootston/cursor.c | 10 +--- rootston/desktop.c | 14 +++++ rootston/output.c | 6 ++ rootston/seat.c | 61 +++----------------- rootston/xcursor.c | 114 +++++++++++++++++++++++++++++++++---- 8 files changed, 170 insertions(+), 77 deletions(-) diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h index c0dbc010..fc71e31d 100644 --- a/include/rootston/cursor.h +++ b/include/rootston/cursor.h @@ -30,7 +30,6 @@ struct roots_cursor { enum roots_cursor_mode mode; // state from input (review if this is necessary) - struct wlr_xcursor_theme *xcursor_theme; struct wlr_seat *wl_seat; struct wl_client *cursor_client; int offs_x, offs_y; diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 376412fb..b12fff70 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -12,6 +12,7 @@ #include #include "rootston/view.h" #include "rootston/config.h" +#include "rootston/xcursor.h" struct roots_output { struct roots_desktop *desktop; @@ -29,6 +30,7 @@ struct roots_desktop { struct roots_server *server; struct roots_config *config; + struct roots_xcursor_theme *xcursor_theme; struct wlr_output_layout *layout; diff --git a/include/rootston/xcursor.h b/include/rootston/xcursor.h index c96e50ef..45fac481 100644 --- a/include/rootston/xcursor.h +++ b/include/rootston/xcursor.h @@ -1,15 +1,44 @@ #ifndef _ROOTSTON_XCURSOR_H #define _ROOTSTON_XCURSOR_H +#include #include +#include +#include -struct wlr_xcursor *get_default_xcursor(struct wlr_xcursor_theme *theme); +#define ROOTS_XCURSOR_SIZE 16 -struct wlr_xcursor *get_move_xcursor(struct wlr_xcursor_theme *theme); +struct roots_xcursor_scaled_theme { + uint32_t scale; + struct wlr_xcursor_theme *theme; + struct wl_list link; +}; -struct wlr_xcursor *get_resize_xcursor(struct wlr_xcursor_theme *theme, - uint32_t edges); +struct roots_xcursor_theme { + char *name; + struct wl_list scaled_themes; // roots_xcursor_scaled_theme::link +}; -struct wlr_xcursor *get_rotate_xcursor(struct wlr_xcursor_theme *theme); +struct roots_xcursor_theme *roots_xcursor_theme_create(const char *name); + +void roots_xcursor_theme_destroy(struct roots_xcursor_theme *theme); + +int roots_xcursor_theme_load(struct roots_xcursor_theme *theme, + uint32_t scale); + +void roots_xcursor_theme_set_default(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor); + +void roots_xcursor_theme_set_move(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor); + +void roots_xcursor_theme_set_resize(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor, uint32_t edges); + +void roots_xcursor_theme_set_rotate(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor); + +void roots_xcursor_theme_xwayland_set_default(struct roots_xcursor_theme *theme, + struct wlr_xwayland *xwayland); #endif diff --git a/rootston/cursor.c b/rootston/cursor.c index c3982e0e..46f4caea 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -27,12 +27,6 @@ void roots_cursor_destroy(struct roots_cursor *cursor) { // TODO } -static void cursor_set_xcursor_image(struct roots_cursor *cursor, - struct wlr_xcursor_image *image) { - wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y, 0); -} - static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t time) { struct roots_desktop *desktop = cursor->seat->input->server->desktop; struct roots_seat *seat = cursor->seat; @@ -50,8 +44,8 @@ static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t t set_compositor_cursor = view_client != cursor->cursor_client; } if (set_compositor_cursor) { - struct wlr_xcursor *xcursor = get_default_xcursor(cursor->xcursor_theme); - cursor_set_xcursor_image(cursor, xcursor->images[0]); + roots_xcursor_theme_set_default(desktop->xcursor_theme, + cursor->cursor); cursor->cursor_client = NULL; } if (view) { diff --git a/rootston/desktop.c b/rootston/desktop.c index 448171ec..e20fceab 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -323,6 +323,14 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->server = server; desktop->config = config; + + desktop->xcursor_theme = roots_xcursor_theme_create("default"); + if (desktop->xcursor_theme == NULL) { + wlr_list_free(desktop->views); + free(desktop); + return NULL; + } + desktop->layout = wlr_output_layout_create(); desktop->compositor = wlr_compositor_create(server->wl_display, server->renderer); @@ -344,6 +352,12 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_signal_add(&desktop->xwayland->events.new_surface, &desktop->xwayland_surface); desktop->xwayland_surface.notify = handle_xwayland_surface; + + if (roots_xcursor_theme_load(desktop->xcursor_theme, 1)) { + wlr_log(L_ERROR, "Cannot load xwayland xcursor theme"); + } + roots_xcursor_theme_xwayland_set_default(desktop->xcursor_theme, + desktop->xwayland); } #endif diff --git a/rootston/output.c b/rootston/output.c index d853c45f..943e14c0 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -11,6 +11,7 @@ #include "rootston/server.h" #include "rootston/desktop.h" #include "rootston/config.h" +#include "rootston/xcursor.h" static inline int64_t timespec_to_msec(const struct timespec *a) { return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; @@ -240,6 +241,11 @@ void output_add_notify(struct wl_listener *listener, void *data) { wlr_output_layout_add_auto(desktop->layout, wlr_output); } + if (roots_xcursor_theme_load(desktop->xcursor_theme, wlr_output->scale)) { + wlr_log(L_ERROR, "Cannot load xcursor theme with scale %d", + wlr_output->scale); + } + struct roots_seat *seat; wl_list_for_each(seat, &input->seats, link) { roots_seat_configure_cursor(seat); diff --git a/rootston/seat.c b/rootston/seat.c index 280443ac..376da67f 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -176,12 +176,6 @@ void roots_seat_configure_cursor(struct roots_seat *seat) { } } -static void seat_set_xcursor_image(struct roots_seat *seat, struct - wlr_xcursor_image *image) { - wlr_cursor_set_image(seat->cursor->cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y, 0); -} - static void roots_seat_init_cursor(struct roots_seat *seat) { seat->cursor = roots_cursor_create(seat); if (!seat->cursor) { @@ -192,33 +186,7 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { struct roots_desktop *desktop = seat->input->server->desktop; wlr_cursor_attach_output_layout(wlr_cursor, desktop->layout); - seat->cursor->xcursor_theme = wlr_xcursor_theme_load("default", 16); - if (seat->cursor->xcursor_theme == NULL) { - wlr_log(L_ERROR, "Cannot load xcursor theme"); - roots_cursor_destroy(seat->cursor); - seat->cursor = NULL; - return; - } - - struct wlr_xcursor *xcursor = get_default_xcursor(seat->cursor->xcursor_theme); - if (xcursor == NULL) { - wlr_log(L_ERROR, "Cannot load xcursor from theme"); - wlr_xcursor_theme_destroy(seat->cursor->xcursor_theme); - roots_cursor_destroy(seat->cursor); - seat->cursor = NULL; - return; - } - - struct wlr_xcursor_image *image = xcursor->images[0]; - seat_set_xcursor_image(seat, image); - - // XXX: xwayland will always have the theme of the last created seat - if (seat->input->server->desktop->xwayland != NULL) { - wlr_xwayland_set_cursor(seat->input->server->desktop->xwayland, - image->buffer, image->width, image->width, - image->height, image->hotspot_x, - image->hotspot_y); - } + roots_xcursor_theme_set_default(desktop->xcursor_theme, wlr_cursor); wl_list_init(&seat->cursor->touch_points); @@ -476,11 +444,8 @@ void roots_seat_remove_device(struct roots_seat *seat, } void roots_seat_configure_xcursor(struct roots_seat *seat) { - struct wlr_xcursor *xcursor = - get_default_xcursor(seat->cursor->xcursor_theme); - struct wlr_xcursor_image *image = xcursor->images[0]; - seat_set_xcursor_image(seat, image); - + roots_xcursor_theme_set_default(seat->input->server->desktop->xcursor_theme, + seat->cursor->cursor); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); } @@ -557,11 +522,8 @@ void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - struct wlr_xcursor *xcursor = get_move_xcursor(seat->cursor->xcursor_theme); - if (xcursor != NULL) { - struct wlr_xcursor_image *image = xcursor->images[0]; - seat_set_xcursor_image(seat, image); - } + roots_xcursor_theme_set_move(seat->input->server->desktop->xcursor_theme, + seat->cursor->cursor); } void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view, @@ -587,11 +549,8 @@ void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view, view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - struct wlr_xcursor *xcursor = get_resize_xcursor(cursor->xcursor_theme, edges); - if (xcursor != NULL) { - seat_set_xcursor_image(seat, xcursor->images[0]); - } - + roots_xcursor_theme_set_resize(seat->input->server->desktop->xcursor_theme, + seat->cursor->cursor, edges); } void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) { @@ -603,8 +562,6 @@ void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - struct wlr_xcursor *xcursor = get_rotate_xcursor(cursor->xcursor_theme); - if (xcursor != NULL) { - seat_set_xcursor_image(seat, xcursor->images[0]); - } + roots_xcursor_theme_set_rotate(seat->input->server->desktop->xcursor_theme, + seat->cursor->cursor); } diff --git a/rootston/xcursor.c b/rootston/xcursor.c index 8697cdc3..6aa74bc4 100644 --- a/rootston/xcursor.c +++ b/rootston/xcursor.c @@ -1,6 +1,85 @@ -#include +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "rootston/xcursor.h" #include "rootston/input.h" +struct roots_xcursor_theme *roots_xcursor_theme_create(const char *name) { + struct roots_xcursor_theme *theme = + calloc(1, sizeof(struct roots_xcursor_theme)); + if (theme == NULL) { + return NULL; + } + theme->name = strdup(name); + wl_list_init(&theme->scaled_themes); + return theme; +} + +void roots_xcursor_theme_destroy(struct roots_xcursor_theme *theme) { + if (theme == NULL) { + return; + } + struct roots_xcursor_scaled_theme *scaled_theme, *tmp; + wl_list_for_each_safe(scaled_theme, tmp, &theme->scaled_themes, link) { + wl_list_remove(&scaled_theme->link); + wlr_xcursor_theme_destroy(scaled_theme->theme); + free(scaled_theme); + } + free(theme->name); + free(theme); +} + +int roots_xcursor_theme_load(struct roots_xcursor_theme *theme, + uint32_t scale) { + struct roots_xcursor_scaled_theme *scaled_theme; + wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { + if (scaled_theme->scale == scale) { + return 0; + } + } + + scaled_theme = calloc(1, sizeof(struct roots_xcursor_scaled_theme)); + if (scaled_theme == NULL) { + return 1; + } + scaled_theme->scale = scale; + scaled_theme->theme = wlr_xcursor_theme_load(NULL, + ROOTS_XCURSOR_SIZE * scale); + if (scaled_theme->theme == NULL) { + free(scaled_theme); + return 1; + } + wl_list_insert(&theme->scaled_themes, &scaled_theme->link); + return 0; +} + +static void roots_xcursor_theme_set(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor, const char *name) { + struct roots_xcursor_scaled_theme *scaled_theme; + wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { + struct wlr_xcursor *xcursor = + wlr_xcursor_theme_get_cursor(scaled_theme->theme, name); + if (xcursor == NULL) { + continue; + } + + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_cursor_set_image(cursor, image->buffer, image->width, + image->width, image->height, image->hotspot_x, image->hotspot_y, + scaled_theme->scale); + } +} + +void roots_xcursor_theme_set_default(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor) { + roots_xcursor_theme_set(theme, cursor, "left_ptr"); +} + +void roots_xcursor_theme_set_move(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor) { + roots_xcursor_theme_set(theme, cursor, "grabbing"); +} + static const char *get_resize_xcursor_name(uint32_t edges) { if (edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { if (edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { @@ -24,19 +103,32 @@ static const char *get_resize_xcursor_name(uint32_t edges) { return "se-resize"; // fallback } -struct wlr_xcursor *get_default_xcursor(struct wlr_xcursor_theme *theme) { - return wlr_xcursor_theme_get_cursor(theme, "left_ptr"); +void roots_xcursor_theme_set_resize(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor, uint32_t edges) { + roots_xcursor_theme_set(theme, cursor, get_resize_xcursor_name(edges)); } -struct wlr_xcursor *get_move_xcursor(struct wlr_xcursor_theme *theme) { - return wlr_xcursor_theme_get_cursor(theme, "grabbing"); +void roots_xcursor_theme_set_rotate(struct roots_xcursor_theme *theme, + struct wlr_cursor *cursor) { + roots_xcursor_theme_set(theme, cursor, "grabbing"); } -struct wlr_xcursor *get_resize_xcursor(struct wlr_xcursor_theme *theme, - uint32_t edges) { - return wlr_xcursor_theme_get_cursor(theme, get_resize_xcursor_name(edges)); -} +void roots_xcursor_theme_xwayland_set_default(struct roots_xcursor_theme *theme, + struct wlr_xwayland *xwayland) { + struct roots_xcursor_scaled_theme *scaled_theme; + wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { + if (scaled_theme->scale == 1) { + struct wlr_xcursor *xcursor = + wlr_xcursor_theme_get_cursor(scaled_theme->theme, "left_ptr"); + if (xcursor == NULL) { + continue; + } -struct wlr_xcursor *get_rotate_xcursor(struct wlr_xcursor_theme *theme) { - return wlr_xcursor_theme_get_cursor(theme, "grabbing"); + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(xwayland, image->buffer, image->width, + image->width, image->height, image->hotspot_x, + image->hotspot_y); + break; + } + } } From 2dccb11741abd99fd71d4ccaba1ad42362d8f204 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 11 Nov 2017 23:53:45 +0100 Subject: [PATCH 3/6] rootston: keep one xcursor_theme per seat --- include/rootston/cursor.h | 1 + rootston/cursor.c | 2 +- rootston/output.c | 11 ++++++----- rootston/seat.c | 12 +++++++----- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h index fc71e31d..575c9d0e 100644 --- a/include/rootston/cursor.h +++ b/include/rootston/cursor.h @@ -30,6 +30,7 @@ struct roots_cursor { enum roots_cursor_mode mode; // state from input (review if this is necessary) + struct roots_xcursor_theme *xcursor_theme; struct wlr_seat *wl_seat; struct wl_client *cursor_client; int offs_x, offs_y; diff --git a/rootston/cursor.c b/rootston/cursor.c index 46f4caea..0795cea6 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -44,7 +44,7 @@ static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t t set_compositor_cursor = view_client != cursor->cursor_client; } if (set_compositor_cursor) { - roots_xcursor_theme_set_default(desktop->xcursor_theme, + roots_xcursor_theme_set_default(cursor->xcursor_theme, cursor->cursor); cursor->cursor_client = NULL; } diff --git a/rootston/output.c b/rootston/output.c index 943e14c0..b35e56cd 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -241,13 +241,14 @@ void output_add_notify(struct wl_listener *listener, void *data) { wlr_output_layout_add_auto(desktop->layout, wlr_output); } - if (roots_xcursor_theme_load(desktop->xcursor_theme, wlr_output->scale)) { - wlr_log(L_ERROR, "Cannot load xcursor theme with scale %d", - wlr_output->scale); - } - struct roots_seat *seat; wl_list_for_each(seat, &input->seats, link) { + if (roots_xcursor_theme_load(seat->cursor->xcursor_theme, + wlr_output->scale)) { + wlr_log(L_ERROR, "Cannot load xcursor theme for output '%s' " + "with scale %d", wlr_output->name, wlr_output->scale); + } + roots_seat_configure_cursor(seat); roots_seat_configure_xcursor(seat); } diff --git a/rootston/seat.c b/rootston/seat.c index 376da67f..ec4e9800 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -186,7 +186,9 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { struct roots_desktop *desktop = seat->input->server->desktop; wlr_cursor_attach_output_layout(wlr_cursor, desktop->layout); - roots_xcursor_theme_set_default(desktop->xcursor_theme, wlr_cursor); + // TODO: be able to configure per-seat cursor themes + seat->cursor->xcursor_theme = desktop->xcursor_theme; + roots_xcursor_theme_set_default(seat->cursor->xcursor_theme, wlr_cursor); wl_list_init(&seat->cursor->touch_points); @@ -444,7 +446,7 @@ void roots_seat_remove_device(struct roots_seat *seat, } void roots_seat_configure_xcursor(struct roots_seat *seat) { - roots_xcursor_theme_set_default(seat->input->server->desktop->xcursor_theme, + roots_xcursor_theme_set_default(seat->cursor->xcursor_theme, seat->cursor->cursor); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); @@ -522,7 +524,7 @@ void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_move(seat->input->server->desktop->xcursor_theme, + roots_xcursor_theme_set_move(seat->cursor->xcursor_theme, seat->cursor->cursor); } @@ -549,7 +551,7 @@ void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view, view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_resize(seat->input->server->desktop->xcursor_theme, + roots_xcursor_theme_set_resize(seat->cursor->xcursor_theme, seat->cursor->cursor, edges); } @@ -562,6 +564,6 @@ void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_rotate(seat->input->server->desktop->xcursor_theme, + roots_xcursor_theme_set_rotate(seat->cursor->xcursor_theme, seat->cursor->cursor); } From 8605243459629f566ed5109ffd896fd57b329ceb Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 12 Nov 2017 11:10:56 +0100 Subject: [PATCH 4/6] Introduce wlr_xcursor_manager --- include/rootston/cursor.h | 2 +- include/rootston/desktop.h | 2 +- include/rootston/xcursor.h | 40 ++------- include/wlr/types/wlr_cursor.h | 1 - include/wlr/types/wlr_xcursor_manager.h | 53 ++++++++++++ include/wlr/xcursor.h | 2 +- rootston/cursor.c | 5 +- rootston/desktop.c | 21 +++-- rootston/output.c | 4 +- rootston/seat.c | 22 ++--- rootston/xcursor.c | 108 +----------------------- types/meson.build | 3 +- types/wlr_xcursor_manager.c | 84 ++++++++++++++++++ 13 files changed, 180 insertions(+), 167 deletions(-) create mode 100644 include/wlr/types/wlr_xcursor_manager.h create mode 100644 types/wlr_xcursor_manager.c diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h index 575c9d0e..f49b6439 100644 --- a/include/rootston/cursor.h +++ b/include/rootston/cursor.h @@ -30,7 +30,7 @@ struct roots_cursor { enum roots_cursor_mode mode; // state from input (review if this is necessary) - struct roots_xcursor_theme *xcursor_theme; + struct wlr_xcursor_manager *xcursor_manager; struct wlr_seat *wl_seat; struct wl_client *cursor_client; int offs_x, offs_y; diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index b12fff70..7371284f 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -30,9 +30,9 @@ struct roots_desktop { struct roots_server *server; struct roots_config *config; - struct roots_xcursor_theme *xcursor_theme; struct wlr_output_layout *layout; + struct wlr_xcursor_manager *xcursor_manager; struct wlr_compositor *compositor; struct wlr_wl_shell *wl_shell; diff --git a/include/rootston/xcursor.h b/include/rootston/xcursor.h index 45fac481..bc00f79c 100644 --- a/include/rootston/xcursor.h +++ b/include/rootston/xcursor.h @@ -1,44 +1,14 @@ #ifndef _ROOTSTON_XCURSOR_H #define _ROOTSTON_XCURSOR_H -#include -#include -#include -#include +#include #define ROOTS_XCURSOR_SIZE 16 -struct roots_xcursor_scaled_theme { - uint32_t scale; - struct wlr_xcursor_theme *theme; - struct wl_list link; -}; +#define ROOTS_XCURSOR_DEFAULT "left_ptr" +#define ROOTS_XCURSOR_MOVE "grabbing" +#define ROOTS_XCURSOR_ROTATE "grabbing" -struct roots_xcursor_theme { - char *name; - struct wl_list scaled_themes; // roots_xcursor_scaled_theme::link -}; - -struct roots_xcursor_theme *roots_xcursor_theme_create(const char *name); - -void roots_xcursor_theme_destroy(struct roots_xcursor_theme *theme); - -int roots_xcursor_theme_load(struct roots_xcursor_theme *theme, - uint32_t scale); - -void roots_xcursor_theme_set_default(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor); - -void roots_xcursor_theme_set_move(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor); - -void roots_xcursor_theme_set_resize(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor, uint32_t edges); - -void roots_xcursor_theme_set_rotate(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor); - -void roots_xcursor_theme_xwayland_set_default(struct roots_xcursor_theme *theme, - struct wlr_xwayland *xwayland); +const char *roots_xcursor_get_resize_name(uint32_t edges); #endif diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 3df74d28..0db32eb2 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -6,7 +6,6 @@ #include #include #include -#include struct wlr_cursor_state; diff --git a/include/wlr/types/wlr_xcursor_manager.h b/include/wlr/types/wlr_xcursor_manager.h new file mode 100644 index 00000000..c78a6e8d --- /dev/null +++ b/include/wlr/types/wlr_xcursor_manager.h @@ -0,0 +1,53 @@ +#ifndef WLR_TYPES_WLR_XCURSOR_MANAGER_H +#define WLR_TYPES_WLR_XCURSOR_MANAGER_H + +#include +#include +#include + +/** + * A scaled XCursor theme. + */ +struct wlr_xcursor_manager_theme { + uint32_t scale; + struct wlr_xcursor_theme *theme; + struct wl_list link; +}; + +/** + * Manage multiple XCursor themes with different scales and set `wlr_cursor` + * images. + * + * This manager can be used to display cursor images on multiple outputs having + * different scale factors. + */ +struct wlr_xcursor_manager { + char *name; + uint32_t size; + struct wl_list scaled_themes; // wlr_xcursor_manager_theme::link +}; + +/** + * Create a new XCursor manager. After initialization, scaled themes need to be + * loaded with `wlr_xcursor_manager_load`. `size` is the unscaled cursor theme + * size. + */ +struct wlr_xcursor_manager *wlr_xcursor_manager_create(const char *name, + uint32_t size); + +void wlr_xcursor_manager_destroy(struct wlr_xcursor_manager *manager); + +int wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager, + uint32_t scale); + +struct wlr_xcursor *wlr_xcursor_manager_get_xcursor( + struct wlr_xcursor_manager *manager, const char *name, uint32_t scale); + +/** + * Set a `wlr_cursor` image. The manager uses all currently loaded scaled + * themes. + */ +void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager, + const char *name, struct wlr_cursor *cursor); + +#endif diff --git a/include/wlr/xcursor.h b/include/wlr/xcursor.h index c12d5405..b6362b06 100644 --- a/include/wlr/xcursor.h +++ b/include/wlr/xcursor.h @@ -61,7 +61,7 @@ struct wlr_xcursor_theme *wlr_xcursor_theme_load(const char *name, int size); void wlr_xcursor_theme_destroy(struct wlr_xcursor_theme *theme); struct wlr_xcursor *wlr_xcursor_theme_get_cursor( - struct wlr_xcursor_theme *theme, const char *name); + struct wlr_xcursor_theme *theme, const char *name); int wlr_xcursor_frame(struct wlr_xcursor *cursor, uint32_t time); diff --git a/rootston/cursor.c b/rootston/cursor.c index 0795cea6..ecd5e9a0 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -6,6 +6,7 @@ #elif __FreeBSD__ #include #endif +#include #include #include "rootston/xcursor.h" #include "rootston/cursor.h" @@ -44,8 +45,8 @@ static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t t set_compositor_cursor = view_client != cursor->cursor_client; } if (set_compositor_cursor) { - roots_xcursor_theme_set_default(cursor->xcursor_theme, - cursor->cursor); + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, + ROOTS_XCURSOR_DEFAULT, cursor->cursor); cursor->cursor_client = NULL; } if (view) { diff --git a/rootston/desktop.c b/rootston/desktop.c index e20fceab..bb030e74 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -324,8 +325,10 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->server = server; desktop->config = config; - desktop->xcursor_theme = roots_xcursor_theme_create("default"); - if (desktop->xcursor_theme == NULL) { + desktop->xcursor_manager = wlr_xcursor_manager_create(NULL, + ROOTS_XCURSOR_SIZE); + if (desktop->xcursor_manager == NULL) { + wlr_log(L_ERROR, "Cannot create XCursor manager"); wlr_list_free(desktop->views); free(desktop); return NULL; @@ -353,11 +356,17 @@ struct roots_desktop *desktop_create(struct roots_server *server, &desktop->xwayland_surface); desktop->xwayland_surface.notify = handle_xwayland_surface; - if (roots_xcursor_theme_load(desktop->xcursor_theme, 1)) { - wlr_log(L_ERROR, "Cannot load xwayland xcursor theme"); + if (wlr_xcursor_manager_load(desktop->xcursor_manager, 1)) { + wlr_log(L_ERROR, "Cannot load XWayland XCursor theme"); + } + struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( + desktop->xcursor_manager, ROOTS_XCURSOR_DEFAULT, 1); + if (xcursor != NULL) { + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(desktop->xwayland, image->buffer, + image->width, image->width, image->height, image->hotspot_x, + image->hotspot_y); } - roots_xcursor_theme_xwayland_set_default(desktop->xcursor_theme, - desktop->xwayland); } #endif diff --git a/rootston/output.c b/rootston/output.c index b35e56cd..cd288195 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -5,13 +5,13 @@ #include #include #include +#include #include #include #include #include "rootston/server.h" #include "rootston/desktop.h" #include "rootston/config.h" -#include "rootston/xcursor.h" static inline int64_t timespec_to_msec(const struct timespec *a) { return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; @@ -243,7 +243,7 @@ void output_add_notify(struct wl_listener *listener, void *data) { struct roots_seat *seat; wl_list_for_each(seat, &input->seats, link) { - if (roots_xcursor_theme_load(seat->cursor->xcursor_theme, + if (wlr_xcursor_manager_load(seat->cursor->xcursor_manager, wlr_output->scale)) { wlr_log(L_ERROR, "Cannot load xcursor theme for output '%s' " "with scale %d", wlr_output->name, wlr_output->scale); diff --git a/rootston/seat.c b/rootston/seat.c index ec4e9800..8a838efe 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -3,6 +3,7 @@ #include #include +#include #include #include "rootston/xcursor.h" @@ -187,8 +188,9 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { wlr_cursor_attach_output_layout(wlr_cursor, desktop->layout); // TODO: be able to configure per-seat cursor themes - seat->cursor->xcursor_theme = desktop->xcursor_theme; - roots_xcursor_theme_set_default(seat->cursor->xcursor_theme, wlr_cursor); + seat->cursor->xcursor_manager = desktop->xcursor_manager; + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + ROOTS_XCURSOR_DEFAULT, wlr_cursor); wl_list_init(&seat->cursor->touch_points); @@ -446,8 +448,8 @@ void roots_seat_remove_device(struct roots_seat *seat, } void roots_seat_configure_xcursor(struct roots_seat *seat) { - roots_xcursor_theme_set_default(seat->cursor->xcursor_theme, - seat->cursor->cursor); + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + ROOTS_XCURSOR_DEFAULT, seat->cursor->cursor); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); } @@ -524,8 +526,8 @@ void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_move(seat->cursor->xcursor_theme, - seat->cursor->cursor); + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + ROOTS_XCURSOR_MOVE, seat->cursor->cursor); } void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view, @@ -551,8 +553,8 @@ void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view, view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_resize(seat->cursor->xcursor_theme, - seat->cursor->cursor, edges); + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + roots_xcursor_get_resize_name(edges), seat->cursor->cursor); } void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) { @@ -564,6 +566,6 @@ void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) { view_maximize(view, false); wlr_seat_pointer_clear_focus(seat->seat); - roots_xcursor_theme_set_rotate(seat->cursor->xcursor_theme, - seat->cursor->cursor); + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, + ROOTS_XCURSOR_ROTATE, seat->cursor->cursor); } diff --git a/rootston/xcursor.c b/rootston/xcursor.c index 6aa74bc4..74e732c9 100644 --- a/rootston/xcursor.c +++ b/rootston/xcursor.c @@ -4,83 +4,7 @@ #include "rootston/xcursor.h" #include "rootston/input.h" -struct roots_xcursor_theme *roots_xcursor_theme_create(const char *name) { - struct roots_xcursor_theme *theme = - calloc(1, sizeof(struct roots_xcursor_theme)); - if (theme == NULL) { - return NULL; - } - theme->name = strdup(name); - wl_list_init(&theme->scaled_themes); - return theme; -} - -void roots_xcursor_theme_destroy(struct roots_xcursor_theme *theme) { - if (theme == NULL) { - return; - } - struct roots_xcursor_scaled_theme *scaled_theme, *tmp; - wl_list_for_each_safe(scaled_theme, tmp, &theme->scaled_themes, link) { - wl_list_remove(&scaled_theme->link); - wlr_xcursor_theme_destroy(scaled_theme->theme); - free(scaled_theme); - } - free(theme->name); - free(theme); -} - -int roots_xcursor_theme_load(struct roots_xcursor_theme *theme, - uint32_t scale) { - struct roots_xcursor_scaled_theme *scaled_theme; - wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { - if (scaled_theme->scale == scale) { - return 0; - } - } - - scaled_theme = calloc(1, sizeof(struct roots_xcursor_scaled_theme)); - if (scaled_theme == NULL) { - return 1; - } - scaled_theme->scale = scale; - scaled_theme->theme = wlr_xcursor_theme_load(NULL, - ROOTS_XCURSOR_SIZE * scale); - if (scaled_theme->theme == NULL) { - free(scaled_theme); - return 1; - } - wl_list_insert(&theme->scaled_themes, &scaled_theme->link); - return 0; -} - -static void roots_xcursor_theme_set(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor, const char *name) { - struct roots_xcursor_scaled_theme *scaled_theme; - wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { - struct wlr_xcursor *xcursor = - wlr_xcursor_theme_get_cursor(scaled_theme->theme, name); - if (xcursor == NULL) { - continue; - } - - struct wlr_xcursor_image *image = xcursor->images[0]; - wlr_cursor_set_image(cursor, image->buffer, image->width, - image->width, image->height, image->hotspot_x, image->hotspot_y, - scaled_theme->scale); - } -} - -void roots_xcursor_theme_set_default(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor) { - roots_xcursor_theme_set(theme, cursor, "left_ptr"); -} - -void roots_xcursor_theme_set_move(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor) { - roots_xcursor_theme_set(theme, cursor, "grabbing"); -} - -static const char *get_resize_xcursor_name(uint32_t edges) { +const char *roots_xcursor_get_resize_name(uint32_t edges) { if (edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { if (edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { return "ne-resize"; @@ -102,33 +26,3 @@ static const char *get_resize_xcursor_name(uint32_t edges) { } return "se-resize"; // fallback } - -void roots_xcursor_theme_set_resize(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor, uint32_t edges) { - roots_xcursor_theme_set(theme, cursor, get_resize_xcursor_name(edges)); -} - -void roots_xcursor_theme_set_rotate(struct roots_xcursor_theme *theme, - struct wlr_cursor *cursor) { - roots_xcursor_theme_set(theme, cursor, "grabbing"); -} - -void roots_xcursor_theme_xwayland_set_default(struct roots_xcursor_theme *theme, - struct wlr_xwayland *xwayland) { - struct roots_xcursor_scaled_theme *scaled_theme; - wl_list_for_each(scaled_theme, &theme->scaled_themes, link) { - if (scaled_theme->scale == 1) { - struct wlr_xcursor *xcursor = - wlr_xcursor_theme_get_cursor(scaled_theme->theme, "left_ptr"); - if (xcursor == NULL) { - continue; - } - - struct wlr_xcursor_image *image = xcursor->images[0]; - wlr_xwayland_set_cursor(xwayland, image->buffer, image->width, - image->width, image->height, image->hotspot_x, - image->hotspot_y); - break; - } - } -} diff --git a/types/meson.build b/types/meson.build index 2603ecfd..4669165a 100644 --- a/types/meson.build +++ b/types/meson.build @@ -20,8 +20,9 @@ lib_wlr_types = static_library( 'wlr_tablet_pad.c', 'wlr_tablet_tool.c', 'wlr_touch.c', - 'wlr_xdg_shell_v6.c', 'wlr_wl_shell.c', + 'wlr_xcursor_manager.c', + 'wlr_xdg_shell_v6.c', ), include_directories: wlr_inc, dependencies: [wayland_server, pixman, wlr_protos], diff --git a/types/wlr_xcursor_manager.c b/types/wlr_xcursor_manager.c new file mode 100644 index 00000000..6c12d04b --- /dev/null +++ b/types/wlr_xcursor_manager.c @@ -0,0 +1,84 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +struct wlr_xcursor_manager *wlr_xcursor_manager_create(const char *name, + uint32_t size) { + struct wlr_xcursor_manager *manager = + calloc(1, sizeof(struct wlr_xcursor_manager)); + if (manager == NULL) { + return NULL; + } + if (name != NULL) { + manager->name = strdup(name); + } + manager->size = size; + wl_list_init(&manager->scaled_themes); + return manager; +} + +void wlr_xcursor_manager_destroy(struct wlr_xcursor_manager *manager) { + if (manager == NULL) { + return; + } + struct wlr_xcursor_manager_theme *theme, *tmp; + wl_list_for_each_safe(theme, tmp, &manager->scaled_themes, link) { + wl_list_remove(&theme->link); + wlr_xcursor_theme_destroy(theme->theme); + free(theme); + } + free(manager->name); + free(manager); +} + +int wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager, + uint32_t scale) { + struct wlr_xcursor_manager_theme *theme; + wl_list_for_each(theme, &manager->scaled_themes, link) { + if (theme->scale == scale) { + return 0; + } + } + + theme = calloc(1, sizeof(struct wlr_xcursor_manager_theme)); + if (theme == NULL) { + return 1; + } + theme->scale = scale; + theme->theme = wlr_xcursor_theme_load(NULL, manager->size * scale); + if (theme->theme == NULL) { + free(theme); + return 1; + } + wl_list_insert(&manager->scaled_themes, &theme->link); + return 0; +} + +struct wlr_xcursor *wlr_xcursor_manager_get_xcursor( + struct wlr_xcursor_manager *manager, const char *name, uint32_t scale) { + struct wlr_xcursor_manager_theme *theme; + wl_list_for_each(theme, &manager->scaled_themes, link) { + if (theme->scale == scale) { + return wlr_xcursor_theme_get_cursor(theme->theme, name); + } + } + return NULL; +} + +void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager, + const char *name, struct wlr_cursor *cursor) { + struct wlr_xcursor_manager_theme *theme; + wl_list_for_each(theme, &manager->scaled_themes, link) { + struct wlr_xcursor *xcursor = + wlr_xcursor_theme_get_cursor(theme->theme, name); + if (xcursor == NULL) { + continue; + } + + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_cursor_set_image(cursor, image->buffer, image->width, + image->width, image->height, image->hotspot_x, image->hotspot_y, + theme->scale); + } +} From 5d986f1e874f93f8235fbcc333af63c5c9c99596 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 12 Nov 2017 15:49:27 +0100 Subject: [PATCH 5/6] Remove unnecessary include --- include/rootston/desktop.h | 2 +- rootston/desktop.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 7371284f..b809db43 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -7,12 +7,12 @@ #include #include #include +#include #include #include #include #include "rootston/view.h" #include "rootston/config.h" -#include "rootston/xcursor.h" struct roots_output { struct roots_desktop *desktop; diff --git a/rootston/desktop.c b/rootston/desktop.c index bb030e74..51bb0e2a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -16,6 +16,7 @@ #include #include "rootston/server.h" #include "rootston/seat.h" +#include "rootston/xcursor.h" // TODO replace me with a signal void view_destroy(struct roots_view *view) { From 2e312a7e27fac0ef299abbdf5f66cf164992f02f Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 12 Nov 2017 22:11:17 +0100 Subject: [PATCH 6/6] Fix hidden cursor when output is added before cursor --- rootston/seat.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/rootston/seat.c b/rootston/seat.c index 8a838efe..3ec6f1b7 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -189,12 +189,11 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { // TODO: be able to configure per-seat cursor themes seat->cursor->xcursor_manager = desktop->xcursor_manager; - wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, - ROOTS_XCURSOR_DEFAULT, wlr_cursor); wl_list_init(&seat->cursor->touch_points); roots_seat_configure_cursor(seat); + roots_seat_configure_xcursor(seat); // add input signals wl_signal_add(&wlr_cursor->events.motion, &seat->cursor->motion); @@ -448,6 +447,16 @@ void roots_seat_remove_device(struct roots_seat *seat, } void roots_seat_configure_xcursor(struct roots_seat *seat) { + struct roots_output *output; + wl_list_for_each(output, &seat->input->server->desktop->outputs, link) { + if (wlr_xcursor_manager_load(seat->cursor->xcursor_manager, + output->wlr_output->scale)) { + wlr_log(L_ERROR, "Cannot load xcursor theme for output '%s' " + "with scale %d", output->wlr_output->name, + output->wlr_output->scale); + } + } + wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, ROOTS_XCURSOR_DEFAULT, seat->cursor->cursor); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,