From: Rémi Bernon rbernon@codeweavers.com
--- include/Makefile.in | 1 + include/kbd.h | 116 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 include/kbd.h
diff --git a/include/Makefile.in b/include/Makefile.in index 9b5f2a5ae02..d06ccd63b92 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -379,6 +379,7 @@ SOURCES = \ iptypes.h \ isguids.h \ ivectorchangedeventargs.idl \ + kbd.h \ knownfolders.h \ ks.h \ ksguid.h \ diff --git a/include/kbd.h b/include/kbd.h new file mode 100644 index 00000000000..3cf0b35ac8e --- /dev/null +++ b/include/kbd.h @@ -0,0 +1,116 @@ +/* + * Copyright 2022 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_KBD_H +#define __WINE_KBD_H + +#include "windef.h" + +typedef struct +{ + BYTE Vk; + BYTE ModBits; +} VK_TO_BIT, *PVK_TO_BIT; + +typedef struct +{ + VK_TO_BIT *pVkToBit; + WORD wMaxModBits; + BYTE ModNumber[]; +} MODIFIERS, *PMODIFIERS; + +#define TYPEDEF_VK_TO_WCHARS(n) \ + typedef struct _VK_TO_WCHARS##n \ + { \ + BYTE VirtualKey; \ + BYTE Attributes; \ + WCHAR wch[n]; \ + } VK_TO_WCHARS##n, *PVK_TO_WCHARS##n + +TYPEDEF_VK_TO_WCHARS(1); +TYPEDEF_VK_TO_WCHARS(2); +TYPEDEF_VK_TO_WCHARS(3); +TYPEDEF_VK_TO_WCHARS(4); +TYPEDEF_VK_TO_WCHARS(5); +TYPEDEF_VK_TO_WCHARS(6); +TYPEDEF_VK_TO_WCHARS(7); +TYPEDEF_VK_TO_WCHARS(8); +TYPEDEF_VK_TO_WCHARS(9); +TYPEDEF_VK_TO_WCHARS(10); + +typedef struct _VK_TO_WCHAR_TABLE +{ + VK_TO_WCHARS1 *pVkToWchars; + BYTE nModifications; + BYTE cbSize; +} VK_TO_WCHAR_TABLE, *PVK_TO_WCHAR_TABLE; + +typedef struct +{ + DWORD dwBoth; + WCHAR wchComposed; + USHORT uFlags; +} DEADKEY, *PDEADKEY; + +typedef struct +{ + BYTE vsc; + WCHAR *pwsz; +} VSC_LPWSTR, *PVSC_LPWSTR; + +typedef struct _VSC_VK +{ + BYTE Vsc; + USHORT Vk; +} VSC_VK, *PVSC_VK; + +#define TYPEDEF_LIGATURE(n) \ + typedef struct _LIGATURE##n \ + { \ + BYTE VirtualKey; \ + WORD ModificationNumber; \ + WCHAR wch[n]; \ + } LIGATURE##n, *PLIGATURE##n; + +TYPEDEF_LIGATURE(1) +TYPEDEF_LIGATURE(2) +TYPEDEF_LIGATURE(3) +TYPEDEF_LIGATURE(4) +TYPEDEF_LIGATURE(5) + +typedef struct tagKbdLayer +{ + MODIFIERS *pCharModifiers; + VK_TO_WCHAR_TABLE *pVkToWcharTable; + DEADKEY *pDeadKey; + VSC_LPWSTR *pKeyNames; + VSC_LPWSTR *pKeyNamesExt; + WCHAR **pKeyNamesDead; + USHORT *pusVSCtoVK; + BYTE bMaxVSCtoVK; + VSC_VK *pVSCtoVK_E0; + VSC_VK *pVSCtoVK_E1; + DWORD fLocaleFlags; + BYTE nLgMax; + BYTE cbLgEntry; + LIGATURE1 *pLigature; + DWORD dwType; + DWORD dwSubType; +} KBDTABLES, *PKBDTABLES; + +#endif /* __WINE_KBD_H */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 236 +++++++++++++++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 55 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 5656d5eb28f..561c1964221 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -36,6 +36,7 @@ #include "ntuser_private.h" #include "wine/server.h" #include "wine/debug.h" +#include "kbd.h"
WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DECLARE_DEBUG_CHANNEL(keyboard); @@ -49,6 +50,168 @@ static const WCHAR keyboard_layouts_keyW[] = '\','C','o','n','t','r','o','l', '\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s' }; +static const WCHAR escW[] = {'E','s','c',0}; +static const WCHAR backspaceW[] = {'B','a','c','k','s','p','a','c','e',0}; +static const WCHAR tabW[] = {'T','a','b',0}; +static const WCHAR enterW[] = {'E','n','t','e','r',0}; +static const WCHAR ctrlW[] = {'C','t','r','l',0}; +static const WCHAR shiftW[] = {'S','h','i','f','t',0}; +static const WCHAR right_shiftW[] = {'R','i','g','h','t',' ','S','h','i','f','t',0}; +static const WCHAR num_mulW[] = {'N','u','m',' ','*',0}; +static const WCHAR altW[] = {'A','l','t',0}; +static const WCHAR spaceW[] = {'S','p','a','c','e',0}; +static const WCHAR caps_lockW[] = {'C','a','p','s',' ','L','o','c','k',0}; +static const WCHAR f1W[] = {'F','1',0}; +static const WCHAR f2W[] = {'F','2',0}; +static const WCHAR f3W[] = {'F','3',0}; +static const WCHAR f4W[] = {'F','4',0}; +static const WCHAR f5W[] = {'F','5',0}; +static const WCHAR f6W[] = {'F','6',0}; +static const WCHAR f7W[] = {'F','7',0}; +static const WCHAR f8W[] = {'F','8',0}; +static const WCHAR f9W[] = {'F','9',0}; +static const WCHAR f10W[] = {'F','1','0',0}; +static const WCHAR pauseW[] = {'P','a','u','s','e',0}; +static const WCHAR scroll_lockW[] = {'S','c','r','o','l','l',' ','L','o','c','k',0}; +static const WCHAR num_7W[] = {'N','u','m',' ','7',0}; +static const WCHAR num_8W[] = {'N','u','m',' ','8',0}; +static const WCHAR num_9W[] = {'N','u','m',' ','9',0}; +static const WCHAR num_minusW[] = {'N','u','m',' ','-',0}; +static const WCHAR num_4W[] = {'N','u','m',' ','4',0}; +static const WCHAR num_5W[] = {'N','u','m',' ','5',0}; +static const WCHAR num_6W[] = {'N','u','m',' ','6',0}; +static const WCHAR num_plusW[] = {'N','u','m',' ','+',0}; +static const WCHAR num_1W[] = {'N','u','m',' ','1',0}; +static const WCHAR num_2W[] = {'N','u','m',' ','2',0}; +static const WCHAR num_3W[] = {'N','u','m',' ','3',0}; +static const WCHAR num_0W[] = {'N','u','m',' ','0',0}; +static const WCHAR num_delW[] = {'N','u','m',' ','D','e','l',0}; +static const WCHAR sys_reqW[] = {'S','y','s',' ','R','e','q',0}; +static const WCHAR f11W[] = {'F','1','1',0}; +static const WCHAR f12W[] = {'F','1','2',0}; +static const WCHAR f13W[] = {'F','1','3',0}; +static const WCHAR f14W[] = {'F','1','4',0}; +static const WCHAR f15W[] = {'F','1','5',0}; +static const WCHAR f16W[] = {'F','1','6',0}; +static const WCHAR f17W[] = {'F','1','7',0}; +static const WCHAR f18W[] = {'F','1','8',0}; +static const WCHAR f19W[] = {'F','1','9',0}; +static const WCHAR f20W[] = {'F','2','0',0}; +static const WCHAR f21W[] = {'F','2','1',0}; +static const WCHAR f22W[] = {'F','2','2',0}; +static const WCHAR f23W[] = {'F','2','3',0}; +static const WCHAR f24W[] = {'F','2','4',0}; +static const WCHAR num_enterW[] = {'N','u','m',' ','E','n','t','e','r',0}; +static const WCHAR right_ctrlW[] = {'R','i','g','h','t',' ','C','t','r','l',0}; +static const WCHAR num_divW[] = {'N','u','m',' ','/',0}; +static const WCHAR prnt_scrnW[] = {'P','r','n','t',' ','S','c','r','n',0}; +static const WCHAR right_altW[] = {'R','i','g','h','t',' ','A','l','t',0}; +static const WCHAR num_lockW[] = {'N','u','m',' ','L','o','c','k',0}; +static const WCHAR breakW[] = {'B','r','e','a','k',0}; +static const WCHAR homeW[] = {'H','o','m','e',0}; +static const WCHAR upW[] = {'U','p',0}; +static const WCHAR page_upW[] = {'P','a','g','e',' ','U','p',0}; +static const WCHAR leftW[] = {'L','e','f','t',0}; +static const WCHAR rightW[] = {'R','i','g','h','t',0}; +static const WCHAR endW[] = {'E','n','d',0}; +static const WCHAR downW[] = {'D','o','w','n',0}; +static const WCHAR page_downW[] = {'P','a','g','e',' ','D','o','w','n',0}; +static const WCHAR insertW[] = {'I','n','s','e','r','t',0}; +static const WCHAR deleteW[] = {'D','e','l','e','t','e',0}; +static const WCHAR zerozeroW[] = {'<','0','0','>',0}; +static const WCHAR helpW[] = {'H','e','l','p',0}; +static const WCHAR left_windowsW[] = {'L','e','f','t',' ','W','i','n','d','o','w','s',0}; +static const WCHAR right_windowsW[] = {'R','i','g','h','t',' ','W','i','n','d','o','w','s',0}; +static const WCHAR applicationW[] = {'A','p','p','l','i','c','a','t','i','o','n',0}; + +static const VSC_LPWSTR key_names[] = +{ + {.vsc = 0x01, .pwsz = (WCHAR *)escW}, + {.vsc = 0x0e, .pwsz = (WCHAR *)backspaceW}, + {.vsc = 0x0f, .pwsz = (WCHAR *)tabW}, + {.vsc = 0x1c, .pwsz = (WCHAR *)enterW}, + {.vsc = 0x1d, .pwsz = (WCHAR *)ctrlW}, + {.vsc = 0x2a, .pwsz = (WCHAR *)shiftW}, + {.vsc = 0x36, .pwsz = (WCHAR *)right_shiftW}, + {.vsc = 0x37, .pwsz = (WCHAR *)num_mulW}, + {.vsc = 0x38, .pwsz = (WCHAR *)altW}, + {.vsc = 0x39, .pwsz = (WCHAR *)spaceW}, + {.vsc = 0x3a, .pwsz = (WCHAR *)caps_lockW}, + {.vsc = 0x3b, .pwsz = (WCHAR *)f1W}, + {.vsc = 0x3c, .pwsz = (WCHAR *)f2W}, + {.vsc = 0x3d, .pwsz = (WCHAR *)f3W}, + {.vsc = 0x3e, .pwsz = (WCHAR *)f4W}, + {.vsc = 0x3f, .pwsz = (WCHAR *)f5W}, + {.vsc = 0x40, .pwsz = (WCHAR *)f6W}, + {.vsc = 0x41, .pwsz = (WCHAR *)f7W}, + {.vsc = 0x42, .pwsz = (WCHAR *)f8W}, + {.vsc = 0x43, .pwsz = (WCHAR *)f9W}, + {.vsc = 0x44, .pwsz = (WCHAR *)f10W}, + {.vsc = 0x45, .pwsz = (WCHAR *)pauseW}, + {.vsc = 0x46, .pwsz = (WCHAR *)scroll_lockW}, + {.vsc = 0x47, .pwsz = (WCHAR *)num_7W}, + {.vsc = 0x48, .pwsz = (WCHAR *)num_8W}, + {.vsc = 0x49, .pwsz = (WCHAR *)num_9W}, + {.vsc = 0x4a, .pwsz = (WCHAR *)num_minusW}, + {.vsc = 0x4b, .pwsz = (WCHAR *)num_4W}, + {.vsc = 0x4c, .pwsz = (WCHAR *)num_5W}, + {.vsc = 0x4d, .pwsz = (WCHAR *)num_6W}, + {.vsc = 0x4e, .pwsz = (WCHAR *)num_plusW}, + {.vsc = 0x4f, .pwsz = (WCHAR *)num_1W}, + {.vsc = 0x50, .pwsz = (WCHAR *)num_2W}, + {.vsc = 0x51, .pwsz = (WCHAR *)num_3W}, + {.vsc = 0x52, .pwsz = (WCHAR *)num_0W}, + {.vsc = 0x53, .pwsz = (WCHAR *)num_delW}, + {.vsc = 0x54, .pwsz = (WCHAR *)sys_reqW}, + {.vsc = 0x57, .pwsz = (WCHAR *)f11W}, + {.vsc = 0x58, .pwsz = (WCHAR *)f12W}, + {.vsc = 0x7c, .pwsz = (WCHAR *)f13W}, + {.vsc = 0x7d, .pwsz = (WCHAR *)f14W}, + {.vsc = 0x7e, .pwsz = (WCHAR *)f15W}, + {.vsc = 0x7f, .pwsz = (WCHAR *)f16W}, + {.vsc = 0x80, .pwsz = (WCHAR *)f17W}, + {.vsc = 0x81, .pwsz = (WCHAR *)f18W}, + {.vsc = 0x82, .pwsz = (WCHAR *)f19W}, + {.vsc = 0x83, .pwsz = (WCHAR *)f20W}, + {.vsc = 0x84, .pwsz = (WCHAR *)f21W}, + {.vsc = 0x85, .pwsz = (WCHAR *)f22W}, + {.vsc = 0x86, .pwsz = (WCHAR *)f23W}, + {.vsc = 0x87, .pwsz = (WCHAR *)f24W}, + {0}, +}; + +static const VSC_LPWSTR key_names_ext[] = +{ + {.vsc = 0x1c, .pwsz = (WCHAR *)num_enterW}, + {.vsc = 0x1d, .pwsz = (WCHAR *)right_ctrlW}, + {.vsc = 0x35, .pwsz = (WCHAR *)num_divW}, + {.vsc = 0x37, .pwsz = (WCHAR *)prnt_scrnW}, + {.vsc = 0x38, .pwsz = (WCHAR *)right_altW}, + {.vsc = 0x45, .pwsz = (WCHAR *)num_lockW}, + {.vsc = 0x46, .pwsz = (WCHAR *)breakW}, + {.vsc = 0x47, .pwsz = (WCHAR *)homeW}, + {.vsc = 0x48, .pwsz = (WCHAR *)upW}, + {.vsc = 0x49, .pwsz = (WCHAR *)page_upW}, + {.vsc = 0x4b, .pwsz = (WCHAR *)leftW}, + {.vsc = 0x4d, .pwsz = (WCHAR *)rightW}, + {.vsc = 0x4f, .pwsz = (WCHAR *)endW}, + {.vsc = 0x50, .pwsz = (WCHAR *)downW}, + {.vsc = 0x51, .pwsz = (WCHAR *)page_downW}, + {.vsc = 0x52, .pwsz = (WCHAR *)insertW}, + {.vsc = 0x53, .pwsz = (WCHAR *)deleteW}, + {.vsc = 0x54, .pwsz = (WCHAR *)zerozeroW}, + {.vsc = 0x56, .pwsz = (WCHAR *)helpW}, + {.vsc = 0x5b, .pwsz = (WCHAR *)left_windowsW}, + {.vsc = 0x5c, .pwsz = (WCHAR *)right_windowsW}, + {.vsc = 0x5d, .pwsz = (WCHAR *)applicationW}, + {0}, +}; + +static const KBDTABLES kbdus_tables = +{ + .pKeyNames = (VSC_LPWSTR *)key_names, + .pKeyNamesExt = (VSC_LPWSTR *)key_names_ext, +};
LONG global_key_state_counter = 0; @@ -628,43 +791,6 @@ static const UINT kbd_en_vk2char[] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
-static const char *kbd_en_vscname[] = -{ - 0, "Esc", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Backspace", "Tab", - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Enter", "Ctrl", 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Shift", 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, "Right Shift", "Num *", "Alt", "Space", "Caps Lock", "F1", "F2", "F3", "F4", "F5", - "F6", "F7", "F8", "F9", "F10", "Pause", "Scroll Lock", "Num 7", "Num 8", "Num 9", "Num -", "Num 4", "Num 5", "Num 6", "Num +", "Num 1", - "Num 2", "Num 3", "Num 0", "Num Del", "Sys Req", 0, 0, "F11", "F12", 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "F13", "F14", "F15", "F16", - "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* extended */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Num Enter", "Right Ctrl", 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, "Num /", 0, "Prnt Scrn", "Right Alt", 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, "Num Lock", "Break", "Home", "Up", "Page Up", 0, "Left", 0, "Right", 0, "End", - "Down", "Page Down", "Insert", "Delete", "<00>", 0, "Help", 0, 0, 0, 0, "Left Windows", "Right Windows", "Application", 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - /****************************************************************************** * NtUserMapVirtualKeyEx (win32u.@) */ @@ -752,11 +878,12 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ) { INT code = ((lparam >> 16) & 0x1ff), vkey, len; - UINT vsc2vk_size, vscname_size; - const char *const *vscname; + const KBDTABLES *kbd_tables = &kbdus_tables; + VSC_LPWSTR *key_name; const UINT *vsc2vk; + UINT vsc2vk_size;
- TRACE_(keyboard)( "lparam %d, buffer %p, size %d.\n", (int)lparam, buffer, size ); + TRACE_(keyboard)( "lparam %#x, buffer %p, size %d.\n", (int)lparam, buffer, size );
if (!buffer || !size) return 0; if ((len = user_driver->pGetKeyNameText( lparam, buffer, size )) >= 0) return len; @@ -765,8 +892,6 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size )
vsc2vk = kbd_en_vsc2vk; vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk); - vscname = kbd_en_vscname; - vscname_size = ARRAYSIZE(kbd_en_vscname);
if (lparam & 0x2000000) { @@ -781,20 +906,21 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ) } }
- if (code < vscname_size) + if (code < 0x100) key_name = kbd_tables->pKeyNames; + else key_name = kbd_tables->pKeyNamesExt; + while (key_name->vsc && key_name->vsc != (BYTE)code) key_name++; + + if (key_name->vsc == (BYTE)code) { - if (vscname[code]) - { - len = min( size - 1, strlen(vscname[code]) ); - ascii_to_unicode( buffer, vscname[code], len ); - } - else if (size > 1) - { - HKL hkl = NtUserGetKeyboardLayout( 0 ); - vkey = NtUserMapVirtualKeyEx( code & 0xff, MAPVK_VSC_TO_VK, hkl ); - buffer[0] = NtUserMapVirtualKeyEx( vkey, MAPVK_VK_TO_CHAR, hkl ); - len = 1; - } + len = min( size - 1, wcslen( key_name->pwsz ) ); + memcpy( buffer, key_name->pwsz, len * sizeof(WCHAR) ); + } + else if (size > 1) + { + HKL hkl = NtUserGetKeyboardLayout( 0 ); + vkey = NtUserMapVirtualKeyEx( code & 0xff, MAPVK_VSC_TO_VK, hkl ); + buffer[0] = NtUserMapVirtualKeyEx( vkey, MAPVK_VK_TO_CHAR, hkl ); + len = 1; } buffer[len] = 0;
From: Rémi Bernon rbernon@codeweavers.com
--- include/kbd.h | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+)
diff --git a/include/kbd.h b/include/kbd.h index 3cf0b35ac8e..de1d2c784d2 100644 --- a/include/kbd.h +++ b/include/kbd.h @@ -113,4 +113,211 @@ typedef struct tagKbdLayer DWORD dwSubType; } KBDTABLES, *PKBDTABLES;
+#define KBD_VERSION 1 +#define GET_KBD_VERSION(table) (HIWORD((table)->fLocaleFlags)) + +#ifndef KBD_TYPE +#define KBD_TYPE 4 +#endif + +#define KBDEXT (USHORT)0x0100 +#define KBDMULTIVK (USHORT)0x0200 +#define KBDSPECIAL (USHORT)0x0400 +#define KBDNUMPAD (USHORT)0x0800 +#define KBDUNICODE (USHORT)0x1000 +#define KBDINJECTEDVK (USHORT)0x2000 +#define KBDMAPPEDVK (USHORT)0x4000 +#define KBDBREAK (USHORT)0x8000 + +#define VK__none_ 0xff +#define VK_ABNT_C1 0xc1 +#define VK_ABNT_C2 0xc2 + +#if (KBD_TYPE <= 6) +#define _EQ(v4) (VK_##v4) +#if (KBD_TYPE == 1) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v1) +#elif (KBD_TYPE == 2) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v2) +#elif (KBD_TYPE == 3) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v3) +#elif (KBD_TYPE == 4) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v4) +#elif (KBD_TYPE == 5) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v5) +#elif (KBD_TYPE == 6) +#define _NE(v1, v2, v3, v4, v5, v6) (VK_##v6) +#endif +#define T00 _EQ(_none_) +#define T01 _EQ(ESCAPE) +#define T02 '1' +#define T03 '2' +#define T04 '3' +#define T05 '4' +#define T06 '5' +#define T07 '6' +#define T08 '7' +#define T09 '8' +#define T0A '9' +#define T0B '0' +#define T0C _EQ(OEM_MINUS) +#define T0D _NE(OEM_PLUS,OEM_4, OEM_PLUS, OEM_PLUS, OEM_PLUS, OEM_PLUS) +#define T0E _EQ(BACK) +#define T0F _EQ(TAB) +#define T10 'Q' +#define T11 'W' +#define T12 'E' +#define T13 'R' +#define T14 'T' +#define T15 'Y' +#define T16 'U' +#define T17 'I' +#define T18 'O' +#define T19 'P' +#define T1A _NE(OEM_4, OEM_6, OEM_4, OEM_4, OEM_4, OEM_4) +#define T1B _NE(OEM_6, OEM_1, OEM_6, OEM_6, OEM_6, OEM_6) +#define T1C _EQ(RETURN) +#define T1D _EQ(LCONTROL) +#define T1E 'A' +#define T1F 'S' +#define T20 'D' +#define T21 'F' +#define T22 'G' +#define T23 'H' +#define T24 'J' +#define T25 'K' +#define T26 'L' +#define T27 _NE(OEM_1, OEM_PLUS, OEM_1, OEM_1, OEM_1, OEM_1) +#define T28 _NE(OEM_7, OEM_3, OEM_7, OEM_7, OEM_3, OEM_3) +#define T29 _NE(OEM_3, OEM_7, OEM_3, OEM_3, OEM_7, OEM_7) +#define T2A _EQ(LSHIFT) +#define T2B _EQ(OEM_5) +#define T2C 'Z' +#define T2D 'X' +#define T2E 'C' +#define T2F 'V' +#define T30 'B' +#define T31 'N' +#define T32 'M' +#define T33 _EQ(OEM_COMMA) +#define T34 _EQ(OEM_PERIOD) +#define T35 _EQ(OEM_2) +#define T36 _EQ(RSHIFT) +#define T37 _EQ(MULTIPLY) +#define T38 _EQ(LMENU) +#define T39 ' ' +#define T3A _EQ(CAPITAL) +#define T3B _EQ(F1) +#define T3C _EQ(F2) +#define T3D _EQ(F3) +#define T3E _EQ(F4) +#define T3F _EQ(F5) +#define T40 _EQ(F6) +#define T41 _EQ(F7) +#define T42 _EQ(F8) +#define T43 _EQ(F9) +#define T44 _EQ(F10) +#define T45 _EQ(NUMLOCK) +#define T46 _EQ(SCROLL) +#define T47 _EQ(HOME) +#define T48 _EQ(UP) +#define T49 _EQ(PRIOR) +#define T4A _EQ(SUBTRACT) +#define T4B _EQ(LEFT) +#define T4C _EQ(CLEAR) +#define T4D _EQ(RIGHT) +#define T4E _EQ(ADD) +#define T4F _EQ(END) +#define T50 _EQ(DOWN) +#define T51 _EQ(NEXT) +#define T52 _EQ(INSERT) +#define T53 _EQ(DELETE) +#define T54 _EQ(SNAPSHOT) +#define T55 _EQ(_none_) +#define T56 _NE(OEM_102, HELP, OEM_102, OEM_102, _none_, OEM_PA2) +#define T57 _NE(F11, RETURN, F11, F11, _none_, HELP) +#define T58 _NE(F12, LEFT, F12, F12, _none_, OEM_102) +#define T59 _EQ(CLEAR) +#define T5A _EQ(OEM_WSCTRL) +#define T5B _EQ(OEM_FINISH) +#define T5C _EQ(OEM_JUMP) +#define T5D _EQ(EREOF) +#define T5E _EQ(OEM_BACKTAB) +#define T5F _EQ(OEM_AUTO) +#define T60 _EQ(_none_) +#define T61 _EQ(_none_) +#define T62 _EQ(ZOOM) +#define T63 _EQ(HELP) +#define T64 _EQ(F13) +#define T65 _EQ(F14) +#define T66 _EQ(F15) +#define T67 _EQ(F16) +#define T68 _EQ(F17) +#define T69 _EQ(F18) +#define T6A _EQ(F19) +#define T6B _EQ(F20) +#define T6C _EQ(F21) +#define T6D _EQ(F22) +#define T6E _EQ(F23) +#define T6F _EQ(OEM_PA3) +#define T70 _EQ(_none_) +#define T71 _EQ(OEM_RESET) +#define T72 _EQ(_none_) +#define T73 _EQ(ABNT_C1) +#define T74 _EQ(_none_) +#define T75 _EQ(_none_) +#define T76 _EQ(F24) +#define T77 _EQ(_none_) +#define T78 _EQ(_none_) +#define T79 _EQ(_none_) +#define T7A _EQ(_none_) +#define T7B _EQ(OEM_PA1) +#define T7C _EQ(TAB) +#define T7D _EQ(_none_) +#define T7E _EQ(ABNT_C2) +#define T7F _EQ(OEM_PA2) +#define X10 _EQ(MEDIA_PREV_TRACK) +#define X19 _EQ(MEDIA_NEXT_TRACK) +#define X1C _EQ(RETURN) +#define X1D _EQ(RCONTROL) +#define X20 _EQ(VOLUME_MUTE) +#define X21 _EQ(LAUNCH_APP2) +#define X22 _EQ(MEDIA_PLAY_PAUSE) +#define X24 _EQ(MEDIA_STOP) +#define X2E _EQ(VOLUME_DOWN) +#define X30 _EQ(VOLUME_UP) +#define X32 _EQ(BROWSER_HOME) +#define X35 _EQ(DIVIDE) +#define X37 _EQ(SNAPSHOT) +#define X38 _EQ(RMENU) +#define X46 _EQ(CANCEL) +#define X47 _EQ(HOME) +#define X48 _EQ(UP) +#define X49 _EQ(PRIOR) +#define X4B _EQ(LEFT) +#define X4D _EQ(RIGHT) +#define X4F _EQ(END) +#define X50 _EQ(DOWN) +#define X51 _NE(NEXT, F1, NEXT, NEXT, _none_, OEM_PA2) +#define X52 _EQ(INSERT) +#define X53 _EQ(DELETE) +#define X5B _EQ(LWIN) +#define X5C _EQ(RWIN) +#define X5D _EQ(APPS) +#define X5E _EQ(POWER) +#define X5F _EQ(SLEEP) +#define X65 _EQ(BROWSER_SEARCH) +#define X66 _EQ(BROWSER_FAVORITES) +#define X67 _EQ(BROWSER_REFRESH) +#define X68 _EQ(BROWSER_STOP) +#define X69 _EQ(BROWSER_FORWARD) +#define X6A _EQ(BROWSER_BACK) +#define X6B _EQ(LAUNCH_APP1) +#define X6C _EQ(LAUNCH_MAIL) +#define X6D _EQ(LAUNCH_MEDIA_SELECT) +#define Y1D _EQ(PAUSE) +#else +#error "Unsupported KBD_TYPE" +#endif + #endif /* __WINE_KBD_H */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 181 +++++++++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 70 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 561c1964221..7c4e0518400 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -207,15 +207,115 @@ static const VSC_LPWSTR key_names_ext[] = {0}, };
+static const USHORT vsc_to_vk[] = +{ + T00, T01, T02, T03, T04, T05, T06, T07, + T08, T09, T0A, T0B, T0C, T0D, T0E, T0F, + T10, T11, T12, T13, T14, T15, T16, T17, + T18, T19, T1A, T1B, T1C, T1D, T1E, T1F, + T20, T21, T22, T23, T24, T25, T26, T27, + T28, T29, T2A, T2B, T2C, T2D, T2E, T2F, + T30, T31, T32, T33, T34, T35, T36 | KBDEXT, T37 | KBDMULTIVK, + T38, T39, T3A, T3B, T3C, T3D, T3E, T3F, + T40, T41, T42, T43, T44, T45 | KBDEXT | KBDMULTIVK, T46 | KBDMULTIVK, T47 | KBDNUMPAD | KBDSPECIAL, + T48 | KBDNUMPAD | KBDSPECIAL, T49 | KBDNUMPAD | KBDSPECIAL, T4A, T4B | KBDNUMPAD | KBDSPECIAL, + T4C | KBDNUMPAD | KBDSPECIAL, T4D | KBDNUMPAD | KBDSPECIAL, T4E, T4F | KBDNUMPAD | KBDSPECIAL, + T50 | KBDNUMPAD | KBDSPECIAL, T51 | KBDNUMPAD | KBDSPECIAL, T52 | KBDNUMPAD | KBDSPECIAL, + T53 | KBDNUMPAD | KBDSPECIAL, T54, T55, T56, T57, + T58, T59, T5A, T5B, T5C, T5D, T5E, T5F, + T60, T61, T62, T63, T64, T65, T66, T67, + T68, T69, T6A, T6B, T6C, T6D, T6E, T6F, + T70, T71, T72, T73, T74, T75, T76, T77, + T78, T79, T7A, T7B, T7C, T7D, T7E +}; + +static const VSC_VK vsc_to_vk_e0[] = +{ + {0x10, X10 | KBDEXT}, + {0x19, X19 | KBDEXT}, + {0x1d, X1D | KBDEXT}, + {0x20, X20 | KBDEXT}, + {0x21, X21 | KBDEXT}, + {0x22, X22 | KBDEXT}, + {0x24, X24 | KBDEXT}, + {0x2e, X2E | KBDEXT}, + {0x30, X30 | KBDEXT}, + {0x32, X32 | KBDEXT}, + {0x35, X35 | KBDEXT}, + {0x37, X37 | KBDEXT}, + {0x38, X38 | KBDEXT}, + {0x47, X47 | KBDEXT}, + {0x48, X48 | KBDEXT}, + {0x49, X49 | KBDEXT}, + {0x4b, X4B | KBDEXT}, + {0x4d, X4D | KBDEXT}, + {0x4f, X4F | KBDEXT}, + {0x50, X50 | KBDEXT}, + {0x51, X51 | KBDEXT}, + {0x52, X52 | KBDEXT}, + {0x53, X53 | KBDEXT}, + {0x5b, X5B | KBDEXT}, + {0x5c, X5C | KBDEXT}, + {0x5d, X5D | KBDEXT}, + {0x5f, X5F | KBDEXT}, + {0x65, X65 | KBDEXT}, + {0x66, X66 | KBDEXT}, + {0x67, X67 | KBDEXT}, + {0x68, X68 | KBDEXT}, + {0x69, X69 | KBDEXT}, + {0x6a, X6A | KBDEXT}, + {0x6b, X6B | KBDEXT}, + {0x6c, X6C | KBDEXT}, + {0x6d, X6D | KBDEXT}, + {0x1c, X1C | KBDEXT}, + {0x46, X46 | KBDEXT}, + {0}, +}; + +static const VSC_VK vsc_to_vk_e1[] = +{ + {0x1d, Y1D}, + {0}, +}; + static const KBDTABLES kbdus_tables = { .pKeyNames = (VSC_LPWSTR *)key_names, .pKeyNamesExt = (VSC_LPWSTR *)key_names_ext, + .pusVSCtoVK = (USHORT *)vsc_to_vk, + .bMaxVSCtoVK = sizeof(vsc_to_vk) / sizeof(vsc_to_vk[0]), + .pVSCtoVK_E0 = (VSC_VK *)vsc_to_vk_e0, + .pVSCtoVK_E1 = (VSC_VK *)vsc_to_vk_e1, };
LONG global_key_state_counter = 0;
+ +static void kbd_tables_init_vsc2vk( const KBDTABLES *tables, BYTE vsc2vk[0x300] ) +{ + const VSC_VK *entry; + WORD vsc; + + memset( vsc2vk, 0, 0x300 ); + + for (vsc = 0; tables->pusVSCtoVK && vsc <= tables->bMaxVSCtoVK; ++vsc) + { + if (tables->pusVSCtoVK[vsc] == VK__none_) continue;; + vsc2vk[vsc] = (BYTE)tables->pusVSCtoVK[vsc]; + } + for (entry = tables->pVSCtoVK_E0; entry && entry->Vsc; entry++) + { + if (entry->Vk == VK__none_) continue;; + vsc2vk[entry->Vsc + 0x100] = (BYTE)entry->Vk; + } + for (entry = tables->pVSCtoVK_E1; entry && entry->Vsc; entry++) + { + if (entry->Vk == VK__none_) continue;; + vsc2vk[entry->Vsc + 0x200] = (BYTE)entry->Vk; + } +} + /********************************************************************** * NtUserAttachThreadInput (win32u.@) */ @@ -716,61 +816,6 @@ WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout ) return ret; }
-/* English keyboard layout (0x0409) */ -static const UINT kbd_en_vsc2vk[] = -{ - 0x00, 0x1b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0xbd, 0xbb, 0x08, 0x09, - 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50, 0xdb, 0xdd, 0x0d, 0xa2, 0x41, 0x53, - 0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0xba, 0xde, 0xc0, 0xa0, 0xdc, 0x5a, 0x58, 0x43, 0x56, - 0x42, 0x4e, 0x4d, 0xbc, 0xbe, 0xbf, 0xa1, 0x6a, 0xa4, 0x20, 0x14, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x90, 0x91, 0x24, 0x26, 0x21, 0x6d, 0x25, 0x0c, 0x27, 0x6b, 0x23, - 0x28, 0x22, 0x2d, 0x2e, 0x2c, 0x00, 0xe2, 0x7a, 0x7b, 0x0c, 0xee, 0xf1, 0xea, 0xf9, 0xf5, 0xf3, - 0x00, 0x00, 0xfb, 0x2f, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xed, - 0x00, 0xe9, 0x00, 0xc1, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x09, 0x00, 0xc2, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0xe000 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x0d, 0xa3, 0x00, 0x00, - 0xad, 0xb7, 0xb3, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, - 0xaf, 0x00, 0xac, 0x00, 0x00, 0x6f, 0x00, 0x2c, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x24, 0x26, 0x21, 0x00, 0x25, 0x00, 0x27, 0x00, 0x23, - 0x28, 0x22, 0x2d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5c, 0x5d, 0x00, 0x5f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xab, 0xa8, 0xa9, 0xa7, 0xa6, 0xb6, 0xb4, 0xb5, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0xe100 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - static const UINT kbd_en_vk2char[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, @@ -796,18 +841,18 @@ static const UINT kbd_en_vk2char[] = */ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) { - const UINT *vsc2vk, *vk2char; - UINT vsc2vk_size, vk2char_size; + const KBDTABLES *kbd_tables = &kbdus_tables; + const UINT *vk2char; + BYTE vsc2vk[0x300]; + UINT vk2char_size; UINT ret;
TRACE_(keyboard)( "code %u, type %u, layout %p.\n", code, type, layout );
if ((ret = user_driver->pMapVirtualKeyEx( code, type, layout )) != -1) return ret;
- /* FIXME: English keyboard layout specific */ + kbd_tables_init_vsc2vk( kbd_tables, vsc2vk );
- vsc2vk = kbd_en_vsc2vk; - vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk); vk2char = kbd_en_vk2char; vk2char_size = ARRAYSIZE(kbd_en_vk2char);
@@ -833,8 +878,8 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) case VK_DECIMAL: code = VK_DELETE; break; }
- for (ret = 0; ret < vsc2vk_size; ++ret) if (vsc2vk[ret] == code) break; - if (ret >= vsc2vk_size) ret = 0; + for (ret = 0; ret < ARRAY_SIZE(vsc2vk); ++ret) if (vsc2vk[ret] == code) break; + if (ret >= ARRAY_SIZE(vsc2vk)) ret = 0;
if (type == MAPVK_VK_TO_VSC) { @@ -846,7 +891,7 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) case MAPVK_VSC_TO_VK: case MAPVK_VSC_TO_VK_EX: if (code & 0xe000) code -= 0xdf00; - if (code >= vsc2vk_size) ret = 0; + if (code >= ARRAY_SIZE(vsc2vk)) ret = 0; else ret = vsc2vk[code];
if (type == MAPVK_VSC_TO_VK) @@ -880,18 +925,14 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ) INT code = ((lparam >> 16) & 0x1ff), vkey, len; const KBDTABLES *kbd_tables = &kbdus_tables; VSC_LPWSTR *key_name; - const UINT *vsc2vk; - UINT vsc2vk_size; + BYTE vsc2vk[0x300];
TRACE_(keyboard)( "lparam %#x, buffer %p, size %d.\n", (int)lparam, buffer, size );
if (!buffer || !size) return 0; if ((len = user_driver->pGetKeyNameText( lparam, buffer, size )) >= 0) return len;
- /* FIXME: English keyboard layout specific */ - - vsc2vk = kbd_en_vsc2vk; - vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk); + kbd_tables_init_vsc2vk( kbd_tables, vsc2vk );
if (lparam & 0x2000000) { @@ -900,7 +941,7 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ) case VK_RSHIFT: case VK_RCONTROL: case VK_RMENU: - for (code = 0; code < vsc2vk_size; ++code) + for (code = 0; code < ARRAY_SIZE(vsc2vk); ++code) if (vsc2vk[code] == (vkey - 1)) break; break; }
From: Rémi Bernon rbernon@codeweavers.com
--- include/kbd.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/include/kbd.h b/include/kbd.h index de1d2c784d2..9bbcd886b1c 100644 --- a/include/kbd.h +++ b/include/kbd.h @@ -21,6 +21,25 @@
#include "windef.h"
+#define KBDBASE 0 +#define KBDSHIFT 1 +#define KBDCTRL 2 +#define KBDALT 4 +#define KBDKANA 8 +#define KBDROYA 0x10 +#define KBDLOYA 0x20 +#define KBDGRPSELTAP 0x80 + +#define WCH_NONE 0xf000 +#define WCH_DEAD 0xf001 +#define WCH_LGTR 0xf002 + +#define CAPLOK 0x01 +#define SGCAPS 0x02 +#define CAPLOKALTGR 0x04 +#define KANALOK 0x08 +#define GRPSELTAP 0x80 + typedef struct { BYTE Vk;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 167 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 141 insertions(+), 26 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 7c4e0518400..afaa3eeca86 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -124,6 +124,119 @@ static const WCHAR left_windowsW[] = {'L','e','f','t',' ','W','i','n','d','o','w static const WCHAR right_windowsW[] = {'R','i','g','h','t',' ','W','i','n','d','o','w','s',0}; static const WCHAR applicationW[] = {'A','p','p','l','i','c','a','t','i','o','n',0};
+static const VK_TO_BIT vk_to_bit[] = +{ + {.Vk = VK_SHIFT, .ModBits = KBDSHIFT}, + {.Vk = VK_CONTROL, .ModBits = KBDCTRL}, + {.Vk = VK_MENU, .ModBits = KBDALT}, + {0}, +}; + +static const MODIFIERS modifiers = +{ + .pVkToBit = (VK_TO_BIT *)vk_to_bit, + .wMaxModBits = 3, + .ModNumber = {0, 1, 2, 3}, +}; + +static const VK_TO_WCHARS2 vk_to_wchars2[] = +{ + {.VirtualKey = VK_OEM_3, .wch = {'`', '~'}}, + {.VirtualKey = '1', .wch = {'1', '!'}}, + {.VirtualKey = '3', .wch = {'3', '#'}}, + {.VirtualKey = '4', .wch = {'4', '$'}}, + {.VirtualKey = '5', .wch = {'5', '%'}}, + {.VirtualKey = '7', .wch = {'7', '&'}}, + {.VirtualKey = '8', .wch = {'8', '*'}}, + {.VirtualKey = '9', .wch = {'9', '('}}, + {.VirtualKey = '0', .wch = {'0', ')'}}, + {.VirtualKey = VK_OEM_PLUS, .wch = {'=', '+'}}, + {.VirtualKey = 'Q', .wch = {'q', 'Q'}, .Attributes = CAPLOK}, + {.VirtualKey = 'W', .wch = {'w', 'W'}, .Attributes = CAPLOK}, + {.VirtualKey = 'E', .wch = {'e', 'E'}, .Attributes = CAPLOK}, + {.VirtualKey = 'R', .wch = {'r', 'R'}, .Attributes = CAPLOK}, + {.VirtualKey = 'T', .wch = {'t', 'T'}, .Attributes = CAPLOK}, + {.VirtualKey = 'Y', .wch = {'y', 'Y'}, .Attributes = CAPLOK}, + {.VirtualKey = 'U', .wch = {'u', 'U'}, .Attributes = CAPLOK}, + {.VirtualKey = 'I', .wch = {'i', 'I'}, .Attributes = CAPLOK}, + {.VirtualKey = 'O', .wch = {'o', 'O'}, .Attributes = CAPLOK}, + {.VirtualKey = 'P', .wch = {'p', 'P'}, .Attributes = CAPLOK}, + {.VirtualKey = 'A', .wch = {'a', 'A'}, .Attributes = CAPLOK}, + {.VirtualKey = 'S', .wch = {'s', 'S'}, .Attributes = CAPLOK}, + {.VirtualKey = 'D', .wch = {'d', 'D'}, .Attributes = CAPLOK}, + {.VirtualKey = 'F', .wch = {'f', 'F'}, .Attributes = CAPLOK}, + {.VirtualKey = 'G', .wch = {'g', 'G'}, .Attributes = CAPLOK}, + {.VirtualKey = 'H', .wch = {'h', 'H'}, .Attributes = CAPLOK}, + {.VirtualKey = 'J', .wch = {'j', 'J'}, .Attributes = CAPLOK}, + {.VirtualKey = 'K', .wch = {'k', 'K'}, .Attributes = CAPLOK}, + {.VirtualKey = 'L', .wch = {'l', 'L'}, .Attributes = CAPLOK}, + {.VirtualKey = VK_OEM_1, .wch = {';', ':'}}, + {.VirtualKey = VK_OEM_7, .wch = {''', '"'}}, + {.VirtualKey = 'Z', .wch = {'z', 'Z'}, .Attributes = CAPLOK}, + {.VirtualKey = 'X', .wch = {'x', 'X'}, .Attributes = CAPLOK}, + {.VirtualKey = 'C', .wch = {'c', 'C'}, .Attributes = CAPLOK}, + {.VirtualKey = 'V', .wch = {'v', 'V'}, .Attributes = CAPLOK}, + {.VirtualKey = 'B', .wch = {'b', 'B'}, .Attributes = CAPLOK}, + {.VirtualKey = 'N', .wch = {'n', 'N'}, .Attributes = CAPLOK}, + {.VirtualKey = 'M', .wch = {'m', 'M'}, .Attributes = CAPLOK}, + {.VirtualKey = VK_OEM_COMMA, .wch = {',', '<'}}, + {.VirtualKey = VK_OEM_PERIOD, .wch = {'.', '>'}}, + {.VirtualKey = VK_OEM_2, .wch = {'/', '?'}}, + {.VirtualKey = VK_DECIMAL, .wch = {'.', '.'}}, + {.VirtualKey = VK_TAB, .wch = {'\t', '\t'}}, + {.VirtualKey = VK_ADD, .wch = {'+', '+'}}, + {.VirtualKey = VK_DIVIDE, .wch = {'/', '/'}}, + {.VirtualKey = VK_MULTIPLY, .wch = {'*', '*'}}, + {.VirtualKey = VK_SUBTRACT, .wch = {'-', '-'}}, + {0}, +}; + +static const VK_TO_WCHARS3 vk_to_wchars3[] = +{ + {.VirtualKey = VK_OEM_4, .wch = {'[', '{', '\x001b'}}, + {.VirtualKey = VK_OEM_6, .wch = {']', '}', '\x001d'}}, + {.VirtualKey = VK_OEM_5, .wch = {'\', '|', '\x001c'}}, + {.VirtualKey = VK_OEM_102, .wch = {'\', '|', '\x001c'}}, + {.VirtualKey = VK_BACK, .wch = {'\b', '\b', '\x007f'}}, + {.VirtualKey = VK_ESCAPE, .wch = {'\x001b', '\x001b', '\x001b'}}, + {.VirtualKey = VK_RETURN, .wch = {'\r', '\r', '\n'}}, + {.VirtualKey = VK_SPACE, .wch = {' ', ' ', ' '}}, + {.VirtualKey = VK_CANCEL, .wch = {'\x0003', '\x0003', '\x0003'}}, + {0}, +}; + +static const VK_TO_WCHARS4 vk_to_wchars4[] = +{ + {.VirtualKey = '2', .wch = {'2', '@', WCH_NONE, '\x0000'}}, + {.VirtualKey = '6', .wch = {'6', '^', WCH_NONE, '\x001e'}}, + {.VirtualKey = VK_OEM_MINUS, .wch = {'-', '_', WCH_NONE, '\x001f'}}, + {0}, +}; + +static const VK_TO_WCHARS1 vk_to_wchars1[] = +{ + {.VirtualKey = VK_NUMPAD0, .wch = {'0'}}, + {.VirtualKey = VK_NUMPAD1, .wch = {'1'}}, + {.VirtualKey = VK_NUMPAD2, .wch = {'2'}}, + {.VirtualKey = VK_NUMPAD3, .wch = {'3'}}, + {.VirtualKey = VK_NUMPAD4, .wch = {'4'}}, + {.VirtualKey = VK_NUMPAD5, .wch = {'5'}}, + {.VirtualKey = VK_NUMPAD6, .wch = {'6'}}, + {.VirtualKey = VK_NUMPAD7, .wch = {'7'}}, + {.VirtualKey = VK_NUMPAD8, .wch = {'8'}}, + {.VirtualKey = VK_NUMPAD9, .wch = {'9'}}, + {0}, +}; + +static const VK_TO_WCHAR_TABLE vk_to_wchar_table[] = +{ + {.pVkToWchars = (VK_TO_WCHARS1 *)vk_to_wchars3, .nModifications = 3, .cbSize = sizeof(vk_to_wchars3[0])}, + {.pVkToWchars = (VK_TO_WCHARS1 *)vk_to_wchars4, .nModifications = 4, .cbSize = sizeof(vk_to_wchars4[0])}, + {.pVkToWchars = (VK_TO_WCHARS1 *)vk_to_wchars2, .nModifications = 2, .cbSize = sizeof(vk_to_wchars2[0])}, + {.pVkToWchars = (VK_TO_WCHARS1 *)vk_to_wchars1, .nModifications = 1, .cbSize = sizeof(vk_to_wchars1[0])}, + {0}, +}; + static const VSC_LPWSTR key_names[] = { {.vsc = 0x01, .pwsz = (WCHAR *)escW}, @@ -280,12 +393,15 @@ static const VSC_VK vsc_to_vk_e1[] =
static const KBDTABLES kbdus_tables = { + .pCharModifiers = (MODIFIERS *)&modifiers, + .pVkToWcharTable = (VK_TO_WCHAR_TABLE *)vk_to_wchar_table, .pKeyNames = (VSC_LPWSTR *)key_names, .pKeyNamesExt = (VSC_LPWSTR *)key_names_ext, .pusVSCtoVK = (USHORT *)vsc_to_vk, .bMaxVSCtoVK = sizeof(vsc_to_vk) / sizeof(vsc_to_vk[0]), .pVSCtoVK_E0 = (VSC_VK *)vsc_to_vk_e0, .pVSCtoVK_E1 = (VSC_VK *)vsc_to_vk_e1, + .fLocaleFlags = MAKELONG(0, KBD_VERSION), };
@@ -316,6 +432,27 @@ static void kbd_tables_init_vsc2vk( const KBDTABLES *tables, BYTE vsc2vk[0x300] } }
+#define NEXT_ENTRY(t, e) ((void *)&(e)->wch[(t)->nModifications]) + +static void kbd_tables_init_vk2char( const KBDTABLES *tables, BYTE vk2char[0x100] ) +{ + const VK_TO_WCHAR_TABLE *table; + const VK_TO_WCHARS1 *entry; + + memset( vk2char, 0, 0x100 ); + + for (table = tables->pVkToWcharTable; table->pVkToWchars; table++) + { + for (entry = table->pVkToWchars; entry->VirtualKey; entry = NEXT_ENTRY(table, entry)) + { + if (entry->VirtualKey & ~0xff) continue; + vk2char[entry->VirtualKey] = entry->wch[0]; + } + } +} + +#undef NEXT_ENTRY + /********************************************************************** * NtUserAttachThreadInput (win32u.@) */ @@ -816,25 +953,6 @@ WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout ) return ret; }
-static const UINT kbd_en_vk2char[] = -{ - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, - ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '+', 0x00, '-', '.', '/', - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ';', '=', ',', '-', '.', '/', - '`', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '[', '\', ']', ''', 0x00, - 0x00, 0x00, '\', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -};
/****************************************************************************** * NtUserMapVirtualKeyEx (win32u.@) @@ -842,9 +960,7 @@ static const UINT kbd_en_vk2char[] = UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) { const KBDTABLES *kbd_tables = &kbdus_tables; - const UINT *vk2char; - BYTE vsc2vk[0x300]; - UINT vk2char_size; + BYTE vsc2vk[0x300], vk2char[0x100]; UINT ret;
TRACE_(keyboard)( "code %u, type %u, layout %p.\n", code, type, layout ); @@ -852,9 +968,7 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) if ((ret = user_driver->pMapVirtualKeyEx( code, type, layout )) != -1) return ret;
kbd_tables_init_vsc2vk( kbd_tables, vsc2vk ); - - vk2char = kbd_en_vk2char; - vk2char_size = ARRAYSIZE(kbd_en_vk2char); + kbd_tables_init_vk2char( kbd_tables, vk2char );
switch (type) { @@ -905,7 +1019,8 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout ) } break; case MAPVK_VK_TO_CHAR: - if (code >= vk2char_size) ret = 0; + if (code >= ARRAY_SIZE(vk2char)) ret = 0; + else if (code >= 'A' && code <= 'Z') ret = code; else ret = vk2char[code]; break; default:
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 89 ++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 50 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index afaa3eeca86..0dbbd7dda3f 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -451,6 +451,43 @@ static void kbd_tables_init_vk2char( const KBDTABLES *tables, BYTE vk2char[0x100 } }
+static UINT kbd_tables_get_mod_bits( const KBDTABLES *tables, UINT mod ) +{ + const MODIFIERS *mods = tables->pCharModifiers; + WORD bits; + + for (bits = 0; bits <= mods->wMaxModBits; ++bits) + if (mods->ModNumber[bits] == mod) return bits; + + return -1; +} + +static WORD kbd_tables_wchar_to_vkey( const KBDTABLES *tables, WCHAR wch ) +{ + const VK_TO_WCHAR_TABLE *table; + const VK_TO_WCHARS1 *entry; + WORD bits; + BYTE mod; + + if (wch == '\x001b') return VK_ESCAPE; + + for (table = tables->pVkToWcharTable; table->pVkToWchars; table++) + { + for (entry = table->pVkToWchars; entry->VirtualKey; entry = NEXT_ENTRY(table, entry)) + { + for (mod = 0; mod < table->nModifications; ++mod) + { + if (entry->wch[mod] == WCH_NONE || entry->wch[mod] != wch) continue; + bits = kbd_tables_get_mod_bits( tables, mod ); + return (bits << 8) | entry->VirtualKey; + } + } + } + + if (wch >= 0x0001 && wch <= 0x001a) return (0x200) | ('A' + wch - 1); /* CTRL + A-Z */ + return wch >= 0x0080 ? -1 : 0; +} + #undef NEXT_ENTRY
/********************************************************************** @@ -893,61 +930,13 @@ BOOL WINAPI NtUserSetKeyboardState( BYTE *state ) */ WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout ) { - WORD shift = 0x100, ctrl = 0x200; + const KBDTABLES *kbd_tables = &kbdus_tables; SHORT ret;
TRACE_(keyboard)( "chr %s, layout %p\n", debugstr_wn(&chr, 1), layout );
if ((ret = user_driver->pVkKeyScanEx( chr, layout )) != -256) return ret; - - /* FIXME: English keyboard layout specific */ - - if (chr == VK_CANCEL || chr == VK_BACK || chr == VK_TAB || chr == VK_RETURN || - chr == VK_ESCAPE || chr == VK_SPACE) ret = chr; - else if (chr >= '0' && chr <= '9') ret = chr; - else if (chr == ')') ret = shift + '0'; - else if (chr == '!') ret = shift + '1'; - else if (chr == '@') ret = shift + '2'; - else if (chr == '#') ret = shift + '3'; - else if (chr == '$') ret = shift + '4'; - else if (chr == '%') ret = shift + '5'; - else if (chr == '^') ret = shift + '6'; - else if (chr == '&') ret = shift + '7'; - else if (chr == '*') ret = shift + '8'; - else if (chr == '(') ret = shift + '9'; - else if (chr >= 'a' && chr <= 'z') ret = chr - 'a' + 'A'; - else if (chr >= 'A' && chr <= 'Z') ret = shift + chr; - else if (chr == ';') ret = VK_OEM_1; - else if (chr == '=') ret = VK_OEM_PLUS; - else if (chr == ',') ret = VK_OEM_COMMA; - else if (chr == '-') ret = VK_OEM_MINUS; - else if (chr == '.') ret = VK_OEM_PERIOD; - else if (chr == '/') ret = VK_OEM_2; - else if (chr == '`') ret = VK_OEM_3; - else if (chr == '[') ret = VK_OEM_4; - else if (chr == '\') ret = VK_OEM_5; - else if (chr == ']') ret = VK_OEM_6; - else if (chr == ''') ret = VK_OEM_7; - else if (chr == ':') ret = shift + VK_OEM_1; - else if (chr == '+') ret = shift + VK_OEM_PLUS; - else if (chr == '<') ret = shift + VK_OEM_COMMA; - else if (chr == '_') ret = shift + VK_OEM_MINUS; - else if (chr == '>') ret = shift + VK_OEM_PERIOD; - else if (chr == '?') ret = shift + VK_OEM_2; - else if (chr == '~') ret = shift + VK_OEM_3; - else if (chr == '{') ret = shift + VK_OEM_4; - else if (chr == '|') ret = shift + VK_OEM_5; - else if (chr == '}') ret = shift + VK_OEM_6; - else if (chr == '"') ret = shift + VK_OEM_7; - else if (chr == 0x7f) ret = ctrl + VK_BACK; - else if (chr == '\n') ret = ctrl + VK_RETURN; - else if (chr == 0xf000) ret = ctrl + '2'; - else if (chr == 0x0000) ret = ctrl + shift + '2'; - else if (chr >= 0x0001 && chr <= 0x001a) ret = ctrl + 'A' + chr - 1; - else if (chr >= 0x001c && chr <= 0x001d) ret = ctrl + VK_OEM_3 + chr; - else if (chr == 0x001e) ret = ctrl + shift + '6'; - else if (chr == 0x001f) ret = ctrl + shift + VK_OEM_MINUS; - else ret = -1; + ret = kbd_tables_wchar_to_vkey( kbd_tables, chr );
TRACE_(keyboard)( "ret %04x\n", ret ); return ret;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/input.c | 122 +++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 70 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 0dbbd7dda3f..4ba85637e24 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -462,6 +462,20 @@ static UINT kbd_tables_get_mod_bits( const KBDTABLES *tables, UINT mod ) return -1; }
+static UINT kbd_tables_get_mod_num( const KBDTABLES *tables, const BYTE *state, BOOL caps ) +{ + const MODIFIERS *mods = tables->pCharModifiers; + const VK_TO_BIT *entry; + WORD bits = 0; + + for (entry = mods->pVkToBit; entry->Vk; ++entry) + if (state[entry->Vk] & 0x80) bits |= entry->ModBits; + if (caps) bits |= KBDSHIFT; + + if (bits > mods->wMaxModBits) return -1; + return mods->ModNumber[bits]; +} + static WORD kbd_tables_wchar_to_vkey( const KBDTABLES *tables, WCHAR wch ) { const VK_TO_WCHAR_TABLE *table; @@ -488,6 +502,37 @@ static WORD kbd_tables_wchar_to_vkey( const KBDTABLES *tables, WCHAR wch ) return wch >= 0x0080 ? -1 : 0; }
+static WCHAR kbd_tables_vkey_to_wchar( const KBDTABLES *tables, UINT vkey, const BYTE *state ) +{ + UINT mod, caps_mod, alt, ctrl, caps; + const VK_TO_WCHAR_TABLE *table; + const VK_TO_WCHARS1 *entry; + + alt = state[VK_MENU] & 0x80; + ctrl = state[VK_CONTROL] & 0x80; + caps = state[VK_CAPITAL] & 1; + + if (ctrl && alt) return WCH_NONE; + if (!ctrl && vkey == VK_ESCAPE) return VK_ESCAPE; + + mod = caps_mod = kbd_tables_get_mod_num( tables, state, FALSE ); + if (caps) caps_mod = kbd_tables_get_mod_num( tables, state, TRUE ); + + for (table = tables->pVkToWcharTable; table->pVkToWchars; table++) + { + if (table->nModifications <= mod) continue; + for (entry = table->pVkToWchars; entry->VirtualKey; entry = NEXT_ENTRY(table, entry)) + { + if (entry->VirtualKey != vkey) continue; + if ((entry->Attributes & CAPLOK) && table->nModifications > caps_mod) return entry->wch[caps_mod]; + return entry->wch[mod]; + } + } + + if (ctrl && vkey >= 'A' && vkey <= 'Z') return vkey - 'A' + 1; + return WCH_NONE; +} + #undef NEXT_ENTRY
/********************************************************************** @@ -1079,86 +1124,23 @@ INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ) INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state, WCHAR *str, int size, UINT flags, HKL layout ) { - BOOL shift, ctrl, alt, numlock; - WCHAR buffer[2]; + const KBDTABLES *kbd_tables = &kbdus_tables; + WCHAR buffer[2] = {0}; INT len;
- TRACE_(keyboard)( "virt %u, scan %u, state %p, str %p, size %d, flags %x, layout %p.\n", + TRACE_(keyboard)( "virt %#x, scan %#x, state %p, str %p, size %d, flags %#x, layout %p.\n", virt, scan, state, str, size, flags, layout );
if (!state) return 0; if ((len = user_driver->pToUnicodeEx( virt, scan, state, str, size, flags, layout )) >= -1) return len;
- alt = state[VK_MENU] & 0x80; - shift = state[VK_SHIFT] & 0x80; - ctrl = state[VK_CONTROL] & 0x80; - numlock = state[VK_NUMLOCK] & 0x01; + if (scan & 0x8000) buffer[0] = 0; /* key up */ + else buffer[0] = kbd_tables_vkey_to_wchar( kbd_tables, virt, state );
- /* FIXME: English keyboard layout specific */ + if (buffer[0] != WCH_NONE) len = 1; + else buffer[0] = len = 0;
- if (scan & 0x8000) buffer[0] = 0; /* key up */ - else if (virt == VK_ESCAPE) buffer[0] = VK_ESCAPE; - else if (!ctrl) - { - switch (virt) - { - case VK_BACK: buffer[0] = '\b'; break; - case VK_OEM_1: buffer[0] = shift ? ':' : ';'; break; - case VK_OEM_2: buffer[0] = shift ? '?' : '/'; break; - case VK_OEM_3: buffer[0] = shift ? '~' : '`'; break; - case VK_OEM_4: buffer[0] = shift ? '{' : '['; break; - case VK_OEM_5: buffer[0] = shift ? '|' : '\'; break; - case VK_OEM_6: buffer[0] = shift ? '}' : ']'; break; - case VK_OEM_7: buffer[0] = shift ? '"' : '''; break; - case VK_OEM_COMMA: buffer[0] = shift ? '<' : ','; break; - case VK_OEM_MINUS: buffer[0] = shift ? '_' : '-'; break; - case VK_OEM_PERIOD: buffer[0] = shift ? '>' : '.'; break; - case VK_OEM_PLUS: buffer[0] = shift ? '+' : '='; break; - case VK_RETURN: buffer[0] = '\r'; break; - case VK_SPACE: buffer[0] = ' '; break; - case VK_TAB: buffer[0] = '\t'; break; - case VK_MULTIPLY: buffer[0] = '*'; break; - case VK_ADD: buffer[0] = '+'; break; - case VK_SUBTRACT: buffer[0] = '-'; break; - case VK_DIVIDE: buffer[0] = '/'; break; - default: - if (virt >= '0' && virt <= '9') - buffer[0] = shift ? ")!@#$%^&*("[virt - '0'] : virt; - else if (virt >= 'A' && virt <= 'Z') - buffer[0] = shift || (state[VK_CAPITAL] & 0x01) ? virt : virt + 'a' - 'A'; - else if (virt >= VK_NUMPAD0 && virt <= VK_NUMPAD9 && numlock && !shift) - buffer[0] = '0' + virt - VK_NUMPAD0; - else if (virt == VK_DECIMAL && numlock && !shift) - buffer[0] = '.'; - else - buffer[0] = 0; - break; - } - } - else if (!alt) /* Control codes */ - { - switch (virt) - { - case VK_OEM_4: buffer[0] = 0x1b; break; - case VK_OEM_5: buffer[0] = 0x1c; break; - case VK_OEM_6: buffer[0] = 0x1d; break; - case '6': buffer[0] = shift ? 0x1e : 0; break; - case VK_OEM_MINUS: buffer[0] = shift ? 0x1f : 0; break; - case VK_BACK: buffer[0] = 0x7f; break; - case VK_RETURN: buffer[0] = shift ? 0 : '\n'; break; - case '2': buffer[0] = shift ? 0xffff : 0xf000; break; - case VK_SPACE: buffer[0] = ' '; break; - default: - if (virt >= 'A' && virt <= 'Z') buffer[0] = virt - 'A' + 1; - else buffer[0] = 0; - break; - } - } - else buffer[0] = 0; - buffer[1] = 0; - len = lstrlenW( buffer ); - if (buffer[0] == 0xffff) buffer[0] = 0; lstrcpynW( str, buffer, size );
TRACE_(keyboard)( "ret %d, str %s.\n", len, debugstr_w(str) );
Is there something I should do about this? I think this is pretty straightforward, it introduces the standard structures for keyboard layout definition and uses them for the nulldrv implementation instead of custom arrays.