Replaced Gnome screensaver hack with D-Bus messages to org.gnome.ScreenSaver.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 28 Dec 2012 03:46:55 -0500
changeset 6774 ad8522052ce6
parent 6773 5ebc5a9e35b4
child 6775 ca20a61fe03b
Replaced Gnome screensaver hack with D-Bus messages to org.gnome.ScreenSaver.
CMakeLists.txt
configure.in
include/SDL_config.h.cmake
include/SDL_config.h.in
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
--- a/CMakeLists.txt	Wed Dec 26 22:26:44 2012 -0800
+++ b/CMakeLists.txt	Fri Dec 28 03:46:55 2012 -0500
@@ -650,6 +650,9 @@
     endif(SDL_HAPTIC AND HAVE_INPUT_EVENTS)
 
     check_include_file("libudev.h" HAVE_LIBUDEV_H)
+
+    # !!! FIXME: this needs pkg-config to find the include path, I think.
+    check_include_file("dbus/dbus.h" HAVE_DBUS_DBUS_H)
   endif(LINUX)
 
   if(INPUT_TSLIB)
--- a/configure.in	Wed Dec 26 22:26:44 2012 -0800
+++ b/configure.in	Fri Dec 28 03:46:55 2012 -0500
@@ -1683,6 +1683,30 @@
     fi
 }
 
+dnl See if the platform offers libdbus for various IPC techniques.
+CheckDBus()
+{
+    AC_ARG_ENABLE(dbus,
+AC_HELP_STRING([--enable-dbus], [enable D-Bus support [[default=yes]]]),
+                        , enable_dbus=yes)
+    if test x$enable_dbus = xyes; then
+        AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+        if test x$PKG_CONFIG != xno; then
+            DBUS_CFLAGS=`$PKG_CONFIG --cflags dbus-1`
+            save_CFLAGS="$CFLAGS"
+            CFLAGS="$save_CFLAGS $DBUS_CFLAGS"
+            AC_CHECK_HEADER(dbus/dbus.h,
+                            have_dbus_dbus_h_hdr=yes,
+                            have_dbus_dbus_h_hdr=no)
+            CFLAGS="$save_CFLAGS"
+            if test x$have_dbus_dbus_h_hdr = xyes; then
+                AC_DEFINE(HAVE_DBUS_DBUS_H, 1, [ ])
+                EXTRA_CFLAGS="$EXTRA_CFLAGS $DBUS_CFLAGS"
+            fi
+        fi
+    fi
+}
+
 dnl See if we can use the Touchscreen input library
 CheckTslib()
 {
@@ -2208,6 +2232,7 @@
         CheckOpenGLX11
         CheckOpenGLESX11
         CheckLibUDev
+        CheckDBus
         CheckInputEvents
         CheckTslib
         CheckUSBHID
--- a/include/SDL_config.h.cmake	Wed Dec 26 22:26:44 2012 -0800
+++ b/include/SDL_config.h.cmake	Fri Dec 28 03:46:55 2012 -0500
@@ -66,6 +66,7 @@
 #cmakedefine HAVE_ALTIVEC_H 1
 #cmakedefine HAVE_PTHREAD_NP_H 1
 #cmakedefine HAVE_LIBUDEV_H 1
+#cmakedefine HAVE_DBUS_DBUS_H 1
 
 /* C library functions */
 #cmakedefine HAVE_MALLOC 1
--- a/include/SDL_config.h.in	Wed Dec 26 22:26:44 2012 -0800
+++ b/include/SDL_config.h.in	Fri Dec 28 03:46:55 2012 -0500
@@ -71,6 +71,7 @@
 #undef HAVE_ALTIVEC_H
 #undef HAVE_PTHREAD_NP_H
 #undef HAVE_LIBUDEV_H
+#undef HAVE_DBUS_DBUS_H
 
 /* C library functions */
 #undef HAVE_MALLOC
--- a/src/video/x11/SDL_x11events.c	Wed Dec 26 22:26:44 2012 -0800
+++ b/src/video/x11/SDL_x11events.c	Fri Dec 28 03:46:55 2012 -0500
@@ -675,7 +675,7 @@
 
 /* !!! FIXME: this should be exposed in a header, or something. */
 int SDL_GetNumTouch(void);
-
+void SDL_dbus_screensaver_tickle(_THIS);
 
 void
 X11_PumpEvents(_THIS)
@@ -688,6 +688,11 @@
         if (!data->screensaver_activity ||
             (int) (now - data->screensaver_activity) >= 30000) {
             XResetScreenSaver(data->display);
+
+            #if SDL_USE_LIBDBUS
+            SDL_dbus_screensaver_tickle(_this);
+            #endif
+
             data->screensaver_activity = now;
         }
     }   
