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
5 Copyright © 2010 Carlos Garcia Campos
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301 USA.
22 Authors: Bastien Nocera <hadess@hadess.net>
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
53 static void totem_scrsaver_finalize (GObject *object);
55 struct TotemScrsaverPrivate {
56 /* Whether the screensaver is disabled */
58 /* The reason for the inhibition */
62 gboolean have_screensaver_dbus;
65 gboolean old_dbus_api;
67 /* To save the screensaver info */
73 /* For use with XTest */
74 int keycode1, keycode2;
79 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
82 screensaver_is_running_dbus (TotemScrsaver *scr)
84 return scr->priv->have_screensaver_dbus;
88 on_inhibit_cb (GObject *source_object,
92 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
93 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
97 value = g_dbus_proxy_call_finish (proxy, res, &error);
99 if (!scr->priv->old_dbus_api &&
100 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
101 g_return_if_fail (scr->priv->reason != NULL);
102 /* try the old API */
103 scr->priv->old_dbus_api = TRUE;
104 g_dbus_proxy_call (proxy,
106 g_variant_new ("(s)",
108 G_DBUS_CALL_FLAGS_NO_AUTO_START,
114 g_warning ("Problem inhibiting the screensaver: %s", error->message);
116 g_error_free (error);
121 /* save the cookie */
122 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
123 g_variant_get (value, "(u)", &scr->priv->cookie);
125 scr->priv->cookie = 0;
126 g_variant_unref (value);
130 on_uninhibit_cb (GObject *source_object,
134 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
135 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
137 GError *error = NULL;
139 value = g_dbus_proxy_call_finish (proxy, res, &error);
141 if (!scr->priv->old_dbus_api &&
142 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
143 /* try the old API */
144 scr->priv->old_dbus_api = TRUE;
145 g_dbus_proxy_call (proxy,
147 g_variant_new ("()"),
148 G_DBUS_CALL_FLAGS_NO_AUTO_START,
154 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
156 g_error_free (error);
161 /* clear the cookie */
162 scr->priv->cookie = 0;
163 g_variant_unref (value);
167 screensaver_inhibit_dbus (TotemScrsaver *scr,
170 TotemScrsaverPrivate *priv = scr->priv;
172 if (!priv->have_screensaver_dbus)
175 scr->priv->old_dbus_api = FALSE;
178 g_return_if_fail (scr->priv->reason != NULL);
179 g_dbus_proxy_call (priv->gs_proxy,
181 g_variant_new ("(ss)",
182 g_get_application_name (),
184 G_DBUS_CALL_FLAGS_NO_AUTO_START,
190 g_dbus_proxy_call (priv->gs_proxy,
192 g_variant_new ("(u)", priv->cookie),
193 G_DBUS_CALL_FLAGS_NO_AUTO_START,
202 screensaver_enable_dbus (TotemScrsaver *scr)
204 screensaver_inhibit_dbus (scr, FALSE);
208 screensaver_disable_dbus (TotemScrsaver *scr)
210 screensaver_inhibit_dbus (scr, TRUE);
214 screensaver_dbus_appeared_cb (GDBusConnection *connection,
216 const gchar *name_owner,
220 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
221 TotemScrsaverPrivate *priv = scr->priv;
223 priv->gs_proxy = g_object_ref (proxy);
225 priv->have_screensaver_dbus = TRUE;
229 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
233 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
234 TotemScrsaverPrivate *priv = scr->priv;
236 if (priv->gs_proxy) {
237 g_object_unref (priv->gs_proxy);
238 priv->gs_proxy = NULL;
241 priv->have_screensaver_dbus = FALSE;
245 screensaver_init_dbus (TotemScrsaver *scr)
247 TotemScrsaverPrivate *priv = scr->priv;
249 priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
251 G_BUS_NAME_WATCHER_FLAGS_NONE,
255 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
256 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
257 screensaver_dbus_appeared_cb,
258 screensaver_dbus_disappeared_cb,
263 screensaver_finalize_dbus (TotemScrsaver *scr)
265 TotemScrsaverPrivate *priv = scr->priv;
267 if (scr->priv->gs_proxy) {
268 g_object_unref (scr->priv->gs_proxy);
271 if (priv->watch_id > 0)
272 g_bus_unwatch_proxy (priv->watch_id);
275 #ifdef GDK_WINDOWING_X11
277 screensaver_enable_x11 (TotemScrsaver *scr)
281 if (scr->priv->have_xtest != FALSE)
283 g_source_remove_by_user_data (scr);
286 #endif /* HAVE_XTEST */
288 XLockDisplay (GDK_DISPLAY());
289 XSetScreenSaver (GDK_DISPLAY(),
292 scr->priv->prefer_blanking,
293 scr->priv->allow_exposures);
294 XUnlockDisplay (GDK_DISPLAY());
299 fake_event (TotemScrsaver *scr)
301 if (scr->priv->disabled)
303 XLockDisplay (GDK_DISPLAY());
304 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
306 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
308 XUnlockDisplay (GDK_DISPLAY());
309 /* Swap the keycode */
310 if (scr->priv->keycode == &scr->priv->keycode1)
311 scr->priv->keycode = &scr->priv->keycode2;
313 scr->priv->keycode = &scr->priv->keycode1;
318 #endif /* HAVE_XTEST */
321 screensaver_disable_x11 (TotemScrsaver *scr)
325 if (scr->priv->have_xtest != FALSE)
327 XLockDisplay (GDK_DISPLAY());
328 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
329 &scr->priv->interval,
330 &scr->priv->prefer_blanking,
331 &scr->priv->allow_exposures);
332 XUnlockDisplay (GDK_DISPLAY());
334 if (scr->priv->timeout != 0) {
335 g_timeout_add_seconds (scr->priv->timeout / 2,
336 (GSourceFunc) fake_event, scr);
338 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
339 (GSourceFunc) fake_event, scr);
344 #endif /* HAVE_XTEST */
346 XLockDisplay (GDK_DISPLAY());
347 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
348 &scr->priv->interval,
349 &scr->priv->prefer_blanking,
350 &scr->priv->allow_exposures);
351 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
352 DontPreferBlanking, DontAllowExposures);
353 XUnlockDisplay (GDK_DISPLAY());
357 screensaver_init_x11 (TotemScrsaver *scr)
362 XLockDisplay (GDK_DISPLAY());
363 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
364 if (scr->priv->have_xtest != FALSE)
366 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
367 if (scr->priv->keycode1 == 0) {
368 g_warning ("scr->priv->keycode1 not existant");
370 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
371 if (scr->priv->keycode2 == 0) {
372 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
373 if (scr->priv->keycode2 == 0) {
374 g_warning ("scr->priv->keycode2 not existant");
377 scr->priv->keycode = &scr->priv->keycode1;
379 XUnlockDisplay (GDK_DISPLAY());
380 #endif /* HAVE_XTEST */
384 screensaver_finalize_x11 (TotemScrsaver *scr)
386 g_source_remove_by_user_data (scr);
391 totem_scrsaver_get_property (GObject *object,
398 scr = TOTEM_SCRSAVER (object);
403 g_value_set_string (value, scr->priv->reason);
406 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
411 totem_scrsaver_set_property (GObject *object,
418 scr = TOTEM_SCRSAVER (object);
423 g_free (scr->priv->reason);
424 scr->priv->reason = g_value_dup_string (value);
427 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
432 totem_scrsaver_class_init (TotemScrsaverClass *klass)
434 GObjectClass *object_class = G_OBJECT_CLASS (klass);
436 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
438 object_class->set_property = totem_scrsaver_set_property;
439 object_class->get_property = totem_scrsaver_get_property;
440 object_class->finalize = totem_scrsaver_finalize;
442 g_object_class_install_property (object_class, PROP_REASON,
443 g_param_spec_string ("reason", NULL, NULL,
444 NULL, G_PARAM_READWRITE));
449 * totem_scrsaver_new:
451 * Creates a #TotemScrsaver object.
452 * If the GNOME screen saver is running, it uses its DBUS interface to
453 * inhibit the screensaver; otherwise it falls back to using the X
454 * screensaver functionality for this.
456 * Returns: a newly created #TotemScrsaver
459 totem_scrsaver_new (void)
461 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
465 totem_scrsaver_init (TotemScrsaver *scr)
467 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
469 TotemScrsaverPrivate);
471 screensaver_init_dbus (scr);
472 #ifdef GDK_WINDOWING_X11
473 screensaver_init_x11 (scr);
475 #warning Unimplemented
480 totem_scrsaver_disable (TotemScrsaver *scr)
482 g_return_if_fail (TOTEM_SCRSAVER (scr));
484 if (scr->priv->disabled != FALSE)
487 scr->priv->disabled = TRUE;
489 if (screensaver_is_running_dbus (scr) != FALSE)
490 screensaver_disable_dbus (scr);
492 #ifdef GDK_WINDOWING_X11
493 screensaver_disable_x11 (scr);
495 #warning Unimplemented
501 totem_scrsaver_enable (TotemScrsaver *scr)
503 g_return_if_fail (TOTEM_SCRSAVER (scr));
505 if (scr->priv->disabled == FALSE)
508 scr->priv->disabled = FALSE;
510 if (screensaver_is_running_dbus (scr) != FALSE)
511 screensaver_enable_dbus (scr);
513 #ifdef GDK_WINDOWING_X11
514 screensaver_enable_x11 (scr);
516 #warning Unimplemented
522 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
524 g_return_if_fail (TOTEM_SCRSAVER (scr));
526 if (scr->priv->disabled == !enable)
530 totem_scrsaver_disable (scr);
532 totem_scrsaver_enable (scr);
536 totem_scrsaver_finalize (GObject *object)
538 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
540 g_free (scr->priv->reason);
542 screensaver_finalize_dbus (scr);
543 #ifdef GDK_WINDOWING_X11
544 screensaver_finalize_x11 (scr);
546 #warning Unimplemented
550 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);