~ubuntu-branches/ubuntu/saucy/gnome-screensaver/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/31_lock_screen_on_suspend.patch/src/gs-monitor.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-05-01 11:08:03 UTC
  • Revision ID: package-import@ubuntu.com-20130501110803-wrmnhjybvxcts33s
Tags: 3.6.1-0ubuntu5
* Add 30_ubuntu-lock-on-suspend_gsetting.patch: Handle
  ubuntu-lock-on-suspend gsettings key. This is introduced in Ubuntu's
  gsettings-desktop-schemas package.
* Add 31_lock_screen_on_suspend.patch: Lock screen on suspend. Listen for
  logind's PrepareForSleep signal, and lock the screen (if configured
  to do so). This mirrors what gnome-shell's screensaver does, obsoleting
  our Ubuntu specific patch in g-s-d.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2004-2006 William Jon McCann <mccann@jhu.edu>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 *
 
19
 * Authors: William Jon McCann <mccann@jhu.edu>
 
20
 *
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <unistd.h>
 
27
#include <string.h>
 
28
 
 
29
#include <glib.h>
 
30
#include <glib-object.h>
 
31
#include <X11/Xlib.h>
 
32
#include <gdk/gdkx.h>
 
33
 
 
34
#include "gnome-screensaver.h"
 
35
 
 
36
#include "gs-manager.h"
 
37
#include "gs-watcher.h"
 
38
#include "gs-fade.h"
 
39
#include "gs-grab.h"
 
40
 
 
41
#include "gs-listener-dbus.h"
 
42
#include "gs-monitor.h"
 
43
#include "gs-prefs.h"
 
44
#include "gs-debug.h"
 
45
 
 
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);
 
49
 
 
50
#define GS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_MONITOR, GSMonitorPrivate))
 
51
 
 
52
struct GSMonitorPrivate
 
53
{
 
54
        GSWatcher      *watcher;
 
55
        GSListener     *listener;
 
56
        GSManager      *manager;
 
57
        GSPrefs        *prefs;
 
58
        GSFade         *fade;
 
59
        GSGrab         *grab;
 
60
        guint           release_grab_id;
 
61
};
 
62
 
 
63
#define FADE_TIMEOUT 10000
 
64
 
 
65
G_DEFINE_TYPE (GSMonitor, gs_monitor, G_TYPE_OBJECT)
 
66
 
 
67
static void
 
68
gs_monitor_class_init (GSMonitorClass *klass)
 
69
{
 
70
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
71
 
 
72
        object_class->finalize = gs_monitor_finalize;
 
73
 
 
74
        g_type_class_add_private (klass, sizeof (GSMonitorPrivate));
 
75
}
 
76
 
 
77
static void
 
78
manager_activated_cb (GSManager *manager,
 
79
                      GSMonitor *monitor)
 
80
{
 
81
}
 
82
 
 
83
static void
 
84
manager_deactivated_cb (GSManager *manager,
 
85
                        GSMonitor *monitor)
 
86
{
 
87
        gs_listener_set_active (monitor->priv->listener, FALSE);
 
88
}
 
89
 
 
90
static gboolean
 
91
watcher_idle_cb (GSWatcher *watcher,
 
92
                 gboolean   is_idle,
 
93
                 GSMonitor *monitor)
 
94
{
 
95
        gboolean res;
 
96
 
 
97
        gs_debug ("Idle signal detected: %d", is_idle);
 
98
 
 
99
        res = gs_listener_set_session_idle (monitor->priv->listener, is_idle);
 
100
 
 
101
        return res;
 
102
}
 
103
 
 
104
static gboolean
 
105
release_grab_timeout (GSMonitor *monitor)
 
106
{
 
107
        gboolean manager_active;
 
108
 
 
109
        manager_active = gs_manager_get_active (monitor->priv->manager);
 
110
        if (! manager_active) {
 
111
                gs_grab_release (monitor->priv->grab);
 
112
        }
 
113
 
 
114
        monitor->priv->release_grab_id = 0;
 
115
        return FALSE;
 
116
}
 
117
 
 
118
static gboolean
 
119
watcher_idle_notice_cb (GSWatcher *watcher,
 
120
                        gboolean   in_effect,
 
121
                        GSMonitor *monitor)
 
122
{
 
123
        gboolean activation_enabled;
 
124
        gboolean handled;
 
125
 
 
126
        gs_debug ("Idle notice signal detected: %d", in_effect);
 
127
 
 
128
        /* only fade if screensaver can activate */
 
129
        activation_enabled = gs_listener_get_activation_enabled (monitor->priv->listener);
 
130
 
 
131
        handled = FALSE;
 
132
        if (in_effect) {
 
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);
 
137
                        } else {
 
138
                                gs_debug ("Could not grab the keyboard so not performing idle warning fade-out");
 
139
                        }
 
140
 
 
141
                        handled = TRUE;
 
142
                }
 
143
        } else {
 
144
                gboolean manager_active;
 
145
 
 
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);
 
151
 
 
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);
 
155
                        }
 
156
                        monitor->priv->release_grab_id = g_timeout_add (1000, (GSourceFunc)release_grab_timeout, monitor);
 
157
                } else {
 
158
                        gs_debug ("manager active, skipping fade cancellation");
 
159
                }
 
160
 
 
161
                handled = TRUE;
 
162
        }
 
163
 
 
164
        return handled;
 
165
}
 
166
 
 
167
static void
 
168
gs_monitor_lock_screen (GSMonitor *monitor)
 
169
{
 
170
        gboolean res;
 
171
        gboolean locked;
 
172
        gboolean active;
 
173
 
 
174
        /* set lock flag before trying to activate screensaver
 
175
           in case something tries to react to the ActiveChanged signal */
 
176
 
 
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);
 
180
 
 
181
        if (! active) {
 
182
                res = gs_listener_set_active (monitor->priv->listener, TRUE);
 
183
                if (! res) {
 
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");
 
187
                }
 
188
        }
 
189
 
 
190
}
 
191
 
 
192
static void
 
193
gs_monitor_simulate_user_activity (GSMonitor *monitor)
 
194
{
 
195
        XResetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
 
196
 
 
197
        /* request that the manager unlock -
 
198
           will pop up a dialog if necessary */
 
199
        gs_manager_request_unlock (monitor->priv->manager);
 
200
}
 
201
 
 
202
static void
 
203
listener_lock_cb (GSListener *listener,
 
204
                  GSMonitor  *monitor)
 
205
{
 
206
        if (! monitor->priv->prefs->lock_disabled) {
 
207
                gs_monitor_lock_screen (monitor);
 
208
        } else {
 
209
                gs_debug ("Locking disabled by the administrator");
 
210
        }
 
211
 
 
212
}
 
213
 
 
214
static void
 
215
listener_quit_cb (GSListener *listener,
 
216
                  GSMonitor  *monitor)
 
217
{
 
218
        gs_listener_set_active (monitor->priv->listener, FALSE);
 
219
        gnome_screensaver_quit ();
 
220
}
 
221
 
 
222
static void
 
223
listener_show_message_cb (GSListener *listener,
 
224
                          const char *summary,
 
225
                          const char *body,
 
226
                          const char *icon,
 
227
                          GSMonitor  *monitor)
 
228
{
 
229
        gs_manager_show_message (monitor->priv->manager,
 
230
                                 summary,
 
231
                                 body,
 
232
                                 icon);
 
233
}
 
234
 
 
235
static gboolean
 
236
listener_active_changed_cb (GSListener *listener,
 
237
                            gboolean    active,
 
238
                            GSMonitor  *monitor)
 
239
{
 
240
        gboolean res;
 
241
        gboolean ret;
 
242
        gboolean idle_watch_enabled;
 
243
 
 
244
        res = gs_manager_set_active (monitor->priv->manager, active);
 
245
        if (! res) {
 
246
                gs_debug ("Unable to set manager active: %d", active);
 
247
                ret = FALSE;
 
248
                goto done;
 
249
        }
 
250
 
 
251
        ret = TRUE;
 
252
 
 
253
 done:
 
254
 
 
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);
 
258
                if (! res) {
 
259
                        gs_debug ("Unable to set the idle watcher active: %d", !active);
 
260
                }
 
261
        }
 
262
 
 
263
        return ret;
 
264
}
 
265
 
 
266
static void
 
267
listener_simulate_user_activity_cb (GSListener *listener,
 
268
                                    GSMonitor  *monitor)
 
269
{
 
270
        gs_monitor_simulate_user_activity (monitor);
 
271
}
 
272
 
 
273
static void
 
274
_gs_monitor_update_from_prefs (GSMonitor *monitor,
 
275
                               GSPrefs   *prefs)
 
276
{
 
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;
 
283
 
 
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);
 
286
 
 
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);
 
295
 
 
296
        /* enable activation when allowed */
 
297
        gs_listener_set_activation_enabled (monitor->priv->listener,
 
298
                                            monitor->priv->prefs->idle_activation_enabled);
 
299
 
 
300
        /* idle detection always enabled */
 
301
        idle_detection_enabled = TRUE;
 
302
 
 
303
        gs_watcher_set_enabled (monitor->priv->watcher, idle_detection_enabled);
 
304
 
 
305
        /* in the case where idle detection is reenabled we may need to
 
306
           activate the watcher too */
 
307
 
 
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);
 
315
        }
 