@@ -785,33 +790,6 @@
 #endif
 }
 
-/* This is so wrong it hurts */
-#define GNOME_SCREENSAVER_HACK
-#ifdef GNOME_SCREENSAVER_HACK
-#include <unistd.h>
-static pid_t screensaver_inhibit_pid;
-static void
-gnome_screensaver_disable()
-{
-    screensaver_inhibit_pid = fork();
-    if (screensaver_inhibit_pid == 0) {
-        close(0);
-        close(1);
-        close(2);
-        execl("/usr/bin/gnome-screensaver-command",
-              "gnome-screensaver-command",
-              "--inhibit",
-              "--reason",
-              "GNOME screensaver doesn't respect MIT-SCREEN-SAVER", NULL);
-        exit(2);
-    }
-}
-static void
-gnome_screensaver_enable()
-{
-    kill(screensaver_inhibit_pid, 15);
-}
-#endif
 
 void
 X11_SuspendScreenSaver(_THIS)
@@ -835,11 +813,9 @@
     }
 #endif
 
-#ifdef GNOME_SCREENSAVER_HACK
+#if SDL_USE_LIBDBUS
     if (_this->suspend_screensaver) {
-        gnome_screensaver_disable();
-    } else {
-        gnome_screensaver_enable();
+        SDL_dbus_screensaver_tickle(_this);
     }
 #endif
 }
--- a/src/video/x11/SDL_x11video.c	Wed Dec 26 22:26:44 2012 -0800
+++ b/src/video/x11/SDL_x11video.c	Fri Dec 28 03:46:55 2012 -0500
@@ -39,6 +39,143 @@
 #include "SDL_x11opengles.h"
 #endif
 
