Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Dealing with keyboard layouts for input on multiple platforms
QtWS25 Last Chance

Dealing with keyboard layouts for input on multiple platforms

Scheduled Pinned Locked Moved Unsolved Game Development
key eventkeycross platformkeyboard mappin
13 Posts 5 Posters 5.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    NeatNit
    wrote on last edited by
    #1

    For the purpose of discussion let's say I'm working on a game.

    My game receives keyboard inputs from keyPressEvent and keyReleaseEvent, which gives me a QKeyEvent. Currently I'm using key() to get which key has been pressed. This has the problem of being dependent on keyboard layout - if a user uses Dvorak for example, the input will change to all over the place, while other layouts like AZERTY and QWERTZ will be just somewhat off. Non-Latin layouts like Hebrew will not work at all.

    I must use another method which identifies a PHYSICAL key rather than the function assigned to it, with a constant code independent of the active keyboard layout.

    QKeyEvent provides two other functions: nativeScanCode() and nativeVirtualKey().

    nativeScanCode can be ruled out immediately because it doesn't work on mac:

    Note: On Mac OS/X, this function is not useful, because there is no way to get the scan code from Carbon or Cocoa.

    So we're left with nativeVirtualKey. This does actually provide a constant code like we want, but now we have a couple of new problems.

    Problem 1: Different codes on different platforms

    Each platform has a different set of virtual key codes. For Windows, the list can be found here. For mac, it's in Events.h. As a simple comparison to demonstrate that they are different, the virtual key code for the letter key O on Windows is 0x4F, while on mac the same key's code is 0x1F. Not to mention, I couldn't even find any relevant info for Linux.

    This makes it impossible to set good default settings that would work on all platforms, forcing me to create separate defaults for each platform (unlike key()).

    Problem 2: Display

    I need to display the assigned keys to the user. The displayed key needs to change depending on the current layout, and the key to display is not the result of a key press event. There is no universal way to do this.

    On Windows, I can use a variation of this code snippet: http://www.setnode.com/blog/mapvirtualkey-getkeynametext-and-a-story-of-how-to/

    But that's just Windows. I have no idea how to do the same for mac or Linux. And besides, having to use different code for different platforms for such a basic thing is a real letdown.

    So now I've come here to ask: does anyone know how to do this, or have a better suggestion? Why isn't this kind of feature built into Qt?

    Thanks. Hope I didn't scare too many people away with this freaking essay..

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Short answer for the why: because it's outside of Qt's scope.

      As for your keyboard setup issue, since we are dealing with a game. I would expect to simply have a configuration panel that allows me to assign the keys I want to the corresponding action.

      Have sensible defaults like awsd for moving the character left/up/down/right and make it easy for people to re-assign the keys they want.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      N 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi and welcome to devnet,

        Short answer for the why: because it's outside of Qt's scope.

        As for your keyboard setup issue, since we are dealing with a game. I would expect to simply have a configuration panel that allows me to assign the keys I want to the corresponding action.

        Have sensible defaults like awsd for moving the character left/up/down/right and make it easy for people to re-assign the keys they want.

        N Offline
        N Offline
        NeatNit
        wrote on last edited by NeatNit
        #3

        @SGaist Problem is that WASD is a bad default for non-QWERTY layouts.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          You could have a set of defaults based on the locale.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • N Offline
            N Offline
            NeatNit
            wrote on last edited by NeatNit
            #5

            It's more complicated than that, which is the source of the problem.

            For starters, there's hundreds of different locales used worldwide. It isn't practical for me to create a separate set of defaults for each one when all I want is to have the exact same physical layout for all of them.

            To make matters worse, many users have more than one keyboard layout installed and switch between them on-the-fly, normally using Alt+Shift (at least on Windows). This means that even if the user sets their own key bindings, if they try to play the game while the wrong layout is active, it wouldn't work or may shuffle around all the keys if the two layouts share letters/keys but at different positions (e.g. QWERTY, QWERTZ, AZERTY, Dvorak).

            Qt has an event type called KeyboardLayoutChange, which should be helpful, but what Qt doesn't have is any other info about keyboard layouts whatsoever. This event has no extra info in it either.

            QLocale doesn't have any keyboard layout info either.

            I am just finding no way to even find the active layout, let alone set defaults based on it.

            1 Reply Last reply
            0
            • N Offline
              N Offline
              NeatNit
              wrote on last edited by
              #6

              Can this thread be moved to the Game Development section? I feel like it might get better suggestions there.

              jsulmJ 1 Reply Last reply
              0
              • N NeatNit

                Can this thread be moved to the Game Development section? I feel like it might get better suggestions there.

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @NeatNit Done

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                N 1 Reply Last reply
                1
                • jsulmJ jsulm

                  @NeatNit Done

                  N Offline
                  N Offline
                  NeatNit
                  wrote on last edited by
                  #8

                  @jsulm Thanks.

                  1 Reply Last reply
                  0
                  • N Offline
                    N Offline
                    NeatNit
                    wrote on last edited by
                    #9

                    Starting to lose hope...

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Well, it's not something that's provided by Qt out of the box, so you'll have to check the platforms you want to support for how they provide that information.

                      You could even consider contributing that to Qt to improve it for everybody.

                      You might also open a feature request on the bug report system for that.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • 8Observer88 Offline
                        8Observer88 Offline
                        8Observer8
                        wrote on last edited by 8Observer8
                        #11

                        I found the next solution only. I changed the system keyboard layout to English using this command:

                        PostMessage(GetForegroundWindow(), WM_INPUTLANGCHANGEREQUEST, 1, 0x04090409);
                        

                        But it is for Windows only, for example:

                        #ifdef _WIN32
                        #include <windows.h>
                        #endif
                        
                        OpenGLWindow::OpenGLWindow()
                        {
                            setTitle("OpenGL ES 2.0, Qt6, C++");
                            resize(350, 350);
                        
                        #ifdef _WIN32
                            PostMessage(GetForegroundWindow(), WM_INPUTLANGCHANGEREQUEST, 1, 0x04090409);
                        #endif
                        
                            QSurfaceFormat surfaceFormat;
                            surfaceFormat.setSwapInterval(1);
                            connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
                            setFormat(surfaceFormat);
                        }
                        
                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SamiV123
                          wrote on last edited by SamiV123
                          #12

                          This is a typical problem in any software (not just games) that is designed without actively thinking about different keyboard layouts.

                          An example is assigning an application shortcut such as Ctrl+" which works fine in In US keyboard layout since " is a single key press. But in the euro layouts " is not a single key press button but it's a character translated by the keyboard layout system and is typically a combination of a modifier key + some other key. So for myself it's Shift+2.

                          This means that Ctrl+" shortcut is completely fubar. Would would it be? Ctrl+Shift+2 ? Forget it, wont' work.

                          There are really 3(+) layers in keyboard event processing.

                          • Primitive keyboard / driver specific scan codes that map directly to to the physical buttons without any regard what the button face (engraving says). Think of this simply as an electronic digital signal that indicates which button on the matrix was pressed.

                          • Virtual keys coming from the device keyboard layout driver. You can think of this as the "universal set of scan codes that map to known IDs". Most keyboards regardless of the engraving have keys such as A, B, C,D, 1, 2, 3 etc and the drivers and the layouts are capable of mapping these universally (at least on QWERTY layouts) to virtual keys that have then designed identifiers. If you program against the native WIn32 you immediately recognize these, VK_ENTER or 'A' 0x41. On Linux X11 provides XK_Return, XK_a, XK_k etc.

                          • Translated character input that can comes through to your application via the layout and IME system. This has nothing to do with key presses per se, even though mostly there were some key presses but the combination of modifier keys and non-modifier keys were mapped to some character. This is how Unicode input works, how IME works and how for example Chinese input works. The user hammers the keyboard and the system translates and maps the key presses to a character

                          • Application level processing triggered by some keyboard input. Logical operation such as "fire weapon" in a video game.

                          Conclusions:

                          • Your application should never rely on characters for shortcuts etc actions since they're always going to fail for some users.
                          • Your application can't rely on scan codes (ahead of time) since they're device specific and not portable.
                          • Your application might have a fighting chance if you rely only on the small subset of virtual keys.

                          In my experience there are enough quirks and surprising platforms, layouts etc that the perfect solution that never fails for anyone is impossible. But with a few assumptions it's possible to get close enough to an acceptable working solution.

                          When defining shortcut keys

                          • Rely on simple virtual keys and modifier key combinations as the default and process these using the OS's VK events.
                          • Don't rely on characters.
                          • Let the user to re-map keys.
                          • For lower latency (such as games) first map the user specified virtual keys to device / platform specific scan codes and then check against the scan codes.
                          1 Reply Last reply
                          0
                          • 8Observer88 Offline
                            8Observer88 Offline
                            8Observer8
                            wrote on last edited by 8Observer8
                            #13

                            I have the same question for WebAssembly: https://forum.qt.io/topic/155454/dealing-with-keyboard-layout-for-input-on-qt-webassembly

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved