From 1cb16b56ab951dc62e76f565490c5b9bc19d3c02 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 21 Oct 2013 16:52:59 +0200 Subject: [PATCH] X11: Add support for fd.o Idle Inhibition 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 | 19 +++++++---- src/video/x11/SDL_x11video.c | 77 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index ba5eca3..ab65cf5 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -953,6 +953,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); +SDL_bool SDL_dbus_screensaver_inhibit(_THIS); void X11_PumpEvents(_THIS) @@ -991,7 +992,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) || @@ -1005,12 +1018,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 c84d4ec..eed8737 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 */ -- 1.8.4.2