1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 Copyright (C) 2004-2006 Bastien Nocera <hadess@hadess.net>
4 Copyright © 2010 Christian Persch
6 The Gnome Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301 USA.
21 Author: Bastien Nocera <hadess@hadess.net>
27 #include <glib/gi18n.h>
31 #ifdef GDK_WINDOWING_X11
33 #include <X11/keysym.h>
36 #include <X11/extensions/XTest.h>
37 #endif /* HAVE_XTEST */
38 #endif /* GDK_WINDOWING_X11 */
40 #include "totem-scrsaver.h"
42 #define GS_SERVICE "org.gnome.ScreenSaver"
43 #define GS_PATH "/org/gnome/ScreenSaver"
44 #define GS_INTERFACE "org.gnome.ScreenSaver"
46 #define XSCREENSAVER_MIN_TIMEOUT 60
48 static GObjectClass *parent_class = NULL;
49 static void totem_scrsaver_finalize (GObject *object);
51 struct TotemScrsaverPrivate {
52 /* Whether the screensaver is disabled */
56 gboolean have_screensaver_dbus;
60 /* To save the screensaver info */
66 /* For use with XTest */
67 int keycode1, keycode2;
72 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
75 screensaver_is_running_dbus (TotemScrsaver *scr)
77 return scr->priv->have_screensaver_dbus;
81 screensaver_inhibit_dbus (TotemScrsaver *scr,
84 TotemScrsaverPrivate *priv = scr->priv;
88 if (!priv->have_screensaver_dbus)
92 value = g_dbus_proxy_call_sync (priv->gs_proxy,
94 g_variant_new ("(ss)",
96 _("Running in presentation mode")),
97 G_DBUS_CALL_FLAGS_NO_AUTO_START,
101 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
102 /* try the old API */
103 g_clear_error (&error);
104 value = g_dbus_proxy_call_sync (priv->gs_proxy,
106 g_variant_new ("(s)",
107 _("Running in presentation mode")),
108 G_DBUS_CALL_FLAGS_NO_AUTO_START,
114 /* save the cookie */
115 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
116 g_variant_get (value, "(u)", &priv->cookie);
119 g_variant_unref (value);
121 g_warning ("Problem inhibiting the screensaver: %s", error->message);
122 g_error_free (error);
126 value = g_dbus_proxy_call_sync (priv->gs_proxy,
128 g_variant_new ("(u)", priv->cookie),
129 G_DBUS_CALL_FLAGS_NO_AUTO_START,
133 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
134 /* try the old API */
135 g_clear_error (&error);
136 value = g_dbus_proxy_call_sync (priv->gs_proxy,
138 g_variant_new ("()"),
139 G_DBUS_CALL_FLAGS_NO_AUTO_START,
145 /* clear the cookie */
147 g_variant_unref (value);
149 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
150 g_error_free (error);
156 screensaver_enable_dbus (TotemScrsaver *scr)
158 screensaver_inhibit_dbus (scr, FALSE);
162 screensaver_disable_dbus (TotemScrsaver *scr)
164 screensaver_inhibit_dbus (scr, TRUE);
168 screensaver_dbus_appeared_cb (GDBusConnection *connection,
170 const gchar *name_owner,
174 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
175 TotemScrsaverPrivate *priv = scr->priv;
177 priv->gs_proxy = g_object_ref (proxy);
179 priv->have_screensaver_dbus = TRUE;
183 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
187 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
188 TotemScrsaverPrivate *priv = scr->priv;
190 if (priv->gs_proxy) {
191 g_object_unref (priv->gs_proxy);
192 priv->gs_proxy = NULL;
195 priv->have_screensaver_dbus = FALSE;
199 screensaver_init_dbus (TotemScrsaver *scr)
201 TotemScrsaverPrivate *priv = scr->priv;
203 priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
205 G_BUS_NAME_WATCHER_FLAGS_NONE,
209 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
210 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
211 screensaver_dbus_appeared_cb,
212 screensaver_dbus_disappeared_cb,
217 screensaver_finalize_dbus (TotemScrsaver *scr)
219 TotemScrsaverPrivate *priv = scr->priv;
221 if (scr->priv->gs_proxy) {
222 g_object_unref (scr->priv->gs_proxy);
225 if (priv->watch_id > 0)
226 g_bus_unwatch_proxy (priv->watch_id);
229 #ifdef GDK_WINDOWING_X11
231 screensaver_enable_x11 (TotemScrsaver *scr)
235 if (scr->priv->have_xtest != FALSE)
237 g_source_remove_by_user_data (scr);
240 #endif /* HAVE_XTEST */
242 XLockDisplay (GDK_DISPLAY());
243 XSetScreenSaver (GDK_DISPLAY(),
246 scr->priv->prefer_blanking,
247 scr->priv->allow_exposures);
248 XUnlockDisplay (GDK_DISPLAY());
253 fake_event (TotemScrsaver *scr)
255 if (scr->priv->disabled)
257 XLockDisplay (GDK_DISPLAY());
258 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
260 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
262 XUnlockDisplay (GDK_DISPLAY());
263 /* Swap the keycode */
264 if (scr->priv->keycode == &scr->priv->keycode1)
265 scr->priv->keycode = &scr->priv->keycode2;
267 scr->priv->keycode = &scr->priv->keycode1;
272 #endif /* HAVE_XTEST */
275 screensaver_disable_x11 (TotemScrsaver *scr)
279 if (scr->priv->have_xtest != FALSE)
281 XLockDisplay (GDK_DISPLAY());
282 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
283 &scr->priv->interval,
284 &scr->priv->prefer_blanking,
285 &scr->priv->allow_exposures);
286 XUnlockDisplay (GDK_DISPLAY());
288 if (scr->priv->timeout != 0) {
289 g_timeout_add_seconds (scr->priv->timeout / 2,
290 (GSourceFunc) fake_event, scr);
292 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
293 (GSourceFunc) fake_event, scr);
298 #endif /* HAVE_XTEST */
300 XLockDisplay (GDK_DISPLAY());
301 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
302 &scr->priv->interval,
303 &scr->priv->prefer_blanking,
304 &scr->priv->allow_exposures);
305 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
306 DontPreferBlanking, DontAllowExposures);
307 XUnlockDisplay (GDK_DISPLAY());
311 screensaver_init_x11 (TotemScrsaver *scr)
316 XLockDisplay (GDK_DISPLAY());
317 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
318 if (scr->priv->have_xtest != FALSE)
320 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
321 if (scr->priv->keycode1 == 0) {
322 g_warning ("scr->priv->keycode1 not existant");
324 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
325 if (scr->priv->keycode2 == 0) {
326 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
327 if (scr->priv->keycode2 == 0) {
328 g_warning ("scr->priv->keycode2 not existant");
331 scr->priv->keycode = &scr->priv->keycode1;
333 XUnlockDisplay (GDK_DISPLAY());
334 #endif /* HAVE_XTEST */
338 screensaver_finalize_x11 (TotemScrsaver *scr)
340 g_source_remove_by_user_data (scr);
345 totem_scrsaver_class_init (TotemScrsaverClass *klass)
347 GObjectClass *object_class = G_OBJECT_CLASS (klass);
349 parent_class = g_type_class_peek_parent (klass);
351 object_class->finalize = totem_scrsaver_finalize;
355 * totem_scrsaver_new:
357 * Creates a #TotemScrsaver object.
358 * If the GNOME screen saver is running, it uses its DBUS interface to
359 * inhibit the screensaver; otherwise it falls back to using the X
360 * screensaver functionality for this.
362 * Returns: a newly created #TotemScrsaver
365 totem_scrsaver_new (void)
367 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
371 totem_scrsaver_init (TotemScrsaver *scr)
373 scr->priv = g_new0 (TotemScrsaverPrivate, 1);
375 screensaver_init_dbus (scr);
376 #ifdef GDK_WINDOWING_X11
377 screensaver_init_x11 (scr);
379 #warning Unimplemented
384 totem_scrsaver_disable (TotemScrsaver *scr)
386 g_return_if_fail (TOTEM_SCRSAVER (scr));
388 if (scr->priv->disabled != FALSE)
391 scr->priv->disabled = TRUE;
393 if (screensaver_is_running_dbus (scr) != FALSE)
394 screensaver_disable_dbus (scr);
396 #ifdef GDK_WINDOWING_X11
397 screensaver_disable_x11 (scr);
399 #warning Unimplemented
405 totem_scrsaver_enable (TotemScrsaver *scr)
407 g_return_if_fail (TOTEM_SCRSAVER (scr));
409 if (scr->priv->disabled == FALSE)
412 scr->priv->disabled = FALSE;
414 if (screensaver_is_running_dbus (scr) != FALSE)
415 screensaver_enable_dbus (scr);
417 #ifdef GDK_WINDOWING_X11
418 screensaver_enable_x11 (scr);
420 #warning Unimplemented
426 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
428 g_return_if_fail (TOTEM_SCRSAVER (scr));
430 if (scr->priv->disabled == !enable)
434 totem_scrsaver_disable (scr);
436 totem_scrsaver_enable (scr);
440 totem_scrsaver_finalize (GObject *object)
442 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
444 screensaver_finalize_dbus (scr);
445 #ifdef GDK_WINDOWING_X11
446 screensaver_finalize_x11 (scr);
448 #warning Unimplemented
452 G_OBJECT_CLASS (parent_class)->finalize (object);