Fix sticky keys for AltGr
We map AltGr to Qt::GroupSwitchModifier, but then ignore it Instead map it to Mod5, which for some reason xkbcommon doesn't expose a define for Also, since the Qt modifiers enum doesn't map nicely to XKB modifiers introduce our own enum to avoid confusion CCBUG: 444335
This commit is contained in:
parent
18535ea959
commit
463d77ec18
4 changed files with 76 additions and 45 deletions
|
@ -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<KWin::Window *>();
|
||||
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<int>("modifierKey");
|
||||
QTest::addColumn<int>("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<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> 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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
49
src/xkb.cpp
49
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<sizeof(xkb_mod_mask_t) * 8> 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<sizeof(xkb_mod_mask_t) * 8> mask{m_modifierState.locked};
|
||||
|
|
17
src/xkb.h
17
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;
|
||||
|
|
Loading…
Reference in a new issue