diff --git a/src/lib/deskflow/IKeyState.h b/src/lib/deskflow/IKeyState.h index fd5e14584..b618963da 100644 --- a/src/lib/deskflow/IKeyState.h +++ b/src/lib/deskflow/IKeyState.h @@ -103,6 +103,16 @@ public: */ virtual void fakeAllKeysUp() = 0; + //! Clear stale modifiers + /*! + Clears stuck modifier state in platform-specific keyboard tracking (e.g. XKB). + Default implementation does nothing. + */ + virtual void clearStaleModifiers() + { + // Default implementation does nothing + } + //! Fake ctrl+alt+del /*! Synthesize a press of ctrl+alt+del. Return true if processing is diff --git a/src/lib/deskflow/IPlatformScreen.h b/src/lib/deskflow/IPlatformScreen.h index c8a3cbda9..b9eb8ecf9 100644 --- a/src/lib/deskflow/IPlatformScreen.h +++ b/src/lib/deskflow/IPlatformScreen.h @@ -187,6 +187,7 @@ public: KeyModifierMask pollActiveModifiers() const override = 0; int32_t pollActiveGroup() const override = 0; void pollPressedKeys(KeyButtonSet &pressedKeys) const override = 0; + void clearStaleModifiers() override = 0; protected: //! Handle system event diff --git a/src/lib/deskflow/KeyState.cpp b/src/lib/deskflow/KeyState.cpp index 0c12ef145..d92407602 100644 --- a/src/lib/deskflow/KeyState.cpp +++ b/src/lib/deskflow/KeyState.cpp @@ -760,6 +760,7 @@ void KeyState::updateKeyState() } // get the current modifier state + clearStaleModifiers(); m_mask = pollActiveModifiers(); // set active modifiers diff --git a/src/lib/deskflow/PlatformScreen.cpp b/src/lib/deskflow/PlatformScreen.cpp index cfa8a4be6..7ed5d3a30 100644 --- a/src/lib/deskflow/PlatformScreen.cpp +++ b/src/lib/deskflow/PlatformScreen.cpp @@ -85,6 +85,11 @@ void PlatformScreen::pollPressedKeys(KeyButtonSet &pressedKeys) const getKeyState()->pollPressedKeys(pressedKeys); } +void PlatformScreen::clearStaleModifiers() +{ + getKeyState()->clearStaleModifiers(); +} + int32_t PlatformScreen::mapClientScrollDirection(int32_t x) const { return (m_invertScrollDirection ? -x : x); diff --git a/src/lib/deskflow/PlatformScreen.h b/src/lib/deskflow/PlatformScreen.h index 1b7998169..6e7bb2d0c 100644 --- a/src/lib/deskflow/PlatformScreen.h +++ b/src/lib/deskflow/PlatformScreen.h @@ -62,6 +62,7 @@ public: KeyModifierMask pollActiveModifiers() const override; int32_t pollActiveGroup() const override; void pollPressedKeys(KeyButtonSet &pressedKeys) const override; + void clearStaleModifiers() override; // IPlatformScreen overrides void enable() override = 0; diff --git a/src/lib/platform/EiKeyState.cpp b/src/lib/platform/EiKeyState.cpp index 6f98451a1..60c484d5f 100644 --- a/src/lib/platform/EiKeyState.cpp +++ b/src/lib/platform/EiKeyState.cpp @@ -309,4 +309,13 @@ void EiKeyState::updateXkbState(uint32_t keyval, bool isPressed) xkb_state_update_key(m_xkbState, keyval, isPressed ? XKB_KEY_DOWN : XKB_KEY_UP); } +void EiKeyState::clearStaleModifiers() +{ + // Recreate the XKB state to clear stuck modifiers that happen when + // modifier keys are press on client and released on server + if (m_xkbState) { + xkb_state_unref(m_xkbState); + } + m_xkbState = xkb_state_new(m_xkbKeymap); +} } // namespace deskflow diff --git a/src/lib/platform/EiKeyState.h b/src/lib/platform/EiKeyState.h index 3e9d9571d..a958a7372 100644 --- a/src/lib/platform/EiKeyState.h +++ b/src/lib/platform/EiKeyState.h @@ -35,6 +35,7 @@ public: void pollPressedKeys(KeyButtonSet &pressedKeys) const override; KeyID mapKeyFromKeyval(std::uint32_t keyval) const; void updateXkbState(std::uint32_t keyval, bool isPressed); + void clearStaleModifiers() override; protected: // KeyState overrides