]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
30ea718fe5047760c4e610b368e43da3bc3d628e
[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 /* Evince/Totem differences */
27 #ifdef ENABLE_DEBUG
28 #define WITH_DBUS
29 #else
30 #undef WITH_DBUS
31 #endif
32
33 #include <glib/gi18n.h>
34
35 #include <gdk/gdk.h>
36
37 #ifdef GDK_WINDOWING_X11
38 #include <gdk/gdkx.h>
39 #include <X11/keysym.h>
40
41 #ifdef HAVE_XTEST
42 #include <X11/extensions/XTest.h>
43 #endif /* HAVE_XTEST */
44 #endif /* GDK_WINDOWING_X11 */
45
46 #ifdef WITH_DBUS
47 #define GS_SERVICE   "org.gnome.ScreenSaver"
48 #define GS_PATH      "/org/gnome/ScreenSaver"
49 #define GS_INTERFACE "org.gnome.ScreenSaver"
50 #endif /* WITH_DBUS */
51
52 #include "totem-scrsaver.h"
53
54 #define XSCREENSAVER_MIN_TIMEOUT 60
55
56 static GObjectClass *parent_class = NULL;
57 static void totem_scrsaver_finalize   (GObject *object);
58
59
60 struct TotemScrsaverPrivate {
61         /* Whether the screensaver is disabled */
62         gboolean disabled;
63
64 #ifdef WITH_DBUS
65         GDBusConnection *connection;
66         guint watch_id;
67         guint32 cookie;
68 #endif /* WITH_DBUS */
69
70         /* To save the screensaver info */
71         int timeout;
72         int interval;
73         int prefer_blanking;
74         int allow_exposures;
75
76         /* For use with XTest */
77         int keycode1, keycode2;
78         int *keycode;
79         gboolean have_xtest;
80 };
81
82 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
83
84 static gboolean
85 screensaver_is_running_dbus (TotemScrsaver *scr)
86 {
87 #ifdef WITH_DBUS
88         return scr->priv->connection != NULL;
89 #else
90         return FALSE;
91 #endif /* WITH_DBUS */
92 }
93
94 static void
95 screensaver_inhibit_dbus (TotemScrsaver *scr,
96                           gboolean       inhibit)
97 {
98 #ifdef WITH_DBUS
99         GError *error = NULL;
100         GVariant *value;
101
102         if (scr->priv->connection == NULL)
103                 return;
104
105         if (inhibit) {
106                 value = g_dbus_connection_call_sync (scr->priv->connection,
107                                                      GS_SERVICE,
108                                                      GS_PATH,
109                                                      GS_INTERFACE,
110                                                      "Inhibit",
111                                                      g_variant_new ("(ss)",
112                                                                     "Evince",
113                                                                     _("Running in presentation mode")),
114                                                      G_DBUS_INVOKE_METHOD_FLAGS_NO_AUTO_START,
115                                                      -1,
116                                                      NULL,
117                                                      &error);
118                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
119                         /* try the old API */
120                         g_clear_error (&error);
121                         value = g_dbus_connection_call_sync (scr->priv->connection,
122                                                              GS_SERVICE,
123                                                              GS_PATH,
124                                                              GS_INTERFACE,
125                                                              "InhibitActivation",
126                                                              g_variant_new ("(s)",
127                                                                             _("Running in presentation mode")),
128                                                              G_DBUS_INVOKE_METHOD_FLAGS_NO_AUTO_START,
129                                                              -1,
130                                                              NULL,
131                                                              &error);
132                 }
133                 if (value != NULL) {
134                         /* save the cookie */
135                         if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
136                                g_variant_get (value, "(u)", &scr->priv->cookie);
137                         else
138                                 scr->priv->cookie = 0;
139                         g_variant_unref (value);
140                 } else {
141                         g_warning ("Problem inhibiting the screensaver: %s", error->message);
142                         g_error_free (error);
143                 }
144
145         } else {
146                 value = g_dbus_connection_call_sync (scr->priv->connection,
147                                                      GS_SERVICE,
148                                                      GS_PATH,
149                                                      GS_INTERFACE,
150                                                      "UnInhibit",
151                                                      g_variant_new ("(u)", scr->priv->cookie),
152                                                      G_DBUS_INVOKE_METHOD_FLAGS_NO_AUTO_START,
153                                                      -1,
154                                                      NULL,
155                                                      &error);
156                 if (error && g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
157                         /* try the old API */
158                         g_clear_error (&error);
159                         value = g_dbus_connection_call_sync (scr->priv->connection,
160                                                              GS_SERVICE,
161                                                              GS_PATH,
162                                                              GS_INTERFACE,
163                                                              "AllowActivation",
164                                                              g_variant_new ("()"),
165                                                              G_DBUS_INVOKE_METHOD_FLAGS_NO_AUTO_START,
166                                                              -1,
167                                                              NULL,
168                                                              &error);
169                 }
170                 if (value != NULL) {
171                         /* clear the cookie */
172                         scr->priv->cookie = 0;
173                         g_variant_unref (value);
174                 } else {
175                         g_warning ("Problem uninhibiting the screensaver: %s", error->message);
176                         g_error_free (error);
177                 }
178         }
179 #endif /* WITH_DBUS */
180 }
181
182 static void
183 screensaver_enable_dbus (TotemScrsaver *scr)
184 {
185         screensaver_inhibit_dbus (scr, FALSE);
186 }
187
188 static void
189 screensaver_disable_dbus (TotemScrsaver *scr)
190 {
191         screensaver_inhibit_dbus (scr, TRUE);
192 }
193
194 #ifdef WITH_DBUS
195 static void
196 screensaver_dbus_appeared_cb (GDBusConnection *connection,
197                               const char      *name,
198                               const char      *name_owner,
199                               gpointer         user_data)
200 {
201         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
202
203         scr->priv->connection = g_object_ref (connection);
204 }
205
206 static void
207 screensaver_dbus_disappeared_cb (GDBusConnection *connection,
208                                  const char      *name,
209                                  gpointer         user_data)
210 {
211         TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
212
213         g_assert (scr->priv->connection == connection);
214         g_object_unref (scr->priv->connection);
215         scr->priv->connection = NULL;
216 }
217 #endif
218
219 static void
220 screensaver_init_dbus (TotemScrsaver *scr)
221 {
222 #ifdef WITH_DBUS
223         scr->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 /* WITH_DBUS */
230 }
231
232 static void
233 screensaver_finalize_dbus (TotemScrsaver *scr)
234 {
235 #ifdef WITH_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 /* WITH_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 static void
359 totem_scrsaver_class_init (TotemScrsaverClass *klass)
360 {
361         GObjectClass *object_class = G_OBJECT_CLASS (klass);
362
363         parent_class = g_type_class_peek_parent (klass);
364
365         object_class->finalize = totem_scrsaver_finalize;
366 }
367
368 TotemScrsaver *
369 totem_scrsaver_new (void)
370 {
371         return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
372 }
373
374 static void
375 totem_scrsaver_init (TotemScrsaver *scr)
376 {
377         scr->priv = g_new0 (TotemScrsaverPrivate, 1);
378
379         screensaver_init_dbus (scr);
380 #ifdef GDK_WINDOWING_X11
381         screensaver_init_x11 (scr);
382 #else
383 #warning Unimplemented
384 #endif
385 }
386
387 void
388 totem_scrsaver_disable (TotemScrsaver *scr)
389 {
390         g_return_if_fail (TOTEM_SCRSAVER (scr));
391
392         if (scr->priv->disabled != FALSE)
393                 return;
394
395         scr->priv->disabled = TRUE;
396
397         if (screensaver_is_running_dbus (scr) != FALSE)
398                 screensaver_disable_dbus (scr);
399         else 
400 #ifdef GDK_WINDOWING_X11
401                 screensaver_disable_x11 (scr);
402 #else
403 #warning Unimplemented
404         {}
405 #endif
406 }
407
408 void
409 totem_scrsaver_enable (TotemScrsaver *scr)
410 {
411         g_return_if_fail (TOTEM_SCRSAVER (scr));
412
413         if (scr->priv->disabled == FALSE)
414                 return;
415
416         scr->priv->disabled = FALSE;
417
418         if (screensaver_is_running_dbus (scr) != FALSE)
419                 screensaver_enable_dbus (scr);
420         else 
421 #ifdef GDK_WINDOWING_X11
422                 screensaver_enable_x11 (scr);
423 #else
424 #warning Unimplemented
425         {}
426 #endif
427 }
428
429 void
430 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
431 {
432         g_return_if_fail (TOTEM_SCRSAVER (scr));
433
434         if (scr->priv->disabled == !enable)
435                 return;
436
437         if (enable == FALSE)
438                 totem_scrsaver_disable (scr);
439         else
440                 totem_scrsaver_enable (scr);
441 }
442
443 static void
444 totem_scrsaver_finalize (GObject *object)
445 {
446         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
447
448         screensaver_finalize_dbus (scr);
449 #ifdef GDK_WINDOWING_X11
450         screensaver_finalize_x11 (scr);
451 #else
452 #warning Unimplemented
453         {}
454 #endif
455
456         g_free (scr->priv);
457
458         if (G_OBJECT_CLASS (parent_class)->finalize != NULL) {
459                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
460         }
461 }
462