1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2004-2006 William Jon McCann <mccann@jhu.edu>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program 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
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
* Authors: William Jon McCann <mccann@jhu.edu>
30
#include <glib-object.h>
34
#include "gnome-screensaver.h"
36
#include "gs-manager.h"
37
#include "gs-watcher.h"
41
#include "gs-listener-dbus.h"
42
#include "gs-monitor.h"
46
static void gs_monitor_class_init (GSMonitorClass *klass);
47
static void gs_monitor_init (GSMonitor *monitor);
48
static void gs_monitor_finalize (GObject *object);
50
#define GS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_MONITOR, GSMonitorPrivate))
52
struct GSMonitorPrivate
60
guint release_grab_id;
63
#define FADE_TIMEOUT 10000
65
G_DEFINE_TYPE (GSMonitor, gs_monitor, G_TYPE_OBJECT)
68
gs_monitor_class_init (GSMonitorClass *klass)
70
GObjectClass *object_class = G_OBJECT_CLASS (klass);
72
object_class->finalize = gs_monitor_finalize;
74
g_type_class_add_private (klass, sizeof (GSMonitorPrivate));
78
manager_activated_cb (GSManager *manager,
84
manager_deactivated_cb (GSManager *manager,
87
gs_listener_set_active (monitor->priv->listener, FALSE);
91
watcher_idle_cb (GSWatcher *watcher,
97
gs_debug ("Idle signal detected: %d", is_idle);
99
res = gs_listener_set_session_idle (monitor->priv->listener, is_idle);
105
release_grab_timeout (GSMonitor *monitor)
107
gboolean manager_active;
109
manager_active = gs_manager_get_active (monitor->priv->manager);
110
if (! manager_active) {
111
gs_grab_release (monitor->priv->grab);
114
monitor->priv->release_grab_id = 0;
119
watcher_idle_notice_cb (GSWatcher *watcher,
123
gboolean activation_enabled;
126
gs_debug ("Idle notice signal detected: %d", in_effect);
128
/* only fade if screensaver can activate */
129
activation_enabled = gs_listener_get_activation_enabled (monitor->priv->listener);
133
if (activation_enabled) {
134
/* start slow fade */
135
if (gs_grab_grab_offscreen (monitor->priv->grab, FALSE)) {
136
gs_fade_async (monitor->priv->fade, FADE_TIMEOUT, NULL, NULL);
138
gs_debug ("Could not grab the keyboard so not performing idle warning fade-out");
144
gboolean manager_active;
146
manager_active = gs_manager_get_active (monitor->priv->manager);
147
/* cancel the fade unless manager was activated */
148
if (! manager_active) {
149
gs_debug ("manager not active, performing fade cancellation");
150
gs_fade_reset (monitor->priv->fade);
152
/* don't release the grab immediately to prevent typing passwords into windows */
153
if (monitor->priv->release_grab_id != 0) {
154
g_source_remove (monitor->priv->release_grab_id);
156
monitor->priv->release_grab_id = g_timeout_add (1000, (GSourceFunc)release_grab_timeout, monitor);
158
gs_debug ("manager active, skipping fade cancellation");
168
gs_monitor_lock_screen (GSMonitor *monitor)
174
/* set lock flag before trying to activate screensaver
175
in case something tries to react to the ActiveChanged signal */
177
gs_manager_get_lock_active (monitor->priv->manager, &locked);
178
gs_manager_set_lock_active (monitor->priv->manager, TRUE);
179
active = gs_manager_get_active (monitor->priv->manager);
182
res = gs_listener_set_active (monitor->priv->listener, TRUE);
184
/* If we've failed then restore lock status */
185
gs_manager_set_lock_active (monitor->priv->manager, locked);
186
gs_debug ("Unable to lock the screen");
193
gs_monitor_simulate_user_activity (GSMonitor *monitor)
195
XResetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
197
/* request that the manager unlock -
198
will pop up a dialog if necessary */
199
gs_manager_request_unlock (monitor->priv->manager);
203
listener_lock_cb (GSListener *listener,
206
if (! monitor->priv->prefs->lock_disabled) {
207
gs_monitor_lock_screen (monitor);
209
gs_debug ("Locking disabled by the administrator");
215
listener_quit_cb (GSListener *listener,
218
gs_listener_set_active (monitor->priv->listener, FALSE);
219
gnome_screensaver_quit ();
223
listener_show_message_cb (GSListener *listener,
229
gs_manager_show_message (monitor->priv->manager,
236
listener_active_changed_cb (GSListener *listener,
242
gboolean idle_watch_enabled;
244
res = gs_manager_set_active (monitor->priv->manager, active);
246
gs_debug ("Unable to set manager active: %d", active);
255
idle_watch_enabled = gs_watcher_get_enabled (monitor->priv->watcher);
256
if (ret && idle_watch_enabled) {
257
res = gs_watcher_set_active (monitor->priv->watcher, !active);
259
gs_debug ("Unable to set the idle watcher active: %d", !active);
267
listener_simulate_user_activity_cb (GSListener *listener,
270
gs_monitor_simulate_user_activity (monitor);
274
_gs_monitor_update_from_prefs (GSMonitor *monitor,
277
gboolean idle_detection_enabled;
278
gboolean idle_detection_active;
279
gboolean activate_watch;
280
gboolean manager_active;
281
gboolean lock_enabled;
282
gboolean user_switch_enabled;
284
lock_enabled = (monitor->priv->prefs->lock_enabled && !monitor->priv->prefs->lock_disabled);
285
user_switch_enabled = (monitor->priv->prefs->user_switch_enabled && !monitor->priv->prefs->user_switch_disabled);
287
gs_manager_set_lock_enabled (monitor->priv->manager, lock_enabled);
288
gs_manager_set_lock_timeout (monitor->priv->manager, monitor->priv->prefs->lock_timeout);
289
gs_manager_set_logout_enabled (monitor->priv->manager, monitor->priv->prefs->logout_enabled);
290
gs_manager_set_user_switch_enabled (monitor->priv->manager, user_switch_enabled);
291
gs_manager_set_keyboard_enabled (monitor->priv->manager, monitor->priv->prefs->keyboard_enabled);
292
gs_manager_set_logout_timeout (monitor->priv->manager, monitor->priv->prefs->logout_timeout);
293
gs_manager_set_logout_command (monitor->priv->manager, monitor->priv->prefs->logout_command);
294
gs_manager_set_keyboard_command (monitor->priv->manager, monitor->priv->prefs->keyboard_command);
296
/* enable activation when allowed */
297
gs_listener_set_activation_enabled (monitor->priv->listener,
298
monitor->priv->prefs->idle_activation_enabled);
300
/* idle detection always enabled */
301
idle_detection_enabled = TRUE;
303
gs_watcher_set_enabled (monitor->priv->watcher, idle_detection_enabled);
305
/* in the case where idle detection is reenabled we may need to
306
activate the watcher too */
308
manager_active = gs_manager_get_active (monitor->priv->manager);
309
idle_detection_active = gs_watcher_get_active (monitor->priv->watcher);
310
activate_watch = (! manager_active
311
&& ! idle_detection_active
312
&& idle_detection_enabled);
313
if (activate_watch) {
314
gs_watcher_set_active (monitor->priv->watcher, TRUE);
317
if (monitor->priv->prefs->status_message_enabled) {
319
g_object_get (monitor->priv->watcher,
320
"status-message", &text,
322
gs_manager_set_status_message (monitor->priv->manager, text);
325
gs_manager_set_status_message (monitor->priv->manager, NULL);
330
disconnect_listener_signals (GSMonitor *monitor)
332
g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_lock_cb, monitor);
333
g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_quit_cb, monitor);
334
g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_active_changed_cb, monitor);
335
g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_simulate_user_activity_cb, monitor);
336
g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_show_message_cb, monitor);
340
connect_listener_signals (GSMonitor *monitor)
342
g_signal_connect (monitor->priv->listener, "lock",
343
G_CALLBACK (listener_lock_cb), monitor);
344
g_signal_connect (monitor->priv->listener, "quit",
345
G_CALLBACK (listener_quit_cb), monitor);
346
g_signal_connect (monitor->priv->listener, "active-changed",
347
G_CALLBACK (listener_active_changed_cb), monitor);
348
g_signal_connect (monitor->priv->listener, "simulate-user-activity",
349
G_CALLBACK (listener_simulate_user_activity_cb), monitor);
350
g_signal_connect (monitor->priv->listener, "show-message",
351
G_CALLBACK (listener_show_message_cb), monitor);
355
on_watcher_status_message_changed (GSWatcher *watcher,
360
g_object_get (watcher, "status-message", &text, NULL);
361
gs_manager_set_status_message (monitor->priv->manager, text);
366
disconnect_watcher_signals (GSMonitor *monitor)
368
g_signal_handlers_disconnect_by_func (monitor->priv->watcher, watcher_idle_cb, monitor);
369
g_signal_handlers_disconnect_by_func (monitor->priv->watcher, watcher_idle_notice_cb, monitor);
370
g_signal_handlers_disconnect_by_func (monitor->priv->watcher, on_watcher_status_message_changed, monitor);
374
connect_watcher_signals (GSMonitor *monitor)
376
g_signal_connect (monitor->priv->watcher, "idle-changed",
377
G_CALLBACK (watcher_idle_cb), monitor);
378
g_signal_connect (monitor->priv->watcher, "idle-notice-changed",
379
G_CALLBACK (watcher_idle_notice_cb), monitor);
380
g_signal_connect (monitor->priv->watcher, "notify::status-message",
381
G_CALLBACK (on_watcher_status_message_changed), monitor);
386
disconnect_manager_signals (GSMonitor *monitor)
388
g_signal_handlers_disconnect_by_func (monitor->priv->manager, manager_activated_cb, monitor);
389
g_signal_handlers_disconnect_by_func (monitor->priv->manager, manager_deactivated_cb, monitor);
393
connect_manager_signals (GSMonitor *monitor)
395
g_signal_connect (monitor->priv->manager, "activated",
396
G_CALLBACK (manager_activated_cb), monitor);
397
g_signal_connect (monitor->priv->manager, "deactivated",
398
G_CALLBACK (manager_deactivated_cb), monitor);
402
disconnect_prefs_signals (GSMonitor *monitor)
404
g_signal_handlers_disconnect_by_func (monitor->priv->prefs, _gs_monitor_update_from_prefs, monitor);
408
connect_prefs_signals (GSMonitor *monitor)
410
g_signal_connect_swapped (monitor->priv->prefs, "changed",
411
G_CALLBACK (_gs_monitor_update_from_prefs), monitor);
415
gs_monitor_init (GSMonitor *monitor)
418
monitor->priv = GS_MONITOR_GET_PRIVATE (monitor);
420
monitor->priv->prefs = gs_prefs_new ();
421
connect_prefs_signals (monitor);
423
monitor->priv->listener = gs_listener_new ();
424
connect_listener_signals (monitor);
426
monitor->priv->fade = gs_fade_new ();
427
monitor->priv->grab = gs_grab_new ();
429
monitor->priv->watcher = gs_watcher_new ();
430
connect_watcher_signals (monitor);
432
monitor->priv->manager = gs_manager_new ();
433
connect_manager_signals (monitor);
435
_gs_monitor_update_from_prefs (monitor, monitor->priv->prefs);
439
gs_monitor_finalize (GObject *object)
443
g_return_if_fail (object != NULL);
444
g_return_if_fail (GS_IS_MONITOR (object));
446
monitor = GS_MONITOR (object);
448
g_return_if_fail (monitor->priv != NULL);
450
disconnect_watcher_signals (monitor);
451
disconnect_listener_signals (monitor);
452
disconnect_manager_signals (monitor);
453
disconnect_prefs_signals (monitor);
455
g_object_unref (monitor->priv->fade);
456
g_object_unref (monitor->priv->grab);
457
g_object_unref (monitor->priv->watcher);
458
g_object_unref (monitor->priv->listener);
459
g_object_unref (monitor->priv->manager);
460
g_object_unref (monitor->priv->prefs);
462
G_OBJECT_CLASS (gs_monitor_parent_class)->finalize (object);
466
gs_monitor_new (void)
470
monitor = g_object_new (GS_TYPE_MONITOR, NULL);
472
return GS_MONITOR (monitor);
476
gs_monitor_start (GSMonitor *monitor,
479
g_return_val_if_fail (GS_IS_MONITOR (monitor), FALSE);
481
if (! gs_listener_acquire (monitor->priv->listener, error)) {