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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index bf0b139..ad3c59d 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 63cfa98..ca9faee 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 927e38b..8ab88f7 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 */