-- v3: win32u: Implement opt-in auto-repeat for WM_(SYS)KEYDOWN messages. winewayland.drv: Configure win32u keyboard repeat delay and speed.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 8 ++++++++ dlls/win32u/ntuser_private.h | 3 +++ dlls/win32u/sysparams.c | 3 +++ dlls/winewayland.drv/wayland_keyboard.c | 16 +++++++++++++++- include/ntuser.h | 1 + 5 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d2909339983..e897ead329e 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -288,6 +288,7 @@ struct send_message_info };
static const INPUT_MESSAGE_SOURCE msg_source_unavailable = { IMDT_UNAVAILABLE, IMO_UNAVAILABLE }; +static BOOL keyboard_auto_repeat_enabled;
/* flag for messages that contain pointers */ /* 32 messages per entry, messages 0..31 map to bits 0..31 */ @@ -508,6 +509,13 @@ static inline BOOL check_hwnd_filter( const MSG *msg, HWND hwnd_filter ) return (msg->hwnd == hwnd_filter || is_child( hwnd_filter, msg->hwnd )); }
+BOOL set_keyboard_auto_repeat( BOOL enable ) +{ + BOOL enabled = keyboard_auto_repeat_enabled; + keyboard_auto_repeat_enabled = enable; + return enabled; +} + /*********************************************************************** * unpack_message * diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index b39e38db5d6..915aeb50bdc 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -242,6 +242,9 @@ HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN; extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN; extern void invalidate_dce( WND *win, const RECT *extra_rect ) DECLSPEC_HIDDEN;
+/* message.c */ +extern BOOL set_keyboard_auto_repeat( BOOL enable ) DECLSPEC_HIDDEN; + /* window.c */ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN; void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index b134c5af680..dd409fe992f 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -6320,6 +6320,9 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ) process_layout = arg; return TRUE;
+ case NtUserCallOneParam_SetKeyboardAutoRepeat: + return set_keyboard_auto_repeat( arg ); + /* temporary exports */ case NtUserGetDeskPattern: return get_entry( &entry_DESKPATTERN, 256, (WCHAR *)arg ); diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index 741dbfe1157..e3bcce443a8 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -219,7 +219,20 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboar static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int rate, int delay) { - FIXME("rate=%d delay=%d stub!\n", rate, delay); + UINT speed; + + TRACE("rate=%d delay=%d\n", rate, delay); + + /* Handle non-negative rate values, ignore invalid (negative) values. A + * rate of 0 disables repeat. */ + if (rate >= 80) speed = 31; + else if (rate >= 5) speed = rate * 400 / 1000 - 1; + else speed = 0; + + delay = max(0, min(3, round(delay / 250.0) - 1)); + NtUserSystemParametersInfo(SPI_SETKEYBOARDSPEED, speed, NULL, 0); + NtUserSystemParametersInfo(SPI_SETKEYBOARDDELAY, delay, NULL, 0); + NtUserCallOneParam(rate > 0, NtUserCallOneParam_SetKeyboardAutoRepeat); }
static const struct wl_keyboard_listener keyboard_listener = { @@ -245,6 +258,7 @@ void wayland_keyboard_init(struct wl_keyboard *wl_keyboard) return; }
+ NtUserCallOneParam(TRUE, NtUserCallOneParam_SetKeyboardAutoRepeat); pthread_mutex_lock(&keyboard->mutex); keyboard->wl_keyboard = wl_keyboard; keyboard->xkb_context = xkb_context; diff --git a/include/ntuser.h b/include/ntuser.h index def89a82aff..b62c2e60538 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -878,6 +878,7 @@ enum NtUserCallOneParam_ReplyMessage, NtUserCallOneParam_SetCaretBlinkTime, NtUserCallOneParam_SetProcessDefaultLayout, + NtUserCallOneParam_SetKeyboardAutoRepeat, /* temporary exports */ NtUserGetDeskPattern, };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 47 ++++++++++++++++++++++++++++++++++++ dlls/win32u/ntuser_private.h | 4 +++ 2 files changed, 51 insertions(+)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e897ead329e..3c59eb8ee1d 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2292,6 +2292,22 @@ static void send_parent_notify( HWND hwnd, WORD event, WORD idChild, POINT pt ) } }
+ +static void handle_keyboard_repeat_message( HWND hwnd ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + MSG *msg = &thread_info->key_repeat_msg; + UINT speed; + + msg->lParam = (msg->lParam & ~(LPARAM)0xffff) + ((msg->lParam + 1) & 0xffff); + + if (NtUserSystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, &speed, 0 )) + NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_KEY_REPEAT, 400 / (speed + 1) ); + + NtUserPostMessage( hwnd, msg->message, msg->wParam, msg->lParam ); +} + + /*********************************************************************** * process_keyboard_message * @@ -2371,6 +2387,33 @@ static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, if (ImmProcessKey( msg->hwnd, NtUserGetKeyboardLayout(0), msg->wParam, msg->lParam, 0 )) msg->wParam = VK_PROCESSKEY;
+ /* set/kill timers for key auto-repeat */ + if (remove && keyboard_auto_repeat_enabled) + { + struct user_thread_info *thread_info = get_user_thread_info(); + + switch (msg->message) + { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + UINT delay; + + if (msg->wParam == VK_PROCESSKEY) break; + + thread_info->key_repeat_msg = *msg; + if (NtUserSystemParametersInfo( SPI_GETKEYBOARDDELAY, 0, &delay, 0 )) + NtUserSetSystemTimer( msg->hwnd, SYSTEM_TIMER_KEY_REPEAT, (delay + 1) * 250 ); + break; + } + + case WM_KEYUP: + case WM_SYSKEYUP: + kill_system_timer( thread_info->key_repeat_msg.hwnd, SYSTEM_TIMER_KEY_REPEAT ); + break; + } + } + return TRUE; }
@@ -3565,6 +3608,10 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ) case SYSTEM_TIMER_TRACK_MOUSE: update_mouse_tracking_info( msg->hwnd ); return 0; + + case SYSTEM_TIMER_KEY_REPEAT: + handle_keyboard_repeat_message( msg->hwnd ); + return 0; } }
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 915aeb50bdc..72a2f24bc49 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -32,6 +32,9 @@ enum system_timer_id { SYSTEM_TIMER_TRACK_MOUSE = 0xfffa, SYSTEM_TIMER_CARET = 0xffff, + + /* not compatible with native */ + SYSTEM_TIMER_KEY_REPEAT = 0xfff0, };
struct rawinput_thread_data @@ -126,6 +129,7 @@ struct user_thread_info struct received_message_info *receive_info; /* Message being currently received */ struct user_key_state_info *key_state; /* Cache of global key state */ struct imm_thread_data *imm_thread_data; /* IMM thread data */ + MSG key_repeat_msg; /* Last WM_KEYDOWN message to repeat */ HKL kbd_layout; /* Current keyboard layout */ UINT kbd_layout_id; /* Current keyboard layout ID */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=140115
Your paranoid android.
=== debian11 (build log) ===
error: patch failed: dlls/win32u/ntuser_private.h:242 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/win32u/ntuser_private.h:242 Task: Patch failed to apply
Fwiw @afrantzis, unless ofc if you don't think you have time for it, it'd be nice if you could request access to the project (on the https://gitlab.winehq.org/wine/wine page), so that you can be added as reviewer and approve winewayland merge requests.
On Wed Nov 22 07:43:44 2023 +0000, Rémi Bernon wrote:
Fwiw @afrantzis, unless ofc if you don't think you have time for it, it'd be nice if you could request access to the project (on the https://gitlab.winehq.org/wine/wine page), so that you can be added as reviewer and approve winewayland merge requests.
Thanks, I have requested access.
This merge request was approved by Alexandros Frantzis.