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 GObjectClass *parent_class = NULL;
49 static void totem_scrsaver_finalize (GObject *object);
51 struct TotemScrsaverPrivate {
52 /* Whether the screensaver is disabled */
55 GDBusConnection *connection;
56 gboolean have_screensaver_dbus;
60 /* To save the screensaver info */
66 /* For use with XTest */
67 int keycode1, keycode2;
77 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
80 screensaver_is_running_dbus (TotemScrsaver *scr)
82 return scr->priv->have_screensaver_dbus;
86 screensaver_inhibit_dbus (TotemScrsaver *scr,
89 TotemScrsaverPrivate *priv = scr->priv;
93 if (!priv->have_screensaver_dbus)
97 value = g_dbus_connection_call_sync (priv->connection,
102 g_variant_new ("(ss)",
104 _("Running in presentation mode")),
105 G_DBUS_CALL_FLAGS_NO_AUTO_START,
109 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
110 /* try the old API */
111 g_clear_error (&error);
112 value = g_dbus_connection_call_sync (priv->connection,
117 g_variant_new ("(s)",
118 _("Running in presentation mode")),
119 G_DBUS_CALL_FLAGS_NO_AUTO_START,
125 /* save the cookie */
126 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
127 g_variant_get (value, "(u)", &priv->cookie);
130 g_variant_unref (value);
132 g_warning ("Problem inhibiting the screensaver: %s", error->message);
133 g_error_free (error);
137 value = g_dbus_connection_call_sync (priv->connection,
142 g_variant_new ("(u)", priv->cookie),
143 G_DBUS_CALL_FLAGS_NO_AUTO_START,
147 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
148 /* try the old API */
149 g_clear_error (&error);
150 value = g_dbus_connection_call_sync (priv->connection,
155 g_variant_new ("()"),
156 G_DBUS_CALL_FLAGS_NO_AUTO_START,
162 /* clear the cookie */
164 g_variant_unref (value);
166 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
167 g_error_free (error);
173 screensaver_enable_dbus (TotemScrsaver *scr)
175 screensaver_inhibit_dbus (scr, FALSE);
179 screensaver_disable_dbus (TotemScrsaver *scr)
181 screensaver_inhibit_dbus (scr, TRUE);
185 screensaver_dbus_appeared_cb (GDBusConnection *connection,
187 const char *name_owner,
190 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
191 TotemScrsaverPrivate *priv = scr->priv;
193 g_assert (connection == priv->connection);
195 priv->have_screensaver_dbus = TRUE;
199 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
203 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
204 TotemScrsaverPrivate *priv = scr->priv;
206 g_assert (connection == priv->connection);
208 priv->have_screensaver_dbus = FALSE;
212 screensaver_finalize_dbus (TotemScrsaver *scr)
214 TotemScrsaverPrivate *priv = scr->priv;
216 if (priv->connection == NULL)
219 g_bus_unwatch_name (priv->watch_id);
221 g_object_unref (priv->connection);
224 #ifdef GDK_WINDOWING_X11
226 screensaver_enable_x11 (TotemScrsaver *scr)
230 if (scr->priv->have_xtest != FALSE)
232 g_source_remove_by_user_data (scr);
235 #endif /* HAVE_XTEST */
237 XLockDisplay (GDK_DISPLAY());
238 XSetScreenSaver (GDK_DISPLAY(),
241 scr->priv->prefer_blanking,
242 scr->priv->allow_exposures);
243 XUnlockDisplay (GDK_DISPLAY());
248 fake_event (TotemScrsaver *scr)
250 if (scr->priv->disabled)
252 XLockDisplay (GDK_DISPLAY());
253 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
255 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
257 XUnlockDisplay (GDK_DISPLAY());
258 /* Swap the keycode */
259 if (scr->priv->keycode == &scr->priv->keycode1)
260 scr->priv->keycode = &scr->priv->keycode2;
262 scr->priv->keycode = &scr->priv->keycode1;
267 #endif /* HAVE_XTEST */
270 screensaver_disable_x11 (TotemScrsaver *scr)
274 if (scr->priv->have_xtest != FALSE)
276 XLockDisplay (GDK_DISPLAY());
277 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
278 &scr->priv->interval,
279 &scr->priv->prefer_blanking,
280 &scr->priv->allow_exposures);
281 XUnlockDisplay (GDK_DISPLAY());
283 if (scr->priv->timeout != 0) {
284 g_timeout_add_seconds (scr->priv->timeout / 2,
285 (GSourceFunc) fake_event, scr);
287 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
288 (GSourceFunc) fake_event, scr);
293 #endif /* HAVE_XTEST */
295 XLockDisplay (GDK_DISPLAY());
296 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
297 &scr->priv->interval,
298 &scr->priv->prefer_blanking,
299 &scr->priv->allow_exposures);
300 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
301 DontPreferBlanking, DontAllowExposures);
302 XUnlockDisplay (GDK_DISPLAY());
306 screensaver_init_x11 (TotemScrsaver *scr)
311 XLockDisplay (GDK_DISPLAY());
312 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
313 if (scr->priv->have_xtest != FALSE)
315 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
316 if (scr->priv->keycode1 == 0) {
317 g_warning ("scr->priv->keycode1 not existant");
319 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
320 if (scr->priv->keycode2 == 0) {
321 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
322 if (scr->priv->keycode2 == 0) {
323 g_warning ("scr->priv->keycode2 not existant");
326 scr->priv->keycode = &scr->priv->keycode1;
328 XUnlockDisplay (GDK_DISPLAY());
329 #endif /* HAVE_XTEST */
333 screensaver_finalize_x11 (TotemScrsaver *scr)
335 g_source_remove_by_user_data (scr);
340 totem_scrsaver_constructed (GObject *object)
342 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
343 TotemScrsaverPrivate *priv = scr->priv;
345 if (priv->connection == NULL)
348 priv->watch_id = g_bus_watch_name_on_connection (priv->connection,
350 G_BUS_NAME_WATCHER_FLAGS_NONE,
351 screensaver_dbus_appeared_cb,
352 screensaver_dbus_disappeared_cb,
357 totem_scrsaver_set_property (GObject *object,
362 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
363 TotemScrsaverPrivate *priv = scr->priv;
366 case PROP_CONNECTION:
367 priv->connection = g_value_dup_object (value);
370 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
376 totem_scrsaver_class_init (TotemScrsaverClass *klass)
378 GObjectClass *object_class = G_OBJECT_CLASS (klass);
380 object_class->set_property = totem_scrsaver_set_property;
381 object_class->constructed = totem_scrsaver_constructed;
382 object_class->finalize = totem_scrsaver_finalize;
384 g_object_class_install_property (object_class,
386 g_param_spec_object ("connection", NULL, NULL,
387 G_TYPE_DBUS_CONNECTION,
389 G_PARAM_CONSTRUCT_ONLY |
390 G_PARAM_STATIC_STRINGS));
394 * totem_scrsaver_new:
395 * @connection: (allow-none): a #GDBusConnection, or %NULL
397 * Creates a #TotemScrsaver object. If @connection is non-%NULL,
398 * and the GNOME screen saver is running, it uses its DBUS interface to
399 * inhibit the screensaver; otherwise it falls back to using the X
400 * screensaver functionality for this.
402 * Returns: a newly created #TotemScrsaver
405 totem_scrsaver_new (GDBusConnection *connection)
407 return g_object_new (TOTEM_TYPE_SCRSAVER,
408 "connection", connection,
413 totem_scrsaver_init (TotemScrsaver *scr)
415 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr, TOTEM_TYPE_SCRSAVER, TotemScrsaverPrivate);
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 (parent_class)->finalize (object);