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
6 The Gnome Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301 USA.
21 Author: Bastien Nocera <hadess@hadess.net>
27 #include <glib/gi18n.h>
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
48 static void totem_scrsaver_finalize (GObject *object);
50 struct TotemScrsaverPrivate {
51 /* Whether the screensaver is disabled */
55 gboolean have_screensaver_dbus;
58 gboolean old_dbus_api;
60 /* To save the screensaver info */
66 /* For use with XTest */
67 int keycode1, keycode2;
72 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
75 screensaver_is_running_dbus (TotemScrsaver *scr)
77 return scr->priv->have_screensaver_dbus;
81 on_inhibit_cb (GObject *source_object,
85 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
86 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
90 value = g_dbus_proxy_call_finish (proxy, res, &error);
92 if (!scr->priv->old_dbus_api &&
93 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
95 scr->priv->old_dbus_api = TRUE;
96 g_dbus_proxy_call (proxy,
99 _("Running in presentation mode")),
100 G_DBUS_CALL_FLAGS_NO_AUTO_START,
106 g_warning ("Problem inhibiting the screensaver: %s", error->message);
108 g_error_free (error);
113 /* save the cookie */
114 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
115 g_variant_get (value, "(u)", &scr->priv->cookie);
117 scr->priv->cookie = 0;
118 g_variant_unref (value);
122 on_uninhibit_cb (GObject *source_object,
126 GDBusProxy *proxy = G_DBUS_PROXY (source_object);
127 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
129 GError *error = NULL;
131 value = g_dbus_proxy_call_finish (proxy, res, &error);
133 if (!scr->priv->old_dbus_api &&
134 g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
135 /* try the old API */
136 scr->priv->old_dbus_api = TRUE;
137 g_dbus_proxy_call (proxy,
139 g_variant_new ("()"),
140 G_DBUS_CALL_FLAGS_NO_AUTO_START,
146 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
148 g_error_free (error);
153 /* clear the cookie */
154 scr->priv->cookie = 0;
155 g_variant_unref (value);
159 screensaver_inhibit_dbus (TotemScrsaver *scr,
162 TotemScrsaverPrivate *priv = scr->priv;
164 if (!priv->have_screensaver_dbus)
167 scr->priv->old_dbus_api = FALSE;
170 g_dbus_proxy_call (priv->gs_proxy,
172 g_variant_new ("(ss)",
174 _("Running in presentation mode")),
175 G_DBUS_CALL_FLAGS_NO_AUTO_START,
181 g_dbus_proxy_call (priv->gs_proxy,
183 g_variant_new ("(u)", priv->cookie),
184 G_DBUS_CALL_FLAGS_NO_AUTO_START,
193 screensaver_enable_dbus (TotemScrsaver *scr)
195 screensaver_inhibit_dbus (scr, FALSE);
199 screensaver_disable_dbus (TotemScrsaver *scr)
201 screensaver_inhibit_dbus (scr, TRUE);
205 screensaver_dbus_appeared_cb (GDBusConnection *connection,
207 const gchar *name_owner,
211 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
212 TotemScrsaverPrivate *priv = scr->priv;
214 priv->gs_proxy = g_object_ref (proxy);
216 priv->have_screensaver_dbus = TRUE;
220 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
224 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
225 TotemScrsaverPrivate *priv = scr->priv;
227 if (priv->gs_proxy) {
228 g_object_unref (priv->gs_proxy);
229 priv->gs_proxy = NULL;
232 priv->have_screensaver_dbus = FALSE;
236 screensaver_init_dbus (TotemScrsaver *scr)
238 TotemScrsaverPrivate *priv = scr->priv;
240 priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
242 G_BUS_NAME_WATCHER_FLAGS_NONE,
246 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
247 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
248 screensaver_dbus_appeared_cb,
249 screensaver_dbus_disappeared_cb,
254 screensaver_finalize_dbus (TotemScrsaver *scr)
256 TotemScrsaverPrivate *priv = scr->priv;
258 if (scr->priv->gs_proxy) {
259 g_object_unref (scr->priv->gs_proxy);
262 if (priv->watch_id > 0)
263 g_bus_unwatch_proxy (priv->watch_id);
266 #ifdef GDK_WINDOWING_X11
268 screensaver_enable_x11 (TotemScrsaver *scr)
272 if (scr->priv->have_xtest != FALSE)
274 g_source_remove_by_user_data (scr);
277 #endif /* HAVE_XTEST */
279 XLockDisplay (GDK_DISPLAY());
280 XSetScreenSaver (GDK_DISPLAY(),
283 scr->priv->prefer_blanking,
284 scr->priv->allow_exposures);
285 XUnlockDisplay (GDK_DISPLAY());
290 fake_event (TotemScrsaver *scr)
292 if (scr->priv->disabled)
294 XLockDisplay (GDK_DISPLAY());
295 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
297 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
299 XUnlockDisplay (GDK_DISPLAY());
300 /* Swap the keycode */
301 if (scr->priv->keycode == &scr->priv->keycode1)
302 scr->priv->keycode = &scr->priv->keycode2;
304 scr->priv->keycode = &scr->priv->keycode1;
309 #endif /* HAVE_XTEST */
312 screensaver_disable_x11 (TotemScrsaver *scr)
316 if (scr->priv->have_xtest != FALSE)
318 XLockDisplay (GDK_DISPLAY());
319 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
320 &scr->priv->interval,
321 &scr->priv->prefer_blanking,
322 &scr->priv->allow_exposures);
323 XUnlockDisplay (GDK_DISPLAY());
325 if (scr->priv->timeout != 0) {
326 g_timeout_add_seconds (scr->priv->timeout / 2,
327 (GSourceFunc) fake_event, scr);
329 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
330 (GSourceFunc) fake_event, scr);
335 #endif /* HAVE_XTEST */
337 XLockDisplay (GDK_DISPLAY());
338 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
339 &scr->priv->interval,
340 &scr->priv->prefer_blanking,
341 &scr->priv->allow_exposures);
342 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
343 DontPreferBlanking, DontAllowExposures);
344 XUnlockDisplay (GDK_DISPLAY());
348 screensaver_init_x11 (TotemScrsaver *scr)
353 XLockDisplay (GDK_DISPLAY());
354 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
355 if (scr->priv->have_xtest != FALSE)
357 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
358 if (scr->priv->keycode1 == 0) {
359 g_warning ("scr->priv->keycode1 not existant");
361 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
362 if (scr->priv->keycode2 == 0) {
363 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
364 if (scr->priv->keycode2 == 0) {
365 g_warning ("scr->priv->keycode2 not existant");
368 scr->priv->keycode = &scr->priv->keycode1;
370 XUnlockDisplay (GDK_DISPLAY());
371 #endif /* HAVE_XTEST */
375 screensaver_finalize_x11 (TotemScrsaver *scr)
377 g_source_remove_by_user_data (scr);
382 totem_scrsaver_class_init (TotemScrsaverClass *klass)
384 GObjectClass *object_class = G_OBJECT_CLASS (klass);
386 g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
388 object_class->finalize = totem_scrsaver_finalize;
392 * totem_scrsaver_new:
394 * Creates a #TotemScrsaver object.
395 * If the GNOME screen saver is running, it uses its DBUS interface to
396 * inhibit the screensaver; otherwise it falls back to using the X
397 * screensaver functionality for this.
399 * Returns: a newly created #TotemScrsaver
402 totem_scrsaver_new (void)
404 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
408 totem_scrsaver_init (TotemScrsaver *scr)
410 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
412 TotemScrsaverPrivate);
414 screensaver_init_dbus (scr);
415 #ifdef GDK_WINDOWING_X11
416 screensaver_init_x11 (scr);
418 #warning Unimplemented
423 totem_scrsaver_disable (TotemScrsaver *scr)
425 g_return_if_fail (TOTEM_SCRSAVER (scr));
427 if (scr->priv->disabled != FALSE)
430 scr->priv->disabled = TRUE;
432 if (screensaver_is_running_dbus (scr) != FALSE)
433 screensaver_disable_dbus (scr);
435 #ifdef GDK_WINDOWING_X11
436 screensaver_disable_x11 (scr);
438 #warning Unimplemented
444 totem_scrsaver_enable (TotemScrsaver *scr)
446 g_return_if_fail (TOTEM_SCRSAVER (scr));
448 if (scr->priv->disabled == FALSE)
451 scr->priv->disabled = FALSE;
453 if (screensaver_is_running_dbus (scr) != FALSE)
454 screensaver_enable_dbus (scr);
456 #ifdef GDK_WINDOWING_X11
457 screensaver_enable_x11 (scr);
459 #warning Unimplemented
465 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
467 g_return_if_fail (TOTEM_SCRSAVER (scr));
469 if (scr->priv->disabled == !enable)
473 totem_scrsaver_disable (scr);
475 totem_scrsaver_enable (scr);
479 totem_scrsaver_finalize (GObject *object)
481 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
483 screensaver_finalize_dbus (scr);
484 #ifdef GDK_WINDOWING_X11
485 screensaver_finalize_x11 (scr);
487 #warning Unimplemented
491 G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);