]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
[totem-screensaver] Use g_bus_watch_proxy instead of g_bus_watch_name
[evince.git] / cut-n-paste / totem-screensaver / totem-scrsaver.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2
3    Copyright (C) 2004-2006 Bastien Nocera <hadess@hadess.net>
4    Copyright © 2010 Christian Persch
5
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.
10
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.
15
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.
20
21    Author: Bastien Nocera <hadess@hadess.net>
22  */
23
24
25 #include "config.h"
26
27 #include <glib/gi18n.h>
28
29 #include <gdk/gdk.h>
30
31 #ifdef GDK_WINDOWING_X11
32 #include <gdk/gdkx.h>
33 #include <X11/keysym.h>
34
35 #ifdef HAVE_XTEST
36 #include <X11/extensions/XTest.h>
37 #endif /* HAVE_XTEST */
38 #endif /* GDK_WINDOWING_X11 */
39
40 #include "totem-scrsaver.h"
41
42 #define GS_SERVICE   "org.gnome.ScreenSaver"
43 #define GS_PATH      "/org/gnome/ScreenSaver"
44 #define GS_INTERFACE "org.gnome.ScreenSaver"
45
46 #define XSCREENSAVER_MIN_TIMEOUT 60
47
48 static GObjectClass *parent_class = NULL;
49 static void totem_scrsaver_finalize   (GObject *object);
50
51 struct TotemScrsaverPrivate {
52         /* Whether the screensaver is disabled */
53         gboolean disabled;
54
55         GDBusProxy *gs_proxy;
56         gboolean have_screensaver_dbus;
57         guint watch_id;
58         guint32 cookie;
59
60         /* To save the screensaver info */
61         int timeout;
62         int interval;
63         int prefer_blanking;
64         int allow_exposures;
65
66         /* For use with XTest */
67         int keycode1, keycode2;
68         int *keycode;
69         gboolean have_xtest;
70 };
71
72 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
73
74 static gboolean
75 screensaver_is_running_dbus (TotemScrsaver *scr)
76 {
77         return scr->priv->have_screensaver_dbus;
78 }
79
80 static void
81 screensaver_inhibit_dbus (TotemScrsaver *scr,
82                           gboolean       inhibit)
83 {
84         TotemScrsaverPrivate *priv = scr->priv;
85         GError *error = NULL;
86         GVariant *value;
87
88         if (!priv->have_screensaver_dbus)
89                 return;
90
91         if (inhibit) {
92                 value = g_dbus_proxy_call_sync (priv->gs_proxy,
93                                                 "Inhibit",
94                                                 g_variant_new ("(ss)",
95                                                                "Evince",
96                                                                _("Running in presentation mode")),
97                                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
98                                                 -1,
99                                                 NULL,
100                                                 &error);
101                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
102                         /* try the old API */
103                         g_clear_error (&error);
104                         value = g_dbus_proxy_call_sync (priv->gs_proxy,
105                                                         "InhibitActivation",
106                                                         g_variant_new ("(s)",
107                                                                        _("Running in presentation mode")),
108                                                         G_DBUS_CALL_FLAGS_NO_AUTO_START,
109                                                         -1,
110                                                         NULL,
111                                                         &error);
112                 }
113                 if (value != NULL) {
114                         /* save the cookie */
115                         if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
116                                g_variant_get (value, "(u)", &priv->cookie);
117                         else
118                                 priv->cookie = 0;
119                         g_variant_unref (value);
120                 } else {
121                         g_warning ("Problem inhibiting the screensaver: %s", error->message);
122                         g_error_free (error);
123                 }
124
125         } else {
126                 value = g_dbus_proxy_call_sync (priv->gs_proxy,
127                                                 "UnInhibit",
128                                                 g_variant_new ("(u)", priv->cookie),
129                                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
130                                                 -1,
131                                                 NULL,
132                                                 &error);
133                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
134                         /* try the old API */
135                         g_clear_error (&error);
136                         value = g_dbus_proxy_call_sync (priv->gs_proxy,
137                                                         "AllowActivation",
138                                                         g_variant_new ("()"),
139                                                         G_DBUS_CALL_FLAGS_NO_AUTO_START,
140                                                         -1,
141                                                         NULL,
142                                                         &error);
143                 }
144                 if (value != NULL) {
145                         /* clear the cookie */
146                         priv->cookie = 0;
147                         g_variant_unref (value);
148                 } else {
149                         g_warning ("Problem uninhibiting the screensaver: %s", error->message);
150                         g_error_free (error);
151                 }
152         }
153 }
154
155 static void
156 screensaver_enable_dbus (TotemScrsaver *scr)
157 {
158         screensaver_inhibit_dbus (scr, FALSE);
159 }
160
161 static void
162 screensaver_disable_dbus (TotemScrsaver *scr)
163 {
164         screensaver_inhibit_dbus (scr, TRUE);
165 }
166
167 static void
168 screensaver_dbus_appeared_cb (GDBusConnection *connection,
169                               const gchar     *name,
170                               const gchar     *name_owner,
171                               GDBusProxy      *proxy,
172                               gpointer         user_data)
173 {
174         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
175         TotemScrsaverPrivate *priv = scr->priv;
176
177         priv->gs_proxy = g_object_ref (proxy);
178
179         priv->have_screensaver_dbus = TRUE;
180 }
181
182 static void
183 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
184                                  const gchar     *name,
185                                  gpointer         user_data)
186 {
187         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
188         TotemScrsaverPrivate *priv = scr->priv;
189
190         if (priv->gs_proxy) {
191                 g_object_unref (priv->gs_proxy);
192                 priv->gs_proxy = NULL;
193         }
194
195         priv->have_screensaver_dbus = FALSE;
196 }
197
198 static void
199 screensaver_init_dbus (TotemScrsaver *scr)
200 {
201         TotemScrsaverPrivate *priv = scr->priv;
202
203         priv->watch_id = g_bus_watch_proxy (G_BUS_TYPE_SESSION,
204                                             GS_SERVICE,
205                                             G_BUS_NAME_WATCHER_FLAGS_NONE,
206                                             GS_PATH,
207                                             GS_INTERFACE,
208                                             G_TYPE_DBUS_PROXY,
209                                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
210                                             G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
211                                             screensaver_dbus_appeared_cb,
212                                             screensaver_dbus_disappeared_cb,
213                                             scr, NULL);
214 }
215
216 static void
217 screensaver_finalize_dbus (TotemScrsaver *scr)
218 {
219         TotemScrsaverPrivate *priv = scr->priv;
220
221         if (scr->priv->gs_proxy) {
222                 g_object_unref (scr->priv->gs_proxy);
223         }
224
225         if (priv->watch_id > 0)
226                 g_bus_unwatch_proxy (priv->watch_id);
227 }
228
229 #ifdef GDK_WINDOWING_X11
230 static void
231 screensaver_enable_x11 (TotemScrsaver *scr)
232 {
233
234 #ifdef HAVE_XTEST
235         if (scr->priv->have_xtest != FALSE)
236         {
237                 g_source_remove_by_user_data (scr);
238                 return;
239         }
240 #endif /* HAVE_XTEST */
241
242         XLockDisplay (GDK_DISPLAY());
243         XSetScreenSaver (GDK_DISPLAY(),
244                         scr->priv->timeout,
245                         scr->priv->interval,
246                         scr->priv->prefer_blanking,
247                         scr->priv->allow_exposures);
248         XUnlockDisplay (GDK_DISPLAY());
249 }
250
251 #ifdef HAVE_XTEST
252 static gboolean
253 fake_event (TotemScrsaver *scr)
254 {
255         if (scr->priv->disabled)
256         {
257                 XLockDisplay (GDK_DISPLAY());
258                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
259                                 True, CurrentTime);
260                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
261                                 False, CurrentTime);
262                 XUnlockDisplay (GDK_DISPLAY());
263                 /* Swap the keycode */
264                 if (scr->priv->keycode == &scr->priv->keycode1)
265                         scr->priv->keycode = &scr->priv->keycode2;
266                 else
267                         scr->priv->keycode = &scr->priv->keycode1;
268         }
269
270         return TRUE;
271 }
272 #endif /* HAVE_XTEST */
273
274 static void
275 screensaver_disable_x11 (TotemScrsaver *scr)
276 {
277
278 #ifdef HAVE_XTEST
279         if (scr->priv->have_xtest != FALSE)
280         {
281                 XLockDisplay (GDK_DISPLAY());
282                 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
283                                 &scr->priv->interval,
284                                 &scr->priv->prefer_blanking,
285                                 &scr->priv->allow_exposures);
286                 XUnlockDisplay (GDK_DISPLAY());
287
288                 if (scr->priv->timeout != 0) {
289                         g_timeout_add_seconds (scr->priv->timeout / 2,
290                                                (GSourceFunc) fake_event, scr);
291                 } else {
292                         g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
293                                                (GSourceFunc) fake_event, scr);
294                 }
295
296                 return;
297         }
298 #endif /* HAVE_XTEST */
299
300         XLockDisplay (GDK_DISPLAY());
301         XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
302                         &scr->priv->interval,
303                         &scr->priv->prefer_blanking,
304                         &scr->priv->allow_exposures);
305         XSetScreenSaver(GDK_DISPLAY(), 0, 0,
306                         DontPreferBlanking, DontAllowExposures);
307         XUnlockDisplay (GDK_DISPLAY());
308 }
309
310 static void
311 screensaver_init_x11 (TotemScrsaver *scr)
312 {
313 #ifdef HAVE_XTEST
314         int a, b, c, d;
315
316         XLockDisplay (GDK_DISPLAY());
317         scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
318         if (scr->priv->have_xtest != FALSE)
319         {
320                 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
321                 if (scr->priv->keycode1 == 0) {
322                         g_warning ("scr->priv->keycode1 not existant");
323                 }
324                 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
325                 if (scr->priv->keycode2 == 0) {
326                         scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
327                         if (scr->priv->keycode2 == 0) {
328                                 g_warning ("scr->priv->keycode2 not existant");
329                         }
330                 }
331                 scr->priv->keycode = &scr->priv->keycode1;
332         }
333         XUnlockDisplay (GDK_DISPLAY());
334 #endif /* HAVE_XTEST */
335 }
336
337 static void
338 screensaver_finalize_x11 (TotemScrsaver *scr)
339 {
340         g_source_remove_by_user_data (scr);
341 }
342 #endif
343
344 static void
345 totem_scrsaver_class_init (TotemScrsaverClass *klass)
346 {
347         GObjectClass *object_class = G_OBJECT_CLASS (klass);
348
349         parent_class = g_type_class_peek_parent (klass);
350
351         object_class->finalize = totem_scrsaver_finalize;
352 }
353
354 /**
355  * totem_scrsaver_new:
356  *
357  * Creates a #TotemScrsaver object.
358  * If the GNOME screen saver is running, it uses its DBUS interface to
359  * inhibit the screensaver; otherwise it falls back to using the X
360  * screensaver functionality for this.
361  *
362  * Returns: a newly created #TotemScrsaver
363  */
364 TotemScrsaver *
365 totem_scrsaver_new (void)
366 {
367         return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
368 }
369
370 static void
371 totem_scrsaver_init (TotemScrsaver *scr)
372 {
373         scr->priv = g_new0 (TotemScrsaverPrivate, 1);
374
375         screensaver_init_dbus (scr);
376 #ifdef GDK_WINDOWING_X11
377         screensaver_init_x11 (scr);
378 #else
379 #warning Unimplemented
380 #endif
381 }
382
383 void
384 totem_scrsaver_disable (TotemScrsaver *scr)
385 {
386         g_return_if_fail (TOTEM_SCRSAVER (scr));
387
388         if (scr->priv->disabled != FALSE)
389                 return;
390
391         scr->priv->disabled = TRUE;
392
393         if (screensaver_is_running_dbus (scr) != FALSE)
394                 screensaver_disable_dbus (scr);
395         else 
396 #ifdef GDK_WINDOWING_X11
397                 screensaver_disable_x11 (scr);
398 #else
399 #warning Unimplemented
400         {}
401 #endif
402 }
403
404 void
405 totem_scrsaver_enable (TotemScrsaver *scr)
406 {
407         g_return_if_fail (TOTEM_SCRSAVER (scr));
408
409         if (scr->priv->disabled == FALSE)
410                 return;
411
412         scr->priv->disabled = FALSE;
413
414         if (screensaver_is_running_dbus (scr) != FALSE)
415                 screensaver_enable_dbus (scr);
416         else 
417 #ifdef GDK_WINDOWING_X11
418                 screensaver_enable_x11 (scr);
419 #else
420 #warning Unimplemented
421         {}
422 #endif
423 }
424
425 void
426 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
427 {
428         g_return_if_fail (TOTEM_SCRSAVER (scr));
429
430         if (scr->priv->disabled == !enable)
431                 return;
432
433         if (enable == FALSE)
434                 totem_scrsaver_disable (scr);
435         else
436                 totem_scrsaver_enable (scr);
437 }
438
439 static void
440 totem_scrsaver_finalize (GObject *object)
441 {
442         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
443
444         screensaver_finalize_dbus (scr);
445 #ifdef GDK_WINDOWING_X11
446         screensaver_finalize_x11 (scr);
447 #else
448 #warning Unimplemented
449         {}
450 #endif
451
452         G_OBJECT_CLASS (parent_class)->finalize (object);
453 }