From 71c643b6f575a784ed631b75bc7c63364099c481 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 28 Dec 2012 03:46:55 -0500 Subject: [PATCH] Replaced Gnome screensaver hack with D-Bus messages to org.gnome.ScreenSaver. --- CMakeLists.txt | 3 + configure.in | 25 ++++++ include/SDL_config.h.cmake | 1 + include/SDL_config.h.in | 1 + src/video/x11/SDL_x11events.c | 40 ++------- src/video/x11/SDL_x11video.c | 147 ++++++++++++++++++++++++++++++++++ src/video/x11/SDL_x11video.h | 9 +++ 7 files changed, 194 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b561c91c..bf3f34a4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -650,6 +650,9 @@ if(UNIX AND NOT APPLE) 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) diff --git a/configure.in b/configure.in index 8fd9280c4..56f96054a 100644 --- a/configure.in +++ b/configure.in @@ -1683,6 +1683,30 @@ AC_HELP_STRING([--enable-libudev], [enable libudev support [[default=yes]]]), 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 @@ case "$host" in CheckOpenGLX11 CheckOpenGLESX11 CheckLibUDev + CheckDBus CheckInputEvents CheckTslib CheckUSBHID diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index d5ae1d815..3e1301dd9 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -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 diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index bcf443d48..666702774 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -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 diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 480bb3149..7daea9aca 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -675,7 +675,7 @@ X11_Pending(Display * display) /* !!! 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 @@ X11_PumpEvents(_THIS) 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 @@ X11_PumpEvents(_THIS) #endif } -/* This is so wrong it hurts */ -#define GNOME_SCREENSAVER_HACK -#ifdef GNOME_SCREENSAVER_HACK -#include -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 @@ X11_SuspendScreenSaver(_THIS) } #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 } diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 52a996a53..a7d48c54e 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -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 @@ X11_CheckWindowManager(_THIS) #endif } + int X11_VideoInit(_THIS) { @@ -401,6 +539,11 @@ X11_VideoInit(_THIS) X11_InitMouse(_this); X11_InitTouch(_this); + +#if SDL_USE_LIBDBUS + X11_InitDBus(_this); +#endif + return 0; } @@ -422,6 +565,10 @@ X11_VideoQuit(_THIS) X11_QuitKeyboard(_this); X11_QuitMouse(_this); X11_QuitTouch(_this); + +#if SDL_USE_LIBDBUS + X11_QuitDBus(_this); +#endif } SDL_bool diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 5c092048f..eee97702b 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -53,6 +53,11 @@ #include #endif +#ifdef HAVE_DBUS_DBUS_H +#define SDL_USE_LIBDBUS 1 +#include +#endif + #include "SDL_x11dyn.h" #include "SDL_x11clipboard.h" @@ -98,6 +103,10 @@ typedef struct SDL_VideoData SDL_Scancode key_layout[256]; SDL_bool selection_waiting; + +#if SDL_USE_LIBDBUS + DBusConnection *dbus; +#endif } SDL_VideoData; extern SDL_bool X11_UseDirectColorVisuals(void);