316
 
 
317
        if (monitor->priv->prefs->status_message_enabled) {
 
318
                char *text;
 
319
                g_object_get (monitor->priv->watcher,
 
320
                              "status-message", &text,
 
321
                              NULL);
 
322
                gs_manager_set_status_message (monitor->priv->manager, text);
 
323
                g_free (text);
 
324
        } else {
 
325
                gs_manager_set_status_message (monitor->priv->manager, NULL);
 
326
        }
 
327
}
 
328
 
 
329
static void
 
330
disconnect_listener_signals (GSMonitor *monitor)
 
331
{
 
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);
 
337
}
 
338
 
 
339
static void
 
340
connect_listener_signals (GSMonitor *monitor)
 
341
{
 
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);
 
352
}
 
353
 
 
354
static void
 
355
on_watcher_status_message_changed (GSWatcher  *watcher,
 
356
                                   GParamSpec *pspec,
 
357
                                   GSMonitor  *monitor)
 
358
{
 
359
        char *text;
 
360
        g_object_get (watcher, "status-message", &text, NULL);
 
361
        gs_manager_set_status_message (monitor->priv->manager, text);
 
362
        g_free (text);
 
363
}
 
364
 
 
365
static void
 
366
disconnect_watcher_signals (GSMonitor *monitor)
 
367
{
 
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);
 
371
}
 
372
 
 
373
static void
 
374
connect_watcher_signals (GSMonitor *monitor)
 
375
{
 
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);
 
382
 
 
383
}
 
384
 
 
385
static void
 
386
disconnect_manager_signals (GSMonitor *monitor)
 
387
{
 
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);
 
390
}
 
391
 
 
392
static void
 
393
connect_manager_signals (GSMonitor *monitor)
 
394
{
 
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);
 
399
}
 
400
 
 
401
static void
 
402
disconnect_prefs_signals (GSMonitor *monitor)
 
403
{
 
404
        g_signal_handlers_disconnect_by_func (monitor->priv->prefs, _gs_monitor_update_from_prefs, monitor);
 
405
}
 
406
 
 
407
static void
 
408
connect_prefs_signals (GSMonitor *monitor)
 
409
{
 
410
        g_signal_connect_swapped (monitor->priv->prefs, "changed",
 
411
                                  G_CALLBACK (_gs_monitor_update_from_prefs), monitor);
 
412
}
 
413
 
 
414
static void
 
415
gs_monitor_init (GSMonitor *monitor)
 
416
{
 
417
 
 
418
        monitor->priv = GS_MONITOR_GET_PRIVATE (monitor);
 
419
 
 
420
        monitor->priv->prefs = gs_prefs_new ();
 
421
        connect_prefs_signals (monitor);
 
422
 
 
423
        monitor->priv->listener = gs_listener_new ();
 
424
        connect_listener_signals (monitor);
 
425
 
 
426
        monitor->priv->fade = gs_fade_new ();
 
427
        monitor->priv->grab = gs_grab_new ();
 
428
 
 
429
        monitor->priv->watcher = gs_watcher_new ();
 
430
        connect_watcher_signals (monitor);
 
431
 
 
432
        monitor->priv->manager = gs_manager_new ();
 
433
        connect_manager_signals (monitor);
 
434
 
 
435
        _gs_monitor_update_from_prefs (monitor, monitor->priv->prefs);
 
436
}
 
437
 
 
438
static void
 
439
gs_monitor_finalize (GObject *object)
 
440
{
 
441
        GSMonitor *monitor;
 
442
 
 
443
        g_return_if_fail (object != NULL);
 
444
        g_return_if_fail (GS_IS_MONITOR (object));
 
445
 
 
446
        monitor = GS_MONITOR (object);
 
447
 
 
448
        g_return_if_fail (monitor->priv != NULL);
 
449
 
 
450
        disconnect_watcher_signals (monitor);
 
451
        disconnect_listener_signals (monitor);
 
452
        disconnect_manager_signals (monitor);
 
453
        disconnect_prefs_signals (monitor);
 
454
 
 
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);
 
461
 
 
462
        G_OBJECT_CLASS (gs_monitor_parent_class)->finalize (object);
 
463
}
 
464
 
 
465
GSMonitor *
 
466
gs_monitor_new (void)
 
467
{
 
468
        GSMonitor *monitor;
 
469
 
 
470
        monitor = g_object_new (GS_TYPE_MONITOR, NULL);
 
471
 
 
472
        return GS_MONITOR (monitor);
 
473
}
 
474
 
 
475
gboolean
 
476
gs_monitor_start (GSMonitor *monitor,
 
477
                  GError   **error)
 
478
{
 
479
        g_return_val_if_fail (GS_IS_MONITOR (monitor), FALSE);
 
480
 
 
481
        if (! gs_listener_acquire (monitor->priv->listener, error)) {
 
482
                return FALSE;
 
483
        }
 
484
 
 
485
        return TRUE;
 
486
}