diff --git a/ChangeLog b/ChangeLog index 1c69b3c88..0586672d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Bug fixes: - #7006 Resolve code scanning issues - #7012 Fix natural horizontal scrolling on Mac client - #6997 Allow Windows to go to sleep depending on system preferences +- #7001 Add option to prevent computer from going to sleep Enhancements: - #6998 Remove functionality related to the screen saver synchronisation diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index c85840d5a..0a1caec7e 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -77,6 +77,7 @@ const char* AppConfig::m_SynergySettingsName[] = { "serverHostname", "tlsCertPath", "tlsKeyLength", + "preventSleep" }; static const char* logLevelNames[] = @@ -239,6 +240,7 @@ void AppConfig::loadSettings() m_UseInternalConfig = loadSetting(kUseInternalConfig, false).toBool(); m_ClientGroupChecked = loadSetting(kGroupClientCheck, false).toBool(); m_ServerHostname = loadSetting(kServerHostname).toString(); + m_PreventSleep = loadSetting(kPreventSleep, false).toBool(); //only change the serial key if the settings being loaded contains a key bool updateSerial = ConfigWriter::make() @@ -299,6 +301,7 @@ void AppConfig::saveSettings() setSetting(kUseInternalConfig, m_UseInternalConfig); setSetting(kGroupClientCheck, m_ClientGroupChecked); setSetting(kServerHostname, m_ServerHostname); + setSetting(kPreventSleep, m_PreventSleep); } m_unsavedChanges = false; @@ -454,6 +457,12 @@ void AppConfig::setLanguageSync(bool newValue) { setSettingModified(m_LanguageSync, newValue); } +bool AppConfig::getPreventSleep() const { return m_PreventSleep; } + +void AppConfig::setPreventSleep(bool newValue) { + setSettingModified(m_PreventSleep, newValue); +} + bool AppConfig::getMinimizeToTray() { return m_MinimizeToTray; } QString AppConfig::settingName(AppConfig::Setting name) { diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index b5d1dfa73..5ff9d2e34 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -114,6 +114,8 @@ class AppConfig: public QObject, public GUI::Config::ConfigBase bool getAutoHide(); void setLanguageSync(bool b); bool getLanguageSync() const; + void setPreventSleep(bool b); + bool getPreventSleep() const; #ifndef SYNERGY_ENTERPRISE bool activationHasRun() const; AppConfig& activationHasRun(bool value); @@ -202,6 +204,7 @@ protected: kServerHostname, kTLSCertPath, kTLSKeyLength, + kPreventSleep }; void setScreenName(const QString& s); @@ -245,6 +248,7 @@ protected: bool m_ActivationHasRun; bool m_MinimizeToTray; bool m_LanguageSync = true; + bool m_PreventSleep = false; bool m_ServerGroupChecked; bool m_UseExternalConfig; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 3166e5c7a..30067ba8f 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -675,6 +675,11 @@ void MainWindow::startSynergy() } #endif + if (m_AppConfig->getPreventSleep()) + { + args << "--prevent-sleep"; + } + // put a space between last log output and new instance. if (!m_pLogOutput->toPlainText().isEmpty()) appendLogRaw(""); diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 15f98449a..de71e57f3 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -64,6 +64,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : connect(m_pCheckBoxAutoConfig, SIGNAL(clicked()), this, SLOT(onChange())); connect(m_pCheckBoxMinimizeToTray, SIGNAL(clicked()), this, SLOT(onChange())); connect(m_pCheckBoxAutoHide, SIGNAL(clicked()), this, SLOT(onChange())); + connect(m_pCheckBoxPreventSleep, SIGNAL(clicked()), this, SLOT(onChange())); connect(m_pLineEditInterface, SIGNAL(textEdited(QString)), this, SLOT(onChange())); connect(m_pSpinBoxPort, SIGNAL(valueChanged(int)), this, SLOT(onChange())); connect(m_pLineEditScreenName, SIGNAL(textEdited(QString)), this, SLOT(onChange())); @@ -84,6 +85,7 @@ void SettingsDialog::accept() appConfig().setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString()); appConfig().setElevateMode(static_cast(m_pComboElevate->currentIndex())); appConfig().setAutoHide(m_pCheckBoxAutoHide->isChecked()); + appConfig().setPreventSleep(m_pCheckBoxPreventSleep->isChecked()); appConfig().setAutoConfig(m_pCheckBoxAutoConfig->isChecked()); appConfig().setMinimizeToTray(m_pCheckBoxMinimizeToTray->isChecked()); appConfig().setTLSCertPath(m_pLineEditCertificatePath->text()); @@ -142,6 +144,7 @@ void SettingsDialog::loadFromConfig() { m_pLineEditLogFilename->setText(appConfig().logFilename()); setIndexFromItemData(m_pComboLanguage, appConfig().language()); m_pCheckBoxAutoHide->setChecked(appConfig().getAutoHide()); + m_pCheckBoxPreventSleep->setChecked(appConfig().getPreventSleep()); m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); m_pLineEditCertificatePath->setText(appConfig().getTLSCertPath()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); @@ -329,6 +332,7 @@ bool SettingsDialog::isModified() || appConfig().language() != m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString() || appConfig().elevateMode() != static_cast(m_pComboElevate->currentIndex()) || appConfig().getAutoHide() != m_pCheckBoxAutoHide->isChecked() + || appConfig().getPreventSleep() != m_pCheckBoxPreventSleep->isChecked() || appConfig().autoConfig() != m_pCheckBoxAutoConfig->isChecked() || appConfig().getMinimizeToTray() != m_pCheckBoxMinimizeToTray->isChecked() || appConfig().getTLSCertPath() != m_pLineEditCertificatePath->text() @@ -347,6 +351,7 @@ void SettingsDialog::enableControls(bool enable) { m_pComboLanguage->setEnabled(enable); m_pComboElevate->setEnabled(enable); m_pCheckBoxAutoHide->setEnabled(enable); + m_pCheckBoxPreventSleep->setEnabled(enable); m_pCheckBoxAutoConfig->setEnabled(enable); m_pCheckBoxMinimizeToTray->setEnabled(enable); m_pLineEditCertificatePath->setEnabled(enable); diff --git a/src/gui/src/SettingsDialogBase.ui b/src/gui/src/SettingsDialogBase.ui index 0f571fea1..8ad704945 100644 --- a/src/gui/src/SettingsDialogBase.ui +++ b/src/gui/src/SettingsDialogBase.ui @@ -991,6 +991,13 @@ font-weight: bold; + + + + Stop this computer from sleeping + + + @@ -1001,6 +1008,7 @@ font-weight: bold; + diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 76cc46666..65b47d0e7 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -247,6 +247,10 @@ MSWindowsScreen::enable() // watch jump zones m_hook.setMode(kHOOK_WATCH_JUMP_ZONE); } + + if (App::instance().argsBase().m_preventSleep) { + ArchMiscWindows::addBusyState(ArchMiscWindows::kSYSTEM); + } } void @@ -262,6 +266,10 @@ MSWindowsScreen::disable() // enable special key sequences on win95 family enableSpecialKeys(true); } + else { + // allow the system to enter power saving mode + ArchMiscWindows::removeBusyState(ArchMiscWindows::kSYSTEM); + } // tell key state m_keyState->disable(); diff --git a/src/lib/platform/OSXScreen.h b/src/lib/platform/OSXScreen.h index 13da1368c..fcc0e20f8 100644 --- a/src/lib/platform/OSXScreen.h +++ b/src/lib/platform/OSXScreen.h @@ -348,5 +348,8 @@ private: CondVar* m_carbonLoopReady; #endif + // handler for assertion preventing the system from going to sleep + IOPMAssertionID m_sleepPreventionAssertionID = 0; + class OSXScreenImpl* m_impl; }; diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm index 583c5e2cb..bd3a69b06 100755 --- a/src/lib/platform/OSXScreen.mm +++ b/src/lib/platform/OSXScreen.mm @@ -749,6 +749,16 @@ OSXScreen::hideCursor() void OSXScreen::enable() { + if(App::instance().argsBase().m_preventSleep) { + CFStringRef reasonForActivity = CFSTR("Synergy application"); + IOReturn result = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, + 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, @@ -798,6 +808,10 @@ 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/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index 222d96427..df97d2ad0 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -141,14 +141,14 @@ bool ArgParser::parsePlatformArg(lib::synergy::ArgsBase& argsBase, const int& argc, const char* const* argv, int& i) { #if WINAPI_MSWINDOWS - if (isArg(i, argc, argv, NULL, "--service")) { + if (isArg(i, argc, argv, nullptr, "--service")) { LOG((CLOG_WARN "obsolete argument --service, use synergyd instead.")); argsBase.m_shouldExit = true; } - else if (isArg(i, argc, argv, NULL, "--exit-pause")) { + else if (isArg(i, argc, argv, nullptr, "--exit-pause")) { argsBase.m_pauseOnExit = true; } - else if (isArg(i, argc, argv, NULL, "--stop-on-desk-switch")) { + else if (isArg(i, argc, argv, nullptr, "--stop-on-desk-switch")) { argsBase.m_stopOnDeskSwitch = true; } else { @@ -163,7 +163,7 @@ ArgParser::parsePlatformArg(lib::synergy::ArgsBase& argsBase, const int& argc, c argsBase.m_display = argv[++i]; } - else if (isArg(i, argc, argv, NULL, "--no-xinitthreads")) { + else if (isArg(i, argc, argv, nullptr, "--no-xinitthreads")) { argsBase.m_disableXInitThreads = true; } @@ -184,19 +184,19 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv) { // We support exactly one argument at a fix position static const int only_index {1}; - if (isArg(only_index, argc, argv, NULL, "--get-active-desktop", 0)) { + if (isArg(only_index, argc, argv, nullptr, "--get-active-desktop", 0)) { args.m_printActiveDesktopName = true; return true; } - else if (isArg(only_index, argc, argv, NULL, "--get-installed-dir", 0)) { + else if (isArg(only_index, argc, argv, nullptr, "--get-installed-dir", 0)) { args.m_getInstalledDir = true; return true; } - else if (isArg(only_index, argc, argv, NULL, "--get-profile-dir", 0)) { + else if (isArg(only_index, argc, argv, nullptr, "--get-profile-dir", 0)) { args.m_getProfileDir = true; return true; } - else if (isArg(only_index, argc, argv, NULL, "--get-arch", 0)) { + else if (isArg(only_index, argc, argv, nullptr, "--get-arch", 0)) { args.m_getArch = true; return true; } @@ -217,7 +217,7 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) // not a daemon argsBase().m_daemon = false; } - else if (isArg(i, argc, argv, NULL, "--daemon")) { + else if (isArg(i, argc, argv, nullptr, "--daemon")) { // daemonize argsBase().m_daemon = true; } @@ -229,11 +229,11 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) // don't try to restart argsBase().m_restartable = false; } - else if (isArg(i, argc, argv, NULL, "--restart")) { + else if (isArg(i, argc, argv, nullptr, "--restart")) { // try to restart argsBase().m_restartable = true; } - else if (isArg(i, argc, argv, NULL, "--no-hooks")) { + else if (isArg(i, argc, argv, nullptr, "--no-hooks")) { argsBase().m_noHooks = true; } else if (isArg(i, argc, argv, "-h", "--help")) { @@ -242,25 +242,25 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) } argsBase().m_shouldExit = true; } - else if (isArg(i, argc, argv, NULL, "--version")) { + else if (isArg(i, argc, argv, nullptr, "--version")) { if (m_app) { m_app->version(); } argsBase().m_shouldExit = true; } - else if (isArg(i, argc, argv, NULL, "--no-tray")) { + else if (isArg(i, argc, argv, nullptr, "--no-tray")) { argsBase().m_disableTray = true; } - else if (isArg(i, argc, argv, NULL, "--ipc")) { + else if (isArg(i, argc, argv, nullptr, "--ipc")) { argsBase().m_enableIpc = true; } - else if (isArg(i, argc, argv, NULL, "--server")) { + else if (isArg(i, argc, argv, nullptr, "--server")) { // HACK: stop error happening when using portable (synergyp) } - else if (isArg(i, argc, argv, NULL, "--client")) { + else if (isArg(i, argc, argv, nullptr, "--client")) { // HACK: stop error happening when using portable (synergyp) } - else if (isArg(i, argc, argv, NULL, "--enable-drag-drop")) { + else if (isArg(i, argc, argv, nullptr, "--enable-drag-drop")) { bool useDragDrop = true; #ifdef WINAPI_XWINDOWS @@ -282,18 +282,21 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) argsBase().m_enableDragDrop = true; } } - else if (isArg(i, argc, argv, NULL, "--enable-crypto")) { + else if (isArg(i, argc, argv, nullptr, "--enable-crypto")) { argsBase().m_enableCrypto = true; } - else if (isArg(i, argc, argv, NULL, "--profile-dir", 1)) { + else if (isArg(i, argc, argv, nullptr, "--profile-dir", 1)) { argsBase().m_profileDirectory = argv[++i]; } - else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { + else if (isArg(i, argc, argv, nullptr, "--plugin-dir", 1)) { argsBase().m_pluginDirectory = argv[++i]; } - else if (isArg(i, argc, argv, NULL, "--tls-cert", 1)) { + else if (isArg(i, argc, argv, nullptr, "--tls-cert", 1)) { argsBase().m_tlsCertFile = argv[++i]; } + else if (isArg(i, argc, argv, nullptr, "--prevent-sleep")) { + argsBase().m_preventSleep = true; + } else { // option not supported here return false; @@ -305,30 +308,20 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) bool ArgParser::parseDeprecatedArgs(int argc, const char* const* argv, int& i) { - if (isArg(i, argc, argv, NULL, "--crypto-pass")) { - LOG((CLOG_NOTE "--crypto-pass is deprecated")); - i++; - return true; - } - else if (isArg(i, argc, argv, NULL, "--res-w")) { - LOG((CLOG_NOTE "--res-w is deprecated")); - i++; - return true; - } - else if (isArg(i, argc, argv, NULL, "--res-h")) { - LOG((CLOG_NOTE "--res-h is deprecated")); - i++; - return true; - } - else if (isArg(i, argc, argv, NULL, "--prm-wc")) { - LOG((CLOG_NOTE "--prm-wc is deprecated")); - i++; - return true; - } - else if (isArg(i, argc, argv, NULL, "--prm-hc")) { - LOG((CLOG_NOTE "--prm-hc is deprecated")); - i++; - return true; + static const std::vector deprecatedArgs = { + "--crypto-pass", + "--res-w", + "--res-h", + "--prm-wc", + "--prm-hc" + }; + + for (auto& arg : deprecatedArgs) { + if (isArg(i, argc, argv, nullptr, arg)) { + LOG((CLOG_NOTE "%s is deprecated", arg)); + i++; + return true; + } } return false; @@ -340,8 +333,8 @@ ArgParser::isArg( const char* name1, const char* name2, int minRequiredParameters) { - if ((name1 != NULL && strcmp(argv[argi], name1) == 0) || - (name2 != NULL && strcmp(argv[argi], name2) == 0)) { + if ((name1 != nullptr && strcmp(argv[argi], name1) == 0) || + (name2 != nullptr && strcmp(argv[argi], name2) == 0)) { // match. check args left. if (argi + minRequiredParameters >= argc) { LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE, diff --git a/src/lib/synergy/ArgsBase.h b/src/lib/synergy/ArgsBase.h index a388d3191..207c31345 100644 --- a/src/lib/synergy/ArgsBase.h +++ b/src/lib/synergy/ArgsBase.h @@ -57,7 +57,8 @@ namespace lib { String m_profileDirectory; /// @brief The profile DIR to use for the application String m_pluginDirectory; /// @brief //TODO Plugins? Get set in ARCH but doesn't seem to get used String m_tlsCertFile; /// @brief Contains the location of the TLS certificate file - bool m_enableLangSync = true; /// @brief Should keyboard input be in same language as on server + bool m_enableLangSync = true; /// @brief Should keyboard input be in same language as on server + bool m_preventSleep = false; /// @brief Stop this computer from sleeping #if SYSAPI_WIN32 bool m_debugServiceWait = false;