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>
29 #include <glib/gi18n.h>
33 #ifdef GDK_WINDOWING_X11
35 #include <X11/keysym.h>
38 #include <X11/extensions/XTest.h>
39 #endif /* HAVE_XTEST */
40 #endif /* GDK_WINDOWING_X11 */
42 #include "totem-scrsaver.h"
44 #define GS_SERVICE "org.gnome.ScreenSaver"
45 #define GS_PATH "/org/gnome/ScreenSaver"
46 #define GS_INTERFACE "org.gnome.ScreenSaver"
48 #define XSCREENSAVER_MIN_TIMEOUT 60
55 static void totem_scrsaver_finalize (GObject *object);
57 struct TotemScrsaverPrivate {
58 /* Whether the screensaver is disabled */
60 /* The reason for the inhibition */
64 gboolean have_screensaver_dbus;
67 gboolean old_dbus_api;
69 /* To save the screensaver info */
75 /* For use with XTest */
76 int keycode1, keycode2;
81 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
84 screensaver_is_running_dbus (TotemScrsaver *scr)
86 return scr->priv->have_screensaver_dbus;
90 on_inhibit_cb (GObject *source_object,
94 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
95 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
99 value = g_dbus_proxy_call_finish (proxy, res, &error);
101 if (!scr->priv->old_dbus_api &&
102 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
103 g_return_if_fail (scr->priv->reason != NULL);
104 /* try the old API */
105 scr->priv->old_dbus_api = TRUE;
106 g_dbus_proxy_call (proxy,
108 g_variant_new ("(s)",
110 G_DBUS_CALL_FLAGS_NO_AUTO_START,
116 g_warning ("Problem inhibiting the screensaver: %s", error->message);
118 g_error_free (error);
123 /* save the cookie */
124 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
125 g_variant_get (value, "(u)", &scr->priv->cookie);
127 scr->priv->cookie = 0;
128 g_variant_unref (value);
132 on_uninhibit_cb (GObject *source_object,
136 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
137 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
139 GError *error = NULL;
141 value = g_dbus_proxy_call_finish (proxy, res, &error);
143 if (!scr->priv->old_dbus_api &&
144 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
145 /* try the old API */
146 scr->priv->old_dbus_api = TRUE;
147 g_dbus_proxy_call (proxy,
149 g_variant_new ("()"),
150 G_DBUS_CALL_FLAGS_NO_AUTO_START,
156 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
158 g_error_free (error);
163 /* clear the cookie */
164 scr->priv->cookie = 0;
165 g_variant_unref (value);
169 screensaver_inhibit_dbus (TotemScrsaver *scr,
172 TotemScrsaverPrivate *priv = scr->priv;
174 if (!priv->have_screensaver_dbus)
177 scr->priv->old_dbus_api = FALSE;
180 g_return_if_fail (scr->priv->reason != NULL);
181 g_dbus_proxy_call (priv->gs_proxy,
183 g_variant_new ("(ss)",
184 g_get_application_name (),
186 G_DBUS_CALL_FLAGS_NO_AUTO_START,
192 g_dbus_proxy_call (priv->gs_proxy,
194 g_variant_new ("(u)", priv->cookie),
195 G_DBUS_CALL_FLAGS_NO_AUTO_START,
204 screensaver_enable_dbus (TotemScrsaver *scr)
206 screensaver_inhibit_dbus (scr, FALSE);
210 screensaver_disable_dbus (TotemScrsaver *scr)
212 screensaver_inhibit_dbus (scr, TRUE);
216 screensaver_dbus_appeared_cb (GDBusConnection *connection,
218 const gchar *name_owner,
222 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
223 TotemScrsaverPrivate *priv = scr->priv;
225 priv->gs_proxy = g_object_ref (proxy);
227 priv->have_screensaver_dbus = TRUE;
231 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
235 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
236 TotemScrsaverPrivate *priv = scr->priv;
238 if (priv->gs_proxy) {
239 g_object_unref (priv->gs_proxy);
240 priv->gs_proxy = NULL;
243 priv->have_screensaver_dbus = FALSE;
247 screensaver_init_dbus (TotemScrsaver *scr)
249 TotemScrsaverPrivate *priv = scr->priv;
251 priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
253 G_BUS_NAME_WATCHER_FLAGS_NONE,
257 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
258 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
259 screensaver_dbus_appeared_cb,
260 screensaver_dbus_disappeared_cb,
265 screensaver_finalize_dbus (TotemScrsaver *scr)
267 TotemScrsaverPrivate *priv = scr->priv;
269 if (scr->priv->gs_proxy) {
270 g_object_unref (scr->priv->gs_proxy);
273 if (priv->watch_id > 0)
274 g_bus_unwatch_proxy (priv->watch_id);
277 #ifdef GDK_WINDOWING_X11
279 screensaver_enable_x11 (TotemScrsaver *scr)
283 if (scr->priv->have_xtest != FALSE)
285 g_source_remove_by_user_data (scr);
288 #endif /* HAVE_XTEST */
290 XLockDisplay (GDK_DISPLAY());
291 XSetScreenSaver (GDK_DISPLAY(),
294 scr->priv->prefer_blanking,
295 scr->priv->allow_exposures);
296 XUnlockDisplay (GDK_DISPLAY());
301 fake_event (TotemScrsaver *scr)
303 if (scr->priv->disabled)
305 XLockDisplay (GDK_DISPLAY());
306 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
308 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
310 XUnlockDisplay (GDK_DISPLAY());
311 /* Swap the keycode */
312 if (scr->priv->keycode == &scr->priv->keycode1)
313 scr->priv->keycode = &scr->priv->keycode2;
315 scr->priv->keycode = &scr->priv->keycode1;
320 #endif /* HAVE_XTEST */
323 screensaver_disable_x11 (TotemScrsaver *scr)
327 if (scr->priv->have_xtest != FALSE)
329 XLockDisplay (GDK_DISPLAY());
330 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
331 &scr->priv->interval,
332 &scr->priv->prefer_blanking,
333 &scr->priv->allow_exposures);
334 XUnlockDisplay (GDK_DISPLAY());
336 if (scr->priv->timeout != 0) {
337 g_timeout_add_seconds (scr->priv->timeout / 2,
338 (GSourceFunc) fake_event, scr);
340 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
341 (GSourceFunc) fake_event, scr);
346 #endif /* HAVE_XTEST */
348 XLockDisplay (GDK_DISPLAY());
349 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
350 &scr->priv->interval,
351 &scr->priv->prefer_blanking,
352 &scr->priv->allow_exposures);
353 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
354 DontPreferBlanking, DontAllowExposures);
355 XUnlockDisplay (GDK_DISPLAY());
359 screensaver_init_x11 (TotemScrsaver *scr)
364 XLockDisplay (GDK_DISPLAY());
365 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
366 if (scr->priv->have_xtest != FALSE)
368 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
369 if (scr->priv->keycode1 == 0) {
370 g_warning ("scr->priv->keycode1 not existant");
372 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
373 if (scr->priv->keycode2 == 0) {
374 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
375 if (scr->priv->keycode2 == 0) {
376 g_warning ("scr->priv->keycode2 not existant");
379 scr->priv->keycode = &scr->priv->keycode1;
381 XUnlockDisplay (GDK_DISPLAY());
382 #endif /* HAVE_XTEST */
386 screensaver_finalize_x11 (TotemScrsaver *scr)
388 g_source_remove_by_user_data (scr);
393 totem_scrsaver_get_property (GObject *object,
400 scr = TOTEM_SCRSAVER (object);
405 g_value_set_string (value, scr->priv->reason);
408 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
413 totem_scrsaver_set_property (GObject *object,
420 scr = TOTEM_SCRSAVER (object);
425 g_free (scr->priv->reason);
426 scr->priv->reason = g_value_dup_string (value);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
434 totem_scrsaver_class_init (TotemScrsaverClass *klass)
436 GObjectClass *object_class = G_OBJECT_CLASS (klass);
438 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
440 object_class->set_property = totem_scrsaver_set_property;
441 object_class->get_property = totem_scrsaver_get_property;
442 object_class->finalize = totem_scrsaver_finalize;
444 g_object_class_install_property (object_class, PROP_REASON,
445 g_param_spec_string ("reason", NULL, NULL,
446 NULL, G_PARAM_READWRITE));
451 * totem_scrsaver_new:
453 * Creates a #TotemScrsaver object.
454 * If the GNOME screen saver is running, it uses its DBUS interface to
455 * inhibit the screensaver; otherwise it falls back to using the X
456 * screensaver functionality for this.
458 * Returns: a newly created #TotemScrsaver
461 totem_scrsaver_new (void)
463 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
467 totem_scrsaver_init (TotemScrsaver *scr)
469 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
471 TotemScrsaverPrivate);
473 screensaver_init_dbus (scr);
474 #ifdef GDK_WINDOWING_X11
475 screensaver_init_x11 (scr);
477 #warning Unimplemented
482 totem_scrsaver_disable (TotemScrsaver *scr)
484 g_return_if_fail (TOTEM_SCRSAVER (scr));
486 if (scr->priv->disabled != FALSE)
489 scr->priv->disabled = TRUE;
491 if (screensaver_is_running_dbus (scr) != FALSE)
492 screensaver_disable_dbus (scr);
494 #ifdef GDK_WINDOWING_X11
495 screensaver_disable_x11 (scr);
497 #warning Unimplemented
503 totem_scrsaver_enable (TotemScrsaver *scr)
505 g_return_if_fail (TOTEM_SCRSAVER (scr));
507 if (scr->priv->disabled == FALSE)
510 scr->priv->disabled = FALSE;
512 if (screensaver_is_running_dbus (scr) != FALSE)
513 screensaver_enable_dbus (scr);
515 #ifdef GDK_WINDOWING_X11
516 screensaver_enable_x11 (scr);
518 #warning Unimplemented
524 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
526 g_return_if_fail (TOTEM_SCRSAVER (scr));
528 if (scr->priv->disabled == !enable)
532 totem_scrsaver_disable (scr);
534 totem_scrsaver_enable (scr);
538 totem_scrsaver_finalize (GObject *object)
540 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
542 g_free (scr->priv->reason);
544 screensaver_finalize_dbus (scr);
545 #ifdef GDK_WINDOWING_X11
546 screensaver_finalize_x11 (scr);
548 #warning Unimplemented
552 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);