From 4ca76b3e59ba4128e23910e09c853f001da1e26b Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 2 Mar 2014 14:59:06 -0500 Subject: [PATCH] Add support for the freedesktop.org Idle Inhibition specification, as per: http://people.freedesktop.org/~hadess/idle-inhibition-spec/ This makes screensaver inhibition work with GNOME 3 and other desktop environments that implement the specification. https://bugzilla.libsdl.org/show_bug.cgi?id=2169 --- src/video/x11/SDL_x11events.c | 18 +++++--- src/video/x11/SDL_x11video.c | 77 +++++++++++++++++++++++++++++++++++ src/video/x11/SDL_x11video.h | 1 + 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index bf0b1391fed6c..ad3c59d6a796e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1029,7 +1029,19 @@ X11_SuspendScreenSaver(_THIS) SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; int dummy; int major_version, minor_version; +#endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */ +#if SDL_USE_LIBDBUS + if (SDL_dbus_screensaver_inhibit(_this)) { + return; + } + + if (_this->suspend_screensaver) { + SDL_dbus_screensaver_tickle(_this); + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER if (SDL_X11_HAVE_XSS) { /* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */ if (!X11_XScreenSaverQueryExtension(data->display, &dummy, &dummy) || @@ -1043,12 +1055,6 @@ X11_SuspendScreenSaver(_THIS) X11_XResetScreenSaver(data->display); } #endif - -#if SDL_USE_LIBDBUS - if (_this->suspend_screensaver) { - SDL_dbus_screensaver_tickle(_this); - } -#endif } #endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 63cfa982451ba..ca9faee31e8f8 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -45,6 +45,7 @@ #include "SDL_loadso.h" static const char *dbus_library = "libdbus-1.so.3"; static void *dbus_handle = NULL; +static unsigned int screensaver_cookie = 0; /* !!! FIXME: this is kinda ugly. */ static SDL_bool @@ -63,10 +64,13 @@ load_dbus_sym(const char *fn, void **addr) 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 DBusMessage *(*DBUS_dbus_connection_send_with_reply_and_block)(DBusConnection *, DBusMessage *, int, DBusError *) = 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 dbus_bool_t (*DBUS_dbus_message_append_args)(DBusMessage *, int, ...) = NULL; +static dbus_bool_t (*DBUS_dbus_message_get_args)(DBusMessage *, DBusError *, int, ...) = 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; @@ -82,9 +86,12 @@ load_dbus_syms(void) 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_send_with_reply_and_block); SDL_DBUS_SYM(dbus_connection_close); SDL_DBUS_SYM(dbus_connection_unref); SDL_DBUS_SYM(dbus_connection_flush); + SDL_DBUS_SYM(dbus_message_append_args); + SDL_DBUS_SYM(dbus_message_get_args); SDL_DBUS_SYM(dbus_message_new_method_call); SDL_DBUS_SYM(dbus_message_unref); SDL_DBUS_SYM(dbus_error_init); @@ -174,6 +181,76 @@ SDL_dbus_screensaver_tickle(_THIS) } } } + +SDL_bool +SDL_dbus_screensaver_inhibit(_THIS) +{ + const SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + DBusConnection *conn = data->dbus; + + if (conn == NULL) + return SDL_FALSE; + + if (_this->suspend_screensaver && + screensaver_cookie != 0) + return SDL_TRUE; + if (!_this->suspend_screensaver && + screensaver_cookie == 0) + return SDL_TRUE; + + if (_this->suspend_screensaver) { + const char *app = "My SDL application"; + const char *reason = "Playing a game"; + + DBusMessage *msg = DBUS_dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "Inhibit"); + if (msg != NULL) { + DBUS_dbus_message_append_args (msg, + DBUS_TYPE_STRING, &app, + DBUS_TYPE_STRING, &reason, + DBUS_TYPE_INVALID); + } + + if (msg != NULL) { + DBusMessage *reply; + + reply = DBUS_dbus_connection_send_with_reply_and_block(conn, msg, 300, NULL); + if (reply) { + if (!DBUS_dbus_message_get_args(reply, NULL, + DBUS_TYPE_UINT32, &screensaver_cookie, + DBUS_TYPE_INVALID)) + screensaver_cookie = 0; + DBUS_dbus_message_unref(reply); + } + + DBUS_dbus_message_unref(msg); + } + + if (screensaver_cookie == 0) { + return SDL_FALSE; + } + return SDL_TRUE; + } else { + DBusMessage *msg = DBUS_dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "UnInhibit"); + DBUS_dbus_message_append_args (msg, + DBUS_TYPE_UINT32, &screensaver_cookie, + DBUS_TYPE_INVALID); + if (msg != NULL) { + if (DBUS_dbus_connection_send(conn, msg, NULL)) { + DBUS_dbus_connection_flush(conn); + } + DBUS_dbus_message_unref(msg); + } + + screensaver_cookie = 0; + return SDL_TRUE; + } +} #endif /* Initialization/Query functions */ diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 927e38b315994..8ab88f728b0d6 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -121,6 +121,7 @@ typedef struct SDL_VideoData extern SDL_bool X11_UseDirectColorVisuals(void); +SDL_bool SDL_dbus_screensaver_inhibit(_THIS); void SDL_dbus_screensaver_tickle(_THIS); #endif /* _SDL_x11video_h */