diff --git a/docs/changelog.rst b/docs/changelog.rst index bb7ef9f61..6ef6c7100 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -178,6 +178,8 @@ Detailed list of changes - Command palette: Improve searching to use word level matching (:pull:`9727`) +- GLFW: Add ``glfwGetKeyboardRepeatDelay()`` to the GLFW API to query the current keyboard key-repeat initial delay and repeat interval from the OS, implemented for X11, Wayland and Cocoa backends + 0.46.2 [2026-03-21] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index f1342b457..4a16bb45e 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -2782,6 +2782,12 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED) return s_double_to_monotonic_t([NSEvent doubleClickInterval]); } +void _glfwPlatformGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval) +{ + if (delay) *delay = s_double_to_monotonic_t([NSEvent keyRepeatDelay]); + if (interval) *interval = s_double_to_monotonic_t([NSEvent keyRepeatInterval]); +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { [window->ns.object miniaturize:nil]; diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 497385dcd..002e58b17 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -4370,6 +4370,7 @@ GLFWAPI void glfwPostEmptyEvent(void); GLFWAPI bool glfwGetIgnoreOSKeyboardProcessing(void); GLFWAPI void glfwSetIgnoreOSKeyboardProcessing(bool enabled); GLFWAPI bool glfwGrabKeyboard(int grab); +GLFWAPI void glfwGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval); /*! @brief Returns the value of an input option for the specified window. * diff --git a/glfw/input.c b/glfw/input.c index d35f11ba6..9ded16610 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -720,6 +720,13 @@ GLFWAPI bool glfwGrabKeyboard(int grab) { return _glfw.keyboard_grabbed; } +GLFWAPI void glfwGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval) { + _GLFW_REQUIRE_INIT(); + if (delay) *delay = ms_to_monotonic_t(500ll); + if (interval) *interval = ms_to_monotonic_t(30ll); + _glfwPlatformGetKeyboardRepeatDelay(delay, interval); +} + GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/glfw/internal.h b/glfw/internal.h index 71a647def..3821b403f 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -745,6 +745,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, float* xscale, float* yscale); monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window); +void _glfwPlatformGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval); void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformMaximizeWindow(_GLFWwindow* window); diff --git a/glfw/null_window.c b/glfw/null_window.c index b46279c9d..1c3c90b00 100644 --- a/glfw/null_window.c +++ b/glfw/null_window.c @@ -311,6 +311,12 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED) return ms_to_monotonic_t(500ll); } +void _glfwPlatformGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval) +{ + if (delay) *delay = ms_to_monotonic_t(500ll); + if (interval) *interval = ms_to_monotonic_t(30ll); +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { if (_glfw.null.focusedWindow == window) diff --git a/glfw/wl_window.c b/glfw/wl_window.c index ff3b8b69c..c176915e9 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -1769,6 +1769,13 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED) return ms_to_monotonic_t(500ll); } +void _glfwPlatformGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval) +{ + if (delay) *delay = _glfw.wl.keyboardRepeatDelay; + if (interval && _glfw.wl.keyboardRepeatRate > 0) + *interval = s_to_monotonic_t(1ll) / (monotonic_t)_glfw.wl.keyboardRepeatRate; +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { if (window->wl.xdg.toplevel) { diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 05c8ea094..6be8e14ca 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2876,6 +2876,18 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED) return ms_to_monotonic_t(500ll); } +void _glfwPlatformGetKeyboardRepeatDelay(monotonic_t *delay, monotonic_t *interval) +{ + XkbDescPtr xkb = XkbAllocKeyboard(); + if (xkb) { + if (XkbGetControls(_glfw.x11.display, XkbRepeatKeysMask, xkb) == Success) { + if (delay) *delay = ms_to_monotonic_t(xkb->ctrls->repeat_delay); + if (interval) *interval = ms_to_monotonic_t(xkb->ctrls->repeat_interval); + } + XkbFreeKeyboard(xkb, 0, True); + } +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen); diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index da2d85780..37a35891a 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -296,6 +296,9 @@ load_glfw(const char* path) { *(void **) (&glfwGrabKeyboard_impl) = dlsym(handle, "glfwGrabKeyboard"); if (glfwGrabKeyboard_impl == NULL) fail("Failed to load glfw function glfwGrabKeyboard with error: %s", dlerror()); + *(void **) (&glfwGetKeyboardRepeatDelay_impl) = dlsym(handle, "glfwGetKeyboardRepeatDelay"); + if (glfwGetKeyboardRepeatDelay_impl == NULL) fail("Failed to load glfw function glfwGetKeyboardRepeatDelay with error: %s", dlerror()); + *(void **) (&glfwGetInputMode_impl) = dlsym(handle, "glfwGetInputMode"); if (glfwGetInputMode_impl == NULL) fail("Failed to load glfw function glfwGetInputMode with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 9ca42a9a6..38d7f433d 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2206,6 +2206,10 @@ typedef bool (*glfwGrabKeyboard_func)(int); GFW_EXTERN glfwGrabKeyboard_func glfwGrabKeyboard_impl; #define glfwGrabKeyboard glfwGrabKeyboard_impl +typedef void (*glfwGetKeyboardRepeatDelay_func)(monotonic_t*, monotonic_t*); +GFW_EXTERN glfwGetKeyboardRepeatDelay_func glfwGetKeyboardRepeatDelay_impl; +#define glfwGetKeyboardRepeatDelay glfwGetKeyboardRepeatDelay_impl + typedef int (*glfwGetInputMode_func)(GLFWwindow*, int); GFW_EXTERN glfwGetInputMode_func glfwGetInputMode_impl; #define glfwGetInputMode glfwGetInputMode_impl