From a1c807ba674056624b3178c9281e08f3b999401a Mon Sep 17 00:00:00 2001 From: crs Date: Wed, 10 Mar 2004 22:03:01 +0000 Subject: [PATCH] Added support for DPMS in X11 screen saver. DPMS is the extension that allows you to power down the display. Previously, synergy would not power on the display if DPMS was enabled and activated and xscreensaver was not running. It also wouldn't disable DPMS so the display would power down normally on a synergy client if there was no input activity. --- configure.in | 2 +- lib/platform/CXWindowsScreenSaver.cpp | 129 ++++++++++++++++++++++++-- lib/platform/CXWindowsScreenSaver.h | 16 ++++ 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/configure.in b/configure.in index 8dbe4e78..e8a9906d 100644 --- a/configure.in +++ b/configure.in @@ -57,8 +57,8 @@ AC_PATH_XTRA save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$X_CFLAGS $CPPFLAGS" AC_CHECK_HEADERS([X11/extensions/XTest.h]) - AC_CHECK_LIB(Xinerama, XineramaQueryExtension, AC_CHECK_HEADERS([X11/extensions/Xinerama.h]) [X_LIBS="$X_LIBS -lXinerama"], , [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]) +AC_CHECK_LIB(Xext, DPMSQueryExtension, AC_CHECK_HEADERS([X11/extensions/dpms.h]) [X_LIBS="$X_LIBS -lXext"], , [$X_LIBS -lX11 $X_EXTRA_LIBS]) CPPFLAGS="$save_CPPFLAGS" dnl checks for types diff --git a/lib/platform/CXWindowsScreenSaver.cpp b/lib/platform/CXWindowsScreenSaver.cpp index a40ae7e4..44c7c0b8 100644 --- a/lib/platform/CXWindowsScreenSaver.cpp +++ b/lib/platform/CXWindowsScreenSaver.cpp @@ -25,6 +25,11 @@ #else # error The XTest extension is required to build synergy #endif +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) +extern "C" { +# include +} +#endif // // CXWindowsScreenSaver @@ -37,6 +42,7 @@ CXWindowsScreenSaver::CXWindowsScreenSaver( m_eventTarget(eventTarget), m_xscreensaver(None), m_xscreensaverActive(false), + m_dpms(false), m_disabled(false), m_suppressDisable(false), m_disableTimer(NULL) @@ -51,6 +57,18 @@ CXWindowsScreenSaver::CXWindowsScreenSaver( m_atomScreenSaverDeactivate = XInternAtom(m_display, "DEACTIVATE", False); + // check for DPMS extension. this is an alternative screen saver + // that powers down the display. +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) + int eventBase, errorBase; + if (DPMSQueryExtension(m_display, &eventBase, &errorBase)) { + if (DPMSCapable(m_display)) { + // we have DPMS + m_dpms = true; + } + } +#endif + // watch top-level windows for changes { bool error = false; @@ -66,15 +84,18 @@ CXWindowsScreenSaver::CXWindowsScreenSaver( } } + // get the built-in settings + XGetScreenSaver(m_display, &m_timeout, &m_interval, + &m_preferBlanking, &m_allowExposures); + + // get the DPMS settings + m_dpmsEnabled = isDPMSEnabled(); + // get the xscreensaver window, if any if (!findXScreenSaver()) { setXScreenSaver(None); } - // get the built-in settings - XGetScreenSaver(m_display, &m_timeout, &m_interval, - &m_preferBlanking, &m_allowExposures); - // install disable timer event handler EVENTQUEUE->adoptHandler(CEvent::kTimer, this, new TMethodEventJob(this, @@ -90,6 +111,7 @@ CXWindowsScreenSaver::~CXWindowsScreenSaver() EVENTQUEUE->removeHandler(CEvent::kTimer, this); if (m_display != NULL) { + enableDPMS(m_dpmsEnabled); XSetScreenSaver(m_display, m_timeout, m_interval, m_preferBlanking, m_allowExposures); clearWatchForXScreenSaver(); @@ -176,6 +198,9 @@ CXWindowsScreenSaver::enable() // for built-in X screen saver XSetScreenSaver(m_display, m_timeout, m_interval, m_preferBlanking, m_allowExposures); + + // for DPMS + enableDPMS(m_dpmsEnabled); } void @@ -190,6 +215,11 @@ CXWindowsScreenSaver::disable() &m_preferBlanking, &m_allowExposures); XSetScreenSaver(m_display, 0, m_interval, m_preferBlanking, m_allowExposures); + + // for DPMS + m_dpmsEnabled = isDPMSEnabled(); + enableDPMS(false); + // FIXME -- now deactivate? } @@ -200,6 +230,9 @@ CXWindowsScreenSaver::activate() m_suppressDisable = true; updateDisableTimer(); + // enable DPMS if it was enabled + enableDPMS(m_dpmsEnabled); + // try xscreensaver findXScreenSaver(); if (m_xscreensaver != None) { @@ -207,8 +240,13 @@ CXWindowsScreenSaver::activate() return; } - // use built-in X screen saver - XForceScreenSaver(m_display, ScreenSaverActive); + // try built-in X screen saver + if (m_timeout != 0) { + XForceScreenSaver(m_display, ScreenSaverActive); + } + + // try DPMS + activateDPMS(true); } void @@ -218,6 +256,14 @@ CXWindowsScreenSaver::deactivate() m_suppressDisable = false; updateDisableTimer(); + // try DPMS + activateDPMS(false); + + // disable DPMS if screen saver is disabled + if (m_disabled) { + enableDPMS(false); + } + // try xscreensaver findXScreenSaver(); if (m_xscreensaver != None) { @@ -237,6 +283,11 @@ CXWindowsScreenSaver::isActive() const return m_xscreensaverActive; } + // check DPMS + if (isDPMSActivated()) { + return true; + } + // can't check built-in X screen saver activity return false; } @@ -282,6 +333,9 @@ CXWindowsScreenSaver::setXScreenSaver(Window window) XWindowAttributes attr; XGetWindowAttributes(m_display, m_xscreensaver, &attr); setXScreenSaverActive(!error && attr.map_state != IsUnmapped); + + // save current DPMS state; xscreensaver may have changed it. + m_dpmsEnabled = isDPMSEnabled(); } else { // screen saver can't be active if it doesn't exist @@ -450,3 +504,66 @@ CXWindowsScreenSaver::handleDisableTimer(const CEvent&, void*) XSendEvent(m_display, m_xscreensaver, False, 0, &event); } } + +void +CXWindowsScreenSaver::activateDPMS(bool activate) +{ +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) + if (m_dpms) { + // DPMSForceLevel will generate a BadMatch if DPMS is disabled + CXWindowsUtil::CErrorLock lock(m_display); + DPMSForceLevel(m_display, activate ? DPMSModeStandby : DPMSModeOn); + } +#endif +} + +void +CXWindowsScreenSaver::enableDPMS(bool enable) +{ +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) + if (m_dpms) { + if (enable) { + DPMSEnable(m_display); + } + else { + DPMSDisable(m_display); + } + } +#endif +} + +bool +CXWindowsScreenSaver::isDPMSEnabled() const +{ +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) + if (m_dpms) { + CARD16 level; + BOOL state; + DPMSInfo(m_display, &level, &state); + return (state != False); + } + else { + return false; + } +#else + return false; +#endif +} + +bool +CXWindowsScreenSaver::isDPMSActivated() const +{ +#if defined(HAVE_X11_EXTENSIONS_DPMS_H) + if (m_dpms) { + CARD16 level; + BOOL state; + DPMSInfo(m_display, &level, &state); + return (level != DPMSModeOn); + } + else { + return false; + } +#else + return false; +#endif +} diff --git a/lib/platform/CXWindowsScreenSaver.h b/lib/platform/CXWindowsScreenSaver.h index b956a84b..20c2237d 100644 --- a/lib/platform/CXWindowsScreenSaver.h +++ b/lib/platform/CXWindowsScreenSaver.h @@ -92,6 +92,18 @@ private: // called periodically to prevent the screen saver from starting void handleDisableTimer(const CEvent&, void*); + // force DPMS to activate or deactivate + void activateDPMS(bool activate); + + // enable/disable DPMS screen saver + void enableDPMS(bool); + + // check if DPMS is enabled + bool isDPMSEnabled() const; + + // check if DPMS is activate + bool isDPMSActivated() const; + private: typedef std::map CWatchList; @@ -128,6 +140,10 @@ private: int m_preferBlanking; int m_allowExposures; + // DPMS screen saver settings + bool m_dpms; + bool m_dpmsEnabled; + // true iff the client wants the screen saver suppressed bool m_disabled;