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