From 835dc4ec2511f9e09581340af0c299d05c5a6fd6 Mon Sep 17 00:00:00 2001 From: pika Date: Mon, 16 Sep 2024 22:19:52 -0500 Subject: [PATCH] fix: gate leave() with canLeave(), allowing cleanup --- ChangeLog | 1 + src/lib/deskflow/IPlatformScreen.h | 13 ++++++++++--- src/lib/deskflow/PlatformScreen.h | 3 ++- src/lib/deskflow/Screen.cpp | 5 ++++- src/lib/platform/EiScreen.cpp | 5 +++-- src/lib/platform/EiScreen.h | 3 ++- src/lib/platform/MSWindowsScreen.cpp | 9 ++++++--- src/lib/platform/MSWindowsScreen.h | 3 ++- src/lib/platform/OSXScreen.h | 3 ++- src/lib/platform/OSXScreen.mm | 8 ++++++-- src/lib/platform/XWindowsScreen.cpp | 13 +++++++++---- src/lib/platform/XWindowsScreen.h | 3 ++- 12 files changed, 49 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index cde532e63..cc805cc2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Bug fixes: - #7522 Fix broken CI caused by renaming project to Deskflow - #7524 Restore protocol compatibility with Synergy - #7525 Remove Google Drive upload from CI +- #7520 Fix stuck keys on leave by separating check/leave logic Enhancements: diff --git a/src/lib/deskflow/IPlatformScreen.h b/src/lib/deskflow/IPlatformScreen.h index 600f661cb..dca999718 100644 --- a/src/lib/deskflow/IPlatformScreen.h +++ b/src/lib/deskflow/IPlatformScreen.h @@ -67,12 +67,19 @@ public: //! Leave screen /*! - Called when the user navigates off the screen. Returns true on - success, false on failure. A typical reason for failure is being + Called when the user navigates off the screen. Returns true if + the leave can proceed. A typical reason for failure is being unable to install the keyboard and mouse snoopers on a primary screen. Secondary screens should not fail. */ - virtual bool leave() = 0; + virtual bool canLeave() = 0; + + //! Leave screen + /*! + Called when the user navigates off the screen. Should be gated + by canLeave(). + */ + virtual void leave() = 0; //! Set clipboard /*! diff --git a/src/lib/deskflow/PlatformScreen.h b/src/lib/deskflow/PlatformScreen.h index 9f21ed34c..cf363b86f 100644 --- a/src/lib/deskflow/PlatformScreen.h +++ b/src/lib/deskflow/PlatformScreen.h @@ -88,7 +88,8 @@ public: virtual void enable() = 0; virtual void disable() = 0; virtual void enter() = 0; - virtual bool leave() = 0; + virtual bool canLeave() = 0; + virtual void leave() = 0; virtual bool setClipboard(ClipboardID, const IClipboard *) = 0; virtual void checkClipboards() = 0; virtual void openScreensaver(bool notify) = 0; diff --git a/src/lib/deskflow/Screen.cpp b/src/lib/deskflow/Screen.cpp index f8e6b104e..9a0f3f1d9 100644 --- a/src/lib/deskflow/Screen.cpp +++ b/src/lib/deskflow/Screen.cpp @@ -137,15 +137,18 @@ bool Screen::leave() { assert(m_entered == true); LOG((CLOG_INFO "leaving screen")); - if (!m_screen->leave()) { + if (!m_screen->canLeave()) { return false; } + if (m_isPrimary) { leavePrimary(); } else { leaveSecondary(); } + m_screen->leave(); + // make sure our idea of clipboard ownership is correct m_screen->checkClipboards(); diff --git a/src/lib/platform/EiScreen.cpp b/src/lib/platform/EiScreen.cpp index ac7eb029f..603aba007 100644 --- a/src/lib/platform/EiScreen.cpp +++ b/src/lib/platform/EiScreen.cpp @@ -345,7 +345,9 @@ void EiScreen::enter() { #endif } -bool EiScreen::leave() { +bool EiScreen::canLeave() { return true; } + +void EiScreen::leave() { if (!is_primary_) { if (ei_pointer_) { ei_device_stop_emulating(ei_pointer_); @@ -359,7 +361,6 @@ bool EiScreen::leave() { } is_on_screen_ = false; - return true; } bool EiScreen::setClipboard(ClipboardID id, const IClipboard *clipboard) { diff --git a/src/lib/platform/EiScreen.h b/src/lib/platform/EiScreen.h index 82ecaab92..08f88e787 100644 --- a/src/lib/platform/EiScreen.h +++ b/src/lib/platform/EiScreen.h @@ -77,7 +77,8 @@ public: void enable() override; void disable() override; void enter() override; - bool leave() override; + bool canLeave() override; + void leave() override; bool setClipboard(ClipboardID, const IClipboard *) override; void checkClipboards() override; void openScreensaver(bool notify) override; diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 6a2228fb0..9b5928059 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -308,7 +308,7 @@ void MSWindowsScreen::enter() { forceShowCursor(); } -bool MSWindowsScreen::leave() { +bool MSWindowsScreen::canLeave() { POINT pos; if (!getThisCursorPos(&pos)) { LOG((CLOG_DEBUG "unable to leave screen as windows security has disabled " @@ -317,6 +317,11 @@ bool MSWindowsScreen::leave() { // leaves the screen return false; } + + return true; +} + +void MSWindowsScreen::leave() { // get keyboard layout of foreground window. we'll use this // keyboard layout for translating keys sent to clients. m_keyLayout = AppUtilWindows::instance().getCurrentKeyboardLayout(); @@ -367,8 +372,6 @@ bool MSWindowsScreen::leave() { m_sendDragThread = new Thread(new TMethodJob( this, &MSWindowsScreen::sendDragThread)); } - - return true; } void MSWindowsScreen::sendDragThread(void *) { diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index a9421f2ba..423cafd1d 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -128,7 +128,8 @@ public: virtual void enable(); virtual void disable(); virtual void enter(); - virtual bool leave(); + virtual bool canLeave(); + virtual void leave(); virtual bool setClipboard(ClipboardID, const IClipboard *); virtual void checkClipboards(); virtual void openScreensaver(bool notify); diff --git a/src/lib/platform/OSXScreen.h b/src/lib/platform/OSXScreen.h index 5da3b651c..48c6066fe 100644 --- a/src/lib/platform/OSXScreen.h +++ b/src/lib/platform/OSXScreen.h @@ -91,7 +91,8 @@ public: void enable() override; void disable() override; void enter() override; - bool leave() override; + bool canLeave() override; + void leave() override; bool setClipboard(ClipboardID, const IClipboard *) override; void checkClipboards() override; void openScreensaver(bool notify) override; diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm index 840724cc5..7b74f8c80 100644 --- a/src/lib/platform/OSXScreen.mm +++ b/src/lib/platform/OSXScreen.mm @@ -883,6 +883,12 @@ OSXScreen::enter() } bool +OSXScreen::canLeave() +{ + return true; +} + +void OSXScreen::leave() { hideCursor(); @@ -920,8 +926,6 @@ OSXScreen::leave() // now off screen m_isOnScreen = false; - - return true; } bool diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index 595a59751..c9bf0283a 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -326,7 +326,15 @@ void XWindowsScreen::enter() { m_isOnScreen = true; } -bool XWindowsScreen::leave() { +bool XWindowsScreen::canLeave() { + // raise and show the window, required to grab mouse and keyboard + XMapRaised(m_display, m_window); + + // see if grabbing the mouse and keyboard, if primary, is possible + return !(m_isPrimary && !grabMouseAndKeyboard()); +} + +void XWindowsScreen::leave() { if (!m_isPrimary) { // restore the previous keyboard auto-repeat state. if the user // changed the auto-repeat configuration while on the client then @@ -347,7 +355,6 @@ bool XWindowsScreen::leave() { // grab the mouse and keyboard, if primary and possible if (m_isPrimary && !grabMouseAndKeyboard()) { XUnmapWindow(m_display, m_window); - return false; } // save current focus @@ -376,8 +383,6 @@ bool XWindowsScreen::leave() { // now off screen m_isOnScreen = false; - - return true; } bool XWindowsScreen::setClipboard(ClipboardID id, const IClipboard *clipboard) { diff --git a/src/lib/platform/XWindowsScreen.h b/src/lib/platform/XWindowsScreen.h index bd29d99da..ab4b7f4ec 100644 --- a/src/lib/platform/XWindowsScreen.h +++ b/src/lib/platform/XWindowsScreen.h @@ -79,7 +79,8 @@ public: void enable() override; void disable() override; void enter() override; - bool leave() override; + bool canLeave() override; + void leave() override; bool setClipboard(ClipboardID, const IClipboard *) override; void checkClipboards() override; void openScreensaver(bool notify) override;