From d5f255cbce59d534d398a9f3635f58d4f234bcff Mon Sep 17 00:00:00 2001 From: Inaya Yousfi Date: Tue, 18 Aug 2026 20:05:45 +0200 Subject: [PATCH] fix(windows): allow modifier key repeat --- docs/consumers/README.md | 4 ++-- src/keyboard/sender/sender_windows.c | 18 +----------------- tests/test_c_api.c | 3 ++- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/docs/consumers/README.md b/docs/consumers/README.md index 08c2cb9..a885d38 100644 --- a/docs/consumers/README.md +++ b/docs/consumers/README.md @@ -161,8 +161,8 @@ Example: again before starting new repeated holds. - On Linux/uinput, this flag does not change the existing backend behavior. - On Windows, repeated keys are tied to the key/modifier mapping resolved by - the original `key_down(..., true)` call. Modifier-only holds do not repeat. - Multiple non-modifier keys may repeat simultaneously. + the original `key_down(..., true)` call. Modifier keys follow the same + opt-in repeat behavior. Multiple keys may repeat simultaneously. - `axidev_io_keyboard_release_all_modifiers()` cancels active Windows emulated repeats before releasing modifiers. - Repeated synthetic Windows events may be observed by the global listener. diff --git a/src/keyboard/sender/sender_windows.c b/src/keyboard/sender/sender_windows.c index fc20457..4a1a454 100644 --- a/src/keyboard/sender/sender_windows.c +++ b/src/keyboard/sender/sender_windows.c @@ -223,22 +223,6 @@ static void axidev_io_windows_repeat_remove_cancelled_locked( } } -static bool axidev_io_windows_key_is_modifier(axidev_io_keyboard_key_t key) { - switch (key) { - case AXIDEV_IO_KEY_SHIFT_LEFT: - case AXIDEV_IO_KEY_SHIFT_RIGHT: - case AXIDEV_IO_KEY_CTRL_LEFT: - case AXIDEV_IO_KEY_CTRL_RIGHT: - case AXIDEV_IO_KEY_ALT_LEFT: - case AXIDEV_IO_KEY_ALT_RIGHT: - case AXIDEV_IO_KEY_SUPER_LEFT: - case AXIDEV_IO_KEY_SUPER_RIGHT: - return true; - default: - return false; - } -} - static uint64_t axidev_io_windows_monotonic_time_ns(void) { return axidev_io_monotonic_time_ms() * 1000000ull; } @@ -723,7 +707,7 @@ axidev_io_result axidev_io_keyboard_sender_key_down_internal( return result; } - if (!repeat || axidev_io_windows_key_is_modifier(resolved_key)) { + if (!repeat) { result = axidev_io_keyboard_sender_hold_modifier_internal(mods); if (result != AXIDEV_IO_RESULT_OK) { return result; diff --git a/tests/test_c_api.c b/tests/test_c_api.c index 99b4cb6..b721847 100644 --- a/tests/test_c_api.c +++ b/tests/test_c_api.c @@ -215,9 +215,10 @@ static void test_windows_repeat_state(void) { (axidev_io_keyboard_key_with_modifier_t){AXIDEV_IO_KEY_SHIFT_LEFT, AXIDEV_IO_MOD_NONE}, true)); - TEST_CHECK_EQ_INT((int)axidev_io_windows_sender_repeat_count_for_tests(), 0); + TEST_CHECK_EQ_INT((int)axidev_io_windows_sender_repeat_count_for_tests(), 1); TEST_CHECK(axidev_io_keyboard_key_up((axidev_io_keyboard_key_with_modifier_t){ AXIDEV_IO_KEY_SHIFT_LEFT, AXIDEV_IO_MOD_NONE})); + TEST_CHECK_EQ_INT((int)axidev_io_windows_sender_repeat_count_for_tests(), 0); TEST_CHECK(axidev_io_keyboard_key_down( (axidev_io_keyboard_key_with_modifier_t){AXIDEV_IO_KEY_A,