Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-66497

Ctrl+Letter shortcuts don't work on Wayland with non-US keyboard layout

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.13.0
    • 5.10.1
    • QPA: Wayland
    • None
    • Qt (Base, Wayland) 5.10.1 on Arch Linux.
       
    • 23453c30084d09d7325e113bbc3d0637c51cb3e7 (qt/qtwayland/dev)

    Description

      Steps to reproduce

      1. Run Wayland compositor (sway in my case)
      2. Run simple program with QTextEdit field (attached test.cpp should be enough)
      3. Type in some text
      4. Ctrl+A should select all text (as expected)
      5. Switch to non-US keyboard layout (Russian in my case)
      6. Ctrl+A will do nothing

      Investigation

      Attached test_2.cpp contains another simple program that shows received key events (QKeyEvent).

       

      Ctrl+A press on X11 with US layout:

      | Keys involved: 1
      | Key code: 65
      | Text: "\u0001"
      | Native scan code: 38
      | Native virtual key: 97
      > Modifiers:
        | Shift: false
        | Ctrl: true
        | Alt: false
        | Meta: false
      > Matches sequences:
        | Unknown key: false
        | Cancel: false
        | Select all: true
      

       

      Ctrl+A press on X11 with RU layout:

      | Keys involved: 1
      | Key code: 65
      | Text: "\u0001"
      | Native scan code: 38
      | Native virtual key: 1734
      > Modifiers:
        | Shift: false
        | Ctrl: true
        | Alt: false
        | Meta: false
      > Matches sequences:
        | Unknown key: false
        | Cancel: false
        | Select all: true
      

       

      Ctrl+A press on Wayland with US layout:

      | Keys involved: 1
      | Key code: 65
      | Text: "\u0001"
      | Native scan code: 38
      | Native virtual key: 97
      > Modifiers:
        | Shift: false
        | Ctrl: true
        | Alt: false
        | Meta: false
      > Matches sequences:
        | Unknown key: false
        | Cancel: false
        | Select all: true
      

       

      And finally... Ctrl+A press on Wayland with RU layout:

      | Keys involved: 1
      | Key code: 1060
      | Text: "ф"
      | Native scan code: 38
      | Native virtual key: 1734
      > Modifiers:
        | Shift: false
        | Ctrl: true
        | Alt: false
        | Meta: false
      > Matches sequences:
        | Unknown key: false
        | Cancel: false
        | Select all: false
      

      Note key code (event->key()) value.

       

      On Wayland QWaylandXkb::keysymToQtKey is responsive for Keysym-QtKey mapping. It's called from following places:

      On X11 QXcbKeyboard::keysymToQtKey is responsive for same task. It's called from following place:

      // Have a temporary keyboard state filled in from state
      // this way we allow for synthetic events to have different state
      // from the current state i.e. you can have Alt+Ctrl pressed
      // and receive a synthetic key event that has neither Alt nor Ctrl pressed
      struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
      if (!kb_state)
          return;
      updateXKBStateFromState(kb_state, state);
      
      xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
      QString string = lookupString(kb_state, code);
      
      // Ιf control modifier is set we should prefer latin character, this is
      // used for standard shortcuts in checks like "key == QKeySequence::Copy",
      // users can still see the actual X11 keysym with QKeyEvent::nativeVirtualKey
      Qt::KeyboardModifiers modifiers = translateModifiers(state);
      xcb_keysym_t translatedSym = XKB_KEY_NoSymbol;
      if (modifiers & Qt::ControlModifier && !isLatin(sym))
          translatedSym = lookupLatinKeysym(code);
      if (translatedSym == XKB_KEY_NoSymbol)
          translatedSym = sym;
      int qtcode = keysymToQtKey(translatedSym, modifiers, string);

      lookupLatinKeysym converts 'ф' into latin 'a' so Ctrl+A will always be reported as Ctrl+A, not Ctrl+Ф. There is no corresponding conversion done in Wayland-related code:

      void QWaylandTextInput::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) 
      {
          // ...
          QString text; int qtkey; std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, qtModifiers);
          // ...
          QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(), time, type, qtkey, qtModifiers, text);

       

      Attachments

        1. test_2.cpp
          2 kB
        2. test.cpp
          0.2 kB

        Issue Links

          For Gerrit Dashboard: QTBUG-66497
          # Subject Branch Project Status CR V

          Activity

            People

              paeglis Gatis Paeglis
              foxcpp Maks Mazurov
              Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes