diff --git a/include/xwayland.h b/include/xwayland.h index 0072106e..99867e3e 100644 --- a/include/xwayland.h +++ b/include/xwayland.h @@ -95,5 +95,7 @@ void xwayland_adjust_usable_area(struct view *view, void xwayland_update_workarea(struct server *server); +void xwayland_reset_cursor(struct server *server); + #endif /* HAVE_XWAYLAND */ #endif /* LABWC_XWAYLAND_H */ diff --git a/src/input/cursor.c b/src/input/cursor.c index 975a295e..3e3c0003 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -26,6 +26,7 @@ #include "resistance.h" #include "ssd.h" #include "view.h" +#include "xwayland.h" #define LAB_CURSOR_SHAPE_V1_VERSION 1 @@ -1403,6 +1404,9 @@ void cursor_reload(struct seat *seat) { cursor_load(seat); +#if HAVE_XWAYLAND + xwayland_reset_cursor(seat->server); +#endif cursor_update_image(seat); } diff --git a/src/xwayland.c b/src/xwayland.c index 2e537038..d4eff83d 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -1128,6 +1128,56 @@ xwayland_adjust_stacking_order(struct server *server) wl_array_release(&views); } +void +xwayland_reset_cursor(struct server *server) +{ + /* + * As xwayland caches the pixel data when not yet started up + * due to the delayed lazy startup approach, we do have to + * re-set the xwayland cursor image. Otherwise the first X11 + * client connected will cause the xwayland server to use + * the cached (and potentially destroyed) pixel data. + * + * Calling this function after reloading the cursor theme + * ensures that the cached pixel data keeps being valid. + * + * To reproduce: + * - Compile with b_sanitize=address,undefined + * - Start labwc (nothing in autostart that could create + * a X11 connection, e.g. no GTK or X11 application) + * - Reconfigure + * - Start some X11 client + */ + + if (!server->xwayland) { + return; + } + + struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( + server->seat.xcursor_manager, XCURSOR_DEFAULT, 1); + + if (xcursor && !server->xwayland->xwm) { + /* Prevents setting the cursor on an active xwayland server */ + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(server->xwayland, image->buffer, + image->width * 4, image->width, + image->height, image->hotspot_x, + image->hotspot_y); + return; + } + + if (server->xwayland->cursor) { + /* + * The previous configured theme has set the + * default cursor or the xwayland server is + * currently running but still has a cached + * xcursor set that will be used on the next + * xwayland destroy -> lazy startup cycle. + */ + zfree(server->xwayland->cursor); + } +} + void xwayland_server_finish(struct server *server) {