diff --git a/autotests/integration/sticky_keys_test.cpp b/autotests/integration/sticky_keys_test.cpp index 5b8794eb23..f0d4d0d9ad 100644 --- a/autotests/integration/sticky_keys_test.cpp +++ b/autotests/integration/sticky_keys_test.cpp @@ -34,6 +34,7 @@ private Q_SLOTS: void init(); void cleanup(); void testStick(); + void testStick_data(); void testLock(); }; @@ -43,6 +44,12 @@ void StickyKeysTest::initTestCase() kaccessConfig.group(QStringLiteral("Keyboard")).writeEntry("StickyKeys", true); kaccessConfig.sync(); + // Use a keyboard layout where right alt triggers Mod5/AltGr + KConfig kxkbrc("kxkbrc"); + kxkbrc.group(QStringLiteral("Layout")).writeEntry("LayoutList", "us"); + kxkbrc.group(QStringLiteral("Layout")).writeEntry("VariantList", "altgr-intl"); + kxkbrc.sync(); + qRegisterMetaType(); QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); QVERIFY(waylandServer()->init(s_socketName)); @@ -68,8 +75,22 @@ void StickyKeysTest::cleanup() Test::destroyWaylandConnection(); } +void StickyKeysTest::testStick_data() +{ + QTest::addColumn("modifierKey"); + QTest::addColumn("expectedMods"); + + QTest::addRow("Shift") << KEY_LEFTSHIFT << 1; + QTest::addRow("Ctrl") << KEY_LEFTCTRL << 4; + QTest::addRow("Alt") << KEY_LEFTALT << 8; + QTest::addRow("AltGr") << KEY_RIGHTALT << 128; +} + void StickyKeysTest::testStick() { + QFETCH(int, modifierKey); + QFETCH(int, expectedMods); + std::unique_ptr keyboard(Test::waylandSeat()->createKeyboard()); std::unique_ptr surface(Test::createSurface()); @@ -85,26 +106,26 @@ void StickyKeysTest::testStick() quint32 timestamp = 0; - // press Ctrl to latch it - Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp); + // press mod to latch it + Test::keyboardKeyPressed(modifierKey, ++timestamp); QVERIFY(modifierSpy.wait()); // arguments are: quint32 depressed, quint32 latched, quint32 locked, quint32 group - QCOMPARE(modifierSpy.first()[0], 4); // verify that Ctrl is depressed - QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is latched + QCOMPARE(modifierSpy.first()[0], expectedMods); // verify that mod is depressed + QCOMPARE(modifierSpy.first()[1], expectedMods); // verify that mod is latched modifierSpy.clear(); - // release Ctrl, the modified should still be latched - Test::keyboardKeyReleased(KEY_LEFTCTRL, ++timestamp); + // release mod, the modified should still be latched + Test::keyboardKeyReleased(modifierKey, ++timestamp); QVERIFY(modifierSpy.wait()); - QCOMPARE(modifierSpy.first()[0], 0); // verify that Ctrl is not depressed - QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is still latched + QCOMPARE(modifierSpy.first()[0], 0); // verify that mod is not depressed + QCOMPARE(modifierSpy.first()[1], expectedMods); // verify that mod is still latched // press and release a letter, this unlatches the modifier modifierSpy.clear(); Test::keyboardKeyPressed(KEY_A, ++timestamp); QVERIFY(modifierSpy.wait()); - QCOMPARE(modifierSpy.first()[0], 0); // verify that Ctrl is not depressed - QCOMPARE(modifierSpy.first()[1], 0); // verify that Ctrl is not latched any more + QCOMPARE(modifierSpy.first()[0], 0); // verify that mod is not depressed + QCOMPARE(modifierSpy.first()[1], 0); // verify that mod is not latched any more Test::keyboardKeyReleased(KEY_A, ++timestamp); } diff --git a/src/plugins/stickykeys/stickykeys.cpp b/src/plugins/stickykeys/stickykeys.cpp index a8e31857c6..babde78b5a 100644 --- a/src/plugins/stickykeys/stickykeys.cpp +++ b/src/plugins/stickykeys/stickykeys.cpp @@ -24,21 +24,21 @@ StickyKeysFilter::StickyKeysFilter() } } -Qt::KeyboardModifier keyToModifier(Qt::Key key) +KWin::Xkb::Modifier keyToModifier(Qt::Key key) { if (key == Qt::Key_Shift) { - return Qt::ShiftModifier; + return KWin::Xkb::Shift; } else if (key == Qt::Key_Alt) { - return Qt::AltModifier; + return KWin::Xkb::Mod1; } else if (key == Qt::Key_Control) { - return Qt::ControlModifier; + return KWin::Xkb::Control; } else if (key == Qt::Key_AltGr) { - return Qt::GroupSwitchModifier; + return KWin::Xkb::Mod5; } else if (key == Qt::Key_Meta) { - return Qt::MetaModifier; + return KWin::Xkb::Mod4; } - return Qt::NoModifier; + return KWin::Xkb::NoModifier; } void StickyKeysFilter::loadConfig(const KConfigGroup &group) diff --git a/src/xkb.cpp b/src/xkb.cpp index 16c7ee5edf..9825889af8 100644 --- a/src/xkb.cpp +++ b/src/xkb.cpp @@ -658,6 +658,7 @@ void Xkb::updateKeymap(xkb_keymap *keymap) m_altModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT); m_metaModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO); m_numModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_NUM); + m_mod5Modifier = xkb_keymap_mod_get_index(m_keymap, "Mod5"); m_numLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_NUM); m_capsLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_CAPS); @@ -1001,41 +1002,39 @@ bool Xkb::switchToLayout(xkb_layout_index_t layout) return true; } -void Xkb::setModifierLatched(Qt::KeyboardModifier mod, bool latched) +void Xkb::setModifierLatched(KWin::Xkb::Modifier mod, bool latched) { xkb_mod_index_t modifier = XKB_MOD_INVALID; switch (mod) { - case Qt::NoModifier: { + case NoModifier: { break; } - case Qt::ShiftModifier: { + case Shift: { modifier = m_shiftModifier; break; } - case Qt::AltModifier: { + case Mod1: { modifier = m_altModifier; break; } - case Qt::ControlModifier: { + case Control: { modifier = m_controlModifier; break; } - case Qt::MetaModifier: { + case Mod4: { modifier = m_metaModifier; break; } - case Qt::GroupSwitchModifier: { - // TODO + case Mod5: { + modifier = m_mod5Modifier; break; } - case Qt::KeypadModifier: { + case Mod2: + case Mod3: + case Lock: break; } - case Qt::KeyboardModifierMask: { - break; - } - } if (modifier != XKB_MOD_INVALID) { std::bitset mask{m_modifierState.latched}; @@ -1048,41 +1047,39 @@ void Xkb::setModifierLatched(Qt::KeyboardModifier mod, bool latched) } } -void Xkb::setModifierLocked(Qt::KeyboardModifier mod, bool locked) +void Xkb::setModifierLocked(KWin::Xkb::Modifier mod, bool locked) { xkb_mod_index_t modifier = XKB_MOD_INVALID; switch (mod) { - case Qt::NoModifier: { + case NoModifier: { break; } - case Qt::ShiftModifier: { + case Shift: { modifier = m_shiftModifier; break; } - case Qt::AltModifier: { + case Mod1: { modifier = m_altModifier; break; } - case Qt::ControlModifier: { + case Control: { modifier = m_controlModifier; break; } - case Qt::MetaModifier: { + case Mod4: { modifier = m_metaModifier; break; } - case Qt::GroupSwitchModifier: { - // TODO + case Mod5: { + modifier = m_mod5Modifier; break; } - case Qt::KeypadModifier: { + case Mod2: + case Mod3: + case Lock: break; } - case Qt::KeyboardModifierMask: { - break; - } - } if (modifier != XKB_MOD_INVALID) { std::bitset mask{m_modifierState.locked}; diff --git a/src/xkb.h b/src/xkb.h index ce0615abdd..f8f3c3ef8d 100644 --- a/src/xkb.h +++ b/src/xkb.h @@ -39,6 +39,18 @@ class KWIN_EXPORT Xkb : public QObject { Q_OBJECT public: + enum Modifier { + NoModifier, + Shift, + Lock, + Control, + Mod1, + Mod2, + Mod3, + Mod4, + Mod5, + }; + Xkb(bool followLocale1 = false); ~Xkb() override; void setConfig(const KSharedConfigPtr &config); @@ -64,8 +76,8 @@ public: void switchToPreviousLayout(); bool switchToLayout(xkb_layout_index_t layout); - void setModifierLatched(Qt::KeyboardModifier mod, bool latched); - void setModifierLocked(Qt::KeyboardModifier mod, bool locked); + void setModifierLatched(KWin::Xkb::Modifier mod, bool latched); + void setModifierLocked(KWin::Xkb::Modifier mod, bool locked); LEDs leds() const { @@ -141,6 +153,7 @@ private: xkb_mod_index_t m_altModifier; xkb_mod_index_t m_metaModifier; xkb_mod_index_t m_numModifier; + xkb_mod_index_t m_mod5Modifier; xkb_led_index_t m_numLock; xkb_led_index_t m_capsLock; xkb_led_index_t m_scrollLock;