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

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

XMLWordPrintable

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

      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);

       

        1. test_2.cpp
          2 kB
        2. test.cpp
          0.2 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

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

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes