server: Send numpad virtual keys if NumLock is active.

If the hardware keyboard event has KBD virtual key information, use it
to detect numpad key events and translate them to the appropriate
virtual keys depending on NumLock (and Shift) state.
This commit is contained in:
Alexandros Frantzis 2024-05-08 12:52:08 +03:00 committed by Alexandre Julliard
parent f5f62c945c
commit 11ef7af768
4 changed files with 52 additions and 3 deletions

View file

@ -1112,6 +1112,31 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout )
return ret;
}
/***********************************************************************
* map_scan_to_kbd_vkey
*
* Map a scancode to a virtual key with KBD information.
*/
USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout )
{
const KBDTABLES *kbd_tables;
USHORT vsc2vk[0x300];
UINT vkey;
if ((vkey = user_driver->pMapVirtualKeyEx( scan, MAPVK_VSC_TO_VK_EX, layout )) != -1) return vkey;
if (!(kbd_tables = user_driver->pKbdLayerDescriptor( layout ))) kbd_tables = &kbdus_tables;
kbd_tables_init_vsc2vk( kbd_tables, vsc2vk );
if (scan & 0xe000) scan -= 0xdf00;
if (scan >= ARRAY_SIZE(vsc2vk)) vkey = 0;
else vkey = vsc2vk[scan];
if (kbd_tables != &kbdus_tables) user_driver->pReleaseKbdTables( kbd_tables );
return vkey;
}
/****************************************************************************
* NtUserGetKeyNameText (win32u.@)
*/

View file

@ -3569,7 +3569,7 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA
scan = scan & 0xff;
if (input->ki.dwFlags & KEYEVENTF_EXTENDEDKEY) scan |= 0xe000;
}
req->input.kbd.vkey = NtUserMapVirtualKeyEx( scan, MAPVK_VSC_TO_VK_EX, layout );
req->input.kbd.vkey = map_scan_to_kbd_vkey( scan, layout );
req->input.kbd.scan = input->ki.wScan & 0xff;
}
else

View file

@ -108,6 +108,7 @@ extern void update_mouse_tracking_info( HWND hwnd );
extern BOOL get_clip_cursor( RECT *rect );
extern BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset );
extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset );
extern USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout );
/* menu.c */
extern HMENU create_menu( BOOL is_popup );

View file

@ -36,6 +36,7 @@
#include "winternl.h"
#include "ntuser.h"
#include "hidusage.h"
#include "kbd.h"
#include "handle.h"
#include "file.h"
@ -1763,7 +1764,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
if (input->type == INPUT_KEYBOARD)
{
unsigned short vkey = input->kbd.vkey;
unsigned short vkey = input->kbd.vkey & 0xff;
if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET;
msg->lparam = (input->kbd.scan << 16) | vkey;
}
@ -2102,6 +2103,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
struct message *msg;
struct thread *foreground;
unsigned char vkey = input->kbd.vkey;
hw_input_t hook_input = *input;
unsigned int message_code, time;
int wait;
@ -2171,6 +2173,27 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
break;
}
/* send numpad vkeys if NumLock is active */
if ((input->kbd.vkey & KBDNUMPAD) && (desktop->keystate[VK_NUMLOCK] & 0x01) &&
!(desktop->keystate[VK_SHIFT] & 0x80))
{
switch (vkey)
{
case VK_INSERT: hook_input.kbd.vkey = vkey = VK_NUMPAD0; break;
case VK_END: hook_input.kbd.vkey = vkey = VK_NUMPAD1; break;
case VK_DOWN: hook_input.kbd.vkey = vkey = VK_NUMPAD2; break;
case VK_NEXT: hook_input.kbd.vkey = vkey = VK_NUMPAD3; break;
case VK_LEFT: hook_input.kbd.vkey = vkey = VK_NUMPAD4; break;
case VK_CLEAR: hook_input.kbd.vkey = vkey = VK_NUMPAD5; break;
case VK_RIGHT: hook_input.kbd.vkey = vkey = VK_NUMPAD6; break;
case VK_HOME: hook_input.kbd.vkey = vkey = VK_NUMPAD7; break;
case VK_UP: hook_input.kbd.vkey = vkey = VK_NUMPAD8; break;
case VK_PRIOR: hook_input.kbd.vkey = vkey = VK_NUMPAD9; break;
case VK_DELETE: hook_input.kbd.vkey = vkey = VK_DECIMAL; break;
default: break;
}
}
if ((foreground = get_foreground_thread( desktop, win )))
{
struct rawinput_message raw_msg = {0};
@ -2217,7 +2240,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
}
if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
if (!(wait = send_hook_ll_message( desktop, msg, &hook_input, sender )))
queue_hardware_message( desktop, msg, 1 );
return wait;