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>
38
#include <X11/extensions/XTest.h>
39
#endif /* HAVE_XTEST */
40
#endif /* GDK_WINDOWING_X11 */
42
#include "totem-scrsaver.h"
44
#define GS_SERVICE "org.gnome.SessionManager"
45
#define GS_PATH "/org/gnome/SessionManager"
46
#define GS_INTERFACE "org.gnome.SessionManager"
47
/* From org.gnome.SessionManager.xml */
48
#define GS_NO_IDLE_FLAG 8
50
#define XSCREENSAVER_MIN_TIMEOUT 60
58
static void totem_scrsaver_finalize (GObject *object);
60
struct TotemScrsaverPrivate {
61
/* Whether the screensaver is disabled */
63
/* The reason for the inhibition */
67
gboolean have_session_dbus;
71
/* To save the screensaver info */
77
/* For use with XTest */
78
int keycode1, keycode2;
83
G_DEFINE_TYPE(TotemScrsaver, totem_scrsaver, G_TYPE_OBJECT)
86
screensaver_is_running_dbus (TotemScrsaver *scr)
88
return scr->priv->have_session_dbus;
92
on_inhibit_cb (GObject *source_object,
96
GDBusProxy *proxy = G_DBUS_PROXY (source_object);
97
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
101
value = g_dbus_proxy_call_finish (proxy, res, &error);
103
g_warning ("Problem inhibiting the screensaver: %s", error->message);
104
g_object_unref (scr);
105
g_error_free (error);
110
/* save the cookie */
111
if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(u)")))
112
g_variant_get (value, "(u)", &scr->priv->cookie);
114
scr->priv->cookie = 0;
115
g_variant_unref (value);
117
g_object_unref (scr);
121
on_uninhibit_cb (GObject *source_object,
125
GDBusProxy *proxy = G_DBUS_PROXY (source_object);
126
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
128
GError *error = NULL;
130
value = g_dbus_proxy_call_finish (proxy, res, &error);
132
g_warning ("Problem uninhibiting the screensaver: %s", error->message);
133
g_object_unref (scr);
134
g_error_free (error);
139
/* clear the cookie */
140
scr->priv->cookie = 0;
141
g_variant_unref (value);
143
g_object_unref (scr);
147
screensaver_inhibit_dbus (TotemScrsaver *scr,
150
TotemScrsaverPrivate *priv = scr->priv;
153
if (!priv->have_session_dbus)
161
g_return_if_fail (scr->priv->reason != NULL);
164
if (scr->priv->window != NULL) {
165
window = gtk_widget_get_window (GTK_WIDGET (scr->priv->window));
167
xid = gdk_x11_window_get_xid (window);
171
g_dbus_proxy_call (priv->gs_proxy,
173
g_variant_new ("(susu)",
174
g_get_application_name (),
178
G_DBUS_CALL_FLAGS_NO_AUTO_START,
184
if (priv->cookie > 0) {
185
g_dbus_proxy_call (priv->gs_proxy,
187
g_variant_new ("(u)", priv->cookie),
188
G_DBUS_CALL_FLAGS_NO_AUTO_START,
198
screensaver_enable_dbus (TotemScrsaver *scr)
200
screensaver_inhibit_dbus (scr, FALSE);
204
screensaver_disable_dbus (TotemScrsaver *scr)
206
screensaver_inhibit_dbus (scr, TRUE);
210
screensaver_dbus_proxy_new_cb (GObject *source,
211
GAsyncResult *result,
214
TotemScrsaver *scr = TOTEM_SCRSAVER (user_data);
215
TotemScrsaverPrivate *priv = scr->priv;
217
priv->gs_proxy = g_dbus_proxy_new_for_bus_finish (result, NULL);
221
priv->have_session_dbus = TRUE;
222
if (priv->reason != NULL && scr->priv->disabled)
223
screensaver_disable_dbus (scr);
227
screensaver_init_dbus (TotemScrsaver *scr)
229
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
230
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
236
screensaver_dbus_proxy_new_cb,
241
screensaver_finalize_dbus (TotemScrsaver *scr)
243
if (scr->priv->gs_proxy) {
244
g_object_unref (scr->priv->gs_proxy);
248
#ifdef GDK_WINDOWING_X11
250
screensaver_enable_x11 (TotemScrsaver *scr)
254
if (scr->priv->have_xtest != FALSE)
256
g_source_remove_by_user_data (scr);
259
#endif /* HAVE_XTEST */
261
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
262
XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
265
scr->priv->prefer_blanking,
266
scr->priv->allow_exposures);
267
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
272
fake_event (TotemScrsaver *scr)
274
if (scr->priv->disabled)
276
/* If the video window isn't focused, don't send out the
277
* events. Note that it probably breaks when popups are used
278
* but we can't do much about that... */
279
if (scr->priv->window != NULL &&
280
gtk_window_has_toplevel_focus (scr->priv->window) == FALSE)
283
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
284
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
286
XTestFakeKeyEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), *scr->priv->keycode,
288
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
289
/* Swap the keycode */
290
if (scr->priv->keycode == &scr->priv->keycode1)
291
scr->priv->keycode = &scr->priv->keycode2;
293
scr->priv->keycode = &scr->priv->keycode1;
298
#endif /* HAVE_XTEST */
301
screensaver_disable_x11 (TotemScrsaver *scr)
305
if (scr->priv->have_xtest != FALSE)
307
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
308
XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
309
&scr->priv->interval,
310
&scr->priv->prefer_blanking,
311
&scr->priv->allow_exposures);
312
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
314
if (scr->priv->timeout != 0) {
315
g_timeout_add_seconds (scr->priv->timeout / 2,
316
(GSourceFunc) fake_event, scr);
318
g_timeout_add_seconds (XSCREENSAVER_MIN_TIMEOUT / 2,
319
(GSourceFunc) fake_event, scr);
324
#endif /* HAVE_XTEST */
326
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
327
XGetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &scr->priv->timeout,
328
&scr->priv->interval,
329
&scr->priv->prefer_blanking,
330
&scr->priv->allow_exposures);
331
XSetScreenSaver(GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 0, 0,
332
DontPreferBlanking, DontAllowExposures);
333
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
337
screensaver_init_x11 (TotemScrsaver *scr)
342
XLockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
343
scr->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &a, &b, &c, &d) == True);
344
if (scr->priv->have_xtest != FALSE)
346
scr->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
347
if (scr->priv->keycode1 == 0) {
348
g_warning ("scr->priv->keycode1 not existant");
350
scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_R);
351
if (scr->priv->keycode2 == 0) {
352
scr->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XK_Alt_L);
353
if (scr->priv->keycode2 == 0) {
354
g_warning ("scr->priv->keycode2 not existant");
357
scr->priv->keycode = &scr->priv->keycode1;
359
XUnlockDisplay (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
360
#endif /* HAVE_XTEST */
364
screensaver_finalize_x11 (TotemScrsaver *scr)
366
g_source_remove_by_user_data (scr);
371
totem_scrsaver_get_property (GObject *object,
378
scr = TOTEM_SCRSAVER (object);
383
g_value_set_string (value, scr->priv->reason);
386
g_value_set_object (value, scr->priv->window);
389
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
394
totem_scrsaver_set_property (GObject *object,
401
scr = TOTEM_SCRSAVER (object);
406
g_free (scr->priv->reason);
407
scr->priv->reason = g_value_dup_string (value);
410
if (scr->priv->window)
411
g_object_unref (scr->priv->window);
412
scr->priv->window = g_value_dup_object (value);
415
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
420
totem_scrsaver_class_init (TotemScrsaverClass *klass)
422
GObjectClass *object_class = G_OBJECT_CLASS (klass);
424
g_type_class_add_private (klass, sizeof (TotemScrsaverPrivate));
426
object_class->set_property = totem_scrsaver_set_property;
427
object_class->get_property = totem_scrsaver_get_property;
428
object_class->finalize = totem_scrsaver_finalize;
430
g_object_class_install_property (object_class, PROP_REASON,
431
g_param_spec_string ("reason", NULL, NULL,
432
NULL, G_PARAM_READWRITE));
433
g_object_class_install_property (object_class, PROP_WINDOW,
434
g_param_spec_object ("window", NULL, NULL,
435
GTK_TYPE_WINDOW, G_PARAM_READWRITE));
439
* totem_scrsaver_new:
441
* Creates a #TotemScrsaver object.
442
* If the GNOME screen saver is running, it uses its DBUS interface to
443
* inhibit the screensaver; otherwise it falls back to using the X
444
* screensaver functionality for this.
446
* Returns: a newly created #TotemScrsaver
449
totem_scrsaver_new (void)
451
return TOTEM_SCRSAVER (g_object_new (TOTEM_TYPE_SCRSAVER, NULL));
455
totem_scrsaver_init (TotemScrsaver *scr)
457
scr->priv = G_TYPE_INSTANCE_GET_PRIVATE (scr,
459
TotemScrsaverPrivate);
461
screensaver_init_dbus (scr);
462
#ifdef GDK_WINDOWING_X11
463
screensaver_init_x11 (scr);
465
#warning Unimplemented
470
totem_scrsaver_disable (TotemScrsaver *scr)
472
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
474
if (scr->priv->disabled != FALSE)
477
scr->priv->disabled = TRUE;
479
if (screensaver_is_running_dbus (scr) != FALSE)
480
screensaver_disable_dbus (scr);
482
#ifdef GDK_WINDOWING_X11
483
screensaver_disable_x11 (scr);
485
#warning Unimplemented
491
totem_scrsaver_enable (TotemScrsaver *scr)
493
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
495
if (scr->priv->disabled == FALSE)
498
scr->priv->disabled = FALSE;
500
if (screensaver_is_running_dbus (scr) != FALSE)
501
screensaver_enable_dbus (scr);
503
#ifdef GDK_WINDOWING_X11
504
screensaver_enable_x11 (scr);
506
#warning Unimplemented
512
totem_scrsaver_set_state (TotemScrsaver *scr, gboolean enable)
514
g_return_if_fail (TOTEM_IS_SCRSAVER (scr));
516
if (scr->priv->disabled == !enable)
520
totem_scrsaver_disable (scr);
522
totem_scrsaver_enable (scr);
526
totem_scrsaver_finalize (GObject *object)
528
TotemScrsaver *scr = TOTEM_SCRSAVER (object);
530
g_free (scr->priv->reason);
531
if (scr->priv->window != NULL)
532
g_object_unref (scr->priv->window);
534
screensaver_finalize_dbus (scr);
535
#ifdef GDK_WINDOWING_X11
536
screensaver_finalize_x11 (scr);
538
#warning Unimplemented
542
G_OBJECT_CLASS (totem_scrsaver_parent_class)->finalize (object);