SUMMARY After switching a keyboard layout, one of the keys used to switch layouts might get stuck in a state such that the wayland client won't receive a "Key" event upon releasing that key (but will receive a "Modifier" event). STEPS TO REPRODUCE 1. Configure two or more keyboard layouts 2. Set the layout switch shortcut to Ctrl+Shift 3. run ``WAYLAND_DEBUG=client dolphin`` 4. Input the following key sequence into an opened window: - Press CTRL - Press SHIFT - Release CTRL - Release SHIFT - Out of curiosity, press CTRL again - Release CTRL OBSERVED RESULT You will see something like this in terminal: ``` wl_keyboard#27.key(38315, 48717702, 29, 1) //CTRL pressed wl_keyboard#27.modifiers(38317, 4, 0, 0, 1) //CTRL pressed wl_keyboard#27.key(38318, 48719295, 42, 1) //SHIFT pressed wl_keyboard#27.modifiers(38320, 5, 0, 0, 1) //SHIFT pressed wl_keyboard#27.modifiers(38322, 1, 0, 0, 1) //CTRL released wl_keyboard#27.modifiers(38323, 1, 0, 0, 0) //CTRL released wl_keyboard#27.key(38324, 48724027, 42, 0) //SHIFT released wl_keyboard#27.modifiers(38326, 0, 0, 0, 0) //SHIFT released wl_keyboard#27.modifiers(38328, 4, 0, 0, 0) //CTRL pressed wl_keyboard#27.key(38329, 48727759, 29, 0) //CTRL released wl_keyboard#27.modifiers(38330, 0, 0, 0, 0) //CTRL released ``` EXPECTED RESULT ``` wl_keyboard#27.key(38315, 48717702, 29, 1) //CTRL pressed wl_keyboard#27.modifiers(38317, 4, 0, 0, 1) //CTRL pressed wl_keyboard#27.key(38318, 48719295, 42, 1) //SHIFT pressed wl_keyboard#27.modifiers(38320, 5, 0, 0, 1) //SHIFT pressed wl_keyboard#27.key(38329, 48727759, 29, 0) // Additional CTRL released "Key event" wl_keyboard#27.modifiers(38322, 1, 0, 0, 1) //CTRL released wl_keyboard#27.modifiers(38323, 1, 0, 0, 0) //CTRL released wl_keyboard#27.key(38324, 48724027, 42, 0) //Just like SHIFT released "Key event" here wl_keyboard#27.modifiers(38326, 0, 0, 0, 0) //SHIFT released wl_keyboard#27.modifiers(38328, 4, 0, 0, 0) //CTRL pressed wl_keyboard#27.key(38329, 48727759, 29, 0) //CTRL released wl_keyboard#27.modifiers(38330, 0, 0, 0, 0) //CTRL released ``` SOFTWARE/OS VERSIONS Operating System: Arch Linux KDE Plasma Version: 6.5.4 KDE Frameworks Version: 6.21.0 Qt Version: 6.10.1 Kernel Version: 6.18.2-arch2-1 (64-bit) Graphics Platform: Wayland ADDITIONAL IMFORMATION This is a problem because after switching layouts, if you were to press the "stuck key" again, the client will only receive a modifier event. This breaks applications like video games that use modifier keys as an input source (see glfw issue: https://github.com/glfw/glfw/issues/1011 , ultimately breaking Minecraft)
Uhm, actually, I've messed up the expected result section a little bit. This is the correct one: ``` wl_keyboard#27.key(38315, 48717702, 29, 1) //CTRL pressed wl_keyboard#27.modifiers(38317, 4, 0, 0, 1) //CTRL pressed wl_keyboard#27.key(38318, 48719295, 42, 1) //SHIFT pressed wl_keyboard#27.modifiers(38320, 5, 0, 0, 1) //SHIFT pressed wl_keyboard#27.key(38329, 48727759, 29, 0) // Additional CTRL released "Key event" wl_keyboard#27.modifiers(38322, 1, 0, 0, 1) //CTRL released wl_keyboard#27.modifiers(38323, 1, 0, 0, 0) //CTRL released wl_keyboard#27.key(38324, 48724027, 42, 0) //Just like SHIFT released "Key event" here wl_keyboard#27.modifiers(38326, 0, 0, 0, 0) //SHIFT released wl_keyboard#27.key(38315, 48717702, 29, 1) //Additional CTRL pressed here wl_keyboard#27.modifiers(38328, 4, 0, 0, 0) //CTRL pressed wl_keyboard#27.key(38329, 48727759, 29, 0) //CTRL released wl_keyboard#27.modifiers(38330, 0, 0, 0, 0) //CTRL released ```
So I debugged this a little bit, and here's what I could find: - When you press or release a button, eventually, KeyboardInputRedirection::processKey() (https://invent.kde.org/plasma/kwin/-/blob/master/src/keyboard_input.cpp#L279) is going to be called. - It will then call m_input->processFilters() (https://invent.kde.org/plasma/kwin/-/blob/master/src/keyboard_input.cpp#L327), which iterates through every filter and tries to apply them. If a filter returns ``true``, the process of applying filters for the current event will stop. (https://invent.kde.org/plasma/kwin/-/blob/master/src/input.h#L153) - If you only press CTRL, ``KWin::GlobalShortcutFilter`` will fail, and the event will be processed by ``KWin::Xwl::XwaylandInputFilter`` and/or (not sure yet) ``KWin::ForwardInputFilter`` keyboardKey() member functions (https://invent.kde.org/plasma/kwin/-/blob/master/src/xwayland/xwayland.cpp#L239), (https://invent.kde.org/plasma/kwin/-/blob/master/src/input.cpp#L2187), which will trigger both KeyboardInterface::sendKey() and KeyboardInterface::sendModifiers() as mentioned in the issue description (and this behavior is absolutely correct). sendKey() and sendModifiers() are defined at (https://invent.kde.org/plasma/kwin/-/blob/master/src/wayland/keyboard.cpp#L190) and (https://invent.kde.org/plasma/kwin/-/blob/master/src/wayland/keyboard.cpp#L227) respectively. - As a bonus, later in the code, sendModifiers() will be called by ``KWin::Xkb::forwardModifiers()`` (https://invent.kde.org/plasma/kwin/-/blob/master/src/keyboard_input.cpp#L333) However, this is what happens if you trigger a layout switch upon CTRL release: - KeyboardInputRedirection::processKey() is called as usual - m_input->processFilters() tries to apply filters as usual - ``KWin::GlobalShortcutFilter`` will be applied successfully, returning ``true``, and thus every other filter will be skipped (including ``KWin::Xwl::XwaylandInputFilter`` and ``KWin::ForwardInputFilter``) - Since all other filters were skipped, neither sendKey(), nor sendModifiers() will be called - However, later in the code, ``KWin::Xkb::forwardModifiers()`` will call sendModifiers() (https://invent.kde.org/plasma/kwin/-/blob/master/src/keyboard_input.cpp#L333), as seen in the issue description (but where is the missing sendKey() call??) So the rough explanation of a problem is as follows: because a GlobalShortcutFilter is being triggered, KeyboardInterface::sendKey() won't be called (but KeyboardInterface::sendModifiers() will be!). Oh, also please keep in mind that I could have interpreted the code incorrectly (I'm a noob)