]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
[shell] Pass the GDBusConnection to TotemScrsaver
[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
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.
9
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.
14
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.
19
20    Author: Bastien Nocera <hadess@hadess.net>
21  */
22
23
24 #include "config.h"
25
26 #include <glib/gi18n.h>
27
28 #include <gdk/gdk.h>
29
30 #ifdef GDK_WINDOWING_X11
31 #include <gdk/gdkx.h>
32 #include <X11/keysym.h>
33
34 #ifdef HAVE_XTEST
35 #include <X11/extensions/XTest.h>
36 #endif /* HAVE_XTEST */
37 #endif /* GDK_WINDOWING_X11 */
38
39 #ifdef ENABLE_DBUS
40 #define GS_SERVICE   "org.gnome.ScreenSaver"
41 #define GS_PATH      "/org/gnome/ScreenSaver"
42 #define GS_INTERFACE "org.gnome.ScreenSaver"
43 #endif /* ENABLE_DBUS */
44
45 #include "totem-scrsaver.h"
46
47 #define XSCREENSAVER_MIN_TIMEOUT 60
48
49 static GObjectClass *parent_class = NULL;
50 static void totem_scrsaver_finalize   (GObject *object);
51
52 struct TotemScrsaverPrivate {
53         /* Whether the screensaver is disabled */
54         gboolean disabled;
55
56 #ifdef ENABLE_DBUS
57         GDBusConnection *connection;
58         gboolean have_screensaver_dbus;
59         guint watch_id;
60         guint32 cookie;
61 #endif /* ENABLE_DBUS */
62
63         /* To save the screensaver info */
64         int timeout;
65         int interval;
66         int prefer_blanking;
67         int allow_exposures;
68
69         /* For use with XTest */
70         int keycode1, keycode2;
71         int *keycode;
72         gboolean have_xtest;
73 };
74
75 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
76
77 static gboolean
78 screensaver_is_running_dbus (TotemScrsaver *scr)
79 {
80 #ifdef ENABLE_DBUS
81         return scr->priv->connection != NULL;
82 #else
83         return FALSE;
84 #endif /* ENABLE_DBUS */
85 }
86
87 static void
88 screensaver_inhibit_dbus (TotemScrsaver *scr,
89                           gboolean       inhibit)
90 {
91 #ifdef ENABLE_DBUS
92         TotemScrsaverPrivate *priv = scr->priv;
93         GError *error = NULL;
94         GVariant *value;
95
96         if (!priv->have_screensaver_dbus)
97                 return;
98
99         if (inhibit) {
100                 value = g_dbus_connection_call_sync (priv->connection,
101                                                      GS_SERVICE,
102                                                      GS_PATH,
103                                                      GS_INTERFACE,
104                                                      "Inhibit",
105                                                      g_variant_new ("(ss)",
106                                                                     "Evince",
107                                                                     _("Running in presentation mode")),
108                                                      G_DBUS_CALL_FLAGS_NO_AUTO_START,
109                                                      -1,
110                                                      NULL,
111                                                      &error);
112                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
113                         /* try the old API */
114                         g_clear_error (&error);
115                         value = g_dbus_connection_call_sync (priv->connection,
116                                                              GS_SERVICE,
117                                                              GS_PATH,
118                                                              GS_INTERFACE,
119                                                              "InhibitActivation",
120                                                              g_variant_new ("(s)",
121                                                                             _("Running in presentation mode")),
122                                                              G_DBUS_CALL_FLAGS_NO_AUTO_START,
123                                                              -1,
124                                                              NULL,
125                                                              &error);
126                 }
127                 if (value != NULL) {
128                         /* save the cookie */
129                         if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
130                                g_variant_get (value, "(u)", &priv->cookie);
131                         else
132                                 priv->cookie = 0;
133                         g_variant_unref (value);
134                 } else {
135                         g_warning ("Problem inhibiting the screensaver: %s", error->message);
136                         g_error_free (error);
137                 }
138
139         } else {
140                 value = g_dbus_connection_call_sync (priv->connection,
141                                                      GS_SERVICE,
142                                                      GS_PATH,
143                                                      GS_INTERFACE,
144                                                      "UnInhibit",
145                                                      g_variant_new ("(u)", priv->cookie),
146                                                      G_DBUS_CALL_FLAGS_NO_AUTO_START,
147                                                      -1,
148                                                      NULL,
149                                                      &error);
150                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
151                         /* try the old API */
152                         g_clear_error (&error);
153                         value = g_dbus_connection_call_sync (priv->connection,
154                                                              GS_SERVICE,
155                                                              GS_PATH,
156                                                              GS_INTERFACE,
157                                                              "AllowActivation",
158                                                              g_variant_new ("()"),
159                                                              G_DBUS_CALL_FLAGS_NO_AUTO_START,
160                                                              -1,
161                                                              NULL,
162                                                              &error);
163                 }
164                 if (value != NULL) {
165                         /* clear the cookie */
166                         priv->cookie = 0;
167                         g_variant_unref (value);
168                 } else {
169                         g_warning ("Problem uninhibiting the screensaver: %s", error->message);
170                         g_error_free (error);
171                 }
172         }
173 #endif /* ENABLE_DBUS */
174 }
175
176 static void
177 screensaver_enable_dbus (TotemScrsaver *scr)
178 {
179         screensaver_inhibit_dbus (scr, FALSE);
180 }
181
182 static void
183 screensaver_disable_dbus (TotemScrsaver *scr)
184 {
185         screensaver_inhibit_dbus (scr, TRUE);
186 }
187
188 #ifdef ENABLE_DBUS
189 static void
190 screensaver_dbus_appeared_cb (GDBusConnection *connection,
191                               const char      *name,
192                               const char      *name_owner,
193                               gpointer         user_data)
194 {
195         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
196         TotemScrsaverPrivate *priv = scr->priv;
197
198         g_assert (connection == priv->connection);
199
200         priv->have_screensaver_dbus = TRUE;
201 }
202
203 static void
204 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
205                                  const char      *name,
206                                  gpointer         user_data)
207 {
208         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
209         TotemScrsaverPrivate *priv = scr->priv;
210
211         g_assert (connection == priv->connection);
212
213         priv->have_screensaver_dbus = FALSE;
214 }
215 #endif
216
217 static void
218 screensaver_init_dbus (TotemScrsaver *scr)
219 {
220 #ifdef ENABLE_DBUS
221         TotemScrsaverPrivate *priv = scr->priv;
222
223         priv->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
224                                                 GS_SERVICE,
225                                                 G_BUS_NAME_WATCHER_FLAGS_NONE,
226                                                 screensaver_dbus_appeared_cb,
227                                                 screensaver_dbus_disappeared_cb,
228                                                 scr, NULL);
229 #endif /* ENABLE_DBUS */
230 }
231
232 static void
233 screensaver_finalize_dbus (TotemScrsaver *scr)
234 {
235 #ifdef ENABLE_DBUS
236         g_bus_unwatch_name (scr->priv->watch_id);
237
238         if (scr->priv->connection != NULL)
239                 g_object_unref (scr->priv->connection);
240 #endif /* ENABLE_DBUS */
241 }
242
243 #ifdef GDK_WINDOWING_X11
244 static void
245 screensaver_enable_x11 (TotemScrsaver *scr)
246 {
247
248 #ifdef HAVE_XTEST
249         if (scr->priv->have_xtest != FALSE)
250         {
251                 g_source_remove_by_user_data (scr);
252                 return;
253         }
254 #endif /* HAVE_XTEST */
255
256         XLockDisplay (GDK_DISPLAY());
257         XSetScreenSaver (GDK_DISPLAY(),
258                         scr->priv->timeout,
259                         scr->priv->interval,
260                         scr->priv->prefer_blanking,
261                         scr->priv->allow_exposures);
262         XUnlockDisplay (GDK_DISPLAY());
263 }
264
265 #ifdef HAVE_XTEST
266 static gboolean
267 fake_event (TotemScrsaver *scr)
268 {
269         if (scr->priv->disabled)
270         {
271                 XLockDisplay (GDK_DISPLAY());
272                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
273                                 True, CurrentTime);
274                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
275                                 False, CurrentTime);
276                 XUnlockDisplay (GDK_DISPLAY());
277                 /* Swap the keycode */
278                 if (scr->priv->keycode == &scr->priv->keycode1)
279                         scr->priv->keycode = &scr->priv->keycode2;
280                 else
281                         scr->priv->keycode = &scr->priv->keycode1;
282         }
283
284         return TRUE;
285 }
286 #endif /* HAVE_XTEST */
287
288 static void
289 screensaver_disable_x11 (TotemScrsaver *scr)
290 {
291
292 #ifdef HAVE_XTEST
293         if (scr->priv->have_xtest != FALSE)
294         {
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                 XUnlockDisplay (GDK_DISPLAY());
301
302                 if (scr->priv->timeout != 0) {
303                         g_timeout_add_seconds (scr->priv->timeout / 2,
304                                                (GSourceFunc) fake_event, scr);
305                 } else {
306                         g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
307                                                (GSourceFunc) fake_event, scr);
308                 }
309
310                 return;
311         }
312 #endif /* HAVE_XTEST */
313
314         XLockDisplay (GDK_DISPLAY());
315         XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
316                         &scr->priv->interval,
317                         &scr->priv->prefer_blanking,
318                         &scr->priv->allow_exposures);
319         XSetScreenSaver(GDK_DISPLAY(), 0, 0,
320                         DontPreferBlanking, DontAllowExposures);
321         XUnlockDisplay (GDK_DISPLAY());
322 }
323
324 static void
325 screensaver_init_x11 (TotemScrsaver *scr)
326 {
327 #ifdef HAVE_XTEST
328         int a, b, c, d;
329
330         XLockDisplay (GDK_DISPLAY());
331         scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
332         if (scr->priv->have_xtest != FALSE)
333         {
334                 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
335                 if (scr->priv->keycode1 == 0) {
336                         g_warning ("scr->priv->keycode1 not existant");
337                 }
338                 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
339                 if (scr->priv->keycode2 == 0) {
340                         scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
341                         if (scr->priv->keycode2 == 0) {
342                                 g_warning ("scr->priv->keycode2 not existant");
343                         }
344                 }
345                 scr->priv->keycode = &scr->priv->keycode1;
346         }
347         XUnlockDisplay (GDK_DISPLAY());
348 #endif /* HAVE_XTEST */
349 }
350
351 static void
352 screensaver_finalize_x11 (TotemScrsaver *scr)
353 {
354         g_source_remove_by_user_data (scr);
355 }
356 #endif
357
358 #ifdef ENABLE_DBUS
359
360 enum {
361         PROP_0,
362         PROP_CONNECTION
363 };
364
365 static void
366 totem_scrsaver_constructed (GObject *object)
367 {
368         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
369         TotemScrsaverPrivate *priv = scr->priv;
370
371         priv->watch_id = g_bus_watch_name_on_connection (priv->connection,
372                                                          GS_SERVICE,
373                                                          G_BUS_NAME_WATCHER_FLAGS_NONE,
374                                                          screensaver_dbus_appeared_cb,
375                                                          screensaver_dbus_disappeared_cb,
376                                                          scr, NULL);
377 }
378
379 static void
380 totem_scrsaver_set_property (GObject      *object,
381                              guint         prop_id,
382                              const GValue *value,
383                              GParamSpec   *pspec)
384 {
385         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
386         TotemScrsaverPrivate *priv = scr->priv;
387
388         switch (prop_id) {
389         case PROP_CONNECTION:
390                 priv->connection = g_value_dup_object (value);
391                 break;
392         default:
393                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
394                 break;
395         }
396 }
397
398 #endif /* ENABLE_DBUS */
399
400 static void
401 totem_scrsaver_class_init (TotemScrsaverClass *klass)
402 {
403         GObjectClass *object_class = G_OBJECT_CLASS (klass);
404
405 #ifdef ENABLE_DBUS
406         g_object_class_install_property (object_class,
407                                          PROP_CONNECTION,
408                                          g_param_spec_object ("connection", NULL, NULL,
409                                                               G_TYPE_DBUS_CONNECTION,
410                                                               G_PARAM_WRITABLE |
411                                                               G_PARAM_CONSTRUCT_ONLY |
412                                                               G_PARAM_STATIC_STRINGS));
413         object_class->set_property = totem_scrsaver_set_property;
414         object_class->constructed = totem_scrsaver_constructed;
415 #endif
416
417         object_class->finalize = totem_scrsaver_finalize;
418 }
419
420 TotemScrsaver *
421 #ifdef ENABLE_DBUS
422 totem_scrsaver_new (GDBusConnection *connection)
423 #else
424 totem_scrsaver_new (void)
425 #endif
426 {
427         return g_object_new (TOTEM_TYPE_SCRSAVER,
428 #ifdef ENABLE_DBUS
429                              "connection", connection,
430 #endif
431                              NULL);
432 }
433
434 static void
435 totem_scrsaver_init (TotemScrsaver *scr)
436 {
437         scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr, TOTEM_TYPE_SCRSAVER, TotemScrsaverPrivate);
438
439         screensaver_init_dbus (scr);
440 #ifdef GDK_WINDOWING_X11
441         screensaver_init_x11 (scr);
442 #else
443 #warning Unimplemented
444 #endif
445 }
446
447 void
448 totem_scrsaver_disable (TotemScrsaver *scr)
449 {
450         g_return_if_fail (TOTEM_SCRSAVER (scr));
451
452         if (scr->priv->disabled != FALSE)
453                 return;
454
455         scr->priv->disabled = TRUE;
456
457         if (screensaver_is_running_dbus (scr) != FALSE)
458                 screensaver_disable_dbus (scr);
459         else 
460 #ifdef GDK_WINDOWING_X11
461                 screensaver_disable_x11 (scr);
462 #else
463 #warning Unimplemented
464         {}
465 #endif
466 }
467
468 void
469 totem_scrsaver_enable (TotemScrsaver *scr)
470 {
471         g_return_if_fail (TOTEM_SCRSAVER (scr));
472
473         if (scr->priv->disabled == FALSE)
474                 return;
475
476         scr->priv->disabled = FALSE;
477
478         if (screensaver_is_running_dbus (scr) != FALSE)
479                 screensaver_enable_dbus (scr);
480         else 
481 #ifdef GDK_WINDOWING_X11
482                 screensaver_enable_x11 (scr);
483 #else
484 #warning Unimplemented
485         {}
486 #endif
487 }
488
489 void
490 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
491 {
492         g_return_if_fail (TOTEM_SCRSAVER (scr));
493
494         if (scr->priv->disabled == !enable)
495                 return;
496
497         if (enable == FALSE)
498                 totem_scrsaver_disable (scr);
499         else
500                 totem_scrsaver_enable (scr);
501 }
502
503 static void
504 totem_scrsaver_finalize (GObject *object)
505 {
506         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
507
508         screensaver_finalize_dbus (scr);
509 #ifdef GDK_WINDOWING_X11
510         screensaver_finalize_x11 (scr);
511 #else
512 #warning Unimplemented
513         {}
514 #endif
515
516         G_OBJECT_CLASS (parent_class)->finalize (object);
517 }