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