Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/tests/input.c | 78 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index b45adeb3cae..3d4f0d03d0d 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -3072,9 +3072,10 @@ static void test_get_async_key_state(void) static void test_keyboard_layout_name(void) { WCHAR klid[KL_NAMELENGTH], tmpklid[KL_NAMELENGTH], layout_path[MAX_PATH], value[5]; - HKL layout, tmplayout, layouts[64]; - DWORD status, value_size; - int i, len; + HKL layout, tmplayout, *layouts, *layouts_preload; + DWORD status, value_size, klid_size, type, id; + int i, j, len; + HKEY hkey; BOOL ret;
if (0) /* crashes on native system */ @@ -3087,15 +3088,77 @@ static void test_keyboard_layout_name(void)
layout = GetKeyboardLayout(0);
- len = GetKeyboardLayoutList(ARRAY_SIZE(layouts), layouts); + len = GetKeyboardLayoutList(0, NULL); + ok(len > 0, "GetKeyboardLayoutList returned %d\n", len); + + layouts = malloc(len * sizeof(HKL)); + ok(layouts != NULL, "Could not allocate memory\n"); + + len = GetKeyboardLayoutList(len, layouts); ok(len > 0, "GetKeyboardLayoutList returned %d\n", len);
+ layouts_preload = calloc(len, sizeof(HKL)); + ok(layouts_preload != NULL, "Could not allocate memory\n"); + + if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Keyboard Layout\Preload", &hkey )) + { + i = 0; + type = REG_SZ; + klid_size = sizeof(klid); + value_size = ARRAY_SIZE(value); + while (i < len && !RegEnumValueW( hkey, i++, value, &value_size, NULL, &type, (void *)&klid, &klid_size )) + { + klid_size = sizeof(klid); + value_size = ARRAY_SIZE(value); + layouts_preload[i - 1] = UlongToHandle( wcstoul( klid, NULL, 16 ) ); + + id = (DWORD_PTR)layouts_preload[i - 1]; + if (id & 0x80000000) todo_wine_if(HIWORD(id) == 0xe001) ok((id & 0xf0000000) == 0xd0000000, "Unexpected preloaded keyboard layout high bits %#x\n", id); + else ok(!(id & 0xf0000000), "Unexpected preloaded keyboard layout high bits %#x\n", id); + } + + ok(i <= len, "Unexpected keyboard count %d in preload list\n", i); + RegCloseKey( hkey ); + } + + if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Keyboard Layout\Substitutes", &hkey )) + { + for (i = 0; i < len && layouts_preload[i]; ++i) + { + type = REG_SZ; + klid_size = sizeof(klid); + swprintf( tmpklid, KL_NAMELENGTH, L"%08x", HandleToUlong( layouts_preload[i] ) ); + if (!RegQueryValueExW( hkey, tmpklid, NULL, &type, (void *)&klid, &klid_size )) + { + layouts_preload[i] = UlongToHandle( wcstoul( klid, NULL, 16 ) ); + + /* Substitute should contain the keyboard layout id, not the HKL high word */ + id = (DWORD_PTR)layouts_preload[i]; + ok(!(id & 0xf0000000), "Unexpected substitute keyboard layout high bits %#x\n", id); + } + else + { + id = (DWORD_PTR)layouts_preload[i]; + ok(!(id & 0xf0000000), "Unexpected preloaded keyboard layout high bits %#x\n", id); + } + } + + RegCloseKey( hkey ); + } + for (i = len - 1; i >= 0; --i) { - UINT id = (UINT_PTR)layouts[i]; + id = (DWORD_PTR)layouts[i]; ActivateKeyboardLayout(layouts[i], 0); GetKeyboardLayoutNameW(klid);
+ for (j = 0; j < len; ++j) + { + swprintf( tmpklid, KL_NAMELENGTH, L"%08X", layouts_preload[j] ); + if (!wcscmp( tmpklid, klid )) break; + } + ok(j < len, "Could not find keyboard layout %p in preload list\n", layout); + if (id & 0x80000000) { todo_wine ok((id >> 28) == 0xf, "hkl high bits %#x, expected 0xf\n", id >> 28); @@ -3120,7 +3183,7 @@ static void test_keyboard_layout_name(void) tmplayout = LoadKeyboardLayoutW(klid, KLF_ACTIVATE);
/* The low word of HKL is the selected user lang and may be different as LoadKeyboardLayoutW also selects the default lang from the layout */ - ok(((UINT_PTR)tmplayout & ~0xffff) == ((UINT_PTR)layouts[i] & ~0xffff), "GetKeyboardLayout returned %p, expected %p\n", tmplayout, layouts[i]); + ok(((UINT_PTR)tmplayout & ~0xffff) == ((UINT_PTR)layouts[i] & ~0xffff), "LoadKeyboardLayoutW returned %p, expected %p\n", tmplayout, layouts[i]);
/* The layout name only depends on the keyboard layout: the high word of HKL. */ GetKeyboardLayoutNameW(tmpklid); @@ -3128,6 +3191,9 @@ static void test_keyboard_layout_name(void) }
ActivateKeyboardLayout(layout, 0); + + free(layouts); + free(layouts_preload); }
static void test_key_names(void)
To avoid iterating the registry every time GetKeyboardLayoutNameW is called.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This is causing some slow down in "Monster Boy and the cursed Kingdom" for instance, which is calling GetKeyboardLayoutNameW frequently. This is also more likely to be slow with Wine Staging, which adds registry keys for a lot of different layouts.
dlls/user32/input.c | 10 ++++++++++ dlls/user32/user_private.h | 1 + 2 files changed, 11 insertions(+)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c index adeb4f66804..1b2360ea083 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1129,6 +1129,7 @@ BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID) */ BOOL WINAPI GetKeyboardLayoutNameW( WCHAR *name ) { + struct user_thread_info *info = get_user_thread_info(); WCHAR klid[KL_NAMELENGTH], value[5]; DWORD value_size, tmp, i = 0; HKEY hkey; @@ -1142,6 +1143,12 @@ BOOL WINAPI GetKeyboardLayoutNameW( WCHAR *name ) return FALSE; }
+ if (info->kbd_layout_id) + { + swprintf( name, KL_NAMELENGTH, L"%08X", info->kbd_layout_id ); + return TRUE; + } + layout = GetKeyboardLayout( 0 ); tmp = HandleToUlong( layout ); if (HIWORD( tmp ) == LOWORD( tmp )) tmp = LOWORD( tmp ); @@ -1166,6 +1173,8 @@ BOOL WINAPI GetKeyboardLayoutNameW( WCHAR *name ) RegCloseKey( hkey ); }
+ info->kbd_layout_id = wcstoul( name, NULL, 16 ); + TRACE_(keyboard)( "ret %s\n", debugstr_w( name ) ); return TRUE; } @@ -1394,6 +1403,7 @@ HKL WINAPI ActivateKeyboardLayout( HKL layout, UINT flags )
old_layout = info->kbd_layout; info->kbd_layout = layout; + if (old_layout != layout) info->kbd_layout_id = 0;
if (!old_layout) return get_locale_kbd_layout(); return old_layout; diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 1c7ac3355bc..1bc41888891 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -198,6 +198,7 @@ struct user_thread_info ULONG_PTR GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */ struct user_key_state_info *key_state; /* Cache of global key state */ HKL kbd_layout; /* Current keyboard layout */ + DWORD kbd_layout_id; /* Current keyboard layout ID */ HWND top_window; /* Desktop window */ HWND msg_window; /* HWND_MESSAGE parent window */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
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=90037
Your paranoid android.
=== debiant2 (32 bit WoW report) ===
user32: msg.c:12605: Test failed: coords not changed: (639 100) (639 105) msg: Timeout
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/driver.c | 26 -------------------------- dlls/user32/input.c | 16 ++++++++-------- dlls/user32/user_private.h | 2 -- dlls/winex11.drv/keyboard.c | 21 --------------------- dlls/winex11.drv/winex11.drv.spec | 2 -- 5 files changed, 8 insertions(+), 59 deletions(-)
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 36438fa44c8..1c3b62eff2b 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -109,11 +109,9 @@ static const USER_DRIVER *load_driver(void) GET_USER_FUNC(Beep); GET_USER_FUNC(GetKeyNameText); GET_USER_FUNC(GetKeyboardLayoutList); - GET_USER_FUNC(LoadKeyboardLayout); GET_USER_FUNC(MapVirtualKeyEx); GET_USER_FUNC(RegisterHotKey); GET_USER_FUNC(ToUnicodeEx); - GET_USER_FUNC(UnloadKeyboardLayout); GET_USER_FUNC(UnregisterHotKey); GET_USER_FUNC(VkKeyScanEx); GET_USER_FUNC(DestroyCursorIcon); @@ -204,11 +202,6 @@ static INT CDECL nulldrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) return -1; /* use default implementation */ }
-static HKL CDECL nulldrv_LoadKeyboardLayout( LPCWSTR name, UINT flags ) -{ - return 0; -} - static UINT CDECL nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout ) { return -1; /* use default implementation */ @@ -225,11 +218,6 @@ static INT CDECL nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, L return -2; /* use default implementation */ }
-static BOOL CDECL nulldrv_UnloadKeyboardLayout( HKL layout ) -{ - return 0; -} - static void CDECL nulldrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk ) { } @@ -416,11 +404,9 @@ static USER_DRIVER null_driver = nulldrv_Beep, nulldrv_GetKeyNameText, nulldrv_GetKeyboardLayoutList, - nulldrv_LoadKeyboardLayout, nulldrv_MapVirtualKeyEx, nulldrv_RegisterHotKey, nulldrv_ToUnicodeEx, - nulldrv_UnloadKeyboardLayout, nulldrv_UnregisterHotKey, nulldrv_VkKeyScanEx, /* cursor/icon functions */ @@ -493,11 +479,6 @@ static UINT CDECL loaderdrv_GetKeyboardLayoutList( INT size, HKL *layouts ) return load_driver()->pGetKeyboardLayoutList( size, layouts ); }
-static HKL CDECL loaderdrv_LoadKeyboardLayout( LPCWSTR name, UINT flags ) -{ - return load_driver()->pLoadKeyboardLayout( name, flags ); -} - static UINT CDECL loaderdrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout ) { return load_driver()->pMapVirtualKeyEx( code, type, layout ); @@ -514,11 +495,6 @@ static INT CDECL loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, return load_driver()->pToUnicodeEx( virt, scan, state, str, size, flags, layout ); }
-static BOOL CDECL loaderdrv_UnloadKeyboardLayout( HKL layout ) -{ - return load_driver()->pUnloadKeyboardLayout( layout ); -} - static void CDECL loaderdrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk ) { load_driver()->pUnregisterHotKey( hwnd, modifiers, vk ); @@ -619,11 +595,9 @@ static USER_DRIVER lazy_load_driver = loaderdrv_Beep, loaderdrv_GetKeyNameText, loaderdrv_GetKeyboardLayoutList, - loaderdrv_LoadKeyboardLayout, loaderdrv_MapVirtualKeyEx, loaderdrv_RegisterHotKey, loaderdrv_ToUnicodeEx, - loaderdrv_UnloadKeyboardLayout, loaderdrv_UnregisterHotKey, loaderdrv_VkKeyScanEx, /* cursor/icon functions */ diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 1b2360ea083..6f4636dffdb 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1538,11 +1538,11 @@ BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) /*********************************************************************** * LoadKeyboardLayoutW (USER32.@) */ -HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags) +HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags ) { - TRACE_(keyboard)("(%s, %d)\n", debugstr_w(pwszKLID), Flags); - - return USER_Driver->pLoadKeyboardLayout(pwszKLID, Flags); + FIXME_(keyboard)( "name %s, flags %x, semi-stub!\n", debugstr_w( name ), flags ); + /* FIXME: semi-stub: returning default layout */ + return get_locale_kbd_layout(); }
/*********************************************************************** @@ -1565,11 +1565,11 @@ HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags) /*********************************************************************** * UnloadKeyboardLayout (USER32.@) */ -BOOL WINAPI UnloadKeyboardLayout(HKL hkl) +BOOL WINAPI UnloadKeyboardLayout( HKL layout ) { - TRACE_(keyboard)("(%p)\n", hkl); - - return USER_Driver->pUnloadKeyboardLayout(hkl); + FIXME_(keyboard)( "layout %p, stub!\n", layout ); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; }
typedef struct __TRACKINGLIST { diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 1bc41888891..db082462f1b 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -66,11 +66,9 @@ typedef struct tagUSER_DRIVER { void (CDECL *pBeep)(void); INT (CDECL *pGetKeyNameText)(LONG, LPWSTR, INT); UINT (CDECL *pGetKeyboardLayoutList)(INT, HKL *); - HKL (CDECL *pLoadKeyboardLayout)(LPCWSTR, UINT); UINT (CDECL *pMapVirtualKeyEx)(UINT, UINT, HKL); BOOL (CDECL *pRegisterHotKey)(HWND, UINT, UINT); INT (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL); - BOOL (CDECL *pUnloadKeyboardLayout)(HKL); void (CDECL *pUnregisterHotKey)(HWND, UINT, UINT); SHORT (CDECL *pVkKeyScanEx)(WCHAR, HKL); /* cursor/icon functions */ diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 7cf2d84ac3c..d86f418a64e 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1850,27 +1850,6 @@ static BOOL match_x11_keyboard_layout(HKL hkl) }
-/*********************************************************************** - * LoadKeyboardLayout (X11DRV.@) - */ -HKL CDECL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags) -{ - FIXME("%s, %04x: semi-stub! Returning default layout.\n", debugstr_w(name), flags); - return get_locale_kbd_layout(); -} - - -/*********************************************************************** - * UnloadKeyboardLayout (X11DRV.@) - */ -BOOL CDECL X11DRV_UnloadKeyboardLayout(HKL hkl) -{ - FIXME("%p: stub!\n", hkl); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - - /*********************************************************************** * ActivateKeyboardLayout (X11DRV.@) */ diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index eb5f7cecc6c..89b9323a6c5 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -7,10 +7,8 @@ @ cdecl ActivateKeyboardLayout(long long) X11DRV_ActivateKeyboardLayout @ cdecl Beep() X11DRV_Beep @ cdecl GetKeyNameText(long ptr long) X11DRV_GetKeyNameText -@ cdecl LoadKeyboardLayout(wstr long) X11DRV_LoadKeyboardLayout @ cdecl MapVirtualKeyEx(long long long) X11DRV_MapVirtualKeyEx @ cdecl ToUnicodeEx(long long ptr ptr long long long) X11DRV_ToUnicodeEx -@ cdecl UnloadKeyboardLayout(long) X11DRV_UnloadKeyboardLayout @ cdecl VkKeyScanEx(long long) X11DRV_VkKeyScanEx @ cdecl DestroyCursorIcon(long) X11DRV_DestroyCursorIcon @ cdecl SetCursor(long) X11DRV_SetCursor
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/input.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 6f4636dffdb..fc928af6723 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1540,7 +1540,16 @@ BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) */ HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags ) { + DWORD tmp; + HKL layout; + FIXME_(keyboard)( "name %s, flags %x, semi-stub!\n", debugstr_w( name ), flags ); + + tmp = wcstoul( name, NULL, 16 ); + layout = UlongToHandle( tmp ); + + if ((flags & KLF_ACTIVATE) && ActivateKeyboardLayout( layout, 0 )) return layout; + /* FIXME: semi-stub: returning default layout */ return get_locale_kbd_layout(); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/input.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c index fc928af6723..5d9bbe14cd6 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -1540,7 +1540,9 @@ BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) */ HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags ) { - DWORD tmp; + WCHAR layout_path[MAX_PATH], value[5]; + DWORD value_size, tmp; + HKEY hkey; HKL layout;
FIXME_(keyboard)( "name %s, flags %x, semi-stub!\n", debugstr_w( name ), flags ); @@ -1548,6 +1550,18 @@ HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags ) tmp = wcstoul( name, NULL, 16 ); layout = UlongToHandle( tmp );
+ wcscpy( layout_path, L"System\CurrentControlSet\Control\Keyboard Layouts\" ); + wcscat( layout_path, name ); + + if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, layout_path, &hkey )) + { + value_size = sizeof(value); + if (!RegGetValueW( hkey, NULL, L"Layout Id", RRF_RT_REG_SZ, NULL, (void *)&value, &value_size )) + layout = UlongToHandle( MAKELONG( LOWORD( tmp ), 0xf000 | (wcstoul( value, NULL, 16 ) & 0xfff) ) ); + + RegCloseKey( hkey ); + } + if ((flags & KLF_ACTIVATE) && ActivateKeyboardLayout( layout, 0 )) return layout;
/* FIXME: semi-stub: returning default layout */
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=90036
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
user32: input.c:757: Test failed: 0 (a4/0): 00 from 00 -> 80 unexpected input.c:757: Test failed: 0 (a4/0): 41 from 01 -> 00 unexpected
=== wvistau64 (64 bit report) ===
user32: input.c:757: Test failed: 0 (a4/0): 01 from 01 -> 00 unexpected input.c:757: Test failed: 0 (a4/0): 11 from 01 -> 00 unexpected input.c:757: Test failed: 0 (a4/0): a2 from 01 -> 00 unexpected
=== w10pro64_ar (64 bit report) ===
user32: input.c:3429: Test failed: expected WM_NCHITTEST message input.c:3430: Test failed: expected WM_RBUTTONDOWN message input.c:3431: Test failed: expected WM_RBUTTONUP message input.c:3460: Test failed: expected WM_LBUTTONDOWN message input.c:3461: Test failed: expected WM_LBUTTONUP message input.c:3514: Test failed: expected loop with WM_NCHITTEST messages input.c:3567: Test failed: expected WM_LBUTTONDOWN message input.c:3568: Test failed: expected WM_LBUTTONUP message