1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 Copyright (C) 2004-2006 Bastien Nocera <hadess@hadess.net>
5 The Gnome Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The Gnome Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the Gnome Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301 USA.
20 Author: Bastien Nocera <hadess@hadess.net>
26 #include <glib/gi18n.h>
30 #ifdef GDK_WINDOWING_X11
32 #include <X11/keysym.h>
35 #include <X11/extensions/XTest.h>
36 #endif /* HAVE_XTEST */
37 #endif /* GDK_WINDOWING_X11 */
39 #include "totem-scrsaver.h"
41 #define GS_SERVICE "org.gnome.ScreenSaver"
42 #define GS_PATH "/org/gnome/ScreenSaver"
43 #define GS_INTERFACE "org.gnome.ScreenSaver"
45 #define XSCREENSAVER_MIN_TIMEOUT 60
47 static GObjectClass *parent_class = NULL;
48 static void totem_scrsaver_finalize (GObject *object);
50 struct TotemScrsaverPrivate {
51 /* Whether the screensaver is disabled */
54 GDBusConnection *connection;
55 gboolean have_screensaver_dbus;
59 /* To save the screensaver info */
65 /* For use with XTest */
66 int keycode1, keycode2;
76 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
79 screensaver_is_running_dbus (TotemScrsaver *scr)
81 return scr->priv->have_screensaver_dbus;
85 screensaver_inhibit_dbus (TotemScrsaver *scr,
88 TotemScrsaverPrivate *priv = scr->priv;
92 if (!priv->have_screensaver_dbus)
96 value = g_dbus_connection_call_sync (priv->connection,
101 g_variant_new ("(ss)",
103 _("Running in presentation mode")),
104 G_DBUS_CALL_FLAGS_NO_AUTO_START,
108 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
109 /* try the old API */
110 g_clear_error (&error);
111 value = g_dbus_connection_call_sync (priv->connection,
116 g_variant_new ("(s)",
117 _("Running in presentation mode")),
118 G_DBUS_CALL_FLAGS_NO_AUTO_START,
124 /* save the cookie */
125 if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
126 g_variant_get (value, "(u)", &priv->cookie);
129 g_variant_unref (value);
131 g_warning ("Problem inhibiting the screensaver: %s", error->message);
132 g_error_free (error);
136 value = g_dbus_connection_call_sync (priv->connection,
141 g_variant_new ("(u)", priv->cookie),
142 G_DBUS_CALL_FLAGS_NO_AUTO_START,
146 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
147 /* try the old API */
148 g_clear_error (&error);
149 value = g_dbus_connection_call_sync (priv->connection,
154 g_variant_new ("()"),
155 G_DBUS_CALL_FLAGS_NO_AUTO_START,
161 /* clear the cookie */
163 g_variant_unref (value);
165 g_warning ("Problem uninhibiting the screensaver: %s", error->message);
166 g_error_free (error);
172 screensaver_enable_dbus (TotemScrsaver *scr)
174 screensaver_inhibit_dbus (scr, FALSE);
178 screensaver_disable_dbus (TotemScrsaver *scr)
180 screensaver_inhibit_dbus (scr, TRUE);
184 screensaver_dbus_appeared_cb (GDBusConnection *connection,
186 const char *name_owner,
189 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
190 TotemScrsaverPrivate *priv = scr->priv;
192 g_assert (connection == priv->connection);
194 priv->have_screensaver_dbus = TRUE;
198 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
202 TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
203 TotemScrsaverPrivate *priv = scr->priv;
205 g_assert (connection == priv->connection);
207 priv->have_screensaver_dbus = FALSE;
211 screensaver_finalize_dbus (TotemScrsaver *scr)
213 TotemScrsaverPrivate *priv = scr->priv;
215 if (priv->connection == NULL)
218 g_bus_unwatch_name (priv->watch_id);
220 g_object_unref (priv->connection);
223 #ifdef GDK_WINDOWING_X11
225 screensaver_enable_x11 (TotemScrsaver *scr)
229 if (scr->priv->have_xtest != FALSE)
231 g_source_remove_by_user_data (scr);
234 #endif /* HAVE_XTEST */
236 XLockDisplay (GDK_DISPLAY());
237 XSetScreenSaver (GDK_DISPLAY(),
240 scr->priv->prefer_blanking,
241 scr->priv->allow_exposures);
242 XUnlockDisplay (GDK_DISPLAY());
247 fake_event (TotemScrsaver *scr)
249 if (scr->priv->disabled)
251 XLockDisplay (GDK_DISPLAY());
252 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
254 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
256 XUnlockDisplay (GDK_DISPLAY());
257 /* Swap the keycode */
258 if (scr->priv->keycode == &scr->priv->keycode1)
259 scr->priv->keycode = &scr->priv->keycode2;
261 scr->priv->keycode = &scr->priv->keycode1;
266 #endif /* HAVE_XTEST */
269 screensaver_disable_x11 (TotemScrsaver *scr)
273 if (scr->priv->have_xtest != FALSE)
275 XLockDisplay (GDK_DISPLAY());
276 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
277 &scr->priv->interval,
278 &scr->priv->prefer_blanking,
279 &scr->priv->allow_exposures);
280 XUnlockDisplay (GDK_DISPLAY());
282 if (scr->priv->timeout != 0) {
283 g_timeout_add_seconds (scr->priv->timeout / 2,
284 (GSourceFunc) fake_event, scr);
286 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
287 (GSourceFunc) fake_event, scr);
292 #endif /* HAVE_XTEST */
294 XLockDisplay (GDK_DISPLAY());
295 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
296 &scr->priv->interval,
297 &scr->priv->prefer_blanking,
298 &scr->priv->allow_exposures);
299 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
300 DontPreferBlanking, DontAllowExposures);
301 XUnlockDisplay (GDK_DISPLAY());
305 screensaver_init_x11 (TotemScrsaver *scr)
310 XLockDisplay (GDK_DISPLAY());
311 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
312 if (scr->priv->have_xtest != FALSE)
314 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
315 if (scr->priv->keycode1 == 0) {
316 g_warning ("scr->priv->keycode1 not existant");
318 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
319 if (scr->priv->keycode2 == 0) {
320 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
321 if (scr->priv->keycode2 == 0) {
322 g_warning ("scr->priv->keycode2 not existant");
325 scr->priv->keycode = &scr->priv->keycode1;
327 XUnlockDisplay (GDK_DISPLAY());
328 #endif /* HAVE_XTEST */
332 screensaver_finalize_x11 (TotemScrsaver *scr)
334 g_source_remove_by_user_data (scr);
339 totem_scrsaver_constructed (GObject *object)
341 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
342 TotemScrsaverPrivate *priv = scr->priv;
344 if (priv->connection == NULL)
347 priv->watch_id = g_bus_watch_name_on_connection (priv->connection,
349 G_BUS_NAME_WATCHER_FLAGS_NONE,
350 screensaver_dbus_appeared_cb,
351 screensaver_dbus_disappeared_cb,
356 totem_scrsaver_set_property (GObject *object,
361 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
362 TotemScrsaverPrivate *priv = scr->priv;
365 case PROP_CONNECTION:
366 priv->connection = g_value_dup_object (value);
369 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
375 totem_scrsaver_class_init (TotemScrsaverClass *klass)
377 GObjectClass *object_class = G_OBJECT_CLASS (klass);
379 object_class->set_property = totem_scrsaver_set_property;
380 object_class->constructed = totem_scrsaver_constructed;
381 object_class->finalize = totem_scrsaver_finalize;
383 g_object_class_install_property (object_class,
385 g_param_spec_object ("connection", NULL, NULL,
386 G_TYPE_DBUS_CONNECTION,
388 G_PARAM_CONSTRUCT_ONLY |
389 G_PARAM_STATIC_STRINGS));
393 * totem_scrsaver_new:
394 * @connection: (allow-none): a #GDBusConnection, or %NULL
396 * Creates a #TotemScrsaver object. If @connection is non-%NULL,
397 * and 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 (GDBusConnection *connection)
406 return g_object_new (TOTEM_TYPE_SCRSAVER,
407 "connection", connection,
412 totem_scrsaver_init (TotemScrsaver *scr)
414 scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr, TOTEM_TYPE_SCRSAVER, TotemScrsaverPrivate);
416 #ifdef GDK_WINDOWING_X11
417 screensaver_init_x11 (scr);
419 #warning Unimplemented
424 totem_scrsaver_disable (TotemScrsaver *scr)
426 g_return_if_fail (TOTEM_SCRSAVER (scr));
428 if (scr->priv->disabled != FALSE)
431 scr->priv->disabled = TRUE;
433 if (screensaver_is_running_dbus (scr) != FALSE)
434 screensaver_disable_dbus (scr);
436 #ifdef GDK_WINDOWING_X11
437 screensaver_disable_x11 (scr);
439 #warning Unimplemented
445 totem_scrsaver_enable (TotemScrsaver *scr)
447 g_return_if_fail (TOTEM_SCRSAVER (scr));
449 if (scr->priv->disabled == FALSE)
452 scr->priv->disabled = FALSE;
454 if (screensaver_is_running_dbus (scr) != FALSE)
455 screensaver_enable_dbus (scr);
457 #ifdef GDK_WINDOWING_X11
458 screensaver_enable_x11 (scr);
460 #warning Unimplemented
466 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
468 g_return_if_fail (TOTEM_SCRSAVER (scr));
470 if (scr->priv->disabled == !enable)
474 totem_scrsaver_disable (scr);
476 totem_scrsaver_enable (scr);
480 totem_scrsaver_finalize (GObject *object)
482 TotemScrsaver *scr = TOTEM_SCRSAVER (object);
484 screensaver_finalize_dbus (scr);
485 #ifdef GDK_WINDOWING_X11
486 screensaver_finalize_x11 (scr);
488 #warning Unimplemented
492 G_OBJECT_CLASS (parent_class)->finalize (object);