GLFW character text input with modifier keys (control, meta, alt)

Hi,

i am developing a Terminal Emulator in C++ chose OpenGL for rendering for being most platform independant. Therefore I also chose GLFW because it is meant to be everywhere (*).

I need to respect users input mappings (such as different keyboard layouts), but also need to know when Control, Alt, or Meta was pressed. As I am translating the GLFW input events into Virtual Terminal input control sequences.

glfwSetKeyCallback provides me access to the modifiers, but no mappings, whereas glfwSetCharCallback provides me the right character input but no modifiers. This seams to be mutually exclusive.

What I tried is to just register both callbacks - as it seems that key callback is always invoked first and char callback always invoked second - and translate the input event in the char callback only if it wasn’t processed in the key callback yet.
However sometimes the char callback is not invoked at all but the key callback only. For example in en_US keyboard layout, pressing Ctrl+[, I can grab everything as expected.
Now, when on keyboard layout de_DE, in order to generate a Ctrl+[, you also need to press AltGr, so Ctrl+Alt(Gr)+[ ([ is on the physical key 8).
This info can be grabbed via key callback, but not via char callback, and the char callback isn’t even invoked for that (because Ctrl was pressed, too?)

How can I untangle this situation and grab the proper char text data while also knowing about modifiers (that were not required to contruct the letters, such as [ in my case - the Ctrl).

edit: I just realized there is a glfwSetCharModsCallback API function, but it’s marked deprecated and it’s not working for the Ctrl+[ on german keyboard (de_DE) layout case. That is, in order to emit a [ in de_DE you must press AltGr+8, and glfw does that fine. But as soon as you ALSO press the control key, the symbol 8 instead of [ is being sent, which makes using the callback useless (as it just seems to mirror what key callback would have known too). Is this a bug in glfwSetCharModsCallback’s, and what’s the reason in dropping this API in the first place?

Many thanks in advance,
Christian.

(*) Except WindowsStore.

Hi,

glfwSetKeyCallback and glfwSetCharCallback are indeed intended for different purposes.

glfwSetCharCallback is for text input, and is the direct text input provided by the operating system as native UTF-32 codepoints.

glfwSetKeyCallback is for physical key presses. The keys are identified by a platform specific scancode and mapped to a US layout virtual key code.

You can get hold of the Key names for keys and scancodes using glfwGetKeyName, which will give an identifiable name (if possible) for a key, such as Z for GLFW_KEY_W on an AZERTY keyboard.

Typically programs use specific key callbacks to generate program events, such as CTRL+C to quit, and char callbacks to input text when in a text input field. If you want to use the C rather than virtual GLFW_KEY_C key you can call glfwGetKeyName to check the key name (it’s possible that some keyboards may not have a C key so it might be useful to have a fallback if you want to support these).

Cheers,

Doug.

Hi,

thanks for your reply. However, I feel like I’m sadly not really delighted yet.

Thinking of a terminal emulator, the user is typing in literally anything, this can be commands, romantic texts, source code, or special key combinations such as Ctrl+[.
It all works fine with glfwSetKeyCallback as long as the user is using en_US keyboard mapping. As soon as the user us using a different (in my case de_DE, German(y)) keyboard layout, then the this callback is not enough anymore, also because of the german umlauts, such as ÄÖÜ, And special symbols, such as [ are on different keys, for example you can type in a [ only when you type AltGr+8.
This is captured via glfwSetCharCallback, that’s nice, but as soon as I also press Ctrl along with AltGr+8 in order to compose a Ctrl+[ the char callback is not even invoked (!).

I do see this event in the key callback however - but as Ctrl+Alt+8 not as Ctrl+[, and that’s not helpful because I do not know what keyboard mapping the user is having, nor do I think I should implement keyboard layouts myself just to see what the user actually pressed (along with the Ctrl key).

I’d like to stick with GLFW because it’s having a clean and nice API, but I’m really not sure how to get all the keyboard input events the way a “terminal emulator” needs them.

Do you have any advice?

Regards,
Christian.

It’s not currently possible to use GLFW to know that the CTRL+[ key has been pressed on keyboard layouts where [ is not accessed without a modifier key.

It might be possible to add functionality to GLFW so that we can translate a virtual key or scancode in the presence of a modifier key such as ALT. You could then translate the ALT+8 to get [.

This would require an issue to be filed on the GLFW Github page to start with. If you don’t have an account I can submit the issue for you.

An alternative might be to let users define the control sequences they want, so they can add CTRL+ALT+8 as the action somehow.

Telling the user to map create custom mappings somehow doesn’t sound right (more like a workaround). I think it would be best to extend the capability of GLFW so others can make use of this functionality too, if they wish.

For reference, I posted to ticket here: https://github.com/glfw/glfw/issues/1618

Many thanks @dougbinks,
Christian.

I should have been a bit clearer on the intended feature proposal, as something similar to glfwSetCharModsCallback won’t work in your case - the key combo is a non printable character and so will not produce a character from the OS.

What you need is a way to translate a portion of the keys pressed. So whilst CTRL+ALT+8 isn’t printable, ALT+8 is so if you get that translated it would give you [ which you can use to deduce CTRL+[ was pressed.