[Wayland] Cursor types support

This commit is contained in:
Aleksei Bavshin 2024-01-07 09:25:33 -08:00 committed by lbonn
parent 1592525edb
commit 8f259ce9b0
4 changed files with 78 additions and 24 deletions

View file

@ -50,7 +50,7 @@ typedef struct {
size_t buffer_count; size_t buffer_count;
struct { struct {
char *theme_name; char *theme_name;
char **name; RofiCursorType type;
struct wl_cursor_theme *theme; struct wl_cursor_theme *theme;
struct wl_cursor *cursor; struct wl_cursor *cursor;
struct wl_cursor_image *image; struct wl_cursor_image *image;
@ -88,6 +88,7 @@ struct _wayland_seat {
int32_t delay; int32_t delay;
} repeat; } repeat;
uint32_t serial; uint32_t serial;
uint32_t pointer_serial;
struct wl_keyboard *keyboard; struct wl_keyboard *keyboard;
struct wl_pointer *pointer; struct wl_pointer *pointer;

View file

@ -44,4 +44,6 @@ gboolean display_get_surface_dimensions(int *width, int *height);
void display_set_surface_dimensions(int width, int height, int x_margin, void display_set_surface_dimensions(int width, int height, int x_margin,
int y_margin, int loc); int y_margin, int loc);
void wayland_display_set_cursor_type(RofiCursorType type);
#endif #endif

View file

@ -622,14 +622,35 @@ static void wayland_pointer_send_events(wayland_seat *self) {
rofi_view_maybe_update(state); rofi_view_maybe_update(state);
} }
static void wayland_pointer_enter(void *data, struct wl_pointer *pointer, static struct wl_cursor *
uint32_t serial, struct wl_surface *surface, rofi_cursor_type_to_wl_cursor(struct wl_cursor_theme *theme,
wl_fixed_t x, wl_fixed_t y) { RofiCursorType type) {
wayland_seat *self = data; static const char *const default_names[] = {
"default", "left_ptr", "top_left_arrow", "left-arrow", NULL};
static const char *const pointer_names[] = {"pointer", "hand1", NULL};
static const char *const text_names[] = {"text", "xterm", NULL};
if (!wayland_cursor_reload_theme(wayland->scale)) const char *const *name;
return; struct wl_cursor *cursor = NULL;
switch (type) {
case ROFI_CURSOR_POINTER:
name = pointer_names;
break;
case ROFI_CURSOR_TEXT:
name = text_names;
break;
default:
name = default_names;
break;
}
for (; cursor == NULL && *name != NULL; ++name) {
cursor = wl_cursor_theme_get_cursor(theme, *name);
}
return cursor;
}
static void wayland_cursor_update_for_seat(wayland_seat *seat) {
if (wayland->cursor.surface == NULL) { if (wayland->cursor.surface == NULL) {
wayland->cursor.surface = wl_compositor_create_surface(wayland->compositor); wayland->cursor.surface = wl_compositor_create_surface(wayland->compositor);
} }
@ -641,11 +662,53 @@ static void wayland_pointer_enter(void *data, struct wl_pointer *pointer,
} }
wl_pointer_set_cursor( wl_pointer_set_cursor(
self->pointer, serial, wayland->cursor.surface, seat->pointer, seat->pointer_serial, wayland->cursor.surface,
wayland->cursor.image->hotspot_x / wayland->cursor.scale, wayland->cursor.image->hotspot_x / wayland->cursor.scale,
wayland->cursor.image->hotspot_y / wayland->cursor.scale); wayland->cursor.image->hotspot_y / wayland->cursor.scale);
} }
static void wayland_pointer_enter(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t x, wl_fixed_t y) {
wayland_seat *self = data;
self->pointer_serial = serial;
if (!wayland_cursor_reload_theme(wayland->scale))
return;
wayland_cursor_update_for_seat(self);
}
void wayland_display_set_cursor_type(RofiCursorType type) {
wayland_seat *seat;
GHashTableIter iter;
struct wl_cursor *cursor;
if (wayland->cursor.type == type) {
return;
}
wayland->cursor.type = type;
if (wayland->cursor.theme == NULL) {
return;
}
cursor = rofi_cursor_type_to_wl_cursor(wayland->cursor.theme, type);
if (cursor == NULL) {
g_info("Failed to load cursor type %d", type);
return;
}
wayland->cursor.cursor = cursor;
g_hash_table_iter_init(&iter, wayland->seats);
while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
if (seat->pointer != NULL) {
wayland_cursor_update_for_seat(seat);
}
}
}
static void wayland_pointer_leave(void *data, struct wl_pointer *pointer, static void wayland_pointer_leave(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface) { uint32_t serial, struct wl_surface *surface) {
wayland_seat *self = data; wayland_seat *self = data;
@ -1140,9 +1203,6 @@ static const struct wl_output_listener wayland_output_listener = {
#endif #endif
}; };
static const char *const wayland_cursor_names[] = {
"left_ptr", "default", "top_left_arrow", "left-arrow", NULL};
static void wayland_registry_handle_global(void *data, static void wayland_registry_handle_global(void *data,
struct wl_registry *registry, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t name, const char *interface,
@ -1337,12 +1397,8 @@ static gboolean wayland_cursor_reload_theme(guint scale) {
wayland->cursor.theme = wl_cursor_theme_load(wayland->cursor.theme_name, wayland->cursor.theme = wl_cursor_theme_load(wayland->cursor.theme_name,
cursor_size, wayland->shm); cursor_size, wayland->shm);
if (wayland->cursor.theme != NULL) { if (wayland->cursor.theme != NULL) {
const char *const *cname = (const char *const *)wayland->cursor.name; wayland->cursor.cursor = rofi_cursor_type_to_wl_cursor(
for (cname = (cname != NULL) ? cname : wayland_cursor_names; wayland->cursor.theme, wayland->cursor.type);
(wayland->cursor.cursor == NULL) && (*cname != NULL); ++cname) {
wayland->cursor.cursor =
wl_cursor_theme_get_cursor(wayland->cursor.theme, *cname);
}
if (wayland->cursor.cursor == NULL) { if (wayland->cursor.cursor == NULL) {
wl_cursor_theme_destroy(wayland->cursor.theme); wl_cursor_theme_destroy(wayland->cursor.theme);
wayland->cursor.theme = NULL; wayland->cursor.theme = NULL;
@ -1370,6 +1426,7 @@ static gboolean wayland_display_setup(GMainLoop *main_loop,
wayland_error, NULL, NULL); wayland_error, NULL, NULL);
wayland->buffer_count = 3; wayland->buffer_count = 3;
wayland->cursor.type = ROFI_CURSOR_DEFAULT;
wayland->scale = 1; wayland->scale = 1;
wayland->outputs = g_hash_table_new(g_direct_hash, g_direct_equal); wayland->outputs = g_hash_table_new(g_direct_hash, g_direct_equal);

View file

@ -176,12 +176,6 @@ static void wayland_rofi_view_get_size(RofiViewState *state, gint *width,
*height = state->height; *height = state->height;
} }
static void wayland_rofi_view_set_cursor(RofiCursorType type) {
(void)type;
// TODO
}
static void wayland_rofi_view_ping_mouse(RofiViewState *state) { (void)state; } static void wayland_rofi_view_ping_mouse(RofiViewState *state) { (void)state; }
static gboolean wayland_rofi_view_reload_idle(G_GNUC_UNUSED gpointer data) { static gboolean wayland_rofi_view_reload_idle(G_GNUC_UNUSED gpointer data) {
@ -479,7 +473,7 @@ static view_proxy view_ = {
.calculate_window_height = wayland_rofi_view_calculate_window_height, .calculate_window_height = wayland_rofi_view_calculate_window_height,
.calculate_window_width = wayland_rofi_view_calculate_window_width, .calculate_window_width = wayland_rofi_view_calculate_window_width,
.window_update_size = wayland_rofi_view_window_update_size, .window_update_size = wayland_rofi_view_window_update_size,
.set_cursor = wayland_rofi_view_set_cursor, .set_cursor = wayland_display_set_cursor_type,
.ping_mouse = wayland_rofi_view_ping_mouse, .ping_mouse = wayland_rofi_view_ping_mouse,
.cleanup = wayland_rofi_view_cleanup, .cleanup = wayland_rofi_view_cleanup,