Here is a revised patch which builds the scancode->DIK table on initialization making no xserver round trips required on lookup.
How does this look?
-aric
Aric Stewart wrote:
Yes, I have verified those vkeys in windows. the VK_OEM_* keys are specificaly VK codes that vary from keyboard to keyboard. VK_OEM_3 is just one example.
-aric
Vitaliy Margolen wrote:
Aric Stewart wrote:
vkey codes similarly do not produce a clean 1 to 1 correspondance. the '@' key (0x1a) is vkey (VK_OEM_3) which is the vkey of the '`' key on the us keyboard.
This is needs to be fixed in x11drv then. Not in dinput. Have you verified what v_keys you getting from windows for these keys?
Vitaliy.
commit f32b8b281a5df115881f2c5c6dd2f273d5b2b657 Author: Aric Stewart aric@codeweavers.com Date: Fri Jul 25 16:07:30 2008 +0900
dinput: the DIK_ keycode is not the same as the scancode.
It is mapped with the keyboard mapping to the resulting character. so the key 'A' is DIK_A nomatter what its scancode or vkey would be. This is relevent to Japanese keymapping where the '@' key is in the '[' location the scancode for both is 0x22 but dinput generates DIK_AT in japanese and DIK_LBRACKET in us_qwerty
reworked to remove the giant case statement and hopefully be more clear. remove japan specific stuff
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index b2c4942..f4918b0 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -48,8 +48,32 @@ struct SysKeyboardImpl { struct IDirectInputDevice2AImpl base; BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; + BYTE ScanCodemap[WINE_DINPUT_KEYBOARD_MAX_KEYS]; };
+static int map_dik_code(DWORD scanCode) +{ + static const int asciiCodes[] = + {/*32*/ DIK_SPACE,0,0,0,0,0,0,DIK_APOSTROPHE,0,0,0,0, DIK_COMMA, /*44*/ \ + /*45*/ DIK_MINUS, DIK_PERIOD, DIK_SLASH,DIK_0,DIK_1,DIK_2,DIK_3, /*51*/ \ + /*52*/ DIK_4,DIK_5,DIK_6,DIK_7,DIK_8,DIK_9,DIK_COLON,DIK_SEMICOLON,0, /*60*/ \ + /*61*/ DIK_EQUALS, 0,0,DIK_AT,DIK_A,DIK_B,DIK_C,DIK_D,DIK_E,DIK_F, /*70*/ \ + /*71*/ DIK_G,DIK_H,DIK_I,DIK_J,DIK_K,DIK_L,DIK_M,DIK_N,DIK_O,DIK_P, /*80*/ \ + /*81*/ DIK_Q,DIK_R,DIK_S,DIK_T,DIK_U,DIK_V,DIK_W,DIK_X,DIK_Y,DIK_Z, /*90*/ \ + /*91*/ DIK_LBRACKET,0,DIK_RBRACKET,DIK_CIRCUMFLEX,DIK_UNDERLINE} /*95*/ ; + int out_code = 0; + DWORD vkCode = MapVirtualKeyA(scanCode,MAPVK_VSC_TO_VK); + CHAR c = MapVirtualKeyA(vkCode,MAPVK_VK_TO_CHAR); + + if (c && c >31 && c < 96) + out_code = asciiCodes[c - 32]; + + if (out_code == 0) + out_code = scanCode; + + return out_code; +} + static void KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ) { SysKeyboardImpl *This = (SysKeyboardImpl *)iface; @@ -63,7 +87,7 @@ static void KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
TRACE("(%p) %ld,%ld\n", iface, wparam, lparam);
- dik_code = hook->scanCode & 0xff; + dik_code = This->ScanCodemap[hook->scanCode]; /* R-Shift is special - it is an extended key with separate scan code */ if (hook->flags & LLKHF_EXTENDED && dik_code != 0x36) dik_code |= 0x80; @@ -205,6 +229,10 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInpu
newDevice->base.data_format.wine_df = df; IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput); + /* Initialize scancode lookup */ + for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) + newDevice->ScanCodemap[i] = map_dik_code(i); + return newDevice;
failed: