SYNERGY-856 - Force prevent sleep (#7047)

* [UB-856] - Set display as busy

* SYNERGY-856 - Prevent sleep on Mac

* SYNERGY-856 - Prevent sleep on Linux

* SYNERGY-856 - Update changelog

* SYNERGY-856 - Set user activity on for Mac to prevent sleep

* SYNERGY-856 - Prevent screen  sleep continuosly

* SYNERGY-856 - Try implementing DBus in the server/client

* SYNERGY-856 - Move inhibitor to arch instead of gui

* SYNERGY-856 - Undo undesired changes

* SYNERGY-856 - Undo remaining undersired changes

* SYNERGY-856 - Compile on MacOS

* SYNERGY-856 - Reduce if/else depth

* SYNERGY-856 - Remove AppDelegate include

* SYNERGY-856 - Update inhibitor code to have more verbose debug output

* SYNERGY-856 - Make methods static

* SYNERGY-856 - Remove unused declarations
This commit is contained in:
Igor Sikachyna 2021-07-12 12:44:08 +03:00 committed by GitHub
parent e69ea6f627
commit 6b1761316a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 17 deletions

View file

@ -11,6 +11,7 @@ Bug fixes:
- #7036 Fix tray icon not changing theme on Big Sur - #7036 Fix tray icon not changing theme on Big Sur
- #7046 Fix MacOS 10.13 build - #7046 Fix MacOS 10.13 build
- #7049 Scroll doesn't work in case of macOS is server - #7049 Scroll doesn't work in case of macOS is server
- #7047 Fix prevent sleep option on Mac and Windows
Enhancements: Enhancements:
- #6998 Remove functionality related to the screen saver synchronisation - #6998 Remove functionality related to the screen saver synchronisation
@ -20,6 +21,7 @@ Enhancements:
- #7030 | #7041 | #7043 Add user notification for secure input on Mac - #7030 | #7041 | #7043 Add user notification for secure input on Mac
- #7044 Apply natural scroll setting independently on each client - #7044 Apply natural scroll setting independently on each client
- #7040 Support "Kana" and "Eisu" keys on Japanese Apple Pro Keyboard (JIS) - #7040 Support "Kana" and "Eisu" keys on Japanese Apple Pro Keyboard (JIS)
- #7047 Add prevent sleep option support to Linux
=========== ===========
v1.14.0-stable v1.14.0-stable

View file

@ -41,4 +41,10 @@ add_library(arch STATIC ${sources})
if (UNIX) if (UNIX)
target_link_libraries(arch ${CMAKE_DL_LIBS} ${libs}) target_link_libraries(arch ${CMAKE_DL_LIBS} ${libs})
if (NOT APPLE)
find_package (Qt5 COMPONENTS DBus)
include_directories(${Qt5DBus_INCLUDE_DIRS})
target_link_libraries (arch Qt5::DBus)
endif()
endif() endif()

View file

@ -23,6 +23,9 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <string> #include <string>
#ifndef __APPLE__
#include <QtDBus>
#endif
// //
// ArchSystemUnix // ArchSystemUnix
@ -100,3 +103,76 @@ ArchSystemUnix::runCommand(const std::string& cmd)
} }
return result; return result;
} }
#ifndef __APPLE__
bool
ArchSystemUnix::DBusInhibitScreenCall(InhibitScreenServices serviceID, bool state, std::string& error)
{
error = "";
static const std::array<QString, 2> services =
{
"org.freedesktop.ScreenSaver",
"org.gnome.SessionManager"
};
static const std::array<QString, 2> paths =
{
"/org/freedesktop/ScreenSaver",
"/org/gnome/SessionManager"
};
static std::array<uint, 2> cookies;
auto serviceNum = static_cast<uint8_t>(serviceID);
QDBusConnection bus = QDBusConnection::sessionBus();
if (!bus.isConnected())
{
error = "bus failed to connect";
return false;
}
QDBusInterface screenSaverInterface(
services[serviceNum],
paths[serviceNum],
services[serviceNum],
bus);
if (!screenSaverInterface.isValid())
{
error = "screen saver interface failed to initialize";
return false;
}
QDBusReply<uint> reply;
if(state)
{
if (cookies[serviceNum])
{
error = "coockies are not empty";
return false;
}
reply = screenSaverInterface.call("Inhibit", "Synergy", "Sleep is manually prevented by the Synergy preferences");
if (reply.isValid())
cookies[serviceNum] = reply.value();
}
else
{
if(!cookies[serviceNum])
{
error = "coockies are empty";
return false;
}
reply = screenSaverInterface.call("UnInhibit", cookies[serviceNum]);
cookies[serviceNum] = 0;
}
if(!reply.isValid())
{
QDBusError qerror = reply.error();
error = qerror.name().toStdString() + " : " + qerror.message().toStdString();
return false;
}
return true;
}
#endif

View file

@ -36,4 +36,12 @@ public:
virtual std::string getLibsUsed(void) const; virtual std::string getLibsUsed(void) const;
static std::string runCommand(const std::string& cmd); static std::string runCommand(const std::string& cmd);
#ifndef __APPLE__
enum class InhibitScreenServices {
kScreenSaver,
kSessionManager
};
static bool DBusInhibitScreenCall(InhibitScreenServices serviceID, bool state, std::string& error);
#endif
}; };

View file

@ -251,6 +251,7 @@ MSWindowsScreen::enable()
if (App::instance().argsBase().m_preventSleep) { if (App::instance().argsBase().m_preventSleep) {
ArchMiscWindows::addBusyState(ArchMiscWindows::kSYSTEM); ArchMiscWindows::addBusyState(ArchMiscWindows::kSYSTEM);
ArchMiscWindows::addBusyState(ArchMiscWindows::kDISPLAY);
} }
} }
@ -270,6 +271,7 @@ MSWindowsScreen::disable()
else { else {
// allow the system to enter power saving mode // allow the system to enter power saving mode
ArchMiscWindows::removeBusyState(ArchMiscWindows::kSYSTEM); ArchMiscWindows::removeBusyState(ArchMiscWindows::kSYSTEM);
ArchMiscWindows::removeBusyState(ArchMiscWindows::kDISPLAY);
} }
// tell key state // tell key state

View file

@ -756,8 +756,10 @@ OSXScreen::enable()
{ {
if(App::instance().argsBase().m_preventSleep) { if(App::instance().argsBase().m_preventSleep) {
CFStringRef reasonForActivity = CFSTR("Synergy application"); CFStringRef reasonForActivity = CFSTR("Synergy application");
IOReturn result = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep,
kIOPMAssertionLevelOn, reasonForActivity, &m_sleepPreventionAssertionID); IOReturn result = IOPMAssertionCreateWithName(kIOPMAssertPreventUserIdleDisplaySleep,
kIOPMAssertionLevelOn, reasonForActivity,
&m_sleepPreventionAssertionID);
if(result != kIOReturnSuccess) { if(result != kIOReturnSuccess) {
m_sleepPreventionAssertionID = 0; m_sleepPreventionAssertionID = 0;
LOG((CLOG_ERR "failed to disable system idle sleep")); LOG((CLOG_ERR "failed to disable system idle sleep"));

View file

@ -26,6 +26,8 @@
#include "synergy/Clipboard.h" #include "synergy/Clipboard.h"
#include "synergy/KeyMap.h" #include "synergy/KeyMap.h"
#include "synergy/XScreen.h" #include "synergy/XScreen.h"
#include "synergy/ArgsBase.h"
#include "synergy/App.h"
#include "arch/XArch.h" #include "arch/XArch.h"
#include "arch/Arch.h" #include "arch/Arch.h"
#include "base/Log.h" #include "base/Log.h"
@ -133,7 +135,7 @@ XWindowsScreen::XWindowsScreen(
if (!disableXInitThreads) { if (!disableXInitThreads) {
// initializes Xlib support for concurrent threads. // initializes Xlib support for concurrent threads.
if (XInitThreads() == 0) if (XInitThreads() == 0)
throw XArch("XInitThreads() returned zero"); throw XArch("XInitThreads() returned zero");
} else { } else {
LOG((CLOG_DEBUG "skipping XInitThreads()")); LOG((CLOG_DEBUG "skipping XInitThreads()"));
} }
@ -245,6 +247,12 @@ XWindowsScreen::enable()
// warp the mouse to the cursor center // warp the mouse to the cursor center
fakeMouseMove(m_xCenter, m_yCenter); 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 void
@ -263,6 +271,12 @@ XWindowsScreen::disable()
if (!m_isPrimary && m_autoRepeat) { if (!m_isPrimary && m_autoRepeat) {
//XAutoRepeatOn(m_display); //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 void
@ -289,8 +303,8 @@ XWindowsScreen::enter()
CARD16 powerlevel; CARD16 powerlevel;
BOOL enabled; BOOL enabled;
if (DPMSQueryExtension(m_display, &dummy, &dummy) && if (DPMSQueryExtension(m_display, &dummy, &dummy) &&
DPMSCapable(m_display) && DPMSCapable(m_display) &&
DPMSInfo(m_display, &powerlevel, &enabled)) DPMSInfo(m_display, &powerlevel, &enabled))
{ {
if (enabled && powerlevel != DPMSModeOn) if (enabled && powerlevel != DPMSModeOn)
DPMSForceLevel(m_display, DPMSModeOn); DPMSForceLevel(m_display, DPMSModeOn);
@ -1332,7 +1346,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*)
XFreeEventData(m_display, cookie); XFreeEventData(m_display, cookie);
return; return;
} }
XFreeEventData(m_display, cookie); XFreeEventData(m_display, cookie);
} }
} }
#endif #endif
@ -1539,9 +1553,9 @@ XWindowsScreen::onKeyPress(XKeyEvent& xkey)
false, false, key, mask, 1, keycode); false, false, key, mask, 1, keycode);
} }
} }
else { else {
LOG((CLOG_DEBUG1 "can't map keycode to key id")); LOG((CLOG_DEBUG1 "can't map keycode to key id"));
} }
} }
void void
@ -1864,7 +1878,7 @@ XWindowsScreen::doSelectEvents(Window w) const
// select events of interest. do this before querying the tree so // select events of interest. do this before querying the tree so
// we'll get notifications of children created after the XQueryTree() // we'll get notifications of children created after the XQueryTree()
// so we won't miss them. // so we won't miss them.
XSelectInput(m_display, w, mask); XSelectInput(m_display, w, mask);
// recurse on child windows // recurse on child windows
Window rw, pw, *cw; Window rw, pw, *cw;
@ -2156,7 +2170,7 @@ XWindowsScreen::selectXIRawMotion()
mask.mask = (unsigned char*)calloc(mask.mask_len, sizeof(char)); mask.mask = (unsigned char*)calloc(mask.mask_len, sizeof(char));
mask.deviceid = XIAllMasterDevices; mask.deviceid = XIAllMasterDevices;
memset(mask.mask, 0, 2); memset(mask.mask, 0, 2);
XISetMask(mask.mask, XI_RawKeyRelease); XISetMask(mask.mask, XI_RawKeyRelease);
XISetMask(mask.mask, XI_RawMotion); XISetMask(mask.mask, XI_RawMotion);
XISelectEvents(m_display, DefaultRootWindow(m_display), &mask, 1); XISelectEvents(m_display, DefaultRootWindow(m_display), &mask, 1);
free(mask.mask); free(mask.mask);
@ -2186,3 +2200,26 @@ XWindowsScreen::updateScrollDirection()
scrollDirectionUpdateThread.detach(); scrollDirectionUpdateThread.detach();
} }
} }
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);
}

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "arch/Arch.h"
#include "synergy/PlatformScreen.h" #include "synergy/PlatformScreen.h"
#include "synergy/KeyMap.h" #include "synergy/KeyMap.h"
#include "common/stdset.h" #include "common/stdset.h"
@ -117,6 +118,11 @@ private:
void onError(); void onError();
static int ioErrorHandler(Display*); static int ioErrorHandler(Display*);
// sleep management
static bool sleepInhibitCall(bool state, ArchSystemUnix::InhibitScreenServices serviceID);
static bool disableIdleSleep();
static bool enableIdleSleep();
private: private:
class KeyEventFilter { class KeyEventFilter {
public: public: