xwayland: reset cursor image on cursor theme reload

As wlr_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 when reloading the cursor
theme. Otherwise the first X11 client connected will cause
the xwayland server to use the cached (and destroyed) pixel
data.

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
This commit is contained in:
Consolatis 2024-06-10 00:01:54 +02:00 committed by Johan Malm
parent 9ff7f27dab
commit 067c59e526
3 changed files with 56 additions and 0 deletions

View file

@ -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 */

View file

@ -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);
}

View file

@ -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)
{