plugins/stickykeys: Disable when two keys are pressed
BUG: 464453
This commit is contained in:
parent
7d3f58d0ca
commit
e3ad1fa04f
3 changed files with 91 additions and 0 deletions
|
@ -37,12 +37,14 @@ private Q_SLOTS:
|
|||
void testStick_data();
|
||||
void testLock();
|
||||
void testLock_data();
|
||||
void testDisableTwoKeys();
|
||||
};
|
||||
|
||||
void StickyKeysTest::initTestCase()
|
||||
{
|
||||
KConfig kaccessConfig("kaccessrc");
|
||||
kaccessConfig.group(QStringLiteral("Keyboard")).writeEntry("StickyKeys", true);
|
||||
kaccessConfig.group(QStringLiteral("Keyboard")).writeEntry("StickyKeysAutoOff", true);
|
||||
kaccessConfig.sync();
|
||||
|
||||
// Use a keyboard layout where right alt triggers Mod5/AltGr
|
||||
|
@ -217,6 +219,69 @@ void StickyKeysTest::testLock()
|
|||
|
||||
Test::keyboardKeyReleased(modifierKey, ++timestamp);
|
||||
}
|
||||
|
||||
void StickyKeysTest::testDisableTwoKeys()
|
||||
{
|
||||
std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
QVERIFY(surface != nullptr);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
QVERIFY(shellSurface != nullptr);
|
||||
Window *waylandWindow = Test::renderAndWaitForShown(surface.get(), QSize(10, 10), Qt::blue);
|
||||
QVERIFY(waylandWindow);
|
||||
|
||||
QSignalSpy modifierSpy(keyboard.get(), &KWayland::Client::Keyboard::modifiersChanged);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
modifierSpy.clear();
|
||||
|
||||
quint32 timestamp = 0;
|
||||
|
||||
// press mod to latch it
|
||||
Test::keyboardKeyPressed(KEY_LEFTSHIFT, ++timestamp);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
// arguments are: quint32 depressed, quint32 latched, quint32 locked, quint32 group
|
||||
QCOMPARE(modifierSpy.first()[0], 1); // verify that mod is depressed
|
||||
QCOMPARE(modifierSpy.first()[1], 1); // verify that mod is latched
|
||||
modifierSpy.clear();
|
||||
|
||||
// press key while modifier is pressed, this disables sticky keys
|
||||
Test::keyboardKeyPressed(KEY_A, ++timestamp);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
QCOMPARE(modifierSpy.first()[0], 1); // verify that mod is depressed
|
||||
QCOMPARE(modifierSpy.first()[1], 0); // verify that mod is not latched any more
|
||||
modifierSpy.clear();
|
||||
|
||||
Test::keyboardKeyReleased(KEY_A, ++timestamp);
|
||||
|
||||
// release mod, the modifier should not be depressed or latched
|
||||
Test::keyboardKeyReleased(KEY_LEFTSHIFT, ++timestamp);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
QCOMPARE(modifierSpy.first()[0], 0); // verify that mod is not depressed
|
||||
QCOMPARE(modifierSpy.first()[1], 0); // verify that mod is not latched
|
||||
modifierSpy.clear();
|
||||
|
||||
// verify that sticky keys are not enabled any more
|
||||
|
||||
// press mod, should be depressed but not latched
|
||||
Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
QCOMPARE(modifierSpy.first()[0], 4); // verify that mod is depressed
|
||||
QCOMPARE(modifierSpy.first()[1], 0); // verify that mod is not latched
|
||||
modifierSpy.clear();
|
||||
|
||||
// release mod, should not be depressed any more
|
||||
Test::keyboardKeyReleased(KEY_LEFTCTRL, ++timestamp);
|
||||
QVERIFY(modifierSpy.wait());
|
||||
QCOMPARE(modifierSpy.first()[0], 0); // verify that mod is not depressed
|
||||
QCOMPARE(modifierSpy.first()[1], 0); // verify that mod is not latched
|
||||
modifierSpy.clear();
|
||||
|
||||
Test::keyboardKeyPressed(KEY_A, ++timestamp);
|
||||
QVERIFY(!modifierSpy.wait(10));
|
||||
Test::keyboardKeyReleased(KEY_A, ++timestamp);
|
||||
QVERIFY(!modifierSpy.wait(10));
|
||||
}
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(KWin::StickyKeysTest)
|
||||
|
|
|
@ -66,6 +66,7 @@ void StickyKeysFilter::loadConfig(const KConfigGroup &group)
|
|||
|
||||
m_lockKeys = group.readEntry<bool>("StickyKeysLatch", true);
|
||||
m_showNotificationForLockedKeys = group.readEntry<bool>("kNotifyModifiers", false);
|
||||
m_disableOnTwoKeys = group.readEntry<bool>("StickyKeysAutoOff", false);
|
||||
|
||||
if (!m_lockKeys) {
|
||||
// locking keys is deactivated, unlock all locked keys
|
||||
|
@ -96,6 +97,12 @@ bool StickyKeysFilter::keyEvent(KWin::KeyEvent *event)
|
|||
{
|
||||
if (m_modifiers.contains(event->key())) {
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
m_pressedModifiers << event->key();
|
||||
} else {
|
||||
m_pressedModifiers.remove(event->key());
|
||||
}
|
||||
|
||||
auto keyState = m_keyStates.find(event->key());
|
||||
|
||||
if (keyState != m_keyStates.end()) {
|
||||
|
@ -135,6 +142,11 @@ bool StickyKeysFilter::keyEvent(KWin::KeyEvent *event)
|
|||
}
|
||||
}
|
||||
} else if (event->type() == QKeyEvent::KeyPress) {
|
||||
|
||||
if (!m_pressedModifiers.isEmpty() && m_disableOnTwoKeys) {
|
||||
disableStickyKeys();
|
||||
}
|
||||
|
||||
// a non-modifier key was pressed, unlatch all unlocked modifiers
|
||||
for (auto it = m_keyStates.keyValueBegin(); it != m_keyStates.keyValueEnd(); ++it) {
|
||||
|
||||
|
@ -151,4 +163,15 @@ bool StickyKeysFilter::keyEvent(KWin::KeyEvent *event)
|
|||
return false;
|
||||
}
|
||||
|
||||
void StickyKeysFilter::disableStickyKeys()
|
||||
{
|
||||
for (auto it = m_keyStates.keyValueBegin(); it != m_keyStates.keyValueEnd(); ++it) {
|
||||
it->second = KeyState::None;
|
||||
KWin::input()->keyboard()->xkb()->setModifierLatched(keyToModifier(static_cast<Qt::Key>(it->first)), false);
|
||||
KWin::input()->keyboard()->xkb()->setModifierLocked(keyToModifier(static_cast<Qt::Key>(it->first)), false);
|
||||
}
|
||||
|
||||
KWin::input()->uninstallInputEventFilter(this);
|
||||
}
|
||||
|
||||
#include "moc_stickykeys.cpp"
|
||||
|
|
|
@ -27,10 +27,13 @@ public:
|
|||
|
||||
private:
|
||||
void loadConfig(const KConfigGroup &group);
|
||||
void disableStickyKeys();
|
||||
|
||||
KConfigWatcher::Ptr m_configWatcher;
|
||||
QMap<int, KeyState> m_keyStates;
|
||||
QList<int> m_modifiers = {Qt::Key_Shift, Qt::Key_Control, Qt::Key_Alt, Qt::Key_AltGr, Qt::Key_Meta};
|
||||
bool m_lockKeys = false;
|
||||
bool m_showNotificationForLockedKeys = false;
|
||||
bool m_disableOnTwoKeys = false;
|
||||
QSet<int> m_pressedModifiers;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue