diff --git a/src/lib/deskflow/IKeyState.h b/src/lib/deskflow/IKeyState.h index 210cb3d50..a8cad37a0 100644 --- a/src/lib/deskflow/IKeyState.h +++ b/src/lib/deskflow/IKeyState.h @@ -116,6 +116,16 @@ class IKeyState : public IInterface */ 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 4c66bbba0..1ca2ceea2 100644 --- a/src/lib/deskflow/IPlatformScreen.h +++ b/src/lib/deskflow/IPlatformScreen.h @@ -198,12 +198,13 @@ class IPlatformScreen : public IScreen, public IPrimaryScreen, public ISecondary virtual KeyModifierMask pollActiveModifiers() const = 0; virtual SInt32 pollActiveGroup() const = 0; virtual void pollPressedKeys(KeyButtonSet &pressedKeys) const = 0; + virtual void clearStaleModifiers() = 0; + // Drag-and-drop overrides virtual String &getDraggingFilename() = 0; virtual void clearDraggingFilename() = 0; virtual bool isDraggingStarted() = 0; virtual bool isFakeDraggingStarted() = 0; - virtual void fakeDraggingFiles(DragFileList fileList) = 0; virtual const String &getDropTarget() const = 0; diff --git a/src/lib/deskflow/KeyState.cpp b/src/lib/deskflow/KeyState.cpp index b3dc5d914..61062642a 100644 --- a/src/lib/deskflow/KeyState.cpp +++ b/src/lib/deskflow/KeyState.cpp @@ -770,6 +770,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 7046ce300..8a0b3f02b 100644 --- a/src/lib/deskflow/PlatformScreen.cpp +++ b/src/lib/deskflow/PlatformScreen.cpp @@ -99,6 +99,11 @@ void PlatformScreen::pollPressedKeys(KeyButtonSet &pressedKeys) const getKeyState()->pollPressedKeys(pressedKeys); } +void PlatformScreen::clearStaleModifiers() +{ + getKeyState()->clearStaleModifiers(); +} + bool PlatformScreen::isDraggingStarted() { if (App::instance().argsBase().m_enableDragDrop) { diff --git a/src/lib/deskflow/PlatformScreen.h b/src/lib/deskflow/PlatformScreen.h index 69e65ffeb..f267f74a6 100644 --- a/src/lib/deskflow/PlatformScreen.h +++ b/src/lib/deskflow/PlatformScreen.h @@ -74,6 +74,7 @@ class PlatformScreen : public IPlatformScreen virtual KeyModifierMask pollActiveModifiers() const; virtual SInt32 pollActiveGroup() const; virtual void pollPressedKeys(KeyButtonSet &pressedKeys) const; + virtual void clearStaleModifiers(); virtual void setDraggingStarted(bool started) { diff --git a/src/lib/platform/EiKeyState.cpp b/src/lib/platform/EiKeyState.cpp index b9a48a345..86deb1fd4 100644 --- a/src/lib/platform/EiKeyState.cpp +++ b/src/lib/platform/EiKeyState.cpp @@ -321,4 +321,13 @@ void EiKeyState::update_xkb_state(uint32_t keyval, bool is_pressed) xkb_state_update_key(xkb_state_, keyval, is_pressed ? 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 (xkb_state_) { + xkb_state_unref(xkb_state_); + } + xkb_state_ = xkb_state_new(xkb_keymap_); +} } // namespace deskflow diff --git a/src/lib/platform/EiKeyState.h b/src/lib/platform/EiKeyState.h index 0084ae0a0..9912f1871 100644 --- a/src/lib/platform/EiKeyState.h +++ b/src/lib/platform/EiKeyState.h @@ -46,6 +46,7 @@ class EiKeyState : public KeyState void pollPressedKeys(KeyButtonSet &pressedKeys) const override; KeyID map_key_from_keyval(std::uint32_t keyval) const; void update_xkb_state(std::uint32_t keyval, bool is_pressed); + void clearStaleModifiers() override; protected: // KeyState overrides