]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
Update totem-scrsaver from totem sources
[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 #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_finalize   (GObject *object);
54
55
56 struct TotemScrsaverPrivate {
57         /* Whether the screensaver is disabled */
58         gboolean disabled;
59
60 #ifdef ENABLE_DBUS
61         DBusGConnection *connection;
62         DBusGProxy *gs_proxy;
63         guint32 cookie;
64 #endif /* ENABLE_DBUS */
65
66         /* To save the screensaver info */
67         int timeout;
68         int interval;
69         int prefer_blanking;
70         int allow_exposures;
71
72         /* For use with XTest */
73         int keycode1, keycode2;
74         int *keycode;
75         gboolean have_xtest;
76 };
77
78 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
79
80 static gboolean
81 screensaver_is_running_dbus (TotemScrsaver *scr)
82 {
83 #ifdef ENABLE_DBUS
84         if (! scr->priv->connection)
85                 return FALSE;
86
87         if (! scr->priv->gs_proxy)
88                 return FALSE;
89
90         return TRUE;
91 #else
92         return FALSE;
93 #endif /* ENABLE_DBUS */
94 }
95
96 static void
97 screensaver_inhibit_dbus (TotemScrsaver *scr,
98                           gboolean       inhibit)
99 {
100 #ifdef ENABLE_DBUS
101         GError *error;
102         gboolean res;
103
104         g_return_if_fail (scr != NULL);
105         g_return_if_fail (scr->priv->connection != NULL);
106         g_return_if_fail (scr->priv->gs_proxy != NULL);
107
108         error = NULL;
109         if (inhibit) {
110                 char   *application;
111                 char   *reason;
112                 guint32 cookie;
113
114                 application = g_strdup ("Evince");
115                 reason = g_strdup (_("Running in presentation mode"));
116
117                 res = dbus_g_proxy_call (scr->priv->gs_proxy,
118                                          "Inhibit",
119                                          &error,
120                                          G_TYPE_STRING, application,
121                                          G_TYPE_STRING, reason,
122                                          G_TYPE_INVALID,
123                                          G_TYPE_UINT, &cookie,
124                                          G_TYPE_INVALID);
125
126                 if (res) {
127                         /* save the cookie */
128                         scr->priv->cookie = cookie;
129                 } else {
130                         /* try the old API */
131                         res = dbus_g_proxy_call (scr->priv->gs_proxy,
132                                                  "InhibitActivation",
133                                                  NULL,
134                                                  G_TYPE_STRING, reason,
135                                                  G_TYPE_INVALID,
136                                                  G_TYPE_INVALID);
137                         if (res)
138                                 g_error_free (error);
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                                                  NULL,
159                                                  G_TYPE_INVALID,
160                                                  G_TYPE_INVALID);
161                         if (res)
162                                 g_error_free (error);
163                 }
164         }
165
166         if (! res) {
167                 if (error) {
168                         g_warning ("Problem inhibiting the screensaver: %s", error->message);
169                         g_error_free (error);
170                 }
171         }
172 #endif /* ENABLE_DBUS */
173 }
174
175 static void
176 screensaver_enable_dbus (TotemScrsaver *scr)
177 {
178         screensaver_inhibit_dbus (scr, FALSE);
179 }
180
181 static void
182 screensaver_disable_dbus (TotemScrsaver *scr)
183 {
184         screensaver_inhibit_dbus (scr, TRUE);
185 }
186
187 #ifdef ENABLE_DBUS
188 static void
189 gs_proxy_destroy_cb (GObject *proxy,
190                      TotemScrsaver *scr)
191 {
192         g_warning ("Detected that GNOME screensaver has left the bus");
193
194         /* just invalidate for now */
195         scr->priv->gs_proxy = NULL;
196 }
197 #endif
198
199 static void
200 screensaver_init_dbus (TotemScrsaver *scr)
201 {
202 #ifdef ENABLE_DBUS
203         GError *error = NULL;
204
205         scr->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
206
207         if (! scr->priv->connection) {
208                 if (error) {
209                         g_warning ("Failed to connect to the session bus: %s", error->message);
210                         g_error_free (error);
211                 }
212                 return;
213         }
214
215         scr->priv->gs_proxy = dbus_g_proxy_new_for_name_owner (scr->priv->connection,
216                                                                GS_SERVICE,
217                                                                GS_PATH,
218                                                                GS_INTERFACE,
219                                                                NULL);
220         if (scr->priv->gs_proxy != NULL) {
221                 g_signal_connect_object (scr->priv->gs_proxy,
222                                          "destroy",
223                                          G_CALLBACK (gs_proxy_destroy_cb),
224                                          scr,
225                                          0);
226
227         }
228 #endif /* ENABLE_DBUS */
229 }
230
231 static void
232 screensaver_finalize_dbus (TotemScrsaver *scr)
233 {
234 #ifdef ENABLE_DBUS
235         if (scr->priv->gs_proxy) {
236                 g_object_unref (scr->priv->gs_proxy);
237         }
238 #endif /* ENABLE_DBUS */
239 }
240
241 #ifdef GDK_WINDOWING_X11
242 static void
243 screensaver_enable_x11 (TotemScrsaver *scr)
244 {
245
246 #ifdef HAVE_XTEST
247         if (scr->priv->have_xtest != FALSE)
248         {
249                 g_source_remove_by_user_data (scr);
250                 return;
251         }
252 #endif /* HAVE_XTEST */
253
254         XLockDisplay (GDK_DISPLAY());
255         XSetScreenSaver (GDK_DISPLAY(),
256                         scr->priv->timeout,
257                         scr->priv->interval,
258                         scr->priv->prefer_blanking,
259                         scr->priv->allow_exposures);
260         XUnlockDisplay (GDK_DISPLAY());
261 }
262
263 #ifdef HAVE_XTEST
264 static gboolean
265 fake_event (TotemScrsaver *scr)
266 {
267         if (scr->priv->disabled)
268         {
269                 XLockDisplay (GDK_DISPLAY());
270                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
271                                 True, CurrentTime);
272                 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
273                                 False, CurrentTime);
274                 XUnlockDisplay (GDK_DISPLAY());
275                 /* Swap the keycode */
276                 if (scr->priv->keycode == &scr->priv->keycode1)
277                         scr->priv->keycode = &scr->priv->keycode2;
278                 else
279                         scr->priv->keycode = &scr->priv->keycode1;
280         }
281
282         return TRUE;
283 }
284 #endif /* HAVE_XTEST */
285
286 static void
287 screensaver_disable_x11 (TotemScrsaver *scr)
288 {
289
290 #ifdef HAVE_XTEST
291         if (scr->priv->have_xtest != FALSE)
292         {
293                 XLockDisplay (GDK_DISPLAY());
294                 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
295                                 &scr->priv->interval,
296                                 &scr->priv->prefer_blanking,
297                                 &scr->priv->allow_exposures);
298                 XUnlockDisplay (GDK_DISPLAY());
299
300                 if (scr->priv->timeout != 0) {
301                         g_timeout_add_seconds (scr->priv->timeout / 2,
302                                                (GSourceFunc) fake_event, scr);
303                 } else {
304                         g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
305                                                (GSourceFunc) fake_event, scr);
306                 }
307
308                 return;
309         }
310 #endif /* HAVE_XTEST */
311
312         XLockDisplay (GDK_DISPLAY());
313         XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
314                         &scr->priv->interval,
315                         &scr->priv->prefer_blanking,
316                         &scr->priv->allow_exposures);
317         XSetScreenSaver(GDK_DISPLAY(), 0, 0,
318                         DontPreferBlanking, DontAllowExposures);
319         XUnlockDisplay (GDK_DISPLAY());
320 }
321
322 static void
323 screensaver_init_x11 (TotemScrsaver *scr)
324 {
325 #ifdef HAVE_XTEST
326         int a, b, c, d;
327
328         XLockDisplay (GDK_DISPLAY());
329         scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
330         if (scr->priv->have_xtest != FALSE)
331         {
332                 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
333                 if (scr->priv->keycode1 == 0) {
334                         g_warning ("scr->priv->keycode1 not existant");
335                 }
336                 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
337                 if (scr->priv->keycode2 == 0) {
338                         scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
339                         if (scr->priv->keycode2 == 0) {
340                                 g_warning ("scr->priv->keycode2 not existant");
341                         }
342                 }
343                 scr->priv->keycode = &scr->priv->keycode1;
344         }
345         XUnlockDisplay (GDK_DISPLAY());
346 #endif /* HAVE_XTEST */
347 }
348
349 static void
350 screensaver_finalize_x11 (TotemScrsaver *scr)
351 {
352         g_source_remove_by_user_data (scr);
353 }
354 #endif
355
356 static void
357 totem_scrsaver_class_init (TotemScrsaverClass *klass)
358 {
359         GObjectClass *object_class = G_OBJECT_CLASS (klass);
360
361         parent_class = g_type_class_peek_parent (klass);
362
363         object_class->finalize = totem_scrsaver_finalize;
364 }
365
366 TotemScrsaver *
367 totem_scrsaver_new (void)
368 {
369         return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
370 }
371
372 static void
373 totem_scrsaver_init (TotemScrsaver *scr)
374 {
375         scr->priv = g_new0 (TotemScrsaverPrivate, 1);
376
377         screensaver_init_dbus (scr);
378 #ifdef GDK_WINDOWING_X11
379         screensaver_init_x11 (scr);
380 #else
381 #warning Unimplemented
382 #endif
383 }
384
385 void
386 totem_scrsaver_disable (TotemScrsaver *scr)
387 {
388         g_return_if_fail (TOTEM_SCRSAVER (scr));
389
390         if (scr->priv->disabled != FALSE)
391                 return;
392
393         scr->priv->disabled = TRUE;
394
395         if (screensaver_is_running_dbus (scr) != FALSE)
396                 screensaver_disable_dbus (scr);
397         else 
398 #ifdef GDK_WINDOWING_X11
399                 screensaver_disable_x11 (scr);
400 #else
401 #warning Unimplemented
402         {}
403 #endif
404 }
405
406 void
407 totem_scrsaver_enable (TotemScrsaver *scr)
408 {
409         g_return_if_fail (TOTEM_SCRSAVER (scr));
410
411         if (scr->priv->disabled == FALSE)
412                 return;
413
414         scr->priv->disabled = FALSE;
415
416         if (screensaver_is_running_dbus (scr) != FALSE)
417                 screensaver_enable_dbus (scr);
418         else 
419 #ifdef GDK_WINDOWING_X11
420                 screensaver_enable_x11 (scr);
421 #else
422 #warning Unimplemented
423         {}
424 #endif
425 }
426
427 void
428 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
429 {
430         g_return_if_fail (TOTEM_SCRSAVER (scr));
431
432         if (scr->priv->disabled == !enable)
433                 return;
434
435         if (enable == FALSE)
436                 totem_scrsaver_disable (scr);
437         else
438                 totem_scrsaver_enable (scr);
439 }
440
441 static void
442 totem_scrsaver_finalize (GObject *object)
443 {
444         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
445
446         screensaver_finalize_dbus (scr);
447 #ifdef GDK_WINDOWING_X11
448         screensaver_finalize_x11 (scr);
449 #else
450 #warning Unimplemented
451         {}
452 #endif
453
454         g_free (scr->priv);
455
456         if (G_OBJECT_CLASS (parent_class)->finalize != NULL) {
457                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
458         }
459 }
460