df097cd376ba8cdd97026169df8acfac6f65f0a2
[ozzloy@gmail.com/oble] / sleep.cpp
1 //http://www.gnome.org/~mccann/gnome-screensaver/docs/gnome-screensaver.html#gs-method-SimulateUserActivity
2 //simulate user activity might be better than the following:
3 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
4
5 Copyright (C) 2004-2006 Bastien Nocera <hadess@hadess.net>
6
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301 USA.
21
22 Author: Bastien Nocera <hadess@hadess.net>
23 */
24
25
26 #include "config.h"
27
28 #include <glib/gi18n.h>
29
30 #include <gdk/gdk.h>
31
32 #ifdef GDK_WINDOWING_X11
33 #include <gdk/gdkx.h>
34 #include <X11/keysym.h>
35
36 #ifdef HAVE_XTEST
37 #include <X11/extensions/XTest.h>
38 #endif /* HAVE_XTEST */
39 #endif /* GDK_WINDOWING_X11 */
40
41 #ifdef WITH_DBUS
42 #include <dbus/dbus.h>
43 #include <dbus/dbus-glib.h>
44
45 #define GS_SERVICE "org.gnome.ScreenSaver"
46 #define GS_PATH "/org/gnome/ScreenSaver"
47 #define GS_INTERFACE "org.gnome.ScreenSaver"
48 #endif /* WITH_DBUS */
49
50 #include "totem-scrsaver.h"
51
52 #define XSCREENSAVER_MIN_TIMEOUT 60
53
54 static GObjectClass *parent_class = NULL;
55 static void totem_scrsaver_finalize (GObject *object);
56
57
58 struct TotemScrsaverPrivate {
59 /* Whether the screensaver is disabled */
60 gboolean disabled;
61
62 #ifdef WITH_DBUS
63 DBusGConnection *connection;
64 DBusGProxy *gs_proxy;
65 guint32 cookie;
66 #endif /* WITH_DBUS */
67
68 /* To save the screensaver info */
69 int timeout;
70 int interval;
71 int prefer_blanking;
72 int allow_exposures;
73
74 /* For use with XTest */
75 int keycode1, keycode2;
76 int *keycode;
77 gboolean have_xtest;
78 };
79
80 G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
81
82 static gboolean
83 screensaver_is_running_dbus (TotemScrsaver *scr)
84 {
85 #ifdef WITH_DBUS
86 if (! scr->priv->connection)
87 return FALSE;
88
89 if (! scr->priv->gs_proxy)
90 return FALSE;
91
92 return TRUE;
93 #else
94 return FALSE;
95 #endif /* WITH_DBUS */
96 }
97
98 static void
99 screensaver_inhibit_dbus (TotemScrsaver *scr,
100 gboolean inhibit)
101 {
102 #ifdef WITH_DBUS
103 GError *error;
104 gboolean res;
105
106 g_return_if_fail (scr != NULL);
107 g_return_if_fail (scr->priv->connection != NULL);
108 g_return_if_fail (scr->priv->gs_proxy != NULL);
109
110 error = NULL;
111 if (inhibit) {
112 char *application;
113 char *reason;
114 guint32 cookie;
115
116 application = g_strdup ("Totem");
117 reason = g_strdup (_("Playing a movie"));
118
119 res = dbus_g_proxy_call (scr->priv->gs_proxy,
120 "Inhibit",
121 &error,
122 G_TYPE_STRING, application,
123 G_TYPE_STRING, reason,
124 G_TYPE_INVALID,
125 G_TYPE_UINT, &cookie,
126 G_TYPE_INVALID);
127
128 if (res) {
129 /* save the cookie */
130 scr->priv->cookie = cookie;
131 } else {
132 /* try the old API */
133 res = dbus_g_proxy_call (scr->priv->gs_proxy,
134 "InhibitActivation",
135 &error,
136 G_TYPE_STRING, reason,
137 G_TYPE_INVALID,
138 G_TYPE_INVALID);
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 &error,
159 G_TYPE_INVALID,
160 G_TYPE_INVALID);
161 }
162 }
163
164 if (! res) {
165 if (error) {
166 g_warning ("Problem inhibiting the screensaver: %s", error->message);
167 g_error_free (error);
168 }
169 }
170 #endif /* WITH_DBUS */
171 }
172
173 static void
174 screensaver_enable_dbus (TotemScrsaver *scr)
175 {
176 screensaver_inhibit_dbus (scr, FALSE);
177 }
178
179 static void
180 screensaver_disable_dbus (TotemScrsaver *scr)
181 {
182 screensaver_inhibit_dbus (scr, TRUE);
183 }
184
185 #ifdef WITH_DBUS
186 static void
187 gs_proxy_destroy_cb (GObject *proxy,
188 TotemScrsaver *scr)
189 {
190 g_warning ("Detected that GNOME screensaver has left the bus");
191
192 /* just invalidate for now */
193 scr->priv->gs_proxy = NULL;
194 }
195 #endif
196
197 static void
198 screensaver_init_dbus (TotemScrsaver *scr)
199 {
200 #ifdef WITH_DBUS
201 GError *error = NULL;
202
203 scr->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
204
205 if (! scr->priv->connection) {
206 if (error) {
207 g_warning ("Failed to connect to the session bus: %s", error->message);
208 g_error_free (error);
209 }
210 return;
211 }
212
213 scr->priv->gs_proxy = dbus_g_proxy_new_for_name_owner (scr->priv->connection,
214 GS_SERVICE,
215 GS_PATH,
216 GS_INTERFACE,
217 NULL);
218 if (scr->priv->gs_proxy != NULL) {
219 g_signal_connect_object (scr->priv->gs_proxy,
220 "destroy",
221 G_CALLBACK (gs_proxy_destroy_cb),
222 scr,
223 0);
224
225 }
226
227 #endif /* WITH_DBUS */
228 }
229
230 static void
231 screensaver_finalize_dbus (TotemScrsaver *scr)
232 {
233 #ifdef WITH_DBUS
234 if (scr->priv->gs_proxy) {
235 g_object_unref (scr->priv->gs_proxy);
236 }
237 #endif /* WITH_DBUS */
238 }
239
240 #ifdef GDK_WINDOWING_X11
241 static void
242 screensaver_enable_x11 (TotemScrsaver *scr)
243 {
244
245 #ifdef HAVE_XTEST
246 if (scr->priv->have_xtest != FALSE)
247 {
248 g_source_remove_by_user_data (scr);
249 return;
250 }
251 #endif /* HAVE_XTEST */
252
253 XLockDisplay (GDK_DISPLAY());
254 XSetScreenSaver (GDK_DISPLAY(),
255 scr->priv->timeout,
256 scr->priv->interval,
257 scr->priv->prefer_blanking,
258 scr->priv->allow_exposures);
259 XUnlockDisplay (GDK_DISPLAY());
260 }
261
262 #ifdef HAVE_XTEST
263 static gboolean
264 fake_event (TotemScrsaver *scr)
265 {
266 if (scr->priv->disabled)
267 {
268 XLockDisplay (GDK_DISPLAY());
269 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
270 True, CurrentTime);
271 XTestFakeKeyEvent (GDK_DISPLAY(), *scr->priv->keycode,
272 False, CurrentTime);
273 XUnlockDisplay (GDK_DISPLAY());
274 /* Swap the keycode */
275 if (scr->priv->keycode == &scr->priv->keycode1)
276 scr->priv->keycode = &scr->priv->keycode2;
277 else
278 scr->priv->keycode = &scr->priv->keycode1;
279 }
280
281 return TRUE;
282 }
283 #endif /* HAVE_XTEST */
284
285 static void
286 screensaver_disable_x11 (TotemScrsaver *scr)
287 {
288
289 #ifdef HAVE_XTEST
290 if (scr->priv->have_xtest != FALSE)
291 {
292 XLockDisplay (GDK_DISPLAY());
293 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
294 &scr->priv->interval,
295 &scr->priv->prefer_blanking,
296 &scr->priv->allow_exposures);
297 XUnlockDisplay (GDK_DISPLAY());
298
299 if (scr->priv->timeout != 0) {
300 g_timeout_add_seconds (scr->priv->timeout / 2,
301 (GSourceFunc) fake_event, scr);
302 } else {
303 g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
304 (GSourceFunc) fake_event, scr);
305 }
306
307 return;
308 }
309 #endif /* HAVE_XTEST */
310
311 XLockDisplay (GDK_DISPLAY());
312 XGetScreenSaver(GDK_DISPLAY(), &scr->priv->timeout,
313 &scr->priv->interval,
314 &scr->priv->prefer_blanking,
315 &scr->priv->allow_exposures);
316 XSetScreenSaver(GDK_DISPLAY(), 0, 0,
317 DontPreferBlanking, DontAllowExposures);
318 XUnlockDisplay (GDK_DISPLAY());
319 }
320
321 static void
322 screensaver_init_x11 (TotemScrsaver *scr)
323 {
324 #ifdef HAVE_XTEST
325 int a, b, c, d;
326
327 XLockDisplay (GDK_DISPLAY());
328 scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
329 if (scr->priv->have_xtest != FALSE)
330 {
331 scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
332 if (scr->priv->keycode1 == 0) {
333 g_warning ("scr->priv->keycode1 not existant");
334 }
335 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
336 if (scr->priv->keycode2 == 0) {
337 scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
338 if (scr->priv->keycode2 == 0) {
339 g_warning ("scr->priv->keycode2 not existant");
340 }
341 }
342 scr->priv->keycode = &scr->priv->keycode1;
343 }
344 XUnlockDisplay (GDK_DISPLAY());
345 #endif /* HAVE_XTEST */
346 }
347
348 static void
349 screensaver_finalize_x11 (TotemScrsaver *scr)
350 {
351 g_source_remove_by_user_data (scr);
352 }
353 #endif
354
355 static void
356 totem_scrsaver_class_init (TotemScrsaverClass *klass)
357 {
358 GObjectClass *object_class = G_OBJECT_CLASS (klass);
359
360 parent_class = g_type_class_peek_parent (klass);
361
362 object_class->finalize = totem_scrsaver_finalize;
363 }
364
365 TotemScrsaver *
366 totem_scrsaver_new (void)
367 {
368 return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
369 }
370
371 static void
372 totem_scrsaver_init (TotemScrsaver *scr)
373 {
374 scr->priv = g_new0 (TotemScrsaverPrivate, 1);
375
376 screensaver_init_dbus (scr);
377 #ifdef GDK_WINDOWING_X11
378 screensaver_init_x11 (scr);
379 #else
380 #warning Unimplemented
381 #endif
382 }
383
384 void
385 totem_scrsaver_disable (TotemScrsaver *scr)
386 {
387 g_return_if_fail (TOTEM_SCRSAVER (scr));
388
389 if (scr->priv->disabled != FALSE)
390 return;
391
392 scr->priv->disabled = TRUE;
393
394 if (screensaver_is_running_dbus (scr) != FALSE)
395 screensaver_disable_dbus (scr);
396 else
397 #ifdef GDK_WINDOWING_X11
398 screensaver_disable_x11 (scr);
399 #else
400 #warning Unimplemented
401 {}
402 #endif
403 }
404
405 void
406 totem_scrsaver_enable (TotemScrsaver *scr)
407 {
408 g_return_if_fail (TOTEM_SCRSAVER (scr));
409
410 if (scr->priv->disabled == FALSE)
411 return;
412
413 scr->priv->disabled = FALSE;
414
415 if (screensaver_is_running_dbus (scr) != FALSE)
416 screensaver_enable_dbus (scr);
417 else
418 #ifdef GDK_WINDOWING_X11
419 screensaver_enable_x11 (scr);
420 #else
421 #warning Unimplemented
422 {}
423 #endif
424 }
425
426 void
427 totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
428 {
429 g_return_if_fail (TOTEM_SCRSAVER (scr));
430
431 if (scr->priv->disabled == !enable)
432 return;
433
434 scr->priv->disabled = !enable;
435 if (scr->priv->disabled != 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 }