+/* !!! FIXME: move dbus stuff to somewhere under src/core/linux ... */
+#if SDL_USE_LIBDBUS
+/* we never link directly to libdbus. */
+#include "SDL_loadso.h"
+static const char *dbus_library = "libdbus-1.so.3";
+static void *dbus_handle = NULL;
+
+/* !!! FIXME: this is kinda ugly. */
+static SDL_bool
+load_dbus_sym(const char *fn, void **addr)
+{
+    *addr = SDL_LoadFunction(dbus_handle, fn);
+    if (*addr == NULL) {
+        /* Don't call SDL_SetError(): SDL_LoadFunction already did. */
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+/* libdbus entry points... */
+static DBusConnection *(*DBUS_dbus_bus_get_private)(DBusBusType, DBusError *) = NULL;
+static void (*DBUS_dbus_connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t) = NULL;
+static dbus_bool_t (*DBUS_dbus_connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *) = NULL;
+static void (*DBUS_dbus_connection_close)(DBusConnection *) = NULL;
+static void (*DBUS_dbus_connection_unref)(DBusConnection *) = NULL;
+static void (*DBUS_dbus_connection_flush)(DBusConnection *) = NULL;
+static DBusMessage *(*DBUS_dbus_message_new_method_call)(const char *, const char *, const char *, const char *) = NULL;
+static void (*DBUS_dbus_message_unref)(DBusMessage *) = NULL;
+static void (*DBUS_dbus_error_init)(DBusError *) = NULL;
+static dbus_bool_t (*DBUS_dbus_error_is_set)(const DBusError *) = NULL;
+static void (*DBUS_dbus_error_free)(DBusError *) = NULL;
+
+static int
+load_dbus_syms(void)
+{
+    /* cast funcs to char* first, to please GCC's strict aliasing rules. */
+    #define SDL_DBUS_SYM(x) \
+        if (!load_dbus_sym(#x, (void **) (char *) &DBUS_##x)) return -1
+
+    SDL_DBUS_SYM(dbus_bus_get_private);
+    SDL_DBUS_SYM(dbus_connection_set_exit_on_disconnect);
+    SDL_DBUS_SYM(dbus_connection_send);
+    SDL_DBUS_SYM(dbus_connection_close);
+    SDL_DBUS_SYM(dbus_connection_unref);
+    SDL_DBUS_SYM(dbus_connection_flush);
+    SDL_DBUS_SYM(dbus_message_new_method_call);
+    SDL_DBUS_SYM(dbus_message_unref);
+    SDL_DBUS_SYM(dbus_error_init);
+    SDL_DBUS_SYM(dbus_error_is_set);
+    SDL_DBUS_SYM(dbus_error_free);
+
+    #undef SDL_DBUS_SYM
+
+    return 0;
+}
+
+static void
+UnloadDBUSLibrary(void)
+{
+    if (dbus_handle != NULL) {
+        SDL_UnloadObject(dbus_handle);
+        dbus_handle = NULL;
+    }
+}
+
+static int
+LoadDBUSLibrary(void)
+{
+    int retval = 0;
+    if (dbus_handle == NULL) {
+        dbus_handle = SDL_LoadObject(dbus_library);
+        if (dbus_handle == NULL) {
+            retval = -1;
+            /* Don't call SDL_SetError(): SDL_LoadObject already did. */
+        } else {
+            retval = load_dbus_syms();
+            if (retval < 0) {
+                UnloadDBUSLibrary();
+            }
+        }
+    }
+
+    return retval;
+}
+
+static void
+X11_InitDBus(_THIS)
+{
+    if (LoadDBUSLibrary() != -1) {
+        SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+        DBusError err;
+        DBUS_dbus_error_init(&err);
+        data->dbus = DBUS_dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+        if (DBUS_dbus_error_is_set(&err)) {
+            DBUS_dbus_error_free(&err);
+            if (data->dbus) {
+                DBUS_dbus_connection_unref(data->dbus);
+                data->dbus = NULL;
+            }
+            return;  /* oh well */
+        }
+        DBUS_dbus_connection_set_exit_on_disconnect(data->dbus, 0);
+    }
+}
+
+static void
+X11_QuitDBus(_THIS)
+{
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    if (data->dbus) {
+        DBUS_dbus_connection_close(data->dbus);
+        DBUS_dbus_connection_unref(data->dbus);
+        data->dbus = NULL;
+    }
+}
+
+void
+SDL_dbus_screensaver_tickle(_THIS)
+{
+    const SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    DBusConnection *conn = data->dbus;
+    if (conn != NULL) {
+        DBusMessage *msg = DBUS_dbus_message_new_method_call("org.gnome.ScreenSaver",
+                                                             "/org/gnome/ScreenSaver",
+                                                             "org.gnome.ScreenSaver",
+                                                             "SimulateUserActivity");
+        if (msg != NULL) {
+            if (DBUS_dbus_connection_send(conn, msg, NULL)) {
+                DBUS_dbus_connection_flush(conn);
+            }
+            DBUS_dbus_message_unref(msg);
+        }
+    }
+}
+#endif
+
 /* Initialization/Query functions */
 static int X11_VideoInit(_THIS);
 static void X11_VideoQuit(_THIS);
@@ -349,6 +486,7 @@
 #endif
 }
 
+
 int
 X11_VideoInit(_THIS)
 {
@@ -401,6 +539,11 @@
     X11_InitMouse(_this);
 
     X11_InitTouch(_this);
+
+#if SDL_USE_LIBDBUS
+    X11_InitDBus(_this);
+#endif
+
     return 0;
 }
 
@@ -422,6 +565,10 @@
     X11_QuitKeyboard(_this);
     X11_QuitMouse(_this);
     X11_QuitTouch(_this);
+
+#if SDL_USE_LIBDBUS
+    X11_QuitDBus(_this);
+#endif
 }
 
 SDL_bool
--- a/src/video/x11/SDL_x11video.h	Wed Dec 26 22:26:44 2012 -0800
+++ b/src/video/x11/SDL_x11video.h	Fri Dec 28 03:46:55 2012 -0500
@@ -53,6 +53,11 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_DBUS_DBUS_H
+#define SDL_USE_LIBDBUS 1
+#include <dbus/dbus.h>
+#endif
+
 #include "SDL_x11dyn.h"
 
 #include "SDL_x11clipboard.h"
@@ -98,6 +103,10 @@
 
     SDL_Scancode key_layout[256];
     SDL_bool selection_waiting;    
+
+#if SDL_USE_LIBDBUS
+    DBusConnection *dbus;
+#endif
 } SDL_VideoData;
 
 extern SDL_bool X11_UseDirectColorVisuals(void);