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;
66 gboolean old_dbus_api;
68 /* To save the screensaver info */
74 /* For use with XTest */
75 int keycode1, keycode2;
80 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
83 screensaver_is_running_dbus (TotemScrsaver *scr)
85 return scr->priv->have_screensaver_dbus;
89 on_inhibit_cb (GObject *source_object,
93 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
94 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
98 value = g_dbus_proxy_call_finish (proxy, res, &error);
100 if (!scr->priv->old_dbus_api &&
101 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
102 g_return_if_fail (scr->priv->reason != NULL);
103 /* try the old API */
104 scr->priv->old_dbus_api = TRUE;
105 g_dbus_proxy_call (proxy,
107 g_variant_new ("(s)",
109 G_DBUS_CALL_FLAGS_NO_AUTO_START,
115 g_warning ("Problem inhibiting the screensaver: %s", error->message);
117 g_error_free (error);
118 g_object_unref (scr);
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);
130 g_object_unref (scr);
134 on_uninhibit_cb (GObject *source_object,
138 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
139 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
141 GError *error = NULL;
143 value = g_dbus_proxy_call_finish (proxy, res, &error);
145 if (!scr->priv->old_dbus_api &&
146 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
147 /* try the old API */
148 scr->priv->old_dbus_api = TRUE;
149 g_dbus_proxy_call (proxy,
151 g_variant_new ("()"),
152 G_DBUS_CALL_FLAGS_NO_AUTO_START,
158 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
160 g_error_free (error);
161 g_object_unref (scr);
166 /* clear the cookie */
167 scr->priv->cookie = 0;
168 g_variant_unref (value);
170 g_object_unref (scr);
174 screensaver_inhibit_dbus (TotemScrsaver *scr,
177 TotemScrsaverPrivate *priv = scr->priv;
179 if (!priv->have_screensaver_dbus)
182 scr->priv->old_dbus_api = FALSE;
186 g_return_if_fail (scr->priv->reason != NULL);
187 g_dbus_proxy_call (priv->gs_proxy,
189 g_variant_new ("(ss)",
190 g_get_application_name (),
192 G_DBUS_CALL_FLAGS_NO_AUTO_START,
198 g_dbus_proxy_call (priv->gs_proxy,
200 g_variant_new ("(u)", priv->cookie),
201 G_DBUS_CALL_FLAGS_NO_AUTO_START,
210 screensaver_enable_dbus (TotemScrsaver *scr)
212 screensaver_inhibit_dbus (scr, FALSE);
216 screensaver_disable_dbus (TotemScrsaver *scr)
218 screensaver_inhibit_dbus (scr, TRUE);
222 screensaver_update_dbus_presence (TotemScrsaver *scr)
224 TotemScrsaverPrivate *priv = scr->priv;
227 name_owner = g_dbus_proxy_get_name_owner (priv->gs_proxy);
229 priv->have_screensaver_dbus = TRUE;
232 /* screensaver just appeared, or reappeared */
233 if (priv->reason != NULL)
234 screensaver_disable_dbus (scr);
236 priv->have_screensaver_dbus = FALSE;
241 screensaver_dbus_owner_changed_cb (GObject *object,
245 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
247 screensaver_update_dbus_presence (scr);
251 screensaver_dbus_proxy_new_cb (GObject *source,
252 GAsyncResult *result,
255 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
256 TotemScrsaverPrivate *priv = scr->priv;
258 priv->gs_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL);
262 screensaver_update_dbus_presence (scr);
264 g_signal_connect (priv->gs_proxy, "notify::g-name-owner",
265 G_CALLBACK (screensaver_dbus_owner_changed_cb),
270 screensaver_init_dbus (TotemScrsaver *scr)
272 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
273 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
279 screensaver_dbus_proxy_new_cb,
284 screensaver_finalize_dbus (TotemScrsaver *scr)
286 if (scr->priv->gs_proxy) {
287 g_object_unref (scr->priv->gs_proxy);
291 #ifdef GDK_WINDOWING_X11
293 screensaver_enable_x11 (TotemScrsaver *scr)
297 if (scr->priv->have_xtest != FALSE)
299 g_source_remove_by_user_data (scr);
302 #endif /* HAVE_XTEST */
304 XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
305 XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
308 scr->priv->prefer_blanking,
309 scr->priv->allow_exposures);
310 XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
315 fake_event (TotemScrsaver *scr)
317 if (scr->priv->disabled)
319 XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
320 XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
322 XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
324 XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
325 /* Swap the keycode */
326 if (scr->priv->keycode == &scr->priv->keycode1)
327 scr->priv->keycode = &scr->priv->keycode2;
329 scr->priv->keycode = &scr->priv->keycode1;
334 #endif /* HAVE_XTEST */
337 screensaver_disable_x11 (TotemScrsaver *scr)
341 if (scr->priv->have_xtest != FALSE)
343 XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
344 XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
345 &scr->priv->interval,
346 &scr->priv->prefer_blanking,
347 &scr->priv->allow_exposures);
348 XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
350 if (scr->priv->timeout != 0) {
351 g_timeout_add_seconds (scr->priv->timeout / 2,
352 (GSourceFunc) fake_event, scr);
354 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
355 (GSourceFunc) fake_event, scr);
360 #endif /* HAVE_XTEST */
362 XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
363 XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
364 &scr->priv->interval,
365 &scr->priv->prefer_blanking,
366 &scr->priv->allow_exposures);
367 XSetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 0, 0,
368 DontPreferBlanking, DontAllowExposures);
369 XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
373 screensaver_init_x11 (TotemScrsaver *scr)
378 XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
379 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &a, &b, &c, &d) == True);
380 if (scr->priv->have_xtest != FALSE)
382 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
383 if (scr->priv->keycode1 == 0) {
384 g_warning ("scr->priv->keycode1 not existant");
386 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_R);
387 if (scr->priv->keycode2 == 0) {
388 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
389 if (scr->priv->keycode2 == 0) {
390 g_warning ("scr->priv->keycode2 not existant");
393 scr->priv->keycode = &scr->priv->keycode1;
395 XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
396 #endif /* HAVE_XTEST */
400 screensaver_finalize_x11 (TotemScrsaver *scr)
402 g_source_remove_by_user_data (scr);
407 totem_scrsaver_get_property (GObject *object,
414 scr = TOTEM_SCRSAVER (object);
419 g_value_set_string (value, scr->priv->reason);
422 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
427 totem_scrsaver_set_property (GObject *object,
434 scr = TOTEM_SCRSAVER (object);
439 g_free (scr->priv->reason);
440 scr->priv->reason = g_value_dup_string (value);
443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
448 totem_scrsaver_class_init (TotemScrsaverClass *klass)
450 GObjectClass *object_class = G_OBJECT_CLASS (klass);
452 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
454 object_class->set_property = totem_scrsaver_set_property;
455 object_class->get_property = totem_scrsaver_get_property;
456 object_class->finalize = totem_scrsaver_finalize;
458 g_object_class_install_property (object_class, PROP_REASON,
459 g_param_spec_string ("reason", NULL, NULL,
460 NULL, G_PARAM_READWRITE));
465 * totem_scrsaver_new:
467 * Creates a #TotemScrsaver object.
468 * If the GNOME screen saver is running, it uses its DBUS interface to
469 * inhibit the screensaver; otherwise it falls back to using the X
470 * screensaver functionality for this.
472 * Returns: a newly created #TotemScrsaver
475 totem_scrsaver_new (void)
477 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
481 totem_scrsaver_init (TotemScrsaver *scr)
483 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
485 TotemScrsaverPrivate);
487 screensaver_init_dbus (scr);
488 #ifdef GDK_WINDOWING_X11
489 screensaver_init_x11 (scr);
491 #warning Unimplemented
496 totem_scrsaver_disable (TotemScrsaver *scr)
498 g_return_if_fail (TOTEM_SCRSAVER (scr));
500 if (scr->priv->disabled != FALSE)
503 scr->priv->disabled = TRUE;
505 if (screensaver_is_running_dbus (scr) != FALSE)
506 screensaver_disable_dbus (scr);
508 #ifdef GDK_WINDOWING_X11
509 screensaver_disable_x11 (scr);
511 #warning Unimplemented
517 totem_scrsaver_enable (TotemScrsaver *scr)
519 g_return_if_fail (TOTEM_SCRSAVER (scr));
521 if (scr->priv->disabled == FALSE)
524 scr->priv->disabled = FALSE;
526 if (screensaver_is_running_dbus (scr) != FALSE)
527 screensaver_enable_dbus (scr);
529 #ifdef GDK_WINDOWING_X11
530 screensaver_enable_x11 (scr);
532 #warning Unimplemented
538 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
540 g_return_if_fail (TOTEM_SCRSAVER (scr));
542 if (scr->priv->disabled == !enable)
546 totem_scrsaver_disable (scr);
548 totem_scrsaver_enable (scr);
552 totem_scrsaver_finalize (GObject *object)
554 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
556 g_free (scr->priv->reason);
558 screensaver_finalize_dbus (scr);
559 #ifdef GDK_WINDOWING_X11
560 screensaver_finalize_x11 (scr);
562 #warning Unimplemented
566 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);