diff --git a/client/displayservers/Wayland/cursor.c b/client/displayservers/Wayland/cursor.c index 022b7a30..11ca15c1 100644 --- a/client/displayservers/Wayland/cursor.c +++ b/client/displayservers/Wayland/cursor.c @@ -90,6 +90,7 @@ static bool loadThemedCursor(const char * name, struct wl_surface ** surface, return NULL; wl_surface_attach(*surface, buffer, 0, 0); + wl_surface_set_buffer_scale(*surface, wlWm.cursorScale); wl_surface_commit(*surface); *hotspot = (struct Point) { @@ -126,6 +127,15 @@ static const char ** nameLists[LG_POINTER_COUNT] = { [LG_POINTER_NOT_ALLOWED] = (const char *[]) { "crossed_circle", "not-allowed", NULL }, }; +static void reloadCursors(void) +{ + if (wlWm.cursorTheme) + for (LG_DSPointer pointer = LG_POINTER_ARROW; pointer < LG_POINTER_COUNT; ++pointer) + for (const char ** names = nameLists[pointer]; *names; ++names) + if (loadThemedCursor(*names, wlWm.cursors + pointer, wlWm.cursorHot + pointer)) + break; +} + bool waylandCursorInit(void) { if (!wlWm.compositor) @@ -142,23 +152,20 @@ bool waylandCursorInit(void) wl_surface_commit(wlWm.cursors[LG_POINTER_SQUARE]); } - const char * cursorTheme = getenv("XCURSOR_THEME"); - const char * cursorSizeEnv = getenv("XCURSOR_SIZE"); - int cursorSize = 24; + wlWm.cursorThemeName = getenv("XCURSOR_THEME"); + wlWm.cursorSize = 24; + const char * cursorSizeEnv = getenv("XCURSOR_SIZE"); if (cursorSizeEnv) { int size = atoi(cursorSizeEnv); if (size) - cursorSize = size; + wlWm.cursorSize = size; } - wlWm.cursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, wlWm.shm); - if (wlWm.cursorTheme) - for (LG_DSPointer pointer = LG_POINTER_ARROW; pointer < LG_POINTER_COUNT; ++pointer) - for (const char ** names = nameLists[pointer]; *names; ++names) - if (loadThemedCursor(*names, wlWm.cursors + pointer, wlWm.cursorHot + pointer)) - break; + wlWm.cursorTheme = wl_cursor_theme_load(wlWm.cursorThemeName, wlWm.cursorSize, wlWm.shm); + wlWm.cursorScale = 1; + reloadCursors(); return true; } @@ -174,8 +181,39 @@ void waylandCursorFree(void) wl_buffer_destroy(wlWm.cursorSquareBuffer); } +void waylandCursorScaleChange(void) +{ + int newScale = ceil(wl_fixed_to_double(wlWm.scale)); + if (newScale == wlWm.cursorScale) + return; + + struct wl_cursor_theme * new = wl_cursor_theme_load(wlWm.cursorThemeName, + wlWm.cursorSize * newScale, wlWm.shm); + + if (!new) + return; + + struct wl_surface * old[LG_POINTER_COUNT]; + memcpy(old, wlWm.cursors, sizeof(old)); + memset(wlWm.cursors, 0, sizeof(wlWm.cursors)); + + if (wlWm.cursorTheme) + wl_cursor_theme_destroy(wlWm.cursorTheme); + + wlWm.cursorTheme = new; + wlWm.cursorScale = newScale; + reloadCursors(); + + waylandSetPointer(wlWm.cursorId); + + for (int i = 0; i < LG_POINTER_COUNT; ++i) + if (old[i]) + wl_surface_destroy(old[i]); +} + void waylandSetPointer(LG_DSPointer pointer) { + wlWm.cursorId = pointer; wlWm.cursor = wlWm.cursors[pointer]; wlWm.cursorHotX = wlWm.cursorHot[pointer].x; wlWm.cursorHotY = wlWm.cursorHot[pointer].y; diff --git a/client/displayservers/Wayland/wayland.h b/client/displayservers/Wayland/wayland.h index e454bd91..d4a4d086 100644 --- a/client/displayservers/Wayland/wayland.h +++ b/client/displayservers/Wayland/wayland.h @@ -143,10 +143,14 @@ struct WaylandDSState struct zxdg_toplevel_decoration_v1 * xdgToplevelDecoration; #endif + const char * cursorThemeName; + int cursorSize; + int cursorScale; struct wl_cursor_theme * cursorTheme; struct wl_buffer * cursorSquareBuffer; struct wl_surface * cursors[LG_POINTER_COUNT]; struct Point cursorHot[LG_POINTER_COUNT]; + LG_DSPointer cursorId; struct wl_surface * cursor; int cursorHotX; int cursorHotY; @@ -238,6 +242,7 @@ void waylandCBInvalidate(void); bool waylandCursorInit(void); void waylandCursorFree(void); void waylandSetPointer(LG_DSPointer pointer); +void waylandCursorScaleChange(void); // gl module #if defined(ENABLE_EGL) || defined(ENABLE_OPENGL) diff --git a/client/displayservers/Wayland/window.c b/client/displayservers/Wayland/window.c index 85720cfd..136d35c9 100644 --- a/client/displayservers/Wayland/window.c +++ b/client/displayservers/Wayland/window.c @@ -48,6 +48,7 @@ void waylandWindowUpdateScale(void) wlWm.scale = maxScale; wlWm.fractionalScale = wl_fixed_from_int(wl_fixed_to_int(maxScale)) != maxScale; wlWm.needsResize = true; + waylandCursorScaleChange(); app_invalidateWindow(true); waylandStopWaitFrame(); }