diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 7dfbe32715..344efec489 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -24,6 +24,7 @@ #define SDL_sysvideo_h_ #include "SDL_messagebox.h" +#include "SDL_mouse.h" #include "SDL_shape.h" #include "SDL_thread.h" #include "SDL_metal.h" @@ -529,6 +530,10 @@ extern int SDL_GetPointDisplayIndex(const SDL_Point *point); extern int SDL_GL_SwapWindowWithResult(SDL_Window *window); +#if defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_EMSCRIPTEN) +const char *SDL_GetCSSCursorName(SDL_SystemCursor id, const char **fallback_name); +#endif + #endif /* SDL_sysvideo_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 2ad82fafb8..ee723a57b1 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -4780,4 +4780,93 @@ void SDL_Metal_GetDrawableSize(SDL_Window *window, int *w, int *h) } } +#if defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_EMSCRIPTEN) +const char *SDL_GetCSSCursorName(SDL_SystemCursor id, const char **fallback_name) +{ + /* Reference: https://www.w3.org/TR/css-ui-4/#cursor */ + /* Also in: https://www.freedesktop.org/wiki/Specifications/cursor-spec/ */ + switch (id) { + case SDL_SYSTEM_CURSOR_ARROW: + return "default"; + + case SDL_SYSTEM_CURSOR_IBEAM: + return "text"; + + case SDL_SYSTEM_CURSOR_WAIT: + return "wait"; + + case SDL_SYSTEM_CURSOR_CROSSHAIR: + return "crosshair"; + + case SDL_SYSTEM_CURSOR_WAITARROW: + return "progress"; + + case SDL_SYSTEM_CURSOR_SIZENWSE: + if (fallback_name) { + /* only a single arrow */ + *fallback_name = "nw-resize"; + } + return "nwse-resize"; + + case SDL_SYSTEM_CURSOR_SIZENESW: + if (fallback_name) { + /* only a single arrow */ + *fallback_name = "ne-resize"; + } + return "nesw-resize"; + + case SDL_SYSTEM_CURSOR_SIZEWE: + if (fallback_name) { + *fallback_name = "col-resize"; + } + return "ew-resize"; + + case SDL_SYSTEM_CURSOR_SIZENS: + if (fallback_name) { + *fallback_name = "row-resize"; + } + return "ns-resize"; + + case SDL_SYSTEM_CURSOR_SIZEALL: + return "all-scroll"; + + case SDL_SYSTEM_CURSOR_NO: + return "not-allowed"; + + case SDL_SYSTEM_CURSOR_HAND: + return "pointer"; + +#if 0 + case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT: + return "nw-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_TOP: + return "n-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT: + return "ne-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_RIGHT: + return "e-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT: + return "se-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM: + return "s-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT: + return "sw-resize"; + + case SDL_SYSTEM_CURSOR_WINDOW_LEFT: + return "w-resize"; +#endif + + default: + SDL_assert(0); + return "default"; + } +} +#endif + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/emscripten/SDL_emscriptenmouse.c b/src/video/emscripten/SDL_emscriptenmouse.c index a3553a2fed..d189e5393c 100644 --- a/src/video/emscripten/SDL_emscriptenmouse.c +++ b/src/video/emscripten/SDL_emscriptenmouse.c @@ -141,49 +141,7 @@ static SDL_Cursor *Emscripten_CreateCursor(SDL_Surface *surface, int hot_x, int static SDL_Cursor *Emscripten_CreateSystemCursor(SDL_SystemCursor id) { - const char *cursor_name = NULL; - - switch (id) { - case SDL_SYSTEM_CURSOR_ARROW: - cursor_name = "default"; - break; - case SDL_SYSTEM_CURSOR_IBEAM: - cursor_name = "text"; - break; - case SDL_SYSTEM_CURSOR_WAIT: - cursor_name = "wait"; - break; - case SDL_SYSTEM_CURSOR_CROSSHAIR: - cursor_name = "crosshair"; - break; - case SDL_SYSTEM_CURSOR_WAITARROW: - cursor_name = "progress"; - break; - case SDL_SYSTEM_CURSOR_SIZENWSE: - cursor_name = "nwse-resize"; - break; - case SDL_SYSTEM_CURSOR_SIZENESW: - cursor_name = "nesw-resize"; - break; - case SDL_SYSTEM_CURSOR_SIZEWE: - cursor_name = "ew-resize"; - break; - case SDL_SYSTEM_CURSOR_SIZENS: - cursor_name = "ns-resize"; - break; - case SDL_SYSTEM_CURSOR_SIZEALL: - cursor_name = "all-scroll"; - break; - case SDL_SYSTEM_CURSOR_NO: - cursor_name = "not-allowed"; - break; - case SDL_SYSTEM_CURSOR_HAND: - cursor_name = "pointer"; - break; - default: - SDL_assert(0); - return NULL; - } + const char *cursor_name = SDL_GetCSSCursorName(id, NULL); return Emscripten_CreateCursorFromString(cursor_name, SDL_FALSE); } diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index c1f372011a..41e5e43480 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -161,6 +161,7 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa struct wl_cursor_theme *theme = NULL; struct wl_cursor *cursor; const char *cssname = NULL; + const char *fallback_name = NULL; const char *legacyname = NULL; char *xcursor_size; @@ -235,51 +236,39 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa /* Next, find the cursor from the theme... */ switch (cdata->system_cursor) { case SDL_SYSTEM_CURSOR_ARROW: - cssname = "default"; legacyname = "left_ptr"; break; case SDL_SYSTEM_CURSOR_IBEAM: - cssname = "text"; legacyname = "xterm"; break; case SDL_SYSTEM_CURSOR_WAIT: - cssname = "wait"; legacyname = "watch"; break; case SDL_SYSTEM_CURSOR_CROSSHAIR: - cssname = "crosshair"; legacyname = "tcross"; break; case SDL_SYSTEM_CURSOR_WAITARROW: - cssname = "progress"; legacyname = "watch"; break; case SDL_SYSTEM_CURSOR_SIZENWSE: - cssname = "nwse-resize"; legacyname = "top_left_corner"; break; case SDL_SYSTEM_CURSOR_SIZENESW: - cssname = "nesw-resize"; legacyname = "top_right_corner"; break; case SDL_SYSTEM_CURSOR_SIZEWE: - cssname = "ew-resize"; legacyname = "sb_h_double_arrow"; break; case SDL_SYSTEM_CURSOR_SIZENS: - cssname = "ns-resize"; legacyname = "sb_v_double_arrow"; break; case SDL_SYSTEM_CURSOR_SIZEALL: - cssname = "all-scroll"; legacyname = "fleur"; break; case SDL_SYSTEM_CURSOR_NO: - cssname = "not-allowed"; legacyname = "pirate"; break; case SDL_SYSTEM_CURSOR_HAND: - cssname = "pointer"; legacyname = "hand2"; break; default: @@ -287,7 +276,12 @@ static SDL_bool wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorDa return SDL_FALSE; } + cssname = SDL_GetCSSCursorName(cdata->system_cursor, &fallback_name); + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, cssname); + if (!cursor) { + cursor = WAYLAND_wl_cursor_theme_get_cursor(theme, fallback_name); + } /* try the legacy name if the fancy new CSS name doesn't work... */ if (!cursor) { diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 9469494020..22878c8f31 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -224,7 +224,7 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id) { SDL_Cursor *cursor = NULL; unsigned int shape = 0; - const char *xcursorname = NULL; + const char *xcursorname = SDL_GetCSSCursorName(id, NULL); switch (id) { default: @@ -234,51 +234,39 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id) /* http://tronche.com/gui/x/xlib/appendix/b/ */ case SDL_SYSTEM_CURSOR_ARROW: shape = XC_left_ptr; - xcursorname = "default"; break; case SDL_SYSTEM_CURSOR_IBEAM: shape = XC_xterm; - xcursorname = "text"; break; case SDL_SYSTEM_CURSOR_WAIT: shape = XC_watch; - xcursorname = "wait"; break; case SDL_SYSTEM_CURSOR_CROSSHAIR: shape = XC_tcross; - xcursorname = "crosshair"; break; case SDL_SYSTEM_CURSOR_WAITARROW: shape = XC_watch; - xcursorname = "progress"; break; case SDL_SYSTEM_CURSOR_SIZENWSE: shape = XC_top_left_corner; - xcursorname = "nwse-resize"; break; case SDL_SYSTEM_CURSOR_SIZENESW: shape = XC_top_right_corner; - xcursorname = "nesw-resize"; break; case SDL_SYSTEM_CURSOR_SIZEWE: shape = XC_sb_h_double_arrow; - xcursorname = "ew-resize"; break; case SDL_SYSTEM_CURSOR_SIZENS: shape = XC_sb_v_double_arrow; - xcursorname = "ns-resize"; break; case SDL_SYSTEM_CURSOR_SIZEALL: shape = XC_fleur; - xcursorname = "all-scroll"; break; case SDL_SYSTEM_CURSOR_NO: shape = XC_pirate; - xcursorname = "not-allowed"; break; case SDL_SYSTEM_CURSOR_HAND: shape = XC_hand2; - xcursorname = "pointer"; break; }