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