Open porres opened 1 year ago
this is what i get just compiling keycode.c
on Pd 0.53.1
print: 1 17 1
print: 1 17 0
print: 2 16 1
print: 2 16 0
print: 3 54 1
print: 3 54 0
print: 4 55 1
print: 4 55 0
print: 5 56 1
print: 5 56 0
print: 6 229 1
print: 6 229 0
print: 7 0 1
print: 7 0 0
print: 8 226 1
print: 8 226 0
print: 9 0 1
print: 9 0 0
print: 0 5 1
print: 0 5 0
print: q 0 1
print: q 0 0
print: w 68 1
print: w 68 0
print: e 72 1
print: e 72 0
print: r 0 1
print: r 0 0
print: t 0 1
print: t 0 0
print: y 0 1
print: y 0 0
print: u 0 1
print: u 0 0
print: i 0 1
print: i 0 0
print: o 0 1
print: o 0 0
print: p 0 1
print: p 0 0
print: a 64 1
print: a 64 0
print: s 0 1
print: s 0 0
print: d 67 1
print: d 67 0
print: f 71 1
print: f 71 0
print: g 0 1
print: g 0 0
print: h 0 1
print: h 0 0
print: j 0 1
print: j 0 0
print: k 0 1
print: k 0 0
print: l 0 1
print: l 0 0
print: ; 0 1
print: ; 0 0
print: z 0 1
print: z 0 0
print: x 69 1
print: x 69 0
print: c 66 1
print: c 66 0
print: v 0 1
print: v 0 0
print: b 65 1
print: b 65 0
print: n 0 1
print: n 0 0
print: m 0 1
print: m 0 0
print: , 0 1
print: , 0 0
print: . 0 1
print: . 0 0
print: / 0 1
print: / 0 0
Values are quite different. The order of letters show your keyboard layout, which seems to be the same as mine.
For numbers between 1 and 0 on my top row I have keycode values from 30-39
@sebshader to the rescue
Maybe this issue https://github.com/depp/keycode/issues/5. @Lucarda we might need to use the python script in that repo to update the table (or keep both and try to support older windows too)
I'm totally confused and partly because of that I'm also angry.
How this is supposed to work?: and if it works why don't we just map the MIDI note in
const unsigned char KEYCODE_TO_HID[256] = {
...
}
I'm doing other stuff (and not having much time) and don't have python installed.
I'm on Win11.
if I have to regenerate the tables as in https://github.com/depp/keycode/tree/master/scripts then it wont work on a Win7 machine?
@Lucarda sorry, I was just saying that because I'm at work but I think I may be able to do it if I get a winuser.h file
@Lucarda basically tcl/tk sends %k values from key events and those have to be mapped to common values for all platforms
Ok. I see that the objects it a general purpose keycode
and not a pckeyboard to MIDI
as @porres is using it. :)
here is my mingw64 winuser.h
@sebshader you might already know this:
$ python extract.py --platform=windows --input=./winuser.h
Writing C:/Users/lucarda/Downloads/attach/porres/keycode-master/data/windows_scancodes.csv
$ cat C:/Users/lucarda/Downloads/attach/porres/keycode-master/data/windows_scancodes.csv
Keycode,Name
1,LBUTTON
2,RBUTTON
3,CANCEL
4,MBUTTON
5,XBUTTON1
6,XBUTTON2
8,BACK
9,TAB
12,CLEAR
13,RETURN
16,SHIFT
17,CONTROL
18,MENU
19,PAUSE
20,CAPITAL
21,KANA
21,HANGEUL
21,HANGUL
22,IME_ON
23,JUNJA
24,FINAL
25,HANJA
25,KANJI
26,IME_OFF
27,ESCAPE
28,CONVERT
29,NONCONVERT
30,ACCEPT
31,MODECHANGE
32,SPACE
33,PRIOR
34,NEXT
35,END
36,HOME
37,LEFT
38,UP
39,RIGHT
40,DOWN
41,SELECT
42,PRINT
43,EXECUTE
44,SNAPSHOT
45,INSERT
46,DELETE
47,HELP
91,LWIN
92,RWIN
93,APPS
95,SLEEP
96,NUMPAD0
97,NUMPAD1
98,NUMPAD2
99,NUMPAD3
100,NUMPAD4
101,NUMPAD5
102,NUMPAD6
103,NUMPAD7
104,NUMPAD8
105,NUMPAD9
106,MULTIPLY
107,ADD
108,SEPARATOR
109,SUBTRACT
110,DECIMAL
111,DIVIDE
112,F1
113,F2
114,F3
115,F4
116,F5
117,F6
118,F7
119,F8
120,F9
121,F10
122,F11
123,F12
124,F13
125,F14
126,F15
127,F16
128,F17
129,F18
130,F19
131,F20
132,F21
133,F22
134,F23
135,F24
136,NAVIGATION_VIEW
137,NAVIGATION_MENU
138,NAVIGATION_UP
139,NAVIGATION_DOWN
140,NAVIGATION_LEFT
141,NAVIGATION_RIGHT
142,NAVIGATION_ACCEPT
143,NAVIGATION_CANCEL
144,NUMLOCK
145,SCROLL
146,OEM_NEC_EQUAL
146,OEM_FJ_JISHO
147,OEM_FJ_MASSHOU
148,OEM_FJ_TOUROKU
149,OEM_FJ_LOYA
150,OEM_FJ_ROYA
160,LSHIFT
161,RSHIFT
162,LCONTROL
163,RCONTROL
164,LMENU
165,RMENU
166,BROWSER_BACK
167,BROWSER_FORWARD
168,BROWSER_REFRESH
169,BROWSER_STOP
170,BROWSER_SEARCH
171,BROWSER_FAVORITES
172,BROWSER_HOME
173,VOLUME_MUTE
174,VOLUME_DOWN
175,VOLUME_UP
176,MEDIA_NEXT_TRACK
177,MEDIA_PREV_TRACK
178,MEDIA_STOP
179,MEDIA_PLAY_PAUSE
180,LAUNCH_MAIL
181,LAUNCH_MEDIA_SELECT
182,LAUNCH_APP1
183,LAUNCH_APP2
186,OEM_1
187,OEM_PLUS
188,OEM_COMMA
189,OEM_MINUS
190,OEM_PERIOD
191,OEM_2
192,OEM_3
195,GAMEPAD_A
196,GAMEPAD_B
197,GAMEPAD_X
198,GAMEPAD_Y
199,GAMEPAD_RIGHT_SHOULDER
200,GAMEPAD_LEFT_SHOULDER
201,GAMEPAD_LEFT_TRIGGER
202,GAMEPAD_RIGHT_TRIGGER
203,GAMEPAD_DPAD_UP
204,GAMEPAD_DPAD_DOWN
205,GAMEPAD_DPAD_LEFT
206,GAMEPAD_DPAD_RIGHT
207,GAMEPAD_MENU
208,GAMEPAD_VIEW
209,GAMEPAD_LEFT_THUMBSTICK_BUTTON
210,GAMEPAD_RIGHT_THUMBSTICK_BUTTON
211,GAMEPAD_LEFT_THUMBSTICK_UP
212,GAMEPAD_LEFT_THUMBSTICK_DOWN
213,GAMEPAD_LEFT_THUMBSTICK_RIGHT
214,GAMEPAD_LEFT_THUMBSTICK_LEFT
215,GAMEPAD_RIGHT_THUMBSTICK_UP
216,GAMEPAD_RIGHT_THUMBSTICK_DOWN
217,GAMEPAD_RIGHT_THUMBSTICK_RIGHT
218,GAMEPAD_RIGHT_THUMBSTICK_LEFT
219,OEM_4
220,OEM_5
221,OEM_6
222,OEM_7
223,OEM_8
225,OEM_AX
226,OEM_102
227,ICO_HELP
228,ICO_00
229,PROCESSKEY
230,ICO_CLEAR
231,PACKET
233,OEM_RESET
234,OEM_JUMP
235,OEM_PA1
236,OEM_PA2
237,OEM_PA3
238,OEM_WSCTRL
239,OEM_CUSEL
240,OEM_ATTN
241,OEM_FINISH
242,OEM_COPY
243,OEM_AUTO
244,OEM_ENLW
245,OEM_BACKTAB
246,ATTN
247,CRSEL
248,EXSEL
249,EREOF
250,PLAY
251,ZOOM
252,NONAME
253,PA1
254,OEM_CLEAR
an update: so it looks like the table should definitely be using these virtual key codes from winuser.h: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes and also it seems like it isn't. so we may have to investigate when these codes changed. also, where is the info for the letters and numbers stored? hopefully that repo above has some answers.
well after all of that it seems like the windows implementation for tcl/tk is wrong (in terms of getting physical location).. they send the 'virtual key' which is in the "WPARAM" of the event and is apparently dependent on layout, when the scancode is actually stored in the "LPARAM" so we might be out of luck w/ this object unfortunately (barring tcl/tk not changing their implementation) https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names
I think in order to see if these virtual codes are actually layout-independent we'd have to test
bind all <KeyPress> {+ puts "keycodepress: %k"}
bind all <KeyRelease> {+ puts "keycoderelease: %k"}
in wish using different layouts on windows
tbh at this point it might be easier to detect keyboard layout at runtime and use platform-specific mappings to qwerty, if possible
tbh at this point it might be easier to detect keyboard layout at runtime and use platform-specific mappings to qwerty, if possible
sounds quite hard! And I wonder how a software like VCV does this then...
I wonder how a software like VCV does this
https://github.com/VCVRack/Rack/blob/05fa24a72bccf4023f5fb1b0fa7f1c26855c0926/src/keyboard.cpp#L31
weird, the code says 'qwerty' and so the 'drive', but I changed the setting to 'azerty' and it still worked so I don't get how they do it in VCV
maybe the juice is in here?
https://github.com/VCVRack/Rack/blob/05fa24a72bccf4023f5fb1b0fa7f1c26855c0926/src/keyboard.cpp#L126
const auto& keyMap = deviceInfos[deviceId].keyMap;
auto it = keyMap.find(key);
if (it == keyMap.end())
they send the 'virtual key' which is in the "WPARAM" of the event and is apparently dependent on layout, when the scancode is actually stored in the "LPARAM" so we might be out of luck w/ this object unfortunately (barring tcl/tk not changing their implementation)
when I have time I'll try
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapvirtualkeya
I did:
#include "m_pd.h"
#ifdef _WIN32
#include <Windows.h>
#endif
static void object_list_iterate(t_objectlist *x, t_symbol *s, int argc, t_atom *argv) {
t_listelem *e;
#ifdef _WIN32
int v;
v = MapVirtualKey(argv[1].a_w.w_float, MAPVK_VK_TO_VSC);
argv[1].a_w.w_float = keycode_to_hid(v);
#else
argv[1].a_w.w_float = keycode_to_hid(argv[1].a_w.w_float);
#endif
for (e = x->b_list; e; e = e->e_next)
pd_list(e->e_who, s, argc, argv);
}
and now I'm getting nicer output (had to check if this is what we want)
print: 1 30 1
print: 1 30 0
print: 2 31 1
print: 2 31 0
print: 3 32 1
print: 3 32 0
print: 4 33 1
print: 4 33 0
print: 5 34 1
print: 5 34 0
print: 6 35 1
print: 6 35 0
print: 7 36 1
print: 7 36 0
print: 8 37 1
print: 8 37 0
print: 9 38 1
print: 9 38 0
print: 0 39 1
print: 0 39 0
print: q 20 1
print: q 20 0
print: w 26 1
print: w 26 0
print: e 8 1
print: e 8 0
print: r 21 1
print: r 21 0
print: t 23 1
print: t 23 0
print: y 28 1
print: y 28 0
print: u 24 1
print: u 24 0
print: i 12 1
print: i 12 0
print: o 18 1
print: o 18 0
print: p 19 1
print: p 19 0
print: a 4 1
print: a 4 0
print: s 22 1
print: s 22 0
print: d 7 1
print: d 7 0
print: f 9 1
print: f 9 0
print: g 10 1
print: g 10 0
print: h 11 1
print: h 11 0
print: j 13 1
print: j 13 0
print: k 14 1
print: k 14 0
print: l 15 1
print: l 15 0
print: ; 51 1
print: ; 51 0
print: z 29 1
print: z 29 0
print: x 27 1
print: x 27 0
print: c 6 1
print: c 6 0
print: v 25 1
print: v 25 0
print: b 5 1
print: b 5 0
print: n 17 1
print: n 17 0
print: m 16 1
print: m 16 0
print: , 54 1
print: , 54 0
print: . 55 1
print: . 55 0
@Lucarda do the outputs change for certain keys if you change the keyboard layout?
I think the right solution is to use a different table for windows if we can figure it out, not use the MapVirtualKey
.
In the keycode repository they switched from virtual keycodes (which tcl sends) to scancodes and in the commit message it said that the virtual keycodes aren't layout-independent.
@Lucarda Edit: actually maybe this is ok as long as the virtual keycode -> scan code mapping changes w/ layout as well..
this is the "]" us key
us
print: ] 48 1
print: ] 48 0
es (spanish)
print: + 46 1
print: + 46 0
this is the ";" us key
us
print: ; 51 1
print: ; 51 0
es (spanish)
print: ñ 53 1
print: ñ 53 0
that's bad :( I tried it here and obviously got the same code (48 / 51) in both US and 'spanish ISO'
may be you are using a notebook keyboard?
i'm using this one but the spanish version
@Lucarda I believe he's on Mac (right @porres? you weren't testing windows, right?)
@sebshader yes I took for granted that he is on Mac.
Edit: actually maybe this is ok as long as the virtual keycode -> scan code mapping changes w/ layout as well..
so we are happy with it? is still unclear to me.
@Lucarda no, not yet. All keys should be (basically) the same across locales and platforms. I'm hoping we can find a similar function in the windows API that does what we need, I'm looking into it right now. (I see there's one that accepts a locale/layout handle or something, maybe there's one for current locale/layout) Also we may have to compromise a bit on left and right 'shift' keys and windows keys and such because it seems like the virtual keycode doesn't distinguish between them
@Lucarda I believe he's on Mac (right @porres? you weren't testing windows, right?)
yes, macbook air, just changed the keyboard setting
good lord this api is a mess (typical windows). it seems like we can get the current locale somehow at least (maybe GetKeyboardLayout
), and use it w/ MapVirtualKeyEx
family somehow
virtual-keys have the notion of left/right control/shift
VK_LSHIFT | 0xA0 | Left SHIFT key |
VK_RSHIFT | 0xA1 | Right SHIFT key |
VK_LCONTROL | 0xA2 | Left CONTROL key |
VK_RCONTROL | 0xA3 | Right CONTROL key |
it seems that keycode have them map to be the same:
print: Shift_L 225 1
print: Shift_L 225 0
print: Shift_R 225 1
print: Shift_R 225 0
@Lucarda could you please test with MapVirtualKeyEx(argv[1].a_w.w_float, MAPVK_VK_TO_VSC, GetKeyboardLayout(0));
instead when you get a free minute?
we may have to live with not being able to deal with layout changing after keycode is loaded, but that probably isn't too big of an issue
that probably isn't too big of an issue
no :)
also imo we should put that in the Windows keycode_to_hid
function since they're already system-dependent but we can sort that out later
could you please test with
MapVirtualKeyEx(argv[1].a_w.w_float, MAPVK_VK_TO_VSC, GetKeyboardLayout(0));
instead when you get a free minute?
same as in: https://github.com/porres/pd-else/issues/1461#issuecomment-1414227477
i'll be AFK for 2 hours.
hmmmmm. maybe we have to use the qwerty layout code??
i think we can force a layout for translation instead of getting it with GetKeyboardLayout(0)
.
continue in 2hs ...
ok when you get back we could also try MapVirtualKeyEx(argv[1].a_w.w_float, MAPVK_VK_TO_VSC, 0);
(going off https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names)
ok when you get back we could also try
MapVirtualKeyEx(argv[1].a_w.w_float, MAPVK_VK_TO_VSC, 0)
;
same as in: https://github.com/porres/pd-else/issues/1461#issuecomment-1414227477
:(
.. I'm sure there must be a way but I have no idea what it might be then
maybe they're 'extended keys'?
thanks guys for the effort, really lucky to have you collaborating here
well I've been looking at some example code and
HKL layout = GetKeyboardLayout(0);
MapVirtualKeyEx((UINT)argv[1].a_w.w_float, MAPVK_VK_TO_VSC, layout);
should work.. maybe there's some kind of cache that needs to be disabled..
@Lucarda if you try the above what is the value if you print 'layout'?
HKL layout = GetKeyboardLayout(0);
post("layout %d", layout);
v =MapVirtualKeyEx((UINT)argv[1].a_w.w_float, MAPVK_VK_TO_VSC, layout);
argv[1].a_w.w_float = keycode_to_hid(v);
gives me pressing the same key first english then spanish:
layout 67699721
print: ; 51 1
layout 67699721
print: ; 51 0
layout 67699721
print: ñ 53 1
layout 67699721
print: ñ 53 0
this is my Windows lang options (the UK stuff came by default in the win installer):
@Lucarda are you closing pd in between switching layouts? because it doesn't look like the layout is changing, and we are unable to receive the 'change layout' messages (I think?) You have to test one, then close pd, then test the other
if i start pd in spanish i get another layout (i'm not sure if this is an %d
or a %s
)
layout 67766281
print: ñ 51 1
layout 67766281
print: ñ 51 0
EDIT: it's a %d
But now you get 51
ok so it looks like it's working then (if those are the same physical key)
Looks that is working.
I get 51 for the same fisical key. But It messes up if you change the keyboard while Pd is open.
Good catch @porres !!!
Hi, tagging @Lucarda and @sebshader here. I asked Lucas to test keycode --> https://github.com/porres/pd-else/blob/master/Classes/Source/keycode.c newly added here.
In order to compile ELSE now you need the latest and unreleased Pd source code (cause I have a new [nchs~] object that uses the multichannel stuff. I compiled the unreleased version and, funny enough, [keycode] doesn't work if I run it in my compiled app on macOS. It works on Pd 0.53-1 nonetheless.
You can compile ELSE with Pd 0.53-1 if you don't compile [nchs~]. One can also just compile keycode itself, of course.
Lucas, please tell us what went wrong, please post screenshots and stuff.
On my ABC qwerty english keyboard I get code values of '4' for 'a', '5' for 'b', '6' for 'c' and so on...