1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
Copyright (C) 2004-2006 Bastien Nocera <hadess@hadess.net>
4
Copyright © 2010 Christian Persch
5
Copyright © 2010 Carlos Garcia Campos
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.
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.
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.
22
Authors: Bastien Nocera <hadess@hadess.net>
29
#include <glib/gi18n.h>
33
#ifdef GDK_WINDOWING_X11
35
#include <X11/keysym.h>
40
#include <X11/extensions/XTest.h>
41
#endif /* HAVE_XTEST */
42
#endif /* GDK_WINDOWING_X11 */
44
#include "totem-scrsaver.h"
46
#define GS_SERVICE "org.gnome.SessionManager"
47
#define GS_PATH "/org/gnome/SessionManager"
48
#define GS_INTERFACE "org.gnome.SessionManager"
49
/* From org.gnome.SessionManager.xml */
50
#define GS_NO_IDLE_FLAG 8
52
#define XSCREENSAVER_MIN_TIMEOUT 60
60
static void totem_scrsaver_finalize (GObject *object);
62
struct TotemScrsaverPrivate {
63
/* Whether the screensaver is disabled */
65
/* The reason for the inhibition */
69
gboolean have_session_dbus;
73
/* To save the screensaver info */
79
/* For use with XTest */
80
int keycode1, keycode2;
85
G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
88
screensaver_is_running_dbus (TotemScrsaver *scr)
90
return scr->priv->have_session_dbus;
94
on_inhibit_cb (GObject *source_object,
98
GDBusProxy *proxy = G_DBUS_PROXY (source_object);
99
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
101
GError *error = NULL;
103
value = g_dbus_proxy_call_finish (proxy, res, &error);
105
g_warning ("Problem inhibiting the screensaver: %s", error->message);
106
g_object_unref (scr);
107
g_error_free (error);
112
/* save the cookie */
113
if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
114
g_variant_get (value, "(u)", &scr->priv->cookie);
116
scr->priv->cookie = 0;
117
g_variant_unref (value);
119
g_object_unref (scr);
123
on_uninhibit_cb (GObject *source_object,
127
GDBusProxy *proxy = G_DBUS_PROXY (source_object);
128
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
130
GError *error = NULL;
132
value = g_dbus_proxy_call_finish (proxy, res, &error);
134
g_warning ("Problem uninhibiting the screensaver: %s", error->message);
135
g_object_unref (scr);
136
g_error_free (error);
141
/* clear the cookie */
142
scr->priv->cookie = 0;
143
g_variant_unref (value);
145
g_object_unref (scr);
149
screensaver_inhibit_dbus (TotemScrsaver *scr,
152
TotemScrsaverPrivate *priv = scr->priv;
155
if (!priv->have_session_dbus)
163
g_return_if_fail (scr->priv->reason != NULL);
166
if (scr->priv->window != NULL) {
167
window = gtk_widget_get_window (GTK_WIDGET (scr->priv->window));
169
xid = gdk_x11_window_get_xid (window);
173
g_dbus_proxy_call (priv->gs_proxy,
175
g_variant_new ("(susu)",
176
g_get_application_name (),
180
G_DBUS_CALL_FLAGS_NO_AUTO_START,
186
if (priv->cookie > 0) {
187
g_dbus_proxy_call (priv->gs_proxy,
189
g_variant_new ("(u)", priv->cookie),
190
G_DBUS_CALL_FLAGS_NO_AUTO_START,
200
screensaver_enable_dbus (TotemScrsaver *scr)
202
screensaver_inhibit_dbus (scr, FALSE);
206
screensaver_disable_dbus (TotemScrsaver *scr)
208
screensaver_inhibit_dbus (scr, TRUE);
212
screensaver_dbus_proxy_new_cb (GObject *source,
213
GAsyncResult *result,
216
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
217
TotemScrsaverPrivate *priv = scr->priv;
219
priv->gs_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL);
223
priv->have_session_dbus = TRUE;
224
if (priv->reason != NULL && scr->priv->disabled)
225
screensaver_disable_dbus (scr);
229
screensaver_init_dbus (TotemScrsaver *scr)
231
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
232
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
238
screensaver_dbus_proxy_new_cb,
243
screensaver_finalize_dbus (TotemScrsaver *scr)
245
if (scr->priv->gs_proxy) {
246
g_object_unref (scr->priv->gs_proxy);
250
#ifdef GDK_WINDOWING_X11
252
screensaver_enable_x11 (TotemScrsaver *scr)
256
if (scr->priv->have_xtest != FALSE)
258
g_source_remove_by_user_data (scr);
261
#endif /* HAVE_XTEST */
263
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
264
XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
267
scr->priv->prefer_blanking,
268
scr->priv->allow_exposures);
269
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
274
fake_event (TotemScrsaver *scr)
276
if (scr->priv->disabled)
278
/* If the video window isn't focused, don't send out the
279
* events. Note that it probably breaks when popups are used
280
* but we can't do much about that... */
281
if (scr->priv->window != NULL &&
282
gtk_window_has_toplevel_focus (scr->priv->window) == FALSE)
285
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
286
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
288
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
290
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
291
/* Swap the keycode */
292
if (scr->priv->keycode == &scr->priv->keycode1)
293
scr->priv->keycode = &scr->priv->keycode2;
295
scr->priv->keycode = &scr->priv->keycode1;
300
#endif /* HAVE_XTEST */
303
screensaver_disable_x11 (TotemScrsaver *scr)
307
if (scr->priv->have_xtest != FALSE)
309
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
310
XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
311
&scr->priv->interval,
312
&scr->priv->prefer_blanking,
313
&scr->priv->allow_exposures);
314
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
316
if (scr->priv->timeout != 0) {
317
g_timeout_add_seconds (scr->priv->timeout / 2,
318
(GSourceFunc) fake_event, scr);
320
g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
321
(GSourceFunc) fake_event, scr);
326
#endif /* HAVE_XTEST */
328
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
329
XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
330
&scr->priv->interval,
331
&scr->priv->prefer_blanking,
332
&scr->priv->allow_exposures);
333
XSetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 0, 0,
334
DontPreferBlanking, DontAllowExposures);
335
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
339
screensaver_init_x11 (TotemScrsaver *scr)
344
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
345
scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &a, &b, &c, &d) == True);
346
if (scr->priv->have_xtest != FALSE)
348
scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
349
if (scr->priv->keycode1 == 0) {
350
g_warning ("scr->priv->keycode1 not existant");
352
scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_R);
353
if (scr->priv->keycode2 == 0) {
354
scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
355
if (scr->priv->keycode2 == 0) {
356
g_warning ("scr->priv->keycode2 not existant");
359
scr->priv->keycode = &scr->priv->keycode1;
361
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
362
#endif /* HAVE_XTEST */
366
screensaver_finalize_x11 (TotemScrsaver *scr)
368
g_source_remove_by_user_data (scr);
373
totem_scrsaver_get_property (GObject *object,
380
scr = TOTEM_SCRSAVER (object);
385
g_value_set_string (value, scr->priv->reason);
388
g_value_set_object (value, scr->priv->window);
391
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
396
totem_scrsaver_set_property (GObject *object,
403
scr = TOTEM_SCRSAVER (object);
408
g_free (scr->priv->reason);
409
scr->priv->reason = g_value_dup_string (value);
412
if (scr->priv->window)
413
g_object_unref (scr->priv->window);
414
scr->priv->window = g_value_dup_object (value);
417
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
422
totem_scrsaver_class_init (TotemScrsaverClass *klass)
424
GObjectClass *object_class = G_OBJECT_CLASS (klass);
426
g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
428
object_class->set_property = totem_scrsaver_set_property;
429
object_class->get_property = totem_scrsaver_get_property;
430
object_class->finalize = totem_scrsaver_finalize;
432
g_object_class_install_property (object_class, PROP_REASON,
433
g_param_spec_string ("reason", NULL, NULL,
434
NULL, G_PARAM_READWRITE));
435
g_object_class_install_property (object_class, PROP_WINDOW,
436
g_param_spec_object ("window", NULL, NULL,
437
GTK_TYPE_WINDOW, G_PARAM_READWRITE));
441
* totem_scrsaver_new:
443
* Creates a #TotemScrsaver object.
444
* If the GNOME screen saver is running, it uses its DBUS interface to
445
* inhibit the screensaver; otherwise it falls back to using the X
446
* screensaver functionality for this.
448
* Returns: a newly created #TotemScrsaver
451
totem_scrsaver_new (void)
453
return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
457
totem_scrsaver_init (TotemScrsaver *scr)
459
scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
461
TotemScrsaverPrivate);
463
screensaver_init_dbus (scr);
464
#ifdef GDK_WINDOWING_X11
465
screensaver_init_x11 (scr);
467
#warning Unimplemented
472
totem_scrsaver_disable (TotemScrsaver *scr)
474
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
476
if (scr->priv->disabled != FALSE)
479
scr->priv->disabled = TRUE;
481
if (screensaver_is_running_dbus (scr) != FALSE)
482
screensaver_disable_dbus (scr);
484
#ifdef GDK_WINDOWING_X11
485
screensaver_disable_x11 (scr);
487
#warning Unimplemented
493
totem_scrsaver_enable (TotemScrsaver *scr)
495
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
497
if (scr->priv->disabled == FALSE)
500
scr->priv->disabled = FALSE;
502
if (screensaver_is_running_dbus (scr) != FALSE)
503
screensaver_enable_dbus (scr);
505
#ifdef GDK_WINDOWING_X11
506
screensaver_enable_x11 (scr);
508
#warning Unimplemented
514
totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
516
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
518
if (scr->priv->disabled == !enable)
522
totem_scrsaver_disable (scr);
524
totem_scrsaver_enable (scr);
528
totem_scrsaver_finalize (GObject *object)
530
TotemScrsaver *scr = TOTEM_SCRSAVER (object);
532
g_free (scr->priv->reason);
533
if (scr->priv->window != NULL)
534
g_object_unref (scr->priv->window);
536
screensaver_finalize_dbus (scr);
537
#ifdef GDK_WINDOWING_X11
538
screensaver_finalize_x11 (scr);
540
#warning Unimplemented
544
G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);