iohook
iohook copied to clipboard
Native keymap — returning unicode representation of the key pressed.
Hello everyone! There is this awesome native-keymap package made by Microsoft, that returns characters in the current keyboard layout. It works absolutely amazingly, but I am having hard time using it with this package. From what I understand, we would have to make lookup tables for each OS that map to the constant-y name in the map.
Expected Behavior
Pressing a key gives a unicode value of that key.
Current Behavior
Pressing a key does not provide the unicode representation of the key. Moreover, it does not recognize shift/ctrl/alt click.
Possible Solution
Use the native-keymap package to give awesome feedback.
Well, we need someone to test it out with the latest version :) Who's in ?
From what I have established, these are the keycode
's returned for iohook with their contant-y representation (I don't have some of the keys on my keyboard):
MacOS:
module.exports = {
'30': 'KeyA',
'48': 'KeyB',
'46': 'KeyC',
'32': 'KeyD',
'18': 'KeyE',
'33': 'KeyF',
'34': 'KeyG',
'35': 'KeyH',
'23': 'KeyI',
'36': 'KeyJ',
'37': 'KeyK',
'38': 'KeyL',
'50': 'KeyM',
'49': 'KeyN',
'24': 'KeyO',
'25': 'KeyP',
'16': 'KeyQ',
'19': 'KeyR',
'31': 'KeyS',
'20': 'KeyT',
'22': 'KeyU',
'47': 'KeyV',
'17': 'KeyW',
'45': 'KeyX',
'21': 'KeyY',
'44': 'KeyZ',
'2': 'Digit1',
'3': 'Digit2',
'4': 'Digit3',
'5': 'Digit4',
'6': 'Digit5',
'7': 'Digit6',
'8': 'Digit7',
'9': 'Digit8',
'10': 'Digit9',
'11': 'Digit0',
'28': 'Enter',
'1': 'Escape',
'14': 'Backspace',
'15': 'Tab',
'57': 'Space',
'12': 'Minus',
'13': 'Equal',
'26': 'BracketLeft',
'27': 'BracketRight',
'0': 'IntlBackslash',
'39': 'Semicolon',
'40': 'Quote',
'51': 'Comma',
'52': 'Period',
'53': 'Slash',
'58': 'CapsLock',
'43': 'Backslash',
'41': 'Backquote',
'29': 'ControlLeft',
'42': 'ShiftLeft',
'56': 'AltLeft',
'3675': 'MetaLeft',
'': 'ControlRight',
'54': 'ShiftRight',
'3640': 'AltRight',
'3676': 'MetaRight',
}
Do you know, does Windows/Linux share these, or do they return different keycodes for each character?
@DCzajkowski I can confirm that Windows does not share these codes. Thank you for sharing these though, I was able to construct a map for an app I'm working on 😄
@jadengore Can you share yours?
@jadengore Do you still have this keymap?
I have MacOS and Linux handy, and may be able to confirm if I grab a Windows VM.
I'm looking for a way to listen for key events using the very popular ccampbell/mousetrap library, and then once the user has picked a combination, using iohook to listen for when that shortcut is pressed.
Mousetrap can return both the key codes pressed ([17, 16, 65]), as well as an ascii representation (e.g. 'ctrl+shift v' and 'ctrl+a s'), but we need a way to translate these to the codes iohook expects. The solution that would probably make most people happy would be able to accept the ascii representation when defining shortcuts.
So, I think the plan would be:
-
Allow
registerKeybinding()
to accept a string as well as a keycode array. -
We parse the string into separate modifiers and characters (
'ctrl+k v'
=>['ctrl', 'k', 'v']
), and then depending on the OS we run those characters through a specific keymap. -
Once we get the right codes, we register them like usual.
I'll try to work on getting keymaps for Linux, and grabbing a Windows VM if nobody with Windows pipes up in the next few hours.
I also have no idea how this will work with keyboards other than US qwerty. Testing on this front with the provided keymaps would be highly appreciated.
Edit: Wait, I actually am seeing a relationship between the rawcode
iohook returns in its event, and the charCode
value mousetrap returns on keypress
events. They are the same.
@anoadragon453 @DCzajkowski Sorry for the delay, you can find the keycodes here: https://github.com/birkholz/soundboard/blob/master/src/keycodes.ts#L5-L69
Thanks @jadengore!
The list below is what we use in win/mac application
const keyNames = {
0: '§',
1: 'Esc',
2: '1',
3: '2',
4: '3',
5: '4',
6: '5',
7: '6',
8: '7',
9: '8',
10: '9',
11: '0',
12: '-',
13: '=',
14: 'Backspace',
15: 'Tab',
16: 'q',
17: 'w',
18: 'e',
19: 'r',
20: 't',
21: 'y',
22: 'u',
23: 'i',
24: 'o',
25: 'p',
26: '[',
27: ']',
28: 'Enter',
29: 'Left Ctrl',
30: 'a',
31: 's',
32: 'd',
33: 'f',
34: 'g',
35: 'h',
36: 'j',
37: 'k',
38: 'l',
39: ';',
40: '\'',
41: '`',
42: 'Left Shift',
43: '\\',
44: 'z',
45: 'x',
46: 'c',
47: 'v',
48: 'b',
49: 'n',
50: 'm',
51: ',',
52: '.',
53: '/',
54: 'Right Shift',
56: 'Left Alt', // macos 'Left ⌥'
57: 'Space',
58: 'CapsLock',
59: 'F1',
60: 'F2',
61: 'F3',
62: 'F4',
63: 'F5',
64: 'F6',
65: 'F7',
66: 'F8',
67: 'F9',
68: 'F10',
87: 'F11',
88: 'F12',
61010: 'Insert',
61011: 'Delete',
60999: 'Home',
61007: 'End',
61001: 'Page Up',
61009: 'Page Down',
3639: 'Print Screen',
3653: 'Pause Break',
3637: 'Num /',
55: 'Num *',
3612: 'Num Enter',
3655: 'Num Home',
3657: 'Num Page Up',
3663: 'Num End',
3665: 'Num Page Down',
57420: 'Num Center 5',
3677: 'Context Menu',
61008: 'Arrow Down',
61005: 'Arrow Right',
61003: 'Arrow Left',
61000: 'Arrow Up',
57380: 'Media Stop',
57360: 'Media Previous',
57378: 'Media Play',
57369: 'Media Next',
57390: 'Volume Down',
57392: 'Volume Up',
57376: 'Volume Mute',
3613: 'Right Ctrl',
3640: 'Right Alt', // macos 'Right ⌥'
3675: 'Left Win', // macos 'Left ⌘'
3676: 'Right Win', // macos 'Right ⌘'
57419: '←',
57416: '↑',
57424: '↓',
57421: '→',
}
Hello fellow coders - Is there any way to know the state of the CapsLock button using iohook, currently it returns the following in either case (on/off) -
keyup { shiftKey: false, altKey: false, ctrlKey: false, metaKey: false, keycode: 58, rawcode: 57, type: 'keyup' }
@gauravbharat I don't think so. iohook detects keyboard events, not the state of the OS. I think you need a different package/your own implementation. I may be wrong though.
I made a JSON file for the Darwin keys: https://github.com/yikuansun/desktopspeedruntools/blob/main/window/keycodenames/darwin.json
As you may be able to tell based on the awkward formatting, I used a little automation to help. Basically, I made an HTML keydown event listener and used event.key
to return key strings. event.code
also works but I preferred event.key
. For the IOhook event listener and the HTML event listener, I had them write their outputs to separate arrays, creating two outputted arrays: one filled with keycodes and one filled with strings, the array indecies matching. I ran the program and pressed every key, skipping some such as CapsLock, F11, and F12, simply because they could not be read by either IOhook or HTML. Afterwards, I merged the arrays into one object and stringified it. The code is composed of the commented-out areas of https://github.com/yikuansun/desktopspeedruntools/blob/main/window/app.js .
If someone could repeat this process for Windows or Linux and share their results, that'd be appreciated!
@gauravbharat I'm also trying to detect the state of Caps Lock. What I noticed is that the matter is more complicated than I originally thought. I connected 2 keyboards at once. It turned out one can have caps enabled and one can have it disabled at the same time. It seems the caps state is internal to the keyboard, not to the system.
Therefore it seems there is no 'global' way to detect it.
Marked as feature request. Hopefully there's a better way to do this cross-os. Either way, really interested in implementing this.
@ash0x0 I've found "keypress" event returns a key representation by reading the source code. I believe it's not in the documentation.
@ash0x0 I've found "keypress" event returns a key representation by reading the source code. I believe it's not in the documentation.
The "keypress"event works for me by combining its keychar value with String.fromCharCode
! Thanks @DCzajkowski
Here's a keymap for Linux: https://github.com/yikuansun/desktopspeedruntools/blob/main/window/keycodenames/linux.json
{"1":"Escape","2":"1","3":"2","4":"3","5":"4","6":"5","7":"6","8":"7","9":"8","10":"9","11":"0","12":"-","13":"=","14":"Backspace","15":"Tab","16":"q","17":"w","18":"e","19":"r","20":"t","21":"y","22":"u","23":"i","24":"o","25":"p","26":"[","27":"]","28":"Enter","29":"Control","30":"a","31":"s","32":"d","33":"f","34":"g","35":"h","36":"j","37":"k","38":"l","39":";","40":"'","41":"`","42":"Shift","43":"\\","44":"z","45":"x","46":"c","47":"v","48":"b","49":"n","50":"m","51":",","52":".","53":"/","54":"Shift","56":"Alt","57":" ","59":"F1","60":"F2","61":"F3","62":"F4","63":"F5","64":"F6","65":"F7","66":"F8","67":"F9","68":"F10","87":"F11","88":"F12","3613":"Control","3640":"Alt","3657":"PageUp","3665":"PageDown","57416":"ArrowUp","57419":"ArrowLeft","57421":"ArrowRight","57424":"ArrowDown"}