fix(wayland): sync locked modifiers from EI keyboard modifiers event
fixes: #8437
This commit is contained in:
parent
23b0d7792d
commit
ac475f0b1b
5 changed files with 50 additions and 1 deletions
|
|
@ -345,6 +345,20 @@ void EiKeyState::updateXkbState(uint32_t keyval, bool isPressed)
|
||||||
xkb_state_update_key(m_xkbState, keyval, isPressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
xkb_state_update_key(m_xkbState, keyval, isPressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EiKeyState::updateLockedModifiers(xkb_mod_mask_t lockedMods)
|
||||||
|
{
|
||||||
|
// The compositor's lock state (Caps/Num/Scroll Lock) is authoritative; it
|
||||||
|
// also covers locks toggled while we weren't seeing the key events.
|
||||||
|
const auto depressedMods = xkb_state_serialize_mods(m_xkbState, XKB_STATE_MODS_DEPRESSED);
|
||||||
|
const auto latchedMods = xkb_state_serialize_mods(m_xkbState, XKB_STATE_MODS_LATCHED);
|
||||||
|
const auto depressedLayout = xkb_state_serialize_layout(m_xkbState, XKB_STATE_LAYOUT_DEPRESSED);
|
||||||
|
const auto latchedLayout = xkb_state_serialize_layout(m_xkbState, XKB_STATE_LAYOUT_LATCHED);
|
||||||
|
const auto lockedLayout = xkb_state_serialize_layout(m_xkbState, XKB_STATE_LAYOUT_LOCKED);
|
||||||
|
xkb_state_update_mask(
|
||||||
|
m_xkbState, depressedMods, latchedMods, lockedMods, depressedLayout, latchedLayout, lockedLayout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void EiKeyState::clearStaleModifiers()
|
void EiKeyState::clearStaleModifiers()
|
||||||
{
|
{
|
||||||
const auto lockedMods = xkb_state_serialize_mods(m_xkbState, XKB_STATE_MODS_LOCKED);
|
const auto lockedMods = xkb_state_serialize_mods(m_xkbState, XKB_STATE_MODS_LOCKED);
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ public:
|
||||||
void pollPressedKeys(KeyButtonSet &pressedKeys) const override;
|
void pollPressedKeys(KeyButtonSet &pressedKeys) const override;
|
||||||
KeyID mapKeyFromKeyval(std::uint32_t keyval) const;
|
KeyID mapKeyFromKeyval(std::uint32_t keyval) const;
|
||||||
void updateXkbState(std::uint32_t keyval, bool isPressed);
|
void updateXkbState(std::uint32_t keyval, bool isPressed);
|
||||||
|
void updateLockedModifiers(xkb_mod_mask_t lockedMods);
|
||||||
void clearStaleModifiers() override;
|
void clearStaleModifiers() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -1025,7 +1025,8 @@ void EiScreen::handleSystemEvent(const Event &)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EI_EVENT_KEYBOARD_MODIFIERS:
|
case EI_EVENT_KEYBOARD_MODIFIERS:
|
||||||
// FIXME
|
LOG_VERBOSE("event: keyboard modifiers locked=0x%x", ei_event_keyboard_get_xkb_mods_locked(event));
|
||||||
|
m_keyState->updateLockedModifiers(ei_event_keyboard_get_xkb_mods_locked(event));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// events below are for a receiver context (barriers)
|
// events below are for a receiver context (barriers)
|
||||||
|
|
|
||||||
|
|
@ -102,4 +102,36 @@ void EiKeyStateTests::clearStaleModifiers_shiftDownAndNumLockOn_shiftClearedAndN
|
||||||
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) != 0);
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EiKeyStateTests::updateLockedModifiers_compositorLockState_numLockFollowsCompositor()
|
||||||
|
{
|
||||||
|
// Real modifier Mod2 is index 4 (Shift, Lock, Control, Mod1, Mod2, ...).
|
||||||
|
constexpr std::uint32_t xkbMod2Mask = 1 << 4;
|
||||||
|
|
||||||
|
TestAppUtil appUtil;
|
||||||
|
EventQueue eventQueue;
|
||||||
|
deskflow::EiKeyState keyState(nullptr, &eventQueue);
|
||||||
|
|
||||||
|
QTemporaryFile keymapFile;
|
||||||
|
QVERIFY(keymapFile.open());
|
||||||
|
const QByteArray keymapData = QByteArray::fromRawData(TestKeymap, sizeof(TestKeymap) - 1);
|
||||||
|
QCOMPARE(keymapFile.write(keymapData), keymapData.size());
|
||||||
|
QVERIFY(keymapFile.flush());
|
||||||
|
keyState.init(keymapFile.handle(), keymapFile.size());
|
||||||
|
|
||||||
|
keyState.updateXkbState(LeftShiftKeycode, true);
|
||||||
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) == 0);
|
||||||
|
|
||||||
|
// NumLock toggled on locally, reported by the compositor
|
||||||
|
keyState.updateLockedModifiers(xkbMod2Mask);
|
||||||
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) != 0);
|
||||||
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierShift) != 0);
|
||||||
|
|
||||||
|
keyState.clearStaleModifiers();
|
||||||
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) != 0);
|
||||||
|
|
||||||
|
// NumLock toggled off locally
|
||||||
|
keyState.updateLockedModifiers(0);
|
||||||
|
QVERIFY((keyState.pollActiveModifiers() & KeyModifierNumLock) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(EiKeyStateTests)
|
QTEST_MAIN(EiKeyStateTests)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class EiKeyStateTests : public QObject
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
void clearStaleModifiers_shiftDownAndNumLockOn_shiftClearedAndNumLockPreserved();
|
void clearStaleModifiers_shiftDownAndNumLockOn_shiftClearedAndNumLockPreserved();
|
||||||
|
void updateLockedModifiers_compositorLockState_numLockFollowsCompositor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Arch m_arch;
|
Arch m_arch;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue