Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 2 +- dlls/user32/input.c | 154 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index e5855e1c51b..aedc0366615 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -275,7 +275,7 @@ static HKL CDECL nulldrv_LoadKeyboardLayout( LPCWSTR name, UINT flags )
static UINT CDECL nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout ) { - return 0; + return -1; /* use default implementation */ }
static BOOL CDECL nulldrv_RegisterHotKey( HWND hwnd, UINT modifiers, UINT vk ) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index b21ec73696d..4eaac54343e 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -777,14 +777,162 @@ UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl) 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, + 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, +}; + + /****************************************************************************** * MapVirtualKeyExW (USER32.@) */ -UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl) +UINT WINAPI MapVirtualKeyExW( UINT code, UINT type, HKL layout ) { - TRACE_(keyboard)("(%X, %d, %p)\n", code, maptype, hkl); + const UINT *vsc2vk, *vk2char; + UINT vsc2vk_size, vk2char_size; + UINT ret; + + TRACE_(keyboard)( "code %u, type %u, layout %p.\n", code, type, layout );
- return USER_Driver->pMapVirtualKeyEx(code, maptype, hkl); + if ((ret = USER_Driver->pMapVirtualKeyEx( code, type, layout )) != -1) return ret; + + /* FIXME: English keyboard layout specific */ + + vsc2vk = kbd_en_vsc2vk; + vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk); + vk2char = kbd_en_vk2char; + vk2char_size = ARRAYSIZE(kbd_en_vk2char); + + switch (type) + { + case MAPVK_VK_TO_VSC_EX: + case MAPVK_VK_TO_VSC: + switch (code) + { + case VK_SHIFT: code = VK_LSHIFT; break; + case VK_CONTROL: code = VK_LCONTROL; break; + case VK_MENU: code = VK_LMENU; break; + case VK_NUMPAD0: code = VK_INSERT; break; + case VK_NUMPAD1: code = VK_END; break; + case VK_NUMPAD2: code = VK_DOWN; break; + case VK_NUMPAD3: code = VK_NEXT; break; + case VK_NUMPAD4: code = VK_LEFT; break; + case VK_NUMPAD5: code = VK_CLEAR; break; + case VK_NUMPAD6: code = VK_RIGHT; break; + case VK_NUMPAD7: code = VK_HOME; break; + case VK_NUMPAD8: code = VK_UP; break; + case VK_NUMPAD9: code = VK_PRIOR; break; + 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; + + if (type == MAPVK_VK_TO_VSC) + { + if (ret >= 0x200) ret = 0; + else ret &= 0xff; + } + else if (ret >= 0x100) ret += 0xdf00; + break; + case MAPVK_VSC_TO_VK: + case MAPVK_VSC_TO_VK_EX: + if (code & 0xe000) code -= 0xdf00; + if (code >= vsc2vk_size) ret = 0; + else ret = vsc2vk[code]; + + if (type == MAPVK_VSC_TO_VK) + { + switch (ret) + { + case VK_LSHIFT: case VK_RSHIFT: ret = VK_SHIFT; break; + case VK_LCONTROL: case VK_RCONTROL: ret = VK_CONTROL; break; + case VK_LMENU: case VK_RMENU: ret = VK_MENU; break; + } + } + break; + case MAPVK_VK_TO_CHAR: + if (code >= vk2char_size) ret = 0; + else ret = vk2char[code]; + break; + default: + FIXME_(keyboard)( "unknown type %d\n", type ); + return 0; + } + + TRACE_(keyboard)( "returning 0x%04x\n", ret ); + return ret; }
/****************************************************************************
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 2 +- dlls/user32/input.c | 85 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index aedc0366615..97733bb9bd3 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -255,7 +255,7 @@ static UINT CDECL nulldrv_GetKeyboardLayoutList( INT size, HKL *layouts )
static INT CDECL nulldrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) { - return 0; + return -1; /* use default implementation */ }
static HKL CDECL nulldrv_GetKeyboardLayout( DWORD thread_id ) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 4eaac54343e..d2e41cd8212 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -853,6 +853,43 @@ static const UINT kbd_en_vk2char[] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+static const WCHAR *kbd_en_vscname[] = +{ + 0, L"Esc", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Backspace", L"Tab", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Enter", L"Ctrl", 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Shift", 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, L"Right Shift", L"Num *", L"Alt", L"Space", L"Caps Lock", L"F1", L"F2", L"F3", L"F4", L"F5", + L"F6", L"F7", L"F8", L"F9", L"F10", L"Pause", L"Scroll Lock", L"Num 7", L"Num 8", L"Num 9", L"Num -", L"Num 4", L"Num 5", L"Num 6", L"Num +", L"Num 1", + L"Num 2", L"Num 3", L"Num 0", L"Num Del", L"Sys Req", 0, 0, L"F11", L"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, L"F13", L"F14", L"F15", L"F16", + L"F17", L"F18", L"F19", L"F20", L"F21", L"F22", L"F23", L"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, L"Num Enter", L"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, L"Num /", 0, L"Prnt Scrn", L"Right Alt", 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, L"Num Lock", L"Break", L"Home", L"Up", L"Page Up", 0, L"Left", 0, L"Right", 0, L"End", + L"Down", L"Page Down", L"Insert", L"Delete", L"<00>", 0, L"Help", 0, 0, 0, 0, L"Left Windows", L"Right Windows", L"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, +}; +
/****************************************************************************** * MapVirtualKeyExW (USER32.@) @@ -1007,10 +1044,52 @@ INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize) /**************************************************************************** * GetKeyNameTextW (USER32.@) */ -INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize) +INT WINAPI GetKeyNameTextW( LONG lparam, LPWSTR buffer, INT size ) { - if (!lpBuffer || !nSize) return 0; - return USER_Driver->pGetKeyNameText( lParam, lpBuffer, nSize ); + INT code = ((lparam >> 16) & 0x1ff), vkey, len; + UINT vsc2vk_size, vscname_size; + const WCHAR *const *vscname; + const UINT *vsc2vk; + WCHAR tmp[2]; + + TRACE_(keyboard)( "lparam %d, buffer %p, size %d.\n", 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); + vscname = kbd_en_vscname; + vscname_size = ARRAYSIZE(kbd_en_vscname); + + if (lparam & 0x2000000) + { + switch ((vkey = vsc2vk[code])) + { + case VK_RSHIFT: + case VK_RCONTROL: + case VK_RMENU: + for (code = 0; code < vsc2vk_size; ++code) + if (vsc2vk[code] == (vkey - 1)) break; + break; + } + } + + if (code >= vscname_size) buffer[0] = 0; + else if (vscname[code]) lstrcpynW( buffer, vscname[code], size ); + else + { + vkey = MapVirtualKeyW( code & 0xff, MAPVK_VSC_TO_VK ); + tmp[0] = MapVirtualKeyW( vkey, MAPVK_VK_TO_CHAR ); + tmp[1] = 0; + lstrcpynW( buffer, tmp, size ); + } + len = wcslen( buffer ); + + TRACE_(keyboard)( "ret %d, str %s.\n", len, debugstr_w(buffer) ); + return len; }
/****************************************************************************
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89598
Your paranoid android.
=== debiant2 (32 bit Chinese:China report) ===
user32: win.c:10155: Test failed: Expected foreground window 0, got 00EB00D4 win.c:10161: Test failed: Expected foreground window 000E0120, got 00EB00D4 win.c:10173: Test failed: GetForegroundWindow() = 000E0120 win.c:10178: Test failed: Expected foreground window 000E0120, got 00EB00D4 win.c:10180: Test failed: GetActiveWindow() = 00000000 win.c:10180: Test failed: GetFocus() = 00000000 win.c:10182: Test failed: Received WM_ACTIVATEAPP(0), did not expect it. win.c:10190: Test failed: Expected foreground window 000E0120, got 00000000 win.c:10192: Test failed: GetActiveWindow() = 00000000 win.c:10192: Test failed: GetFocus() = 00000000 win.c:10200: Test failed: Received WM_ACTIVATEAPP(1), did not expect it.
This is basically the reverse of ToUnicodeEx.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 9 +------ dlls/user32/input.c | 61 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 97733bb9bd3..e3cf41561b5 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -300,14 +300,7 @@ static void CDECL nulldrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
static SHORT CDECL nulldrv_VkKeyScanEx( WCHAR ch, HKL layout ) { - static const short ctrl_vks[] = { - 0x332, 0x241, 0x242, 0x003, 0x244, 0x245, 0x246, 0x247, - 0x008, 0x009, 0x20d, 0x24b, 0x24c, 0x00d, 0x24e, 0x24f, - 0x250, 0x251, 0x252, 0x253, 0x254, 0x255, 0x256, 0x257, - 0x258, 0x259, 0x25a, 0x01b, 0x2dc, 0x2dd, 0x336, 0x3bd - }; - - return ch < ARRAY_SIZE(ctrl_vks) ? ctrl_vks[ch] : -1; + return -256; /* use default implementation */ }
static void CDECL nulldrv_DestroyCursorIcon( HCURSOR cursor ) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index d2e41cd8212..4ecc73c4ad0 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -674,9 +674,66 @@ WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl) /****************************************************************************** * VkKeyScanExW (USER32.@) */ -WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl) +WORD WINAPI VkKeyScanExW( WCHAR chr, HKL layout ) { - return USER_Driver->pVkKeyScanEx(cChar, dwhkl); + WORD shift = 0x100, ctrl = 0x200; + 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; + + TRACE_(keyboard)( "ret %04x\n", ret ); + return ret; }
/**********************************************************************
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89599
Your paranoid android.
=== debiant2 (32 bit report) ===
user32: win.c:10161: Test failed: Expected foreground window 000E0120, got 00EB00D4 win.c:10171: Test failed: Expected foreground window 000E0120, got 00000000 win.c:10173: Test failed: GetActiveWindow() = 00000000 win.c:10173: Test failed: GetFocus() = 00000000 win.c:10181: Test failed: Received WM_ACTIVATEAPP(1), did not expect it. win.c:10197: Test failed: Expected foreground window 000E0120, got 00EB00D4
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 54 +------------------------------ dlls/user32/input.c | 77 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 56 deletions(-)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index e3cf41561b5..c075a49a350 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -198,59 +198,7 @@ static void CDECL nulldrv_Beep(void)
static UINT CDECL nulldrv_GetKeyboardLayoutList( INT size, HKL *layouts ) { - HKEY hKeyKeyboard; - DWORD rc; - INT count = 0; - ULONG_PTR baselayout; - LANGID langid; - - baselayout = GetUserDefaultLCID(); - langid = PRIMARYLANGID(LANGIDFROMLCID(baselayout)); - if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) - baselayout = MAKELONG( baselayout, 0xe001 ); /* IME */ - else - baselayout |= baselayout << 16; - - /* Enumerate the Registry */ - rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,L"System\CurrentControlSet\Control\Keyboard Layouts",&hKeyKeyboard); - if (rc == ERROR_SUCCESS) - { - do { - WCHAR szKeyName[9]; - HKL layout; - rc = RegEnumKeyW(hKeyKeyboard, count, szKeyName, 9); - if (rc == ERROR_SUCCESS) - { - layout = (HKL)(ULONG_PTR)wcstoul(szKeyName,NULL,16); - if (baselayout != 0 && layout == (HKL)baselayout) - baselayout = 0; /* found in the registry do not add again */ - if (size && layouts) - { - if (count >= size ) break; - layouts[count] = layout; - } - count ++; - } - } while (rc == ERROR_SUCCESS); - RegCloseKey(hKeyKeyboard); - } - - /* make sure our base layout is on the list */ - if (baselayout != 0) - { - if (size && layouts) - { - if (count < size) - { - layouts[count] = (HKL)baselayout; - count++; - } - } - else - count++; - } - - return count; + return ~0; /* use default implementation */ }
static INT CDECL nulldrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 4ecc73c4ad0..4895a007500 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -77,6 +77,43 @@ static WORD get_key_state(void) }
+/*********************************************************************** + * get_locale_kbd_layout + */ +static HKL get_locale_kbd_layout(void) +{ + ULONG_PTR layout; + LANGID langid; + + /* FIXME: + * + * layout = main_key_tab[kbd_layout].lcid; + * + * Winword uses return value of GetKeyboardLayout as a codepage + * to translate ANSI keyboard messages to unicode. But we have + * a problem with it: for instance Polish keyboard layout is + * identical to the US one, and therefore instead of the Polish + * locale id we return the US one. + */ + + layout = GetUserDefaultLCID(); + + /* + * Microsoft Office expects this value to be something specific + * for Japanese and Korean Windows with an IME the value is 0xe001 + * We should probably check to see if an IME exists and if so then + * set this word properly. + */ + langid = PRIMARYLANGID( LANGIDFROMLCID( layout ) ); + if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) + layout = MAKELONG( layout, 0xe001 ); /* IME */ + else + layout = MAKELONG( layout, layout ); + + return (HKL)layout; +} + + /********************************************************************** * set_capture_window */ @@ -1297,11 +1334,45 @@ BOOL WINAPI BlockInput(BOOL fBlockIt) * Return number of values available if either input parm is * 0, per MS documentation. */ -UINT WINAPI GetKeyboardLayoutList(INT nBuff, HKL *layouts) +UINT WINAPI GetKeyboardLayoutList( INT size, HKL *layouts ) { - TRACE_(keyboard)( "(%d, %p)\n", nBuff, layouts ); + WCHAR klid[KL_NAMELENGTH]; + UINT count, tmp, i = 0; + HKEY hkey; + HKL layout; + + TRACE_(keyboard)( "size %d, layouts %p.\n", size, layouts ); + + if ((count = USER_Driver->pGetKeyboardLayoutList( size, layouts )) != ~0) return count; + + layout = get_locale_kbd_layout(); + count = 0; + + count++; + if (size && layouts) + { + layouts[count - 1] = layout; + if (count == size) return count; + } + + if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, L"System\CurrentControlSet\Control\Keyboard Layouts", &hkey )) + { + while (!RegEnumKeyW( hkey, i++, klid, ARRAY_SIZE(klid) )) + { + tmp = wcstoul( klid, NULL, 16 ); + if (layout == UlongToHandle( tmp )) continue; + + count++; + if (size && layouts) + { + layouts[count - 1] = UlongToHandle( tmp ); + if (count == size) break; + } + } + RegCloseKey( hkey ); + }
- return USER_Driver->pGetKeyboardLayoutList( nBuff, layouts ); + return count; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 4895a007500..97be83369d9 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1336,8 +1336,8 @@ BOOL WINAPI BlockInput(BOOL fBlockIt) */ UINT WINAPI GetKeyboardLayoutList( INT size, HKL *layouts ) { - WCHAR klid[KL_NAMELENGTH]; - UINT count, tmp, i = 0; + WCHAR klid[KL_NAMELENGTH], value[5]; + DWORD value_size, count, tmp, i = 0; HKEY hkey; HKL layout;
@@ -1360,6 +1360,10 @@ UINT WINAPI GetKeyboardLayoutList( INT size, HKL *layouts ) while (!RegEnumKeyW( hkey, i++, klid, ARRAY_SIZE(klid) )) { tmp = wcstoul( klid, NULL, 16 ); + value_size = sizeof(value); + if (!RegGetValueW( hkey, klid, L"Layout Id", RRF_RT_REG_SZ, NULL, (void *)&value, &value_size )) + tmp = MAKELONG( LOWORD( tmp ), 0xf000 | (wcstoul( value, NULL, 16 ) & 0xfff) ); + if (layout == UlongToHandle( tmp )) continue;
count++;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89601
Your paranoid android.
=== debiant2 (32 bit report) ===
user32: win.c:10155: Test failed: Expected foreground window 0, got 00EB00D4 win.c:10161: Test failed: Expected foreground window 000E0120, got 00EB00D4
=== debiant2 (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 27