Keyboard keys and characters
utcc.utoronto.ca
utcc.utoronto.ca
* scancodes (what the hardware actually sends). Nobody should really touch this directly these days. Note that this is variable-length and encodes press and release differently.
* keycodes (sometimes useful if you want to bind by location of the key, e.g. WASD, but you should probably avoid these outside of games. There are only 8 bits of these. If you have multiple keyboards with different layouts your life will be pain.)
* keysyms (semantic info; this resolves shifts, keyboard layout, etc. The range here covers all of Unicode (but encoded differently) + a few more. Note that the release event is often for a different keysym from the press event! Hold events appear as press events but can be distinguished if you're careful.)
* strings (this layer resolves compose and such. I suppose input methods as well?)
* modifiers (including shifts, locks, and latches. Note that there are no events for modifier changes! You only get the list of modifiers when some other event happens, which is annoying.)
* TTY-encoded keys (only relevant for TTY programs). Many keys do not send events or send ambiguous events, at least by default. There are no release events, and hold events cannot be distinguished from repeated press events.
One particular annoyance I have is that "both shifts to toggle CapsLock" breaks programs that listen for the (unmodified) CapsLock keysym since there is an extra modifier bit set.
Running into this now in MS-DOS!
I’m in the middle of learning some low-level assembly language 16-bit x86/BIOS/MS-DOS & bare metal if necessary (I/O ports) programming (for fun, on my original IBM PC). I’m trying to program a game and there is no BIOS or DOS interrupt routine to get the key-up scan codes, just key down and/or the translated codes, even though the keyboard and interrupt controller send both to a BIOS interrupt handler. There is a BIOS function for getting the left and right shift, alt, Ctrl, and well as the states of scroll lock, caps lock, num lock, and insert states, which are derived from those keyboard events since it obviously tracks when those keys go up and down. [0] So I can use the shift keys for a game for now as a workaround, but only for moving left or right like in Breakout or Space Invaders.
I ran across examples of how to capture all the scancodes by taking over interrupt 9. [1] Usually those examples also emulate what the BIOS would do, but for a game I wouldn’t care about that. That would give me the ability to track any key’s state that I care about.
So it’s interesting to see how it works (in the normal BIOS interrupt handler) that “Ctrl” and “A” are equal keys at one level, just having up/down scan codes. 1D and 9D for Ctrl up/down for instance. And the next level up will give you translated ASCII (or other codes for non-ascii keys like function, arrow, or Alt- keys), Ctrl-A is 01 (SOH), A by itself is ‘a’ (61h), shift A is ‘A’ (41h), or the opposite if Caps Lock is on. I don’t think it even supports combos like Shift-Ctrl-A etc. [2] (Other OSes take over and do things different and I don’t really know much about that. Don’t modern OSes give you access to whether keys are being pressed? Pygame has key up and down events and I think DirectX lets you check if a key is down.)
[0] http://www.ctyme.com/intr/rb-1756.htm
[1] https://stackoverflow.com/questions/12882342/override-defaul...
[2] https://www.plantation-productions.com/Webster/www.artofasm....
I politely disagree here, sometimes you do want scan codes. I am working (very slowly lol) on a QWOP-like browser game. I want to hit the keys that are positioned like Q, W, O, and P. I use the dvorak keyboard layout. Using scancodes means that I still capture the right keys for non-QWERTY layouts.
Of course, my FIPS key at work seems to use scan codes to press laid out keys, so it sends all the wrong characters (over the network, not on my local machine for whatever reason) unless I first switch back to QWERTY first.
If I type `q'`, my keyboard will send scancodes 20 (Q), 52 (' / "). This gets translated into symbols `q'`, which end up as characters `q'`. However, with a slightly different configuration I'll type `a'`, my keyboard will send scancodes 20 (Q), 52 (' / "), it gets translated into symbols `a'`, and they end up as the character `á`.
It sorta-kinda works, but when you are a keyboard you are basically at the mercy of the OS to interpret your intentions. Reliably inputting anything beyond basic ascii is incredibly difficult, and you get stuck trying to deal with dead keys, compose keys, numpad unicode input... Heck, even directly typing symbols like `&` is tricky because you essentially have to emulate <shift down><7 down><7 up><shift up>, which means that something like <& down><5 down><& up><5 up> will give you a surprise `%` instead of a plain `5`.
I'm into custom keyboards and I'd love to have a layer where I could just have a simple key to input stuff more complex than plain letters, but there's just no way to do so reliably.
On linux at least, you can create a custom keyboard with all the characters you want. And then bind your CAPSLOCK key to switch between your two keyboards.
Use something with a sane key event handling system. List here: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
(My particular use that drove me down this rabbit hole was using "Shift" for selection. You CANNOT DO THIS with "standard" terminals as you cannot detect when shift gets pressed or released without also pressing another key.)
I'll wait ...
(It's this kind of basic stuff that doesn't work that makes me absolutely laugh my ass off when people claim that "AI will take all the programming jobs".)