From 156b0be9f13b3427973f1d83a004947225b2d8b6 Mon Sep 17 00:00:00 2001 From: Preston Maness Date: Wed, 16 Dec 2015 10:45:57 -0600 Subject: [PATCH] client (Linux): Reinstate XScreenSaver API-based idle detection on GNU/Linux. --- client/hostinfo_unix.cpp | 68 +++++++++++++++++++++++++++++++++++++++- configure.ac | 20 ++++++++++++ lib/prefs.cpp | 2 +- lib/prefs.h | 6 +++- 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/client/hostinfo_unix.cpp b/client/hostinfo_unix.cpp index 617f8241fd..c05989515e 100644 --- a/client/hostinfo_unix.cpp +++ b/client/hostinfo_unix.cpp @@ -41,6 +41,10 @@ #include #endif +#if HAVE_XSS +#include //X-based idle detection +#endif + #include #include #include @@ -1947,6 +1951,62 @@ bool interrupts_idle(time_t t) { } return last_irq < t; } + +#if HAVE_XSS +// Ask the X server for user idle time (using XScreenSaver API) +// Return true if the idle time exceeds idle_threshold. +// +bool xss_idle(long idle_threshold) { + static XScreenSaverInfo* xssInfo = NULL; + static Display* disp = NULL; + static bool error = false; + // some X call failed - always return not idle + + if (error) return false; + + long idle_time = 0; + + if (disp == NULL) { + disp = XOpenDisplay(NULL); + // XOpenDisplay may return NULL if there is no running X + // or DISPLAY points to wrong/invalid display + // + if (disp == NULL) { + error = true; + //msg_printf(NULL, MSG_INFO, "XDisplay not found."); + return false; + } + int event_base_return, error_base_return; + xssInfo = XScreenSaverAllocInfo(); + if (!XScreenSaverQueryExtension( + disp, &event_base_return, &error_base_return + )){ + error = true; + //msg_printf(NULL, MSG_INFO, "XScreenSaverQueryExtension() failed."); + return false; + } + } + + XScreenSaverQueryInfo(disp, DefaultRootWindow(disp), xssInfo); + idle_time = xssInfo->idle; + + // convert from milliseconds to seconds + // + idle_time = idle_time / 1000; + + //msg_printf(NULL, MSG_INFO, "XSS idle detection succeeded."); + //msg_printf(NULL, MSG_INFO, "idle threshold: %ld", idle_threshold); + //msg_printf(NULL, MSG_INFO, "idle_time: %ld", idle_time); + + if ( idle_threshold < idle_time ) { + //msg_printf(NULL, MSG_INFO, "System is idle according to X."); + } else { + //msg_printf(NULL, MSG_INFO, "System is active according to X."); + } + return idle_threshold < idle_time; +} +#endif // HAVE_XSS + #endif // LINUX_LIKE_SYSTEM bool HOST_INFO::users_idle(bool check_all_logins, double idle_time_to_run) { @@ -1972,6 +2032,12 @@ bool HOST_INFO::users_idle(bool check_all_logins, double idle_time_to_run) { return false; } +#if HAVE_XSS + if (!xss_idle((long)(idle_time_to_run * 60))) { + return false; + } +#endif // HAVE_XSS + // Lets at least check the dev entries which should be correct for // USB keyboards and mice. If the linux kernel doc is correct it should // also work for bluetooth input devices as well. @@ -1990,7 +2056,7 @@ bool HOST_INFO::users_idle(bool check_all_logins, double idle_time_to_run) { if (!device_idle(idle_time, "/dev/input/mice")) return false; if (!device_idle(idle_time, "/dev/kbd")) return false; // solaris -#endif +#endif // LINUX_LIKE_SYSTEM return true; } diff --git a/configure.ac b/configure.ac index 792c6fb508..919fd46f14 100644 --- a/configure.ac +++ b/configure.ac @@ -200,6 +200,7 @@ configured_to_build= if test x$enable_client = xyes ; then configured_to_build="client" + enable_xss="yes" fi if test x$enable_manager = xyes ; then configured_to_build="${configured_to_build} manager" @@ -628,6 +629,15 @@ fi AM_CONDITIONAL(BUILD_GRAPHICS_API, [ test "$have_glut" = yes -a "$have_jpeg" = 1]) +dnl check for X screen saver lib (X-based idle detection on Linux) +if test "$enable_xss" == yes; then + AC_CHECK_LIB([Xss], [XScreenSaverAllocInfo], [have_Xss="yes"], [have_Xss="no"]) + AC_CHECK_HEADER([X11/extensions/scrnsaver.h], [have_Xss="yes"], [have_Xss="no"]) + if test "$have_Xss" == no; then + AC_MSG_WARN([libxss missing, disabling X ScreenSaver user idle detection]) + fi +fi + dnl -------------------------------------------------------------------------------- dnl put double-inclusion protection into config.h AH_TOP([ @@ -1194,6 +1204,16 @@ if test "${ac_cv_func_res_init}" != "yes" ; then fi LIBS=$svlibs +if (test "$enable_xss" == yes) && (test "$have_Xss" == yes); then + SAH_CHECK_LIB([Xss],[XScreenSaverAllocInfo],[ + AC_DEFINE([HAVE_XSS],[1],[Define to 1 if you have xss library]) + CLIENTLIBS="${sah_lib_last} ${CLIENTLIBS}"]) + SAH_CHECK_LIB([X11],[XOpenDisplay],[ + AC_DEFINE([HAVE_X11],[1],[Define to 1 if you have X11 library]) + CLIENTLIBS="${sah_lib_last} ${CLIENTLIBS}"]) + echo DEBUG: CLIENTLIBS=${CLIENTLIBS} >&5 +fi + SAH_CHECK_LIB([resolv],[res_query],[ AC_DEFINE([HAVE_RESOLV],[1],[Define to 1 if you have the resolv library]) CLIENTLIBS="${sah_lib_last} ${CLIENTLIBS}"]) diff --git a/lib/prefs.cpp b/lib/prefs.cpp index 3a8267ef81..9bd41608e1 100644 --- a/lib/prefs.cpp +++ b/lib/prefs.cpp @@ -149,7 +149,7 @@ bool TIME_SPAN::suspended(double hour) const { TIME_SPAN::TimeMode TIME_SPAN::mode() const { if (end_hour == start_hour || (start_hour == 0 && end_hour == 24)) { - return Always; + return Always2; } else if (start_hour == 24 && end_hour == 0) { return Never; } diff --git a/lib/prefs.h b/lib/prefs.h index ebbe3cc6f7..da81ea7e0a 100644 --- a/lib/prefs.h +++ b/lib/prefs.h @@ -89,7 +89,11 @@ struct TIME_SPAN { double end_hour; enum TimeMode { - Always = 7000, + // "Always" is defined by X.h, which itself is (indirectly) included + // from client/hostinfo_unix.cpp when including the XSS API + // (). Hence, renaming here (and in + // prefs.cpp). + Always2 = 7000, Never, Between };