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;