Aric Stewart wrote:
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 as with the proper keyboard scancodes it works out.
I'm still not clear why do you need to translate the v_key into char? This involves a round trip to the X server for each key press.
Besides this will depend on the state of the num-lock, shift, etc. Which should not be the case for dinput. It should always return the same code for the key regardless of anything else.
Vitaliy.
Well the main problem is with Japanese keyboards I was testing with. Often the scan codes, nor the vkey of the keyboards did not line up the characters in the other keyboards. Yet dinput on windows correctly set the DIK codes to represent the character being pressed. An example is the key to the right of 'P'. It is scancode 0x1a on both qwerty_us and the Japanese keyboard. However on the us keyboard it is '[' while on the Japanese keyboard it is '@' (it is vkey VKEY_OEM_3, which is '`' on the us keyboard)
I saw similar problems with scan 0x1B ('[' in Japanese and ']' on qwerty) 0x2b (']' vs '')
I did pretty extensive testing with shift on windows and with my code and do not recall any specific problems though most of those tests where with the Japanese keyboard. I can try some more. I am curious what SHIFT+'2' (qwerty) produces as that is '@'
I am not sure of a better way to try to solve this problem without having a bunch of special case situations which struck me as bad.
-aric
Vitaliy Margolen wrote:
Aric Stewart wrote:
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 as with the proper keyboard scancodes it works out.
I'm still not clear why do you need to translate the v_key into char? This involves a round trip to the X server for each key press.
Besides this will depend on the state of the num-lock, shift, etc. Which should not be the case for dinput. It should always return the same code for the key regardless of anything else.
Vitaliy.
This is all well and good but I don't see a problem. In dinput that is. Are those scan codes match to what you are getting on windows? They should since they are hardware dependent. But might not. However v_key should stay the same.
And even if Wine returns different DIKs on different keyboard layouts for some questionable keys. Why is it a problem? In all the programs and games I've seen one can remap their keys to whatever they want.
The reason I'm so against adding extra X calls - it dramatically affects latency of the input. We already have horrid latency with mouse. All because thread that talks to X is busy doing other things.
Vitaliy.
Aric Stewart wrote:
Well the main problem is with Japanese keyboards I was testing with. Often the scan codes, nor the vkey of the keyboards did not line up the characters in the other keyboards. Yet dinput on windows correctly set the DIK codes to represent the character being pressed. An example is the key to the right of 'P'. It is scancode 0x1a on both qwerty_us and the Japanese keyboard. However on the us keyboard it is '[' while on the Japanese keyboard it is '@' (it is vkey VKEY_OEM_3, which is '`' on the us keyboard)
I saw similar problems with scan 0x1B ('[' in Japanese and ']' on qwerty) 0x2b (']' vs '')
I did pretty extensive testing with shift on windows and with my code and do not recall any specific problems though most of those tests where with the Japanese keyboard. I can try some more. I am curious what SHIFT+'2' (qwerty) produces as that is '@'
I am not sure of a better way to try to solve this problem without having a bunch of special case situations which struck me as bad.
-aric
Vitaliy Margolen wrote:
Aric Stewart wrote:
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 as with the proper keyboard scancodes it works out.
I'm still not clear why do you need to translate the v_key into char? This involves a round trip to the X server for each key press.
Besides this will depend on the state of the num-lock, shift, etc. Which should not be the case for dinput. It should always return the same code for the key regardless of anything else.
Vitaliy.
Am Mittwoch, den 30.07.2008, 18:12 -0600 schrieb Vitaliy Margolen: Disclaimer: I didn't thoroughly read the thread, but if I understood the problem area correctly, the following comments apply:
And even if Wine returns different DIKs on different keyboard layouts for some questionable keys. Why is it a problem? In all the programs and games I've seen one can remap their keys to whatever they want.
It is a problem, because Wine should be compatible to Windows. Also, I wouldn't understand why the key containing minus and underscore would be called "slash" in the game.
The reason I'm so against adding extra X calls - it dramatically affects latency of the input. We already have horrid latency with mouse. All because thread that talks to X is busy doing other things.
Thats why you should not look up what DIK code to use on each key event, but once on DirectInput initialization you should create a map from vkey do DIK. SDL uses something like the DIK codes seem to be with their SDLK constants. As SDL is also LGPL one might take a look into SDL how it is implemented there.
Regards, Michael Karcher
Yes this is a specific problem I am seeing. In a Japanese online Mahjong game, there appears to be no way to remap the keys and the game is using the top 2 rows of the keyboard to control the movement of the tiles in the game.
the top row scan codes for a japanese keyboard are: 1 2 3 4 5 6 7 8 9 0 - ^ \ 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x29, second row q w e r t y u i o p @ [ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B
Notice how 0x0C (-) 0x0d(^) 0x1A(@) and 0x1B([) have scan codes that do not correspnd to the character on the qwerty keyboard. This means with the current code if the user presses the key to the right of 'P' it generates a DIK_LBRACKET which is actaully they key two to the right, so the wrong tile gets highlighted. The program is looking for DIK_AT for that key.
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.
So I am seeing a real world problematic behavior in wine that I am trying to correct. Your presumption that ALL programs let the user remap their keys seem overly broad.
I like Michael's idea of initializing this lookup array on initialization of the keyboard. Then we only have to worry about it if the user switches keyboard layouts mid program and since last i looked wine does not support that anyway we would be ok.
If i built the lookup table at that point would you have any objection to that?
-aric
Michael Karcher wrote:
Am Mittwoch, den 30.07.2008, 18:12 -0600 schrieb Vitaliy Margolen: Disclaimer: I didn't thoroughly read the thread, but if I understood the problem area correctly, the following comments apply:
And even if Wine returns different DIKs on different keyboard layouts for some questionable keys. Why is it a problem? In all the programs and games I've seen one can remap their keys to whatever they want.
It is a problem, because Wine should be compatible to Windows. Also, I wouldn't understand why the key containing minus and underscore would be called "slash" in the game.
The reason I'm so against adding extra X calls - it dramatically affects latency of the input. We already have horrid latency with mouse. All because thread that talks to X is busy doing other things.
Thats why you should not look up what DIK code to use on each key event, but once on DirectInput initialization you should create a map from vkey do DIK. SDL uses something like the DIK codes seem to be with their SDLK constants. As SDL is also LGPL one might take a look into SDL how it is implemented there.
Regards, Michael Karcher
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.
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.
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:
Please bottom post on this ML.
Aric Stewart wrote:
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.
Few problems with your patch:
- if (c && c >31 && c < 96)
Checking for c != 0 is redundant here.
- dik_code = hook->scanCode & 0xff;
- dik_code = This->ScanCodemap[hook->scanCode];
Scan code can be larger then 256 so "& 0xff" is really necessary.
- BYTE ScanCodemap[WINE_DINPUT_KEYBOARD_MAX_KEYS];
You should make this array static and initialize it only once per process
+static int map_dik_code(DWORD scanCode) +{
- int out_code = 0;
- static const int asciiCodes[] =
{/*32*/ DIK_SPACE,0,0,0,0,0,0,DIK_APOSTROPHE,0,0,0,0, DIK_COMMA, /*44*/ \
Please rearrange array to have some-what reasonable and same number of elements in each line, like 10 (or 5, 8).
newDevice->ScanCodemap[i] = map_dik_code(i);
Please stay consistent with types. If it's a BYTE then you should return BYTE from the function.
Vitaliy.
Thanks for the feedback. Resubmitted.
-aric
Vitaliy Margolen wrote:
Please bottom post on this ML.
Aric Stewart wrote:
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.
Few problems with your patch:
- if (c && c >31 && c < 96)
Checking for c != 0 is redundant here.
- dik_code = hook->scanCode & 0xff;
- dik_code = This->ScanCodemap[hook->scanCode];
Scan code can be larger then 256 so "& 0xff" is really necessary.
- BYTE ScanCodemap[WINE_DINPUT_KEYBOARD_MAX_KEYS];
You should make this array static and initialize it only once per process
+static int map_dik_code(DWORD scanCode) +{
- int out_code = 0;
- static const int asciiCodes[] =
{/*32*/ DIK_SPACE,0,0,0,0,0,0,DIK_APOSTROPHE,0,0,0,0,
DIK_COMMA, /*44*/ \
Please rearrange array to have some-what reasonable and same number of elements in each line, like 10 (or 5, 8).
newDevice->ScanCodemap[i] = map_dik_code(i);
Please stay consistent with types. If it's a BYTE then you should return BYTE from the function.
Vitaliy.
Aric Stewart aric@codeweavers.com writes:
I like Michael's idea of initializing this lookup array on initialization of the keyboard. Then we only have to worry about it if the user switches keyboard layouts mid program and since last i looked wine does not support that anyway we would be ok.
Wine does support dynamic keyboard changes, so you'd need to refresh the mapping at that point. I doubt it's worth the trouble.
Am Donnerstag, den 31.07.2008, 08:53 +0200 schrieb Michael Karcher:
SDL uses something like the DIK codes seem to be with their SDLK constants.
Argl! That sentence sense no make does. I meant to say: "SDL's SDLK_* constants seem to be conceptually what Window's DIK_* are."
Regards, Michael Karcher
Doing tests with shift show that the presence of the shift key does not affect MapVirtualKey so SHIFT+2 still returns '2' since it is scancode based i doubt that numlock would either. So I do not think we need to worry about that.
-aric
Vitaliy Margolen wrote:
Aric Stewart wrote:
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 as with the proper keyboard scancodes it works out.
I'm still not clear why do you need to translate the v_key into char? This involves a round trip to the X server for each key press.
Besides this will depend on the state of the num-lock, shift, etc. Which should not be the case for dinput. It should always return the same code for the key regardless of anything else.
Vitaliy.