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