diff --git a/ChangeLog b/ChangeLog index 23d4e3709..39150aaa0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ Bug fixes: - #7057 | #7058 Fix copy paste logic, when OS reported about clipboard update too late - #7055 Add secure input notification on Linux - #7052 Add secure input notification on Windows -- #7047 Fix prevent sleep option on Mac and Windows +- #7047 | #7060 Fix prevent sleep option on Mac and Windows Enhancements: - #6998 Remove functionality related to the screen saver synchronisation diff --git a/src/lib/platform/MSWindowsPowerManager.cpp b/src/lib/platform/MSWindowsPowerManager.cpp new file mode 100644 index 000000000..4d0b24eab --- /dev/null +++ b/src/lib/platform/MSWindowsPowerManager.cpp @@ -0,0 +1,37 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2021 Symless Ltd. + * Copyright (C) 2008 Volker Lanz (vl@fidra.de) + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "MSWindowsPowerManager.h" +#include "arch/win32/ArchMiscWindows.h" + +MSWindowsPowerManager::~MSWindowsPowerManager() +{ + enableSleep(); +} + +void MSWindowsPowerManager::disableSleep() +{ + ArchMiscWindows::addBusyState(ArchMiscWindows::kSYSTEM); + ArchMiscWindows::addBusyState(ArchMiscWindows::kDISPLAY); +} + +void MSWindowsPowerManager::enableSleep() +{ + // allow the system to enter power saving mode + ArchMiscWindows::removeBusyState(ArchMiscWindows::kSYSTEM); + ArchMiscWindows::removeBusyState(ArchMiscWindows::kDISPLAY); +} diff --git a/src/lib/platform/MSWindowsPowerManager.h b/src/lib/platform/MSWindowsPowerManager.h new file mode 100644 index 000000000..42eaa9ede --- /dev/null +++ b/src/lib/platform/MSWindowsPowerManager.h @@ -0,0 +1,38 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2021 Symless Ltd. + * Copyright (C) 2008 Volker Lanz (vl@fidra.de) + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef MSWINDOWSPOWERMANAGER_H +#define MSWINDOWSPOWERMANAGER_H + + +class MSWindowsPowerManager +{ +public: + ~MSWindowsPowerManager(); + + /** + * @brief Prevents the system from sleep automatically + */ + void disableSleep(); + + /** + * @brief Enable automatically sleeping + */ + void enableSleep(); +}; + +#endif // MSWINDOWSPOWERMANAGER_H diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index ac1ca8be3..f630c65d5 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -164,6 +164,10 @@ MSWindowsScreen::MSWindowsScreen( LOG((CLOG_ERR "failed to get desktop path, no drop target available, error=%d", GetLastError())); } + if (App::instance().argsBase().m_preventSleep) { + m_powerManager.disableSleep(); + } + OleInitialize(0); m_dropWindow = createDropWindow(m_class, "DropWindow"); m_dropTarget = new MSWindowsDropTarget(); @@ -248,11 +252,6 @@ MSWindowsScreen::enable() // watch jump zones m_hook.setMode(kHOOK_WATCH_JUMP_ZONE); } - - if (App::instance().argsBase().m_preventSleep) { - ArchMiscWindows::addBusyState(ArchMiscWindows::kSYSTEM); - ArchMiscWindows::addBusyState(ArchMiscWindows::kDISPLAY); - } } void @@ -268,11 +267,6 @@ MSWindowsScreen::disable() // enable special key sequences on win95 family enableSpecialKeys(true); } - else { - // allow the system to enter power saving mode - ArchMiscWindows::removeBusyState(ArchMiscWindows::kSYSTEM); - ArchMiscWindows::removeBusyState(ArchMiscWindows::kDISPLAY); - } // tell key state m_keyState->disable(); @@ -2086,4 +2080,4 @@ MSWindowsScreen::updateScrollDirection() }); scrollDirectionUpdateThread.detach(); } -} \ No newline at end of file +} diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index d72889cfa..dbab41285 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -19,6 +19,7 @@ #pragma once #include "platform/MSWindowsHook.h" +#include "platform/MSWindowsPowerManager.h" #include "synergy/PlatformScreen.h" #include "synergy/DragInformation.h" #include "platform/synwinhk.h" @@ -374,4 +375,5 @@ private: // -1 for natural scrolling direction, 1 otherwise SInt32 m_scrollDirectionMouse = 1; SInt32 m_scrollDirectionTouchpad = 1; + MSWindowsPowerManager m_powerManager; }; diff --git a/src/lib/platform/OSXPowerManager.cpp b/src/lib/platform/OSXPowerManager.cpp new file mode 100644 index 000000000..734b2a81d --- /dev/null +++ b/src/lib/platform/OSXPowerManager.cpp @@ -0,0 +1,50 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2021 Symless Ltd. + * Copyright (C) 2008 Volker Lanz (vl@fidra.de) + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "OSXPowerManager.h" +#include "base/Log.h" + +OSXPowerManager::OSXPowerManager() +{ +} + +OSXPowerManager::~OSXPowerManager() +{ + enableSleep(); +} + +void OSXPowerManager::disableSleep() +{ + if (!m_sleepPreventionAssertionID) { + CFStringRef reasonForActivity = CFSTR("Synergy application"); + IOReturn result = IOPMAssertionCreateWithName(kIOPMAssertPreventUserIdleDisplaySleep, + kIOPMAssertionLevelOn, reasonForActivity, + &m_sleepPreventionAssertionID); + if (result != kIOReturnSuccess) { + m_sleepPreventionAssertionID = 0; + LOG((CLOG_ERR "failed to disable system idle sleep")); + } + } +} + +void OSXPowerManager::enableSleep() +{ + if (m_sleepPreventionAssertionID) { + IOPMAssertionRelease(m_sleepPreventionAssertionID); + } +} diff --git a/src/lib/platform/OSXPowerManager.h b/src/lib/platform/OSXPowerManager.h new file mode 100644 index 000000000..0babc1dc3 --- /dev/null +++ b/src/lib/platform/OSXPowerManager.h @@ -0,0 +1,48 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2021 Symless Ltd. + * Copyright (C) 2008 Volker Lanz (vl@fidra.de) + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef OSXPOWERMANAGER_H +#define OSXPOWERMANAGER_H + +#include + +class OSXPowerManager +{ +public: + OSXPowerManager(); + ~OSXPowerManager(); + + /** + * @brief Prevents the system from sleep automatically + */ + void disableSleep(); + + /** + * @brief Enable automatically sleeping + */ + void enableSleep(); + + OSXPowerManager(const OSXPowerManager&) = delete; + OSXPowerManager& operator=(const OSXPowerManager&) = delete; + +private: + // handler for assertion preventing the system from going to sleep + IOPMAssertionID m_sleepPreventionAssertionID = 0; +}; + +#endif // OSXPOWERMANAGER_H diff --git a/src/lib/platform/OSXScreen.h b/src/lib/platform/OSXScreen.h index 62af60833..6756cfb85 100644 --- a/src/lib/platform/OSXScreen.h +++ b/src/lib/platform/OSXScreen.h @@ -19,6 +19,7 @@ #pragma once #include "platform/OSXClipboard.h" +#include "platform/OSXPowerManager.h" #include "synergy/PlatformScreen.h" #include "synergy/DragInformation.h" #include "base/EventTypes.h" @@ -30,7 +31,6 @@ #include #include #include -#include #include extern "C" { @@ -347,8 +347,7 @@ private: CondVar* m_carbonLoopReady; #endif - // handler for assertion preventing the system from going to sleep - IOPMAssertionID m_sleepPreventionAssertionID = 0; + OSXPowerManager m_powerManager; class OSXScreenImpl* m_impl; }; diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm index 0bf2731bc..b08c6ee66 100644 --- a/src/lib/platform/OSXScreen.mm +++ b/src/lib/platform/OSXScreen.mm @@ -119,7 +119,11 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso try { m_screensaver = new OSXScreenSaver(m_events, getEventTarget()); m_keyState = new OSXKeyState(m_events); - + + if (App::instance().argsBase().m_preventSleep) { + m_powerManager.disableSleep(); + } + // only needed when running as a server. if (m_isPrimary) { @@ -175,7 +179,7 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso if (m_switchEventHandlerRef != 0) { RemoveEventHandler(m_switchEventHandlerRef); } - + CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this); delete m_keyState; @@ -195,6 +199,7 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso OSXScreen::~OSXScreen() { disable(); + m_events->adoptBuffer(NULL); m_events->removeHandler(Event::kSystem, m_events->getSystemTarget()); @@ -754,18 +759,6 @@ OSXScreen::hideCursor() void OSXScreen::enable() { - if(App::instance().argsBase().m_preventSleep) { - CFStringRef reasonForActivity = CFSTR("Synergy application"); - - IOReturn result = IOPMAssertionCreateWithName(kIOPMAssertPreventUserIdleDisplaySleep, - kIOPMAssertionLevelOn, reasonForActivity, - &m_sleepPreventionAssertionID); - if(result != kIOReturnSuccess) { - m_sleepPreventionAssertionID = 0; - LOG((CLOG_ERR "failed to disable system idle sleep")); - } - } - // watch the clipboard m_clipboardTimer = m_events->newTimer(1.0, NULL); m_events->adoptHandler(Event::kTimer, m_clipboardTimer, @@ -815,10 +808,6 @@ OSXScreen::enable() void OSXScreen::disable() { - if(App::instance().argsBase().m_preventSleep && m_sleepPreventionAssertionID) { - IOPMAssertionRelease(m_sleepPreventionAssertionID); - } - if (m_autoShowHideCursor) { showCursor(); } diff --git a/src/lib/platform/XWindowsPowerManager.cpp b/src/lib/platform/XWindowsPowerManager.cpp new file mode 100644 index 000000000..49be4e8b4 --- /dev/null +++ b/src/lib/platform/XWindowsPowerManager.cpp @@ -0,0 +1,60 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2002 Chris Schoeneman + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "XWindowsPowerManager.h" +#include "arch/Arch.h" +#include "base/Log.h" + +namespace{ + +bool sleepInhibitCall(bool state, ArchSystemUnix::InhibitScreenServices serviceID) +{ + std::string error; + + if (!ArchSystemUnix::DBusInhibitScreenCall(serviceID, state, error)) + { + LOG((CLOG_DEBUG "DBus inhibit error %s", error.c_str())); + return false; + } + + return true; +} + +} + +XWindowsPowerManager::~XWindowsPowerManager() +{ + enableSleep(); +} + +void XWindowsPowerManager::disableSleep() const +{ + if (!sleepInhibitCall(true, ArchSystemUnix::InhibitScreenServices::kScreenSaver) && + !sleepInhibitCall(true, ArchSystemUnix::InhibitScreenServices::kSessionManager)) + { + LOG((CLOG_INFO "Failed to prevent system from going to sleep")); + } +} + +void XWindowsPowerManager::enableSleep() const +{ + if (!sleepInhibitCall(false, ArchSystemUnix::InhibitScreenServices::kScreenSaver) && + !sleepInhibitCall(false, ArchSystemUnix::InhibitScreenServices::kSessionManager)) + { + LOG((CLOG_INFO "Failed to enable system idle sleep")); + } +} diff --git a/src/lib/platform/XWindowsPowerManager.h b/src/lib/platform/XWindowsPowerManager.h new file mode 100644 index 000000000..dc03af6e5 --- /dev/null +++ b/src/lib/platform/XWindowsPowerManager.h @@ -0,0 +1,42 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2002 Chris Schoeneman + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef XWINDOWSPOWERMANAGER_H +#define XWINDOWSPOWERMANAGER_H + + +class XWindowsPowerManager +{ +public: + XWindowsPowerManager() = default; + ~XWindowsPowerManager(); + + /** + * @brief Prevent the system from sleep + */ + void disableSleep() const; + + /** + * @brief Enables automatical sleep + */ + void enableSleep() const; + + XWindowsPowerManager(const XWindowsPowerManager&) = delete; + XWindowsPowerManager& operator=(const XWindowsPowerManager&) = delete; +}; + +#endif // XWINDOWSPOWERMANAGER_H diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index bf2472d66..a6d1f04e7 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -182,6 +182,11 @@ XWindowsScreen::XWindowsScreen( XTestGrabControl(m_display, True); } + // disable sleep if the flag is set + if (App::instance().argsBase().m_preventSleep) { + m_powerManager.disableSleep(); + } + // initialize the clipboards for (ClipboardID id = 0; id < kClipboardEnd; ++id) { m_clipboard[id] = new XWindowsClipboard(m_display, m_window, id); @@ -247,12 +252,6 @@ XWindowsScreen::enable() // warp the mouse to the cursor center fakeMouseMove(m_xCenter, m_yCenter); } - - // disable sleep if the flag is set - if (App::instance().argsBase().m_preventSleep && - !disableIdleSleep()) { - LOG((CLOG_INFO "Failed to prevent system from going to sleep")); - } } void @@ -271,12 +270,6 @@ XWindowsScreen::disable() if (!m_isPrimary && m_autoRepeat) { //XAutoRepeatOn(m_display); } - - // enable sleep when the display is disabled - if (App::instance().argsBase().m_preventSleep && - !enableIdleSleep()) { - LOG((CLOG_INFO "Failed to enable system idle sleep")); - } } void @@ -2201,25 +2194,3 @@ XWindowsScreen::updateScrollDirection() } } -bool XWindowsScreen::sleepInhibitCall(bool state, ArchSystemUnix::InhibitScreenServices serviceID) -{ - std::string error; - if(!ArchSystemUnix::DBusInhibitScreenCall(serviceID, state, error)) - { - LOG((CLOG_DEBUG "DBus inhibit error %s", error.c_str())); - return false; - } - return true; -} - -bool XWindowsScreen::disableIdleSleep() -{ - return sleepInhibitCall(true, ArchSystemUnix::InhibitScreenServices::kScreenSaver) || - sleepInhibitCall(true, ArchSystemUnix::InhibitScreenServices::kSessionManager); -} - -bool XWindowsScreen::enableIdleSleep() -{ - return sleepInhibitCall(false, ArchSystemUnix::InhibitScreenServices::kScreenSaver) || - sleepInhibitCall(false, ArchSystemUnix::InhibitScreenServices::kSessionManager); -} diff --git a/src/lib/platform/XWindowsScreen.h b/src/lib/platform/XWindowsScreen.h index 9e1c4e8c6..b674b708d 100644 --- a/src/lib/platform/XWindowsScreen.h +++ b/src/lib/platform/XWindowsScreen.h @@ -23,6 +23,7 @@ #include "synergy/KeyMap.h" #include "common/stdset.h" #include "common/stdvector.h" +#include "platform/XWindowsPowerManager.h" #if X_DISPLAY_MISSING # error X11 is required to build synergy @@ -118,11 +119,6 @@ private: void onError(); static int ioErrorHandler(Display*); - // sleep management - static bool sleepInhibitCall(bool state, ArchSystemUnix::InhibitScreenServices serviceID); - static bool disableIdleSleep(); - static bool enableIdleSleep(); - private: class KeyEventFilter { public: @@ -263,4 +259,5 @@ private: // -1 for natural scrolling direction, 1 otherwise SInt32 m_scrollDirectionMouse = 1; SInt32 m_scrollDirectionTouchpad = 1; + XWindowsPowerManager m_powerManager; };