diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-05 15:05:25 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-05 15:05:25 +0100 |
| commit | 522728de8cf1d4f24ab5d56ab400b8d6676228b4 (patch) | |
| tree | bf7595024fdcb59e4f6db4bc9726d2ed02eef161 /src/drivers | |
| parent | 11325da073a78b5a012e64b9732e253b50289763 (diff) | |
Wayland: use modern approach to cursor shapes with the "Cursor shape" protocol.
This removes the need to guess names of files each theme gives to cursor shapes
and makes linking with dbus superfluous when the compositor supports
the new protocol.
The old, surface-based approach to cursor shapes remains used for custom shapes.
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.H | 6 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 105 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 13 |
3 files changed, 111 insertions, 13 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H index 084e0c967..8ef7a1e10 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H @@ -2,7 +2,7 @@ // Definition of the Wayland Screen interface // for the Fast Light Tool Kit (FLTK). // -// Copyright 2010-2024 by Bill Spitzak and others. +// Copyright 2010-2026 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -110,6 +110,10 @@ public: #if HAVE_XDG_DIALOG struct xdg_wm_dialog_v1 *xdg_wm_dialog; #endif +#if HAVE_CURSOR_SHAPE + struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager; + struct wp_cursor_shape_device_v1 *wp_cursor_shape_device; +#endif // constructor Fl_Wayland_Screen_Driver(); diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index a0911cb51..ea4c8f97c 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -1,7 +1,7 @@ // // Implementation of Wayland Screen interface // -// Copyright 1998-2025 by Bill Spitzak and others. +// Copyright 1998-2026 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -39,6 +39,9 @@ #if HAVE_XDG_DIALOG # include "xdg-dialog-client-protocol.h" #endif +#if HAVE_CURSOR_SHAPE +# include "cursor-shape-client-protocol.h" +#endif #include <assert.h> #include <sys/mman.h> #include <poll.h> @@ -127,7 +130,7 @@ void Fl_Wayland_Screen_Driver::do_set_cursor( struct wl_buffer *buffer; const int scale = seat->pointer_scale; - if (!seat->cursor_theme || !seat->wl_pointer) + if ((!seat->cursor_theme && !wl_cursor) || !seat->wl_pointer) return; if (!wl_cursor) wl_cursor = seat->default_cursor; @@ -226,7 +229,48 @@ static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t se // use custom cursor if present struct wl_cursor *cursor = fl_wl_xid(win)->custom_cursor ? fl_wl_xid(win)->custom_cursor->wl_cursor : NULL; - Fl_Wayland_Screen_Driver::do_set_cursor(seat, cursor); +#if HAVE_CURSOR_SHAPE + static struct cursor_shape_struct { + Fl_Cursor c; + int shape; + } cursor_shape_array[] = { + {FL_CURSOR_ARROW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT }, + {FL_CURSOR_CROSS, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR }, + {FL_CURSOR_WAIT, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT }, + {FL_CURSOR_INSERT, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT }, + {FL_CURSOR_HAND, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB }, + {FL_CURSOR_HELP, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP }, + {FL_CURSOR_MOVE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE }, + {FL_CURSOR_N, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE }, + {FL_CURSOR_E, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE }, + {FL_CURSOR_W, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE }, + {FL_CURSOR_S, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE }, + {FL_CURSOR_NS, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE }, + {FL_CURSOR_WE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE }, + {FL_CURSOR_SW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE }, + {FL_CURSOR_SE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE }, + {FL_CURSOR_NE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE }, + {FL_CURSOR_NW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE }, + {FL_CURSOR_NESW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE }, + {FL_CURSOR_NWSE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE } + }; + + Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); + if (scr_driver->wp_cursor_shape_device && !cursor) { + int shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT; + for (int i = 0; i < sizeof(cursor_shape_array)/sizeof(cursor_shape_struct); i++) { + if (cursor_shape_array[i].c == Fl_Wayland_Window_Driver::driver(win)->standard_cursor()) { + shape = cursor_shape_array[i].shape; + break; + } + } + wp_cursor_shape_device_v1_set_shape(scr_driver->wp_cursor_shape_device, serial, shape); + } else { +#endif + Fl_Wayland_Screen_Driver::do_set_cursor(seat, cursor); +#if HAVE_CURSOR_SHAPE + } +#endif seat->serial = serial; seat->pointer_enter_serial = serial; set_event_xy(win); @@ -472,6 +516,15 @@ static struct wl_surface_listener cursor_surface_listener = { static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat) { + Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); + if (!seat->cursor_surface) { + seat->cursor_surface = wl_compositor_create_surface(scr_driver->wl_compositor); + wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); + } +#if HAVE_CURSOR_SHAPE + if (scr_driver->wp_cursor_shape_manager) return; +#endif + char *name; int size; struct wl_cursor_theme *theme; @@ -481,10 +534,8 @@ static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat) { size = 24; } size *= seat->pointer_scale; - Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); theme = wl_cursor_theme_load(name, size, scr_driver->wl_shm); free(name); - //struct wl_cursor_theme *old_theme = seat->cursor_theme; if (theme != NULL) { if (seat->cursor_theme) { // caution to destroy theme because Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor) caches used cursors @@ -497,10 +548,6 @@ static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat) { seat->default_cursor = scr_driver->xc_cursor[Fl_Wayland_Screen_Driver::arrow] = wl_cursor_theme_get_cursor(seat->cursor_theme, "left_ptr"); } - if (!seat->cursor_surface) { - seat->cursor_surface = wl_compositor_create_surface(scr_driver->wl_compositor); - wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); - } } @@ -1043,12 +1090,19 @@ void Fl_Wayland_Screen_Driver::disable_im() { static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { + Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) { seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); seat->pointer_scale = 1; +#if HAVE_CURSOR_SHAPE + if (scr_driver->wp_cursor_shape_manager) { + scr_driver->wp_cursor_shape_device = + wp_cursor_shape_manager_v1_get_pointer(scr_driver->wp_cursor_shape_manager, seat->wl_pointer); + } +#endif // HAVE_CURSOR_SHAPE init_cursors(seat); } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) { wl_pointer_release(seat->wl_pointer); @@ -1066,7 +1120,6 @@ static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capa wl_keyboard_release(seat->wl_keyboard); seat->wl_keyboard = NULL; } - Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); scr_driver->enable_im(); } @@ -1334,6 +1387,11 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis scr_driver->xdg_wm_dialog = (struct xdg_wm_dialog_v1 *) wl_registry_bind(wl_registry, id, &xdg_wm_dialog_v1_interface, 1); #endif // HAVE_XDG_DIALOG +#if HAVE_CURSOR_SHAPE + } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { + scr_driver->wp_cursor_shape_manager = (struct wp_cursor_shape_manager_v1 *) + wl_registry_bind(wl_registry, id, &wp_cursor_shape_manager_v1_interface, 1); +#endif // HAVE_CURSOR_SHAPE } } @@ -1412,6 +1470,10 @@ Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Unix_Screen_Driver() { #if HAVE_XDG_DIALOG xdg_wm_dialog = NULL; #endif +#if HAVE_CURSOR_SHAPE + wp_cursor_shape_manager = NULL; + wp_cursor_shape_device = NULL; +#endif } @@ -1432,7 +1494,12 @@ static void sync_done(void *data, struct wl_callback *cb, uint32_t time) { Fl_Wayland_Screen_Driver::compositor = (pair->found_wf_shell ? Fl_Wayland_Screen_Driver::WAYFIRE : Fl_Wayland_Screen_Driver::MUTTER); } - if (scr_driver->seat) try_update_cursor(scr_driver->seat); + if (scr_driver->seat) { +#if HAVE_CURSOR_SHAPE + if (!scr_driver->wp_cursor_shape_manager) +#endif + try_update_cursor(scr_driver->seat); + } if (Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::OWL) scr_driver->init_workarea(); } @@ -1566,6 +1633,22 @@ void Fl_Wayland_Screen_Driver::close_display() { xdg_wm_base_destroy(xdg_wm_base); xdg_wm_base = NULL; Fl_Wayland_Plugin *plugin = Fl_Wayland_Window_Driver::gl_plugin(); if (plugin) plugin->terminate(); +#if HAVE_XDG_DIALOG + if (xdg_wm_dialog) { + xdg_wm_dialog_v1_destroy(xdg_wm_dialog); + xdg_wm_dialog = NULL; + } +#endif // HAVE_XDG_DIALOG +#if HAVE_CURSOR_SHAPE + if (wp_cursor_shape_device ) { + wp_cursor_shape_device_v1_destroy(wp_cursor_shape_device); + wp_cursor_shape_device = NULL; + } + if (wp_cursor_shape_manager ) { + wp_cursor_shape_manager_v1_destroy(wp_cursor_shape_manager); + wp_cursor_shape_manager = NULL; + } +#endif // HAVE_CURSOR_SHAPE Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display)); wl_registry_destroy(wl_registry); wl_registry = NULL; diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index 7cd9810a9..9b709ee0a 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -1,7 +1,7 @@ // // Implementation of the Wayland window driver. // -// Copyright 1998-2025 by Bill Spitzak and others. +// Copyright 1998-2026 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -1682,6 +1682,17 @@ void Fl_Wayland_Window_Driver::makeWindow() int Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor c) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow); +#if HAVE_CURSOR_SHAPE + if (scr_driver->wp_cursor_shape_device) { + if (xid->custom_cursor) { + delete_cursor(xid->custom_cursor); + xid->custom_cursor = NULL; + } + if (c == FL_CURSOR_NONE) return 0; + standard_cursor_ = c; + return 1; + } +#endif // HAVE_CURSOR_SHAPE if (!scr_driver->seat->cursor_theme) return 1; // Cursor names are the files of directory /usr/share/icons/XXXX/cursors/ // where XXXX is the name of the current 'cursor theme'. |
