From 5ab8a665bef166ea7a4198b53fc7f54c0da6b253 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 21 Mar 2019 13:06:13 +0530 Subject: [PATCH] GLFW: Add more standard cursor shapes Also use an enum for the cursor shapes --- glfw/cocoa_window.m | 33 ++++++++++-------- glfw/glfw3.h | 45 ++++++++----------------- glfw/input.c | 11 ++---- glfw/internal.h | 2 +- glfw/wl_init.c | 34 ++++++++----------- glfw/wl_platform.h | 1 + glfw/wl_window.c | 79 +++++++++++++++++++++++++------------------- glfw/x11_window.c | 33 +++++++++--------- kitty/glfw-wrapper.c | 3 ++ kitty/glfw-wrapper.h | 49 ++++++++++----------------- 10 files changed, 135 insertions(+), 155 deletions(-) diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index eddc99dae..2110f9d26 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -1940,21 +1940,26 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape) { - - if (shape == GLFW_ARROW_CURSOR) - cursor->ns.object = [NSCursor arrowCursor]; - else if (shape == GLFW_IBEAM_CURSOR) - cursor->ns.object = [NSCursor IBeamCursor]; - else if (shape == GLFW_CROSSHAIR_CURSOR) - cursor->ns.object = [NSCursor crosshairCursor]; - else if (shape == GLFW_HAND_CURSOR) - cursor->ns.object = [NSCursor pointingHandCursor]; - else if (shape == GLFW_HRESIZE_CURSOR) - cursor->ns.object = [NSCursor resizeLeftRightCursor]; - else if (shape == GLFW_VRESIZE_CURSOR) - cursor->ns.object = [NSCursor resizeUpDownCursor]; +#define C(name, val) case name: cursor->ns.object = [NSCursor val]; break; +#define U(name, val) case name: cursor->ns.object = [[NSCursor class] performSelector:@selector(val)]; break; + switch(shape) { + C(GLFW_ARROW_CURSOR, arrowCursor); + C(GLFW_IBEAM_CURSOR, IBeamCursor); + C(GLFW_CROSSHAIR_CURSOR, crosshairCursor); + C(GLFW_HAND_CURSOR, pointingHandCursor); + C(GLFW_HRESIZE_CURSOR, resizeLeftRightCursor); + C(GLFW_VRESIZE_CURSOR, resizeUpDownCursor); + U(GLFW_NW_RESIZE_CURSOR, _windowResizeNorthWestSouthEastCursor); + U(GLFW_NE_RESIZE_CURSOR, _windowResizeNorthEastSouthWestCursor); + U(GLFW_SW_RESIZE_CURSOR, _windowResizeNorthEastSouthWestCursor); + U(GLFW_SE_RESIZE_CURSOR, _windowResizeNorthWestSouthEastCursor); + case GLFW_INVALID_CURSOR: + return GLFW_FALSE; + } +#undef C +#undef U if (!cursor->ns.object) { diff --git a/glfw/glfw3.h b/glfw/glfw3.h index b0a89f1ca..5e5a55124 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1032,36 +1032,19 @@ extern "C" { * @ingroup input * @{ */ -/*! @brief The regular arrow cursor shape. - * - * The regular arrow cursor. - */ -#define GLFW_ARROW_CURSOR 0x00036001 -/*! @brief The text input I-beam cursor shape. - * - * The text input I-beam cursor shape. - */ -#define GLFW_IBEAM_CURSOR 0x00036002 -/*! @brief The crosshair shape. - * - * The crosshair shape. - */ -#define GLFW_CROSSHAIR_CURSOR 0x00036003 -/*! @brief The hand shape. - * - * The hand shape. - */ -#define GLFW_HAND_CURSOR 0x00036004 -/*! @brief The horizontal resize arrow shape. - * - * The horizontal resize arrow shape. - */ -#define GLFW_HRESIZE_CURSOR 0x00036005 -/*! @brief The vertical resize arrow shape. - * - * The vertical resize arrow shape. - */ -#define GLFW_VRESIZE_CURSOR 0x00036006 +typedef enum { + GLFW_ARROW_CURSOR, + GLFW_IBEAM_CURSOR, + GLFW_CROSSHAIR_CURSOR, + GLFW_HAND_CURSOR, + GLFW_HRESIZE_CURSOR, + GLFW_VRESIZE_CURSOR, + GLFW_NW_RESIZE_CURSOR, + GLFW_NE_RESIZE_CURSOR, + GLFW_SW_RESIZE_CURSOR, + GLFW_SE_RESIZE_CURSOR, + GLFW_INVALID_CURSOR +} GLFWCursorShape; /*! @} */ #define GLFW_CONNECTED 0x00040001 @@ -4160,7 +4143,7 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot, * * @ingroup input */ -GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape); +GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape); /*! @brief Destroys a cursor. * diff --git a/glfw/input.c b/glfw/input.c index 5d007cb4c..e586a887a 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -831,20 +831,15 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot, return (GLFWcursor*) cursor; } -GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape) +GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape) { _GLFWcursor* cursor; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (shape != GLFW_ARROW_CURSOR && - shape != GLFW_IBEAM_CURSOR && - shape != GLFW_CROSSHAIR_CURSOR && - shape != GLFW_HAND_CURSOR && - shape != GLFW_HRESIZE_CURSOR && - shape != GLFW_VRESIZE_CURSOR) + if (shape >= GLFW_INVALID_CURSOR) { - _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape); + _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor: %d", shape); return NULL; } diff --git a/glfw/internal.h b/glfw/internal.h index 11d8a3f5c..cd97dd91e 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -608,7 +608,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot, int count); -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape); +int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape); void _glfwPlatformDestroyCursor(_GLFWcursor* cursor); void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor); diff --git a/glfw/wl_init.c b/glfw/wl_init.c index 680676d03..71023578e 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -126,21 +126,15 @@ static void pointerHandleLeave(void* data, _glfwInputCursorEnter(window, GLFW_FALSE); } -static void setCursor(const char* name) +static void setCursor(GLFWCursorShape shape) { struct wl_buffer* buffer; struct wl_cursor* cursor; struct wl_cursor_image* image; struct wl_surface* surface = _glfw.wl.cursorSurface; - cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, - name); - if (!cursor) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Standard cursor %s not found", name); - return; - } + cursor = _glfwLoadCursor(shape); + if (!cursor) return; // TODO: handle animated cursors too. image = cursor->images[0]; @@ -167,7 +161,7 @@ static void pointerHandleMotion(void* data, wl_fixed_t sy) { _GLFWwindow* window = _glfw.wl.pointerFocus; - const char* cursorName = NULL; + GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR; if (!window) return; @@ -189,34 +183,34 @@ static void pointerHandleMotion(void* data, return; case topDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - cursorName = "n-resize"; + cursorShape = GLFW_VRESIZE_CURSOR; else - cursorName = "left_ptr"; + cursorShape = GLFW_ARROW_CURSOR; break; case leftDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - cursorName = "nw-resize"; + cursorShape = GLFW_NW_RESIZE_CURSOR; else - cursorName = "w-resize"; + cursorShape = GLFW_HRESIZE_CURSOR; break; case rightDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - cursorName = "ne-resize"; + cursorShape = GLFW_NE_RESIZE_CURSOR; else - cursorName = "e-resize"; + cursorShape = GLFW_HRESIZE_CURSOR; break; case bottomDecoration: if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH) - cursorName = "sw-resize"; + cursorShape = GLFW_SW_RESIZE_CURSOR; else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH) - cursorName = "se-resize"; + cursorShape = GLFW_SE_RESIZE_CURSOR; else - cursorName = "s-resize"; + cursorShape = GLFW_VRESIZE_CURSOR; break; default: assert(0); } - setCursor(cursorName); + setCursor(cursorShape); } static void pointerHandleButton(void* data, diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index c46e957bc..c1fb800a0 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -323,3 +323,4 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwSetupWaylandDataDevice(); void _glfwSetupWaylandPrimarySelectionDevice(); void animateCursorImage(id_type timer_id, void *data); +struct wl_cursor* _glfwLoadCursor(GLFWCursorShape); diff --git a/glfw/wl_window.c b/glfw/wl_window.c index db4157077..4f13b9622 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -877,26 +877,50 @@ handleEvents(double timeout) glfw_dbus_session_bus_dispatch(); } -// Translates a GLFW standard cursor to a theme cursor name -// -static const char *translateCursorShape(int shape) +static struct wl_cursor* +try_cursor_names(int arg_count, ...) { + struct wl_cursor* ans = NULL; + va_list ap; + va_start(ap, arg_count); + for (int i = 0; i < arg_count && !ans; i++) { + const char *name = va_arg(ap, const char *); + ans = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name); + } + va_end(ap); + return ans; +} + +struct wl_cursor* _glfwLoadCursor(GLFWCursorShape shape) { + static GLFWbool warnings[GLFW_INVALID_CURSOR] = {0}; +#define NUMARGS(...) (sizeof((const char*[]){__VA_ARGS__})/sizeof(const char*)) +#define C(name, ...) case name: { \ + ans = try_cursor_names(NUMARGS(__VA_ARGS__), __VA_ARGS__); \ + if (!ans && !warnings[name]) {\ + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Could not find standard cursor: %s", #name); \ + warnings[name] = GLFW_TRUE; \ + } \ + break; } + + struct wl_cursor* ans = NULL; switch (shape) { - case GLFW_ARROW_CURSOR: - return "left_ptr"; - case GLFW_IBEAM_CURSOR: - return "xterm"; - case GLFW_CROSSHAIR_CURSOR: - return "crosshair"; - case GLFW_HAND_CURSOR: - return "hand2"; - case GLFW_HRESIZE_CURSOR: - return "sb_h_double_arrow"; - case GLFW_VRESIZE_CURSOR: - return "sb_v_double_arrow"; + C(GLFW_ARROW_CURSOR, "left_ptr", "default") + C(GLFW_IBEAM_CURSOR, "xterm", "ibeam", "text") + C(GLFW_CROSSHAIR_CURSOR, "crosshair", "cross") + C(GLFW_HAND_CURSOR, "hand2", "grab", "grabbing", "closedhand") + C(GLFW_HRESIZE_CURSOR, "sb_h_double_arrow", "h_double_arrow", "col-resize") + C(GLFW_VRESIZE_CURSOR, "sb_v_double_arrow", "v_double_arrow", "row-resize") + C(GLFW_NW_RESIZE_CURSOR, "top_left_corner", "nw-resize") + C(GLFW_NE_RESIZE_CURSOR, "top_right_corner", "ne-resize") + C(GLFW_SW_RESIZE_CURSOR, "bottom_left_corner", "sw-resize") + C(GLFW_SE_RESIZE_CURSOR, "bottom_right_corner", "se-resize") + case GLFW_INVALID_CURSOR: + break; } - return NULL; + return ans; +#undef NUMARGS +#undef C } ////////////////////////////////////////////////////////////////////////// @@ -1405,20 +1429,12 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape) { struct wl_cursor* standardCursor; - standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, - translateCursorShape(shape)); - if (!standardCursor) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Standard cursor \"%s\" not found", - translateCursorShape(shape)); - return GLFW_FALSE; - } - + standardCursor = _glfwLoadCursor(shape); + if (!standardCursor) return GLFW_FALSE; cursor->wl.cursor = standardCursor; cursor->wl.currentImage = 0; return GLFW_TRUE; @@ -1555,13 +1571,8 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) setCursorImage(&cursor->wl); else { - defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, translateCursorShape(GLFW_ARROW_CURSOR)); - if (!defaultCursor) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Standard arrow cursor not found"); - return; - } + defaultCursor = _glfwLoadCursor(GLFW_ARROW_CURSOR); + if (!defaultCursor) return; _GLFWcursorWayland cursorWayland = { defaultCursor, NULL, diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 7c00d2a16..8ca8ff85f 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2632,24 +2632,25 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape) { int native = 0; - - if (shape == GLFW_ARROW_CURSOR) - native = XC_left_ptr; - else if (shape == GLFW_IBEAM_CURSOR) - native = XC_xterm; - else if (shape == GLFW_CROSSHAIR_CURSOR) - native = XC_crosshair; - else if (shape == GLFW_HAND_CURSOR) - native = XC_hand2; - else if (shape == GLFW_HRESIZE_CURSOR) - native = XC_sb_h_double_arrow; - else if (shape == GLFW_VRESIZE_CURSOR) - native = XC_sb_v_double_arrow; - else - return GLFW_FALSE; +#define C(name, val) case name: native = val; break; + switch(shape) { + C(GLFW_ARROW_CURSOR, XC_left_ptr); + C(GLFW_IBEAM_CURSOR, XC_xterm); + C(GLFW_CROSSHAIR_CURSOR, XC_crosshair); + C(GLFW_HAND_CURSOR, XC_hand2); + C(GLFW_HRESIZE_CURSOR, XC_sb_h_double_arrow); + C(GLFW_VRESIZE_CURSOR, XC_sb_v_double_arrow); + C(GLFW_NW_RESIZE_CURSOR, XC_top_left_corner); + C(GLFW_NE_RESIZE_CURSOR, XC_top_right_corner); + C(GLFW_SW_RESIZE_CURSOR, XC_bottom_left_corner); + C(GLFW_SE_RESIZE_CURSOR, XC_bottom_right_corner); + case GLFW_INVALID_CURSOR: + return GLFW_FALSE; + } +#undef C cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native); if (!cursor->x11.handle) diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 3f5595582..5970e085a 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -62,6 +62,9 @@ load_glfw(const char* path) { *(void **) (&glfwGetMonitorPos_impl) = dlsym(handle, "glfwGetMonitorPos"); if (glfwGetMonitorPos_impl == NULL) fail("Failed to load glfw function glfwGetMonitorPos with error: %s", dlerror()); + *(void **) (&glfwGetMonitorWorkarea_impl) = dlsym(handle, "glfwGetMonitorWorkarea"); + if (glfwGetMonitorWorkarea_impl == NULL) fail("Failed to load glfw function glfwGetMonitorWorkarea with error: %s", dlerror()); + *(void **) (&glfwGetMonitorPhysicalSize_impl) = dlsym(handle, "glfwGetMonitorPhysicalSize"); if (glfwGetMonitorPhysicalSize_impl == NULL) fail("Failed to load glfw function glfwGetMonitorPhysicalSize with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 3f09e8354..06c48bc85 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -789,36 +789,19 @@ * @ingroup input * @{ */ -/*! @brief The regular arrow cursor shape. - * - * The regular arrow cursor. - */ -#define GLFW_ARROW_CURSOR 0x00036001 -/*! @brief The text input I-beam cursor shape. - * - * The text input I-beam cursor shape. - */ -#define GLFW_IBEAM_CURSOR 0x00036002 -/*! @brief The crosshair shape. - * - * The crosshair shape. - */ -#define GLFW_CROSSHAIR_CURSOR 0x00036003 -/*! @brief The hand shape. - * - * The hand shape. - */ -#define GLFW_HAND_CURSOR 0x00036004 -/*! @brief The horizontal resize arrow shape. - * - * The horizontal resize arrow shape. - */ -#define GLFW_HRESIZE_CURSOR 0x00036005 -/*! @brief The vertical resize arrow shape. - * - * The vertical resize arrow shape. - */ -#define GLFW_VRESIZE_CURSOR 0x00036006 +typedef enum { + GLFW_ARROW_CURSOR, + GLFW_IBEAM_CURSOR, + GLFW_CROSSHAIR_CURSOR, + GLFW_HAND_CURSOR, + GLFW_HRESIZE_CURSOR, + GLFW_VRESIZE_CURSOR, + GLFW_NW_RESIZE_CURSOR, + GLFW_NE_RESIZE_CURSOR, + GLFW_SW_RESIZE_CURSOR, + GLFW_SE_RESIZE_CURSOR, + GLFW_INVALID_CURSOR +} GLFWCursorShape; /*! @} */ #define GLFW_CONNECTED 0x00040001 @@ -1489,6 +1472,10 @@ typedef void (*glfwGetMonitorPos_func)(GLFWmonitor*, int*, int*); glfwGetMonitorPos_func glfwGetMonitorPos_impl; #define glfwGetMonitorPos glfwGetMonitorPos_impl +typedef void (*glfwGetMonitorWorkarea_func)(GLFWmonitor*, int*, int*, int*, int*); +glfwGetMonitorWorkarea_func glfwGetMonitorWorkarea_impl; +#define glfwGetMonitorWorkarea glfwGetMonitorWorkarea_impl + typedef void (*glfwGetMonitorPhysicalSize_func)(GLFWmonitor*, int*, int*); glfwGetMonitorPhysicalSize_func glfwGetMonitorPhysicalSize_impl; #define glfwGetMonitorPhysicalSize glfwGetMonitorPhysicalSize_impl @@ -1753,7 +1740,7 @@ typedef GLFWcursor* (*glfwCreateCursor_func)(const GLFWimage*, int, int, int); glfwCreateCursor_func glfwCreateCursor_impl; #define glfwCreateCursor glfwCreateCursor_impl -typedef GLFWcursor* (*glfwCreateStandardCursor_func)(int); +typedef GLFWcursor* (*glfwCreateStandardCursor_func)(GLFWCursorShape); glfwCreateStandardCursor_func glfwCreateStandardCursor_impl; #define glfwCreateStandardCursor glfwCreateStandardCursor_impl