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;
64 gboolean old_dbus_api;
66 /* To save the screensaver info */
72 /* For use with XTest */
73 int keycode1, keycode2;
78 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
81 screensaver_is_running_dbus (TotemScrsaver *scr)
83 return scr->priv->have_screensaver_dbus;
87 on_inhibit_cb (GObject *source_object,
91 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
92 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
96 value = g_dbus_proxy_call_finish (proxy, res, &error);
98 if (!scr->priv->old_dbus_api &&
99 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
100 g_return_if_fail (scr->priv->reason != NULL);
101 /* try the old API */
102 scr->priv->old_dbus_api = TRUE;
103 g_dbus_proxy_call (proxy,
105 g_variant_new ("(s)",
107 G_DBUS_CALL_FLAGS_NO_AUTO_START,
113 g_warning ("Problem inhibiting the screensaver: %s", error->message);
115 g_error_free (error);
120 /* save the cookie */
121 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
122 g_variant_get (value, "(u)", &scr->priv->cookie);
124 scr->priv->cookie = 0;
125 g_variant_unref (value);
129 on_uninhibit_cb (GObject *source_object,
133 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
134 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
136 GError *error = NULL;
138 value = g_dbus_proxy_call_finish (proxy, res, &error);
140 if (!scr->priv->old_dbus_api &&
141 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
142 /* try the old API */
143 scr->priv->old_dbus_api = TRUE;
144 g_dbus_proxy_call (proxy,
146 g_variant_new ("()"),
147 G_DBUS_CALL_FLAGS_NO_AUTO_START,
153 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
155 g_error_free (error);
160 /* clear the cookie */
161 scr->priv->cookie = 0;
162 g_variant_unref (value);
166 screensaver_inhibit_dbus (TotemScrsaver *scr,
169 TotemScrsaverPrivate *priv = scr->priv;
171 if (!priv->have_screensaver_dbus)
174 scr->priv->old_dbus_api = FALSE;
177 g_return_if_fail (scr->priv->reason != NULL);
178 g_dbus_proxy_call (priv->gs_proxy,
180 g_variant_new ("(ss)",
181 g_get_application_name (),
183 G_DBUS_CALL_FLAGS_NO_AUTO_START,
189 g_dbus_proxy_call (priv->gs_proxy,
191 g_variant_new ("(u)", priv->cookie),
192 G_DBUS_CALL_FLAGS_NO_AUTO_START,
201 screensaver_enable_dbus (TotemScrsaver *scr)
203 screensaver_inhibit_dbus (scr, FALSE);
207 screensaver_disable_dbus (TotemScrsaver *scr)
209 screensaver_inhibit_dbus (scr, TRUE);
213 screensaver_update_dbus_presence (TotemScrsaver *scr)
215 TotemScrsaverPrivate *priv = scr->priv;
218 name_owner = g_dbus_proxy_get_name_owner (priv->gs_proxy);
220 priv->have_screensaver_dbus = TRUE;
223 priv->have_screensaver_dbus = FALSE;
228 screensaver_dbus_owner_changed_cb (GObject *object,
232 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
234 screensaver_update_dbus_presence (scr);
238 screensaver_dbus_proxy_new_cb (GObject *source,
239 GAsyncResult *result,
242 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
243 TotemScrsaverPrivate *priv = scr->priv;
245 priv->gs_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL);
249 screensaver_update_dbus_presence (scr);
251 g_signal_connect (priv->gs_proxy, "notify::g-name-owner",
252 G_CALLBACK (screensaver_dbus_owner_changed_cb),
257 screensaver_init_dbus (TotemScrsaver *scr)
259 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
260 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
266 screensaver_dbus_proxy_new_cb,
271 screensaver_finalize_dbus (TotemScrsaver *scr)
273 if (scr->priv->gs_proxy) {
274 g_object_unref (scr->priv->gs_proxy);
278 #ifdef GDK_WINDOWING_X11
280 screensaver_enable_x11 (TotemScrsaver *scr)
284 if (scr->priv->have_xtest != FALSE)
286 g_source_remove_by_user_data (scr);
289 #endif /* HAVE_XTEST */
291 XLockDisplay (GDK_DISPLAY());
292 XSetScreenSaver (GDK_DISPLAY(),
295 scr->priv->prefer_blanking,
296 scr->priv->allow_exposures);
297 XUnlockDisplay (GDK_DISPLAY());
302 fake_event (TotemScrsaver *scr)
304 if (scr->priv->disabled)
306 XLockDisplay (GDK_DISPLAY());
307 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
309 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
311 XUnlockDisplay (GDK_DISPLAY());
312 /* Swap the keycode */
313 if (scr->priv->keycode == &scr->priv->keycode1)
314 scr->priv->keycode = &scr->priv->keycode2;
316 scr->priv->keycode = &scr->priv->keycode1;
321 #endif /* HAVE_XTEST */
324 screensaver_disable_x11 (TotemScrsaver *scr)
328 if (scr->priv->have_xtest != FALSE)
330 XLockDisplay (GDK_DISPLAY());
331 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
332 &scr->priv->interval,
333 &scr->priv->prefer_blanking,
334 &scr->priv->allow_exposures);
335 XUnlockDisplay (GDK_DISPLAY());
337 if (scr->priv->timeout != 0) {
338 g_timeout_add_seconds (scr->priv->timeout / 2,
339 (GSourceFunc) fake_event, scr);
341 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
342 (GSourceFunc) fake_event, scr);
347 #endif /* HAVE_XTEST */
349 XLockDisplay (GDK_DISPLAY());
350 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
351 &scr->priv->interval,
352 &scr->priv->prefer_blanking,
353 &scr->priv->allow_exposures);
354 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
355 DontPreferBlanking, DontAllowExposures);
356 XUnlockDisplay (GDK_DISPLAY());
360 screensaver_init_x11 (TotemScrsaver *scr)
365 XLockDisplay (GDK_DISPLAY());
366 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
367 if (scr->priv->have_xtest != FALSE)
369 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
370 if (scr->priv->keycode1 == 0) {
371 g_warning ("scr->priv->keycode1 not existant");
373 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
374 if (scr->priv->keycode2 == 0) {
375 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
376 if (scr->priv->keycode2 == 0) {
377 g_warning ("scr->priv->keycode2 not existant");
380 scr->priv->keycode = &scr->priv->keycode1;
382 XUnlockDisplay (GDK_DISPLAY());
383 #endif /* HAVE_XTEST */
387 screensaver_finalize_x11 (TotemScrsaver *scr)
389 g_source_remove_by_user_data (scr);
394 totem_scrsaver_get_property (GObject *object,
401 scr = TOTEM_SCRSAVER (object);
406 g_value_set_string (value, scr->priv->reason);
409 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
414 totem_scrsaver_set_property (GObject *object,
421 scr = TOTEM_SCRSAVER (object);
426 g_free (scr->priv->reason);
427 scr->priv->reason = g_value_dup_string (value);
430 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
435 totem_scrsaver_class_init (TotemScrsaverClass *klass)
437 GObjectClass *object_class = G_OBJECT_CLASS (klass);
439 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
441 object_class->set_property = totem_scrsaver_set_property;
442 object_class->get_property = totem_scrsaver_get_property;
443 object_class->finalize = totem_scrsaver_finalize;
445 g_object_class_install_property (object_class, PROP_REASON,
446 g_param_spec_string ("reason", NULL, NULL,
447 NULL, G_PARAM_READWRITE));
452 * totem_scrsaver_new:
454 * Creates a #TotemScrsaver object.
455 * If the GNOME screen saver is running, it uses its DBUS interface to
456 * inhibit the screensaver; otherwise it falls back to using the X
457 * screensaver functionality for this.
459 * Returns: a newly created #TotemScrsaver
462 totem_scrsaver_new (void)
464 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
468 totem_scrsaver_init (TotemScrsaver *scr)
470 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
472 TotemScrsaverPrivate);
474 screensaver_init_dbus (scr);
475 #ifdef GDK_WINDOWING_X11
476 screensaver_init_x11 (scr);
478 #warning Unimplemented
483 totem_scrsaver_disable (TotemScrsaver *scr)
485 g_return_if_fail (TOTEM_SCRSAVER (scr));
487 if (scr->priv->disabled != FALSE)
490 scr->priv->disabled = TRUE;
492 if (screensaver_is_running_dbus (scr) != FALSE)
493 screensaver_disable_dbus (scr);
495 #ifdef GDK_WINDOWING_X11
496 screensaver_disable_x11 (scr);
498 #warning Unimplemented
504 totem_scrsaver_enable (TotemScrsaver *scr)
506 g_return_if_fail (TOTEM_SCRSAVER (scr));
508 if (scr->priv->disabled == FALSE)
511 scr->priv->disabled = FALSE;
513 if (screensaver_is_running_dbus (scr) != FALSE)
514 screensaver_enable_dbus (scr);
516 #ifdef GDK_WINDOWING_X11
517 screensaver_enable_x11 (scr);
519 #warning Unimplemented
525 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
527 g_return_if_fail (TOTEM_SCRSAVER (scr));
529 if (scr->priv->disabled == !enable)
533 totem_scrsaver_disable (scr);
535 totem_scrsaver_enable (scr);
539 totem_scrsaver_finalize (GObject *object)
541 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
543 g_free (scr->priv->reason);
545 screensaver_finalize_dbus (scr);
546 #ifdef GDK_WINDOWING_X11
547 screensaver_finalize_x11 (scr);
549 #warning Unimplemented
553 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);