Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard layout problem on .appimage file #2

Open
Lagetta opened this issue Jun 18, 2020 · 5 comments
Open

Keyboard layout problem on .appimage file #2

Lagetta opened this issue Jun 18, 2020 · 5 comments

Comments

@Lagetta
Copy link

Lagetta commented Jun 18, 2020

It seems that whenever I start a Blue nebula .appimage file, depending on what keyboard layout I use, seems that some of the keys are unrecognisable in gameplay. On chat it's normal.

More specific: US on default module - spacebar is not working. LT 1-9 keys above letters.

@TheAssassin
Copy link
Member

We suspect it's the SDL2 library we ship with the game. We already tried building our own, but that introduced more issues than it solved.

What I could well imagine is to only load our own SDL2 libraries when there's none on the system. That way, you could install SDL2 yourself from apt or whatever when there are issues. Not an ideal solution, but it's better than having issues with the keyboard.

@TheAssassin
Copy link
Member

Collection of potentially related links:

I'm really not an SDL2 expert, but it looks like the key codes reading in BN is maybe incomplete. I'm tracing how the SDL2 key press events propagate within the codebase. We might have to open the issue there, actually.

@TheAssassin
Copy link
Member

So here's what I got so far:

The key handling is implemented in engine/main.cpp. There, a function called checkinput() processes all incoming SDL2 events. Among these events are SDL_KEYDOWN and SDL_KEYUP. In SDL-speak, those are regular key press events. There's some handling to recognize key spam and stuff, but we can ignore that for now. The function delegates the event to a special method processkey().

processkey() is defined in engine/console.cpp. There's a little bit of special keys handling (F4, return, tab, ...), with some platform-specific magic. What's interesting to us is how the event is further propagated. There's a slightly weird if, which, in its true branch just seems to do some state resetting. The funky bit is the else branch, where the key press is propagated into more handlers: consolekey() and hud::keypress() as well as execbind().
The logic is basically, attempt to have it handled by consolekey() first, then attempt hud::keypress. If both return false and the key is bound(?), it finally attempts to handle the key in execbind().

We have to look into consolebind(), hud::keypress() and execbind() to see how they work internally. But this already shows there's definitely some different handling of the keys, depending on whether you press them in the console or not.

@TheAssassin
Copy link
Member

consolekey() relies on a variable called commandmillis. Looking at other code, e.g., game/game.cpp, once that variable is > 0, we're in "console mode" (i.e., the chat is open). Don't know why they did it like that. consolekey() uses that exact same check. It immediately returns false if the precondition is not met, otherwise it returns true as expected.
We can therefore assume that as long as you're in the chat, only consolekey() will be asked to handle the key press. Makes sense, right?
This function in particular handles the keys return (including the keypad one), home (pos1?), end, delete, backspace, the arrow keys and tab specially, as well as v for the paste feature. There's some differentiation between down and up events. I can't see any "regular key press" fallback handler as you'd expect for non-special keys, they must be handled elsewhere. The only alterations of commandbuf (which I assume contains the current command) are done for delete, backspace, tab (for completion) and V (for paste), but that's it.

Next candidate: hud::keypress(). This one's declared in shared/igame.h, but there's also a declaration of some UI::keypress().
The definition of the hud one is in game/hud.cpp. Fun fact: this one calls the UI one and lets it handle the key press (unless you're in a compass menu, there it forwards it to keycmenu()).
So, we need to look into UI::keypress(), which is defined in engine/ui.cpp. There's special handling of some editor stuff, mouse presses, etc. What is interesting to us is the second-last line: if(isdown) e->key(code);. In this case e is an object of type editor. Let's see if that handles arbitrary characters.

editor is defined in textedit.h (it's declared in shared/iengine.h as well) and probably is responsible for managing the line editor in the console/chat interface. We have special handling for the keys up, down, -4 and -5 (probably mouse stuff, given the code in UI::keypress()), pageup, pagedown, home (aka pos1), end, left, right, delete, backspace, both shift, V and return. There's no fallback handler of any kind, which is a little surprising.

Back in UI::keypress(). The magic must be in one of these if branches. The first one contains a call e->insert(keyname);. That looks interesting! Seems fieldmode == FIELDKEY and e-> mode != EDITORREADONLY seem to refer to the active editor. This if branch has special handling for the escape key (that closes the editor, apparently). For all other keys, getkeyname is called. If that returns a C string and this is a "down" event, after a sanity check, this insert call is made. editor::insert() does what you'd expect, it inserts text. into a buffer. Clearly, we need to check getkeyname, as it returns the character(s) (might be more than one when e.g., accents are used, there are such keyboards supposedly) that will be added to the editor prompt.

getkeyname() is defined in engine/console.cpp again, for some reason. It accepts an integer keycode and translates it to some string. If it can't, it returns a null pointer.
It uses a call keyms.access(code) internally. This object is defined as a global static variable hashtable<int, keym> keyms(128);. It's used all over that file. I don't see how it's populated. Going to continue tracing that tomorrow.

@TheAssassin
Copy link
Member

So, keyms is actually populated from config/keymap.cfg, apparently.

Not entirely robust, the whole construct. We should consider moving the entire keymap definition into source code, or alternatively use unique keys to identify entries both in the cubescript and C++ code files. Right now, it all relies on the keymap adding the right keys in the right order. If an entry was missing for instance, it wouldn't work any more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants