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
50 static void totem_scrsaver_finalize (GObject *object);
52 struct TotemScrsaverPrivate {
53 /* Whether the screensaver is disabled */
57 gboolean have_screensaver_dbus;
60 gboolean old_dbus_api;
62 /* To save the screensaver info */
68 /* For use with XTest */
69 int keycode1, keycode2;
74 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
77 screensaver_is_running_dbus (TotemScrsaver *scr)
79 return scr->priv->have_screensaver_dbus;
83 on_inhibit_cb (GObject *source_object,
87 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
88 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
92 value = g_dbus_proxy_call_finish (proxy, res, &error);
94 if (!scr->priv->old_dbus_api &&
95 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
97 scr->priv->old_dbus_api = TRUE;
98 g_dbus_proxy_call (proxy,
100 g_variant_new ("(s)",
101 _("Running in presentation mode")),
102 G_DBUS_CALL_FLAGS_NO_AUTO_START,
108 g_warning ("Problem inhibiting the screensaver: %s", error->message);
110 g_error_free (error);
115 /* save the cookie */
116 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
117 g_variant_get (value, "(u)", &scr->priv->cookie);
119 scr->priv->cookie = 0;
120 g_variant_unref (value);
124 on_uninhibit_cb (GObject *source_object,
128 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
129 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
131 GError *error = NULL;
133 value = g_dbus_proxy_call_finish (proxy, res, &error);
135 if (!scr->priv->old_dbus_api &&
136 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
137 /* try the old API */
138 scr->priv->old_dbus_api = TRUE;
139 g_dbus_proxy_call (proxy,
141 g_variant_new ("()"),
142 G_DBUS_CALL_FLAGS_NO_AUTO_START,
148 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
150 g_error_free (error);
155 /* clear the cookie */
156 scr->priv->cookie = 0;
157 g_variant_unref (value);
161 screensaver_inhibit_dbus (TotemScrsaver *scr,
164 TotemScrsaverPrivate *priv = scr->priv;
166 if (!priv->have_screensaver_dbus)
169 scr->priv->old_dbus_api = FALSE;
172 g_dbus_proxy_call (priv->gs_proxy,
174 g_variant_new ("(ss)",
176 _("Running in presentation mode")),
177 G_DBUS_CALL_FLAGS_NO_AUTO_START,
183 g_dbus_proxy_call (priv->gs_proxy,
185 g_variant_new ("(u)", priv->cookie),
186 G_DBUS_CALL_FLAGS_NO_AUTO_START,
195 screensaver_enable_dbus (TotemScrsaver *scr)
197 screensaver_inhibit_dbus (scr, FALSE);
201 screensaver_disable_dbus (TotemScrsaver *scr)
203 screensaver_inhibit_dbus (scr, TRUE);
207 screensaver_dbus_appeared_cb (GDBusConnection *connection,
209 const gchar *name_owner,
213 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
214 TotemScrsaverPrivate *priv = scr->priv;
216 priv->gs_proxy = g_object_ref (proxy);
218 priv->have_screensaver_dbus = TRUE;
222 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
226 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
227 TotemScrsaverPrivate *priv = scr->priv;
229 if (priv->gs_proxy) {
230 g_object_unref (priv->gs_proxy);
231 priv->gs_proxy = NULL;
234 priv->have_screensaver_dbus = FALSE;
238 screensaver_init_dbus (TotemScrsaver *scr)
240 TotemScrsaverPrivate *priv = scr->priv;
242 priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
244 G_BUS_NAME_WATCHER_FLAGS_NONE,
248 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
249 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
250 screensaver_dbus_appeared_cb,
251 screensaver_dbus_disappeared_cb,
256 screensaver_finalize_dbus (TotemScrsaver *scr)
258 TotemScrsaverPrivate *priv = scr->priv;
260 if (scr->priv->gs_proxy) {
261 g_object_unref (scr->priv->gs_proxy);
264 if (priv->watch_id > 0)
265 g_bus_unwatch_proxy (priv->watch_id);
268 #ifdef GDK_WINDOWING_X11
270 screensaver_enable_x11 (TotemScrsaver *scr)
274 if (scr->priv->have_xtest != FALSE)
276 g_source_remove_by_user_data (scr);
279 #endif /* HAVE_XTEST */
281 XLockDisplay (GDK_DISPLAY());
282 XSetScreenSaver (GDK_DISPLAY(),
285 scr->priv->prefer_blanking,
286 scr->priv->allow_exposures);
287 XUnlockDisplay (GDK_DISPLAY());
292 fake_event (TotemScrsaver *scr)
294 if (scr->priv->disabled)
296 XLockDisplay (GDK_DISPLAY());
297 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
299 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
301 XUnlockDisplay (GDK_DISPLAY());
302 /* Swap the keycode */
303 if (scr->priv->keycode == &scr->priv->keycode1)
304 scr->priv->keycode = &scr->priv->keycode2;
306 scr->priv->keycode = &scr->priv->keycode1;
311 #endif /* HAVE_XTEST */
314 screensaver_disable_x11 (TotemScrsaver *scr)
318 if (scr->priv->have_xtest != FALSE)
320 XLockDisplay (GDK_DISPLAY());
321 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
322 &scr->priv->interval,
323 &scr->priv->prefer_blanking,
324 &scr->priv->allow_exposures);
325 XUnlockDisplay (GDK_DISPLAY());
327 if (scr->priv->timeout != 0) {
328 g_timeout_add_seconds (scr->priv->timeout / 2,
329 (GSourceFunc) fake_event, scr);
331 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
332 (GSourceFunc) fake_event, scr);
337 #endif /* HAVE_XTEST */
339 XLockDisplay (GDK_DISPLAY());
340 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
341 &scr->priv->interval,
342 &scr->priv->prefer_blanking,
343 &scr->priv->allow_exposures);
344 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
345 DontPreferBlanking, DontAllowExposures);
346 XUnlockDisplay (GDK_DISPLAY());
350 screensaver_init_x11 (TotemScrsaver *scr)
355 XLockDisplay (GDK_DISPLAY());
356 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
357 if (scr->priv->have_xtest != FALSE)
359 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
360 if (scr->priv->keycode1 == 0) {
361 g_warning ("scr->priv->keycode1 not existant");
363 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
364 if (scr->priv->keycode2 == 0) {
365 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
366 if (scr->priv->keycode2 == 0) {
367 g_warning ("scr->priv->keycode2 not existant");
370 scr->priv->keycode = &scr->priv->keycode1;
372 XUnlockDisplay (GDK_DISPLAY());
373 #endif /* HAVE_XTEST */
377 screensaver_finalize_x11 (TotemScrsaver *scr)
379 g_source_remove_by_user_data (scr);
384 totem_scrsaver_class_init (TotemScrsaverClass *klass)
386 GObjectClass *object_class = G_OBJECT_CLASS (klass);
388 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
390 object_class->finalize = totem_scrsaver_finalize;
394 * totem_scrsaver_new:
396 * Creates a #TotemScrsaver object.
397 * If the GNOME screen saver is running, it uses its DBUS interface to
398 * inhibit the screensaver; otherwise it falls back to using the X
399 * screensaver functionality for this.
401 * Returns: a newly created #TotemScrsaver
404 totem_scrsaver_new (void)
406 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
410 totem_scrsaver_init (TotemScrsaver *scr)
412 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
414 TotemScrsaverPrivate);
416 screensaver_init_dbus (scr);
417 #ifdef GDK_WINDOWING_X11
418 screensaver_init_x11 (scr);
420 #warning Unimplemented
425 totem_scrsaver_disable (TotemScrsaver *scr)
427 g_return_if_fail (TOTEM_SCRSAVER (scr));
429 if (scr->priv->disabled != FALSE)
432 scr->priv->disabled = TRUE;
434 if (screensaver_is_running_dbus (scr) != FALSE)
435 screensaver_disable_dbus (scr);
437 #ifdef GDK_WINDOWING_X11
438 screensaver_disable_x11 (scr);
440 #warning Unimplemented
446 totem_scrsaver_enable (TotemScrsaver *scr)
448 g_return_if_fail (TOTEM_SCRSAVER (scr));
450 if (scr->priv->disabled == FALSE)
453 scr->priv->disabled = FALSE;
455 if (screensaver_is_running_dbus (scr) != FALSE)
456 screensaver_enable_dbus (scr);
458 #ifdef GDK_WINDOWING_X11
459 screensaver_enable_x11 (scr);
461 #warning Unimplemented
467 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
469 g_return_if_fail (TOTEM_SCRSAVER (scr));
471 if (scr->priv->disabled == !enable)
475 totem_scrsaver_disable (scr);
477 totem_scrsaver_enable (scr);
481 totem_scrsaver_finalize (GObject *object)
483 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
485 screensaver_finalize_dbus (scr);
486 #ifdef GDK_WINDOWING_X11
487 screensaver_finalize_x11 (scr);
489 #warning Unimplemented
493 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);