I'm not sure if this is the best way to solve this issue, should we somehow move this behavior to user32?
Thanks to @AntiUltimate on the VKx discord for finding out that this was the cause of the linked wine bug.
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=45148
Derek Lesho (4): winex11: Set the scan code prefix when necessary. winemac: Set the scan code prefix when necessary. wineandroid: Set the scan code prefix when necessary. users/tests: Test scan code prefix for MAPVK_VK_TO_VSC.
dlls/user32/tests/input.c | 10 ++++++++++ dlls/wineandroid.drv/keyboard.c | 9 ++++++++- dlls/winemac.drv/keyboard.c | 9 ++++++++- dlls/winex11.drv/keyboard.c | 9 ++++++++- 4 files changed, 34 insertions(+), 3 deletions(-)
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/winex11.drv/keyboard.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 131c5f5442..3b7a6fa252 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -2077,7 +2077,7 @@ SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl) */ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) { - UINT ret = 0; + UINT ret = 0, prefix = 0; int keyc; Display *display = thread_init_display();
@@ -2107,6 +2107,13 @@ UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) break; } } + + /* set scan code prefix */ + if (wCode == VK_RCONTROL || wCode == VK_RMENU) + prefix = 0xE0; + + if (wMapType == MAPVK_VK_TO_VSC_EX) + ret |= ((prefix << 8) & 0xFF00); break;
case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/winemac.drv/keyboard.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index aed4ff0d6e..b1f8d1cba5 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -1367,7 +1367,7 @@ BOOL CDECL macdrv_GetKeyboardLayoutName(LPWSTR name) UINT CDECL macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) { struct macdrv_thread_data *thread_data = macdrv_init_thread_data(); - UINT ret = 0; + UINT ret = 0, prefix = 0; int keyc;
TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl); @@ -1392,6 +1392,13 @@ UINT CDECL macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) break; } } + + /* set scan code prefix */ + if (wCode == VK_RCONTROL || wCode == VK_RMENU) + prefix = 0xE0; + + if (wMapType == MAPVK_VK_TO_VSC_EX) + ret |= ((prefix << 8) & 0xFF00); break;
case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/wineandroid.drv/keyboard.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c index 2c37c42e0d..a07e4c6ac2 100644 --- a/dlls/wineandroid.drv/keyboard.c +++ b/dlls/wineandroid.drv/keyboard.c @@ -909,7 +909,7 @@ INT CDECL ANDROID_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) */ UINT CDECL ANDROID_MapVirtualKeyEx( UINT code, UINT maptype, HKL hkl ) { - UINT ret = 0; + UINT ret = 0, prefix = 0; const char *s;
TRACE_(key)( "code=0x%x, maptype=%d, hkl %p\n", code, maptype, hkl ); @@ -932,6 +932,13 @@ UINT CDECL ANDROID_MapVirtualKeyEx( UINT code, UINT maptype, HKL hkl ) break; } if (code < ARRAY_SIZE( vkey_to_scancode )) ret = vkey_to_scancode[code]; + + /* set scan code prefix */ + if (code == VK_RCONTROL || code == VK_RMENU) + prefix = 0xE0; + + if (maptype == MAPVK_VK_TO_VSC_EX) + ret |= ((prefix << 8) & 0xFF00); break; case MAPVK_VSC_TO_VK: case MAPVK_VSC_TO_VK_EX:
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/user32/tests/input.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index d0e7603811..4349e792db 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1873,6 +1873,16 @@ static void test_key_map(void) vkey, numpad_scan); } } + + /* test the scan code prefixes of the right variant of a keys */ + s = MapVirtualKeyExA(VK_RCONTROL, MAPVK_VK_TO_VSC, kl); + ok(s >> 8 == 0x00, "Scan code prefixes should not be returned when not using MAPVK_VK_TO_VSC_EX %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RCONTROL, MAPVK_VK_TO_VSC_EX, kl); + ok(s >> 8 == 0xE0, "Scan code prefix for VK_RCONTROL should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RMENU, MAPVK_VK_TO_VSC_EX, kl); + ok(s >> 8 == 0xE0, "Scan code prefix for VK_RMENU should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RSHIFT, MAPVK_VK_TO_VSC_EX, kl); + ok (s >> 8 == 0x00, "The scan code shouldn't have a prefix, got %#1x\n", s >> 8); }
#define shift 1
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=59834
Your paranoid android.
=== wxppro (32 bit report) ===
user32: input.c:1881: Test failed: Scan code prefix for VK_RCONTROL should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was 0 input.c:1883: Test failed: Scan code prefix for VK_RMENU should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was 0
=== w2003std (32 bit report) ===
user32: input.c:1881: Test failed: Scan code prefix for VK_RCONTROL should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was 0 input.c:1883: Test failed: Scan code prefix for VK_RMENU should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was 0
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- v2: Add broken detection for windows < Vista and rename the patch. Note: The testbot won't allow me to submit user32 test on XP and below so I'm not 100% sure this will pass. --- dlls/user32/tests/input.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index d0e7603811..ddaf7541e4 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1873,6 +1873,16 @@ static void test_key_map(void) vkey, numpad_scan); } } + + /* test the scan code prefixes of the right variant of a keys */ + s = MapVirtualKeyExA(VK_RCONTROL, MAPVK_VK_TO_VSC, kl); + ok(s >> 8 == 0x00, "Scan code prefixes should not be returned when not using MAPVK_VK_TO_VSC_EX %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RCONTROL, MAPVK_VK_TO_VSC_EX, kl); + ok(s >> 8 == 0xE0 || broken(s == 0), "Scan code prefix for VK_RCONTROL should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RMENU, MAPVK_VK_TO_VSC_EX, kl); + ok(s >> 8 == 0xE0 || broken(s == 0), "Scan code prefix for VK_RMENU should be 0xE0 when MAPVK_VK_TO_VSC_EX is set, was %#1x\n", s >> 8); + s = MapVirtualKeyExA(VK_RSHIFT, MAPVK_VK_TO_VSC_EX, kl); + ok(s >> 8 == 0x00 || broken(s == 0), "The scan code shouldn't have a prefix, got %#1x\n", s >> 8); }
#define shift 1