]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
0339171cecbf214a663a8a029f1c17bd04a6738b
[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., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, 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 #include <dbus/dbus.h>
41 #include <dbus/dbus-glib.h>
42
43 #define GS_SERVICE   "org.gnome.ScreenSaver"
44 #define GS_PATH      "/org/gnome/ScreenSaver"
45 #define GS_INTERFACE "org.gnome.ScreenSaver"
46 #endif /* ENABLE_DBUS */
47
48 #include "totem-scrsaver.h"
49
50 #define XSCREENSAVER_MIN_TIMEOUT 60
51
52 static GObjectClass *parent_class = NULL;
53 static void totem_scrsaver_class_init (TotemScrsaverClass *class);
54 static void totem_scrsaver_init       (TotemScrsaver      *parser);
55 static void totem_scrsaver_finalize   (GObject *object);
56
57
58 struct TotemScrsaverPrivate {
59         /* Whether the screensaver is disabled */
60         gboolean disabled;
61
62 #ifdef ENABLE_DBUS
63         DBusGConnection *connection;
64         DBusGProxy *gs_proxy;
65         guint32 cookie;
66 #endif /* ENABLE_DBUS */
67
68         /* To save the screensaver info */
69         int timeout;
70         int interval;
71         int prefer_blanking;
72         int allow_exposures;
73
74         /* For use with XTest */
75         int keycode1, keycode2;
76         int *keycode;
77         gboolean have_xtest;
78 };
79
80 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
81
82 static gboolean
83 screensaver_is_running_dbus (TotemScrsaver *scr)
84 {
85 #ifdef ENABLE_DBUS
86         if (! scr->priv->connection)
87                 return FALSE;
88
89         if (! scr->priv->gs_proxy)
90                 return FALSE;
91
92         return TRUE;
93 #else
94         return FALSE;
95 #endif /* ENABLE_DBUS */
96 }
97
98 static void
99 screensaver_inhibit_dbus (TotemScrsaver *scr,
100                           gboolean       inhibit)
101 {
102 #ifdef ENABLE_DBUS
103         GError *error;
104         gboolean res;
105
106         g_return_if_fail (scr != NULL);
107         g_return_if_fail (scr->priv->connection != NULL);
108         g_return_if_fail (scr->priv->gs_proxy != NULL);
109
110         error = NULL;
111         if (inhibit) {
112                 char   *application;
113                 char   *reason;
114                 guint32 cookie;
115
116                 application = g_strdup ("Evince");
117                 reason = g_strdup (_("Running in presentation mode"));
118
119                 res = dbus_g_proxy_call (scr->priv->gs_proxy,
120                                          "Inhibit",
121                                          &error,
122                                          G_TYPE_STRING, application,
123                                          G_TYPE_STRING, reason,
124                                          G_TYPE_INVALID,
125                                          G_TYPE_UINT, &cookie,
126                                          G_TYPE_INVALID);
127
128                 if (res) {
129                         /* save the cookie */
130                         scr->priv->cookie = cookie;
131                 } else {
132                         /* try the old API */
133                         res = dbus_g_proxy_call (scr->priv->gs_proxy,
134                                                  "InhibitActivation",
135                                                  &error,
136                                                  G_TYPE_STRING, reason,
137                                                  G_TYPE_INVALID,
138                                                  G_TYPE_INVALID);
139                 }
140
141                 g_free (reason);
142                 g_free (application);
143
144         } else {
145                 res = dbus_g_proxy_call (scr->priv->gs_proxy,
146                                          "UnInhibit",
147                                          &error,
148                                          G_TYPE_UINT, scr->priv->cookie,
149                                          G_TYPE_INVALID,
150                                          G_TYPE_INVALID);
151                 if (res) {
152                         /* clear the cookie */
153                         scr->priv->cookie = 0;
154                 } else {
155                         /* try the old API */
156                         res = dbus_g_proxy_call (scr->priv->gs_proxy,
157                                                  "AllowActivation",
158                                                  &error,
159                                                  G_TYPE_INVALID,
160                                                  G_TYPE_INVALID);
161                 }
162         }
163
164         if (! res) {
165                 if (error) {
166                         g_warning ("Problem inhibiting the screensaver: %s", error->message);
167                         g_error_free (error);
168                 }
169         }
170 #endif /* ENABLE_DBUS */
171 }
172
173 static void
174 screensaver_enable_dbus (TotemScrsaver *scr)
175 {
176         screensaver_inhibit_dbus (scr, FALSE);
177 }
178
179 static void
180 screensaver_disable_dbus (TotemScrsaver *scr)
181 {
182         screensaver_inhibit_dbus (scr, TRUE);
183 }
184
185 #ifdef ENABLE_DBUS
186 static void
187 gs_proxy_destroy_cb (GObject *proxy,
188                      TotemScrsaver *scr)
189 {
190         g_warning ("Detected that GNOME screensaver has left the bus");
191
192         /* just invalidate for now */
193         scr->priv->gs_proxy = NULL;
194 }
195 #endif
196
197 #ifdef ENABLE_DBUS
198 static void
199 screensaver_init_dbus (TotemScrsaver *scr, DBusGConnection *connection)
200 {
201         GError *error = NULL;
202
203         if (!connection)
204                 scr->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
205         else
206                 scr->priv->connection = connection;
207
208         if (! scr->priv->connection) {
209                 if (error) {
210                         g_warning ("Failed to connect to the session bus: %s", error->message);
211                         g_error_free (error);
212                 }
213                 return;
214         }
215
216         scr->priv->gs_proxy = dbus_g_proxy_new_for_name_owner (scr->priv->connection,
217                                                                GS_SERVICE,
218                                                                GS_PATH,
219                                                                GS_INTERFACE,
220                                                                NULL);
221         if (scr->priv->gs_proxy != NULL) {
222                 g_signal_connect_object (scr->priv->gs_proxy,
223                                          "destroy",
224                                          G_CALLBACK (gs_proxy_destroy_cb),
225                                          scr,
226                                          0);
227
228         }
229
230 }
231 #endif /* ENABLE_DBUS */
232
233 static void
234 screensaver_finalize_dbus (TotemScrsaver *scr)
235 {
236 #ifdef ENABLE_DBUS
237         if (scr->priv->gs_proxy) {
238                 g_object_unref (scr->priv->gs_proxy);
239         }
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                 {
304                         g_timeout_add_seconds (scr->priv->timeout / 2,
305                                                (GSourceFunc) fake_event, scr);
306                 } else {
307                         g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
308                                         (GSourceFunc) fake_event, scr);
309                 }
310
311                 return;
312         }
313 #endif /* HAVE_XTEST */
314
315         XLockDisplay (GDK_DISPLAY());
316         XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
317                         &scr->priv->interval,
318                         &scr->priv->prefer_blanking,
319                         &scr->priv->allow_exposures);
320         XSetScreenSaver(GDK_DISPLAY(), 0, 0,
321                         DontPreferBlanking, DontAllowExposures);
322         XUnlockDisplay (GDK_DISPLAY());
323 }
324
325 static void
326 screensaver_init_x11 (TotemScrsaver *scr)
327 {
328 #ifdef HAVE_XTEST
329         int a, b, c, d;
330
331         XLockDisplay (GDK_DISPLAY());
332         scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
333         if (scr->priv->have_xtest != FALSE)
334         {
335                 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
336                 if (scr->priv->keycode1 == 0) {
337                         g_warning ("scr->priv->keycode1 not existant");
338                 }
339                 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
340                 if (scr->priv->keycode2 == 0) {
341                         scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
342                         if (scr->priv->keycode2 == 0) {
343                                 g_warning ("scr->priv->keycode2 not existant");
344                         }
345                 }
346                 scr->priv->keycode = &scr->priv->keycode1;
347         }
348         XUnlockDisplay (GDK_DISPLAY());
349 #endif /* HAVE_XTEST */
350 }
351
352 static void
353 screensaver_finalize_x11 (TotemScrsaver *scr)
354 {
355         g_source_remove_by_user_data (scr);
356 }
357 #endif
358
359 static void
360 totem_scrsaver_class_init (TotemScrsaverClass *klass)
361 {
362         GObjectClass *object_class = G_OBJECT_CLASS (klass);
363
364         parent_class = g_type_class_peek_parent (klass);
365
366         object_class->finalize = totem_scrsaver_finalize;
367 }
368
369 #ifdef ENABLE_DBUS
370 TotemScrsaver *
371 totem_scrsaver_new      (DBusGConnection *connection)
372 {
373         TotemScrsaver * scr;
374         scr = TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
375
376         screensaver_init_dbus (scr, connection);
377 #ifdef GDK_WINDOWING_X11
378         screensaver_init_x11 (scr);
379 #else
380 #warning Unimplemented
381 #endif
382         
383         return scr;
384 }
385 #else
386 TotemScrsaver *
387 totem_scrsaver_new()
388 {
389         TotemScrsaver * scr;
390         scr = TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
391
392 #ifdef GDK_WINDOWING_X11
393         screensaver_init_x11 (scr);
394 #else
395 #warning Unimplemented
396 #endif
397         
398         return scr;
399 }
400 #endif
401
402 static void
403 totem_scrsaver_init (TotemScrsaver *scr)
404 {
405         scr->priv = g_new0 (TotemScrsaverPrivate, 1);
406
407         
408 }
409
410 void
411 totem_scrsaver_disable (TotemScrsaver *scr)
412 {
413         g_return_if_fail (TOTEM_SCRSAVER (scr));
414
415         if (scr->priv->disabled != FALSE)
416                 return;
417
418         scr->priv->disabled = TRUE;
419
420         if (screensaver_is_running_dbus (scr) != FALSE)
421                 screensaver_disable_dbus (scr);
422         else 
423 #ifdef GDK_WINDOWING_X11
424                 screensaver_disable_x11 (scr);
425 #else
426 #warning Unimplemented
427         {}
428 #endif
429 }
430
431 void
432 totem_scrsaver_enable (TotemScrsaver *scr)
433 {
434         g_return_if_fail (TOTEM_SCRSAVER (scr));
435
436         if (scr->priv->disabled == FALSE)
437                 return;
438
439         scr->priv->disabled = FALSE;
440
441         if (screensaver_is_running_dbus (scr) != FALSE)
442                 screensaver_enable_dbus (scr);
443         else 
444 #ifdef GDK_WINDOWING_X11
445                 screensaver_enable_x11 (scr);
446 #else
447 #warning Unimplemented
448         {}
449 #endif
450 }
451
452 static void
453 totem_scrsaver_finalize (GObject *object)
454 {
455         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
456
457         screensaver_finalize_dbus (scr);
458 #ifdef GDK_WINDOWING_X11
459         screensaver_finalize_x11 (scr);
460 #else
461 #warning Unimplemented
462         {}
463 #endif
464
465         g_free (scr->priv);
466
467         if (G_OBJECT_CLASS (parent_class)->finalize != NULL) {
468                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
469         }
470 }
471