I'm about to make my own keyboard layout maps

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

I'm about to make my own keyboard layout maps

Post by grump »

I need to detect when certain symbols on the keyboard are pressed/released.

Code: Select all

// complete list of symbols I'm interested in
*+,<-.>/?!#$%6&():;[]=@"`012345789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
love.keypressed tells you key and scancode, but not the symbol - there is no difference between q and Q, or / and ? on US keyboards.

love.textinput/textedited can be used to get symbols, but there is no release event for those. And there is no correlation between key events and text input, even if I choose to ignore all the special cases (weird composing, dead keys etc.). My only concern is making it work on standard western PC keyboards anyway, where each of the symbols I'm interested in can be created by pressing modifier(s) + key once.

So the only way I see to make this work is to make my own keymaps for each supported layout that can tell me which combination of keys creates one of the symbols from my list, and probably provide a keyboard layout selection UI for the user. I can think of ways to use love.keyboard.getKeyFromScancode to implement automatic layout detection, but I don't see a way around having my own keymaps.

Any input on how to do this? Or anyone have an idea what is the best way to obtain those keymaps for as many layouts as possible with as little work as possible? Some tool or database maybe, because I can't find anything that's usable without doing a lot of work on my own. All of this is madness and I don't want to do it.

Edit: context is making keydown/keyup events work in an emulator for a system with radically different scan codes and a unique layout, in a way that feels intuitive to the user. The system is based on polling a key matrix, so accurate keydown/keyup events are required.
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: I'm about to make my own keyboard layout maps

Post by pgimeno »

Whew, have you peeked down that rabbit hole and noticed its depth?

Android does not generate accurate key down/up events. I don't remember the details but I think it generated both at the same time, or did not generate one of them, or something like that. IIRC it also generated textinput before keypressed, unlike normal keyboards. Test it to be sure. This basically means that this idea is plainly infeasible in Android: you don't have information of when the key is pressed and when it is released.

If you disregard Android, you can cache certain keypressed events, wait for a subsequent textinput event if it is generated, and use that as the input character. This may not work for every layout or in all circumstances. For example, having caps lock on will return upper case characters by this method, and using shift in the emulated machine just because the input is in upper case, won't probably produce the expected results. There are also issues of ambiguity; for example, '*' is shifted in some layouts, and if the emulated machine needs it to be input unshifted (that's the case of C64), it means that when shift was pressed, you transmitted the shift to the emulated machine, and in order to input a '*', you need to undo the shift key before transmitting the '*' key. Other keyboard layouts need the right Alt key for some symbols (e.g. in a Spanish keyboard, [ ] are entered with it), and if you're using it for some emulated key, you need to undo that as well. Pretty messy.

I know of one project that is doing this kind of keyboard madness: OpenMSX. It also supports localized versions of the emulated machines. It still has issues with some keyboard layouts, that no one has been able to fix yet. It actually has three input modes; "character" is that one, and the others are "key" (a legacy one that is broken but kept for compatibility) and "positional" (scancode-based). When I run into problems, which I do often because '#' is one of the affected characters in a Spanish layout and it's common to need it, I just switch to positional mode and keep working; in fact I wrote the patch to implement positional mode because I thought it was basic, and "key" was completely useless. "key" is basically the same as "positional" but with keycodes instead of scancodes.

My advice would be to go with scancodes. Imagine your PC keyboard as if it was the keyboard of the original machine, and press the corresponding keys to enter the characters as you would in the real one. That's what "positional" does in OpenMSX.

PS. What's the '6' between the '%' and the '&'? Should it be removed, or should it be another symbol?
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: I'm about to make my own keyboard layout maps

Post by grump »

pgimeno wrote: Mon Apr 19, 2021 6:28 pm Whew, have you peeked down that rabbit hole and noticed its depth?
Yeah, I have, this is not even my first ride with something like this, but it's been a while. What gives me hope this time is the fact that the symbol list is short and fixed and is almost void of weird characters. I looked at VICE and they too are using custom keymaps that the user can select.
Android does not generate accurate key down/up events
I chose not to care about anything that doesn't have a physical keyboard by default.
If you disregard Android, you can cache certain keypressed events, wait for a subsequent textinput event if it is generated, and use that as the input character. This may not work for every layout or in all circumstances.
What I'm currently doing is use keypressed/keyreleased for all non-character keys. This works flawlessly. And textinput + setKeyRepeat for everything else - the first char of the text is my key and it is considered pressed until the emulated system is done polling the keyboard once. That works well for the mapping aspect but sucks for timing and emulation accuracy in general.
There are also issues of ambiguity; for example, '*' is shifted in some layouts, and if the emulated machine needs it to be input unshifted (that's the case of C64)
Yeah, this is solved and implemented already.
My advice would be to go with scancodes. Imagine your PC keyboard as if it was the keyboard of the original machine, and press the corresponding keys to enter the characters as you would in the real one.
Heh, the easy way but that's a very frustrating way to use a computer.
PS. What's the '6' between the '%' and the '&'? Should it be removed, or should it be another symbol?
Just a copy/paste error from when I made the string from a Lua table. The 6 is missing between 5 and 7 - 6 was probably afraid of 7, because 7 8 9.
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: I'm about to make my own keyboard layout maps

Post by pgimeno »

grump wrote: Mon Apr 19, 2021 7:01 pm What I'm currently doing is use keypressed/keyreleased for all non-character keys. This works flawlessly. And textinput + setKeyRepeat for everything else - the first char of the text is my key and it is considered pressed until the emulated system is done polling the keyboard once. That works well for the mapping aspect but sucks for timing and emulation accuracy in general.
So, basic idea is: assume that a textinput event is always preceded by a keydown event; so, on textinput, process the char and assume that the key that activated it is the one that produced the keydown. That gives you one key to monitor for down/up state, associated to a particular symbol. I think that's how it works in OpenMSX too. I don't recommend caching the association, e.g. to let the user switch keyboard layouts on the fly. I'm almost sure that the keydown and textinput come both in the same frame, but it's worth testing just in case. That gives you a "deadline" for keydown events that don't have any associated textinput event, in case you need to know if they exist. If there is a keydown and no associated textinput when reaching love.update, the last keydown should be processed as a key, not as a symbol.

grump wrote: Mon Apr 19, 2021 7:01 pm Heh, the easy way but that's a very frustrating way to use a computer.
Depends. I guess there's no such thing for Commodore as the Recreated ZX Spectrum? (a bluetooth keyboard that is a pretty accurate replica of the original machine) :)

I am fairly comfortable using OpenMSX in positional mode. Granted, I am not a common user.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 15 guests