]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/totem-screensaver/totem-scrsaver.c
c7011cf10ba4af94e6ea884a5933c9857e82932f
[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                         g_timeout_add_seconds (scr->priv->timeout / 2,
298                                                (GSourceFunc) fake_event, scr);
299                 } else {
300                         g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
301                                         (GSourceFunc) fake_event, scr);
302                 }
303
304                 return;
305         }
306 #endif /* HAVE_XTEST */
307
308         XLockDisplay (GDK_DISPLAY());
309         XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
310                         &scr->priv->interval,
311                         &scr->priv->prefer_blanking,
312                         &scr->priv->allow_exposures);
313         XSetScreenSaver(GDK_DISPLAY(), 0, 0,
314                         DontPreferBlanking, DontAllowExposures);
315         XUnlockDisplay (GDK_DISPLAY());
316 }
317
318 static void
319 screensaver_init_x11 (TotemScrsaver *scr)
320 {
321 #ifdef HAVE_XTEST
322         int a, b, c, d;
323
324         XLockDisplay (GDK_DISPLAY());
325         scr->priv->have_xtest = XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d);
326         if(scr->priv->have_xtest == True)
327         {
328                 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
329                 if (scr->priv->keycode1 == 0) {
330                         g_warning ("scr->priv->keycode1 not existant");
331                 }
332                 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
333                 if (scr->priv->keycode2 == 0) {
334                         scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
335                         if (scr->priv->keycode2 == 0) {
336                                 g_warning ("scr->priv->keycode2 not existant");
337                         }
338                 }
339                 scr->priv->keycode = &scr->priv->keycode1;
340         }
341         XUnlockDisplay (GDK_DISPLAY());
342 #endif /* HAVE_XTEST */
343 }
344
345 static void
346 screensaver_finalize_x11 (TotemScrsaver *scr)
347 {
348         g_source_remove_by_user_data (scr);
349 }
350
351 static void
352 totem_scrsaver_class_init (TotemScrsaverClass *klass)
353 {
354         GObjectClass *object_class = G_OBJECT_CLASS (klass);
355
356         parent_class = g_type_class_peek_parent (klass);
357
358         object_class->finalize = totem_scrsaver_finalize;
359 }
360
361 #ifdef ENABLE_DBUS
362 TotemScrsaver *
363 totem_scrsaver_new      (DBusGConnection *connection)
364 {
365         TotemScrsaver * scr;
366         scr = TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
367
368         screensaver_init_dbus (scr, connection);
369         screensaver_init_x11 (scr);
370         
371         return scr;
372 }
373 #else
374 TotemScrsaver *
375 totem_scrsaver_new()
376 {
377         TotemScrsaver * scr;
378         scr = TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
379
380         screensaver_init_x11 (scr);
381         
382         return scr;
383 }
384 #endif
385
386 static void
387 totem_scrsaver_init (TotemScrsaver *scr)
388 {
389         scr->priv = g_new0 (TotemScrsaverPrivate, 1);
390 }
391
392 void
393 totem_scrsaver_disable (TotemScrsaver *scr)
394 {
395         if (scr->priv->disabled != FALSE)
396                 return;
397
398         scr->priv->disabled = TRUE;
399
400         if (screensaver_is_running_dbus (scr) != FALSE)
401                 screensaver_disable_dbus (scr);
402         else 
403                 screensaver_disable_x11 (scr);
404 }
405
406 void
407 totem_scrsaver_enable (TotemScrsaver *scr)
408 {
409         if (scr->priv->disabled == FALSE)
410                 return;
411
412         scr->priv->disabled = FALSE;
413
414         if (screensaver_is_running_dbus (scr) != FALSE)
415                 screensaver_enable_dbus (scr);
416         else 
417                 screensaver_enable_x11 (scr);
418 }
419
420 static void
421 totem_scrsaver_finalize (GObject *object)
422 {
423         TotemScrsaver *scr = TOTEM_SCRSAVER (object);
424
425         screensaver_finalize_dbus (scr);
426         screensaver_finalize_x11 (scr);
427
428         g_free (scr->priv);
429
430         if (G_OBJECT_CLASS (parent_class)->finalize != NULL) {
431                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
432         }
433 }
434