~lightdm-team/lightdm/1.4

« back to all changes in this revision

Viewing changes to src/seat.c

  • Committer: Robert Ancell
  • Date: 2014-03-13 02:15:38 UTC
  • Revision ID: robert.ancell@canonical.com-20140313021538-u2mxfxrrfw5u58ic
Tags: 1.4.7
Releasing 1.4.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2011 Robert Ancell.
 
3
 * Author: Robert Ancell <robert.ancell@canonical.com>
 
4
 * 
 
5
 * This program is free software: you can redistribute it and/or modify it under
 
6
 * the terms of the GNU General Public License as published by the Free Software
 
7
 * Foundation, either version 3 of the License, or (at your option) any later
 
8
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 
9
 * license.
 
10
 */
 
11
 
 
12
#include <stdlib.h>
 
13
#include <string.h>
 
14
#include <sys/wait.h>
 
15
 
 
16
#include "seat.h"
 
17
#include "guest-account.h"
 
18
 
 
19
enum {
 
20
    DISPLAY_ADDED,
 
21
    DISPLAY_REMOVED,
 
22
    STOPPED,
 
23
    LAST_SIGNAL
 
24
};
 
25
static guint signals[LAST_SIGNAL] = { 0 };
 
26
 
 
27
struct SeatPrivate
 
28
{
 
29
    /* Configuration for this seat */
 
30
    GHashTable *properties;
 
31
 
 
32
    /* TRUE if able to switch users */
 
33
    gboolean can_switch;
 
34
 
 
35
    /* Name of guest account */
 
36
    gchar *guest_username;
 
37
 
 
38
    /* The displays for this seat */
 
39
    GList *displays;
 
40
 
 
41
    /* The active display */
 
42
    Display *active_display;
 
43
 
 
44
    /* TRUE if stopping this seat (waiting for displays to stop) */
 
45
    gboolean stopping;
 
46
 
 
47
    /* TRUE if stopped */
 
48
    gboolean stopped;
 
49
};
 
50
 
 
51
G_DEFINE_TYPE (Seat, seat, G_TYPE_OBJECT);
 
52
 
 
53
typedef struct
 
54
{
 
55
    const gchar *name;
 
56
    GType type;
 
57
} SeatModule;
 
58
static GHashTable *seat_modules = NULL;
 
59
 
 
60
void
 
61
seat_register_module (const gchar *name, GType type)
 
62
{
 
63
    SeatModule *module;
 
64
 
 
65
    if (!seat_modules)
 
66
        seat_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
67
 
 
68
    g_debug ("Registered seat module %s", name);
 
69
 
 
70
    module = g_malloc0 (sizeof (SeatModule));
 
71
    module->name = g_strdup (name);
 
72
    module->type = type;
 
73
    g_hash_table_insert (seat_modules, g_strdup (name), module);
 
74
}
 
75
 
 
76
Seat *
 
77
seat_new (const gchar *module_name)
 
78
{
 
79
    Seat *seat;
 
80
    SeatModule *m = NULL;
 
81
  
 
82
    g_return_val_if_fail (module_name != NULL, NULL);
 
83
 
 
84
    if (seat_modules)
 
85
        m = g_hash_table_lookup (seat_modules, module_name);
 
86
    if (!m)
 
87
        return NULL;
 
88
 
 
89
    seat = g_object_new (m->type, NULL);
 
90
 
 
91
    return seat;
 
92
}
 
93
 
 
94
void
 
95
seat_set_property (Seat *seat, const gchar *name, const gchar *value)
 
96
{
 
97
    g_return_if_fail (seat != NULL);
 
98
    g_hash_table_insert (seat->priv->properties, g_strdup (name), g_strdup (value));
 
99
}
 
100
 
 
101
gboolean
 
102
seat_has_property (Seat *seat, const gchar *name)
 
103
{
 
104
    g_return_val_if_fail (seat != NULL, FALSE);
 
105
    return g_hash_table_lookup (seat->priv->properties, name) != NULL;
 
106
}
 
107
 
 
108
const gchar *
 
109
seat_get_string_property (Seat *seat, const gchar *name)
 
110
{
 
111
    g_return_val_if_fail (seat != NULL, NULL);
 
112
    return g_hash_table_lookup (seat->priv->properties, name);
 
113
}
 
114
 
 
115
gboolean
 
116
seat_get_boolean_property (Seat *seat, const gchar *name)
 
117
{
 
118
    return g_strcmp0 (seat_get_string_property (seat, name), "true") == 0;
 
119
}
 
120
 
 
121
gint
 
122
seat_get_integer_property (Seat *seat, const gchar *name)
 
123
{
 
124
    const gchar *value;
 
125
 
 
126
    value = seat_get_string_property (seat, name);
 
127
    return value ? atoi (value) : 0;
 
128
}
 
129
 
 
130
void
 
131
seat_set_can_switch (Seat *seat, gboolean can_switch)
 
132
{
 
133
    g_return_if_fail (seat != NULL);
 
134
 
 
135
    seat->priv->can_switch = can_switch;
 
136
}
 
137
 
 
138
gboolean
 
139
seat_start (Seat *seat)
 
140
{
 
141
    g_return_val_if_fail (seat != NULL, FALSE);
 
142
  
 
143
    SEAT_GET_CLASS (seat)->setup (seat);
 
144
    return SEAT_GET_CLASS (seat)->start (seat);
 
145
}
 
146
 
 
147
GList *
 
148
seat_get_displays (Seat *seat)
 
149
{
 
150
    g_return_val_if_fail (seat != NULL, NULL);
 
151
    return seat->priv->displays;
 
152
}
 
153
 
 
154
void
 
155
seat_set_active_display (Seat *seat, Display *display)
 
156
{
 
157
    g_return_if_fail (seat != NULL);
 
158
    SEAT_GET_CLASS (seat)->set_active_display (seat, display);
 
159
}
 
160
 
 
161
Display *
 
162
seat_get_active_display (Seat *seat)
 
163
{
 
164
    g_return_val_if_fail (seat != NULL, NULL);
 
165
    return seat->priv->active_display;
 
166
}
 
167
 
 
168
gboolean
 
169
seat_get_can_switch (Seat *seat)
 
170
{
 
171
    g_return_val_if_fail (seat != NULL, FALSE);
 
172
    return seat->priv->can_switch;
 
173
}
 
174
 
 
175
gboolean
 
176
seat_get_allow_guest (Seat *seat)
 
177
{
 
178
    g_return_val_if_fail (seat != NULL, FALSE);  
 
179
    return seat_get_boolean_property (seat, "allow-guest") && guest_account_is_installed ();
 
180
}
 
181
 
 
182
gboolean
 
183
seat_get_greeter_allow_guest (Seat *seat)
 
184
{
 
185
    g_return_val_if_fail (seat != NULL, FALSE);  
 
186
    return seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest");
 
187
}
 
188
 
 
189
static gboolean
 
190
switch_to_user (Seat *seat, const gchar *username, gboolean unlock)
 
191
{
 
192
    GList *link;
 
193
 
 
194
    /* Switch to active display if it exists */
 
195
    for (link = seat->priv->displays; link; link = link->next)
 
196
    {
 
197
        Display *display = link->data;
 
198
 
 
199
        /* If already logged in, then switch to that display */
 
200
        if (g_strcmp0 (display_get_username (display), username) == 0)        
 
201
        {
 
202
            if (username)
 
203
                g_debug ("Switching to existing session for user %s", username);
 
204
            else
 
205
                g_debug ("Switching to existing greeter");
 
206
            if (unlock)
 
207
                display_unlock (display);
 
208
            seat_set_active_display (seat, display);
 
209
            return TRUE;
 
210
        }
 
211
    }
 
212
 
 
213
    return FALSE;
 
214
}
 
215
 
 
216
static gboolean
 
217
display_switch_to_user_cb (Display *display, User *user, Seat *seat)
 
218
{
 
219
    return switch_to_user (seat, user_get_name (user), TRUE);
 
220
}
 
221
 
 
222
static gboolean
 
223
display_switch_to_guest_cb (Display *display, Seat *seat)
 
224
{
 
225
    /* No guest account */
 
226
    if (!seat->priv->guest_username)
 
227
        return FALSE;
 
228
 
 
229
    return switch_to_user (seat, seat->priv->guest_username, TRUE);
 
230
}
 
231
 
 
232
static const gchar *
 
233
display_get_guest_username_cb (Display *display, Seat *seat)
 
234
{
 
235
    if (seat->priv->guest_username)
 
236
        return seat->priv->guest_username;
 
237
 
 
238
    seat->priv->guest_username = guest_account_setup ();
 
239
    return g_strdup (seat->priv->guest_username);
 
240
}
 
241
 
 
242
static gboolean
 
243
run_script (Seat *seat, Display *display, const gchar *script_name, User *user)
 
244
{
 
245
    Process *script;
 
246
    gboolean result = FALSE;
 
247
  
 
248
    script = process_new ();
 
249
 
 
250
    process_set_command (script, script_name);
 
251
 
 
252
    /* Set POSIX variables */
 
253
    process_set_clear_environment (script, TRUE);
 
254
    process_set_env (script, "SHELL", "/bin/sh");
 
255
 
 
256
    /* Variables required for regression tests */
 
257
    if (g_getenv ("LIGHTDM_TEST_ROOT"))
 
258
    {
 
259
        process_set_env (script, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
 
260
        process_set_env (script, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
 
261
        process_set_env (script, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
 
262
        process_set_env (script, "PATH", g_getenv ("PATH"));
 
263
    }
 
264
    else
 
265
        process_set_env (script, "PATH", "/usr/local/bin:/usr/bin:/bin");
 
266
 
 
267
    if (user)
 
268
    {
 
269
        process_set_env (script, "USER", user_get_name (user));
 
270
        process_set_env (script, "LOGNAME", user_get_name (user));
 
271
        process_set_env (script, "HOME", user_get_home_directory (user));
 
272
    }
 
273
    else
 
274
        process_set_env (script, "HOME", "/");
 
275
 
 
276
    SEAT_GET_CLASS (seat)->run_script (seat, display, script);
 
277
 
 
278
    if (process_start (script, TRUE))
 
279
    {
 
280
        int exit_status;
 
281
 
 
282
        exit_status = process_get_exit_status (script);
 
283
        if (WIFEXITED (exit_status))
 
284
        {
 
285
            g_debug ("Exit status of %s: %d", script_name, WEXITSTATUS (exit_status));
 
286
            result = WEXITSTATUS (exit_status) == EXIT_SUCCESS;
 
287
        }
 
288
    }
 
289
 
 
290
    g_object_unref (script);
 
291
 
 
292
    return result;
 
293
}
 
294
 
 
295
static void
 
296
seat_real_run_script (Seat *seat, Display *display, Process *process)
 
297
{  
 
298
}
 
299
 
 
300
static void
 
301
emit_upstart_signal (const gchar *signal)
 
302
{
 
303
    g_return_if_fail (signal != NULL);
 
304
    g_return_if_fail (signal[0] != 0);
 
305
 
 
306
    if (getuid () != 0)
 
307
        return;
 
308
 
 
309
    gchar *cmd = g_strdup_printf ("initctl -q emit %s DISPLAY_MANAGER=lightdm", signal);
 
310
    g_spawn_command_line_async (cmd, NULL); /* OK if it fails, probably not installed */
 
311
    g_free (cmd);
 
312
}
 
313
 
 
314
static gboolean
 
315
display_display_server_ready_cb (Display *display, Seat *seat)
 
316
{
 
317
    const gchar *script;
 
318
 
 
319
    /* Run setup script */
 
320
    script = seat_get_string_property (seat, "display-setup-script");
 
321
    if (script && !run_script (seat, display, script, NULL))
 
322
        return FALSE;
 
323
 
 
324
    emit_upstart_signal ("login-session-start");
 
325
 
 
326
    return TRUE;
 
327
}
 
328
 
 
329
static Session *
 
330
display_create_session_cb (Display *display, Seat *seat)
 
331
{
 
332
    return SEAT_GET_CLASS (seat)->create_session (seat, display);
 
333
}
 
334
 
 
335
static gboolean
 
336
display_start_greeter_cb (Display *display, Seat *seat)
 
337
{
 
338
    Session *session;
 
339
    const gchar *script;
 
340
 
 
341
    session = display_get_session (display);
 
342
 
 
343
    script = seat_get_string_property (seat, "greeter-setup-script");
 
344
    if (script)
 
345
        return !run_script (seat, display, script, session_get_user (session));
 
346
    else
 
347
        return FALSE;
 
348
}
 
349
 
 
350
static gboolean
 
351
display_start_session_cb (Display *display, Seat *seat)
 
352
{
 
353
    Session *session;
 
354
    const gchar *script;
 
355
 
 
356
    session = display_get_session (display);
 
357
 
 
358
    script = seat_get_string_property (seat, "session-setup-script");
 
359
    if (script)
 
360
        return !run_script (seat, display, script, session_get_user (session));
 
361
    else
 
362
        return FALSE;
 
363
}
 
364
 
 
365
static void
 
366
session_stopped_cb (Session *session, Seat *seat)
 
367
{
 
368
    Display *display = NULL;
 
369
    GList *link;
 
370
    const gchar *script;
 
371
  
 
372
    /* Work out what display this session is on, it's a bit hacky because we really should know already... */
 
373
    for (link = seat->priv->displays; link; link = link->next)
 
374
    {
 
375
        Display *d = link->data;
 
376
        if (display_get_session (d) == session)
 
377
        {
 
378
            display = d;
 
379
            break;
 
380
        }
 
381
    }
 
382
    g_return_if_fail (display != NULL);
 
383
 
 
384
    /* Cleanup */
 
385
    script = seat_get_string_property (seat, "session-cleanup-script");
 
386
    if (script)
 
387
        run_script (seat, display, script, session_get_user (session));
 
388
 
 
389
    if (seat->priv->guest_username && strcmp (session_get_username (session), seat->priv->guest_username) == 0)
 
390
    {
 
391
        g_free (seat->priv->guest_username);
 
392
        seat->priv->guest_username = NULL;
 
393
    }
 
394
}
 
395
 
 
396
static gboolean
 
397
display_session_started_cb (Display *display, Seat *seat)
 
398
{
 
399
    g_signal_connect (display_get_session (display), "stopped", G_CALLBACK (session_stopped_cb), seat);
 
400
    emit_upstart_signal ("desktop-session-start");
 
401
    return FALSE;
 
402
}
 
403
 
 
404
static void
 
405
display_ready_cb (Display *display, Seat *seat)
 
406
{
 
407
    /* Switch to this new display */
 
408
    g_debug ("New display ready, switching to it");
 
409
    SEAT_GET_CLASS (seat)->set_active_display (seat, display);
 
410
}
 
411
 
 
412
static void
 
413
check_stopped (Seat *seat)
 
414
{
 
415
    if (seat->priv->stopping &&
 
416
        !seat->priv->stopped &&
 
417
        g_list_length (seat->priv->displays) == 0)
 
418
    {
 
419
        seat->priv->stopped = TRUE;
 
420
        g_debug ("Seat stopped");
 
421
        g_signal_emit (seat, signals[STOPPED], 0);
 
422
    }
 
423
}
 
424
 
 
425
static void
 
426
display_stopped_cb (Display *display, Seat *seat)
 
427
{
 
428
    seat->priv->displays = g_list_remove (seat->priv->displays, display);
 
429
    g_signal_handlers_disconnect_matched (display, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
 
430
    g_signal_emit (seat, signals[DISPLAY_REMOVED], 0, display);
 
431
    g_object_unref (display);
 
432
 
 
433
    check_stopped (seat);
 
434
}
 
435
 
 
436
static gboolean
 
437
switch_to_user_or_start_greeter (Seat *seat, const gchar *username, gboolean use_existing, gboolean is_guest, const gchar *session_name, gboolean is_lock, gboolean autologin, int autologin_timeout)
 
438
{
 
439
    Display *display;
 
440
    DisplayServer *display_server;
 
441
 
 
442
    /* Switch to existing if it exists */
 
443
    if (use_existing && switch_to_user (seat, username, FALSE))
 
444
        return TRUE;
 
445
 
 
446
    /* If one don't exist then start a greeter */
 
447
    if (autologin)
 
448
    {
 
449
        if (is_guest)
 
450
            g_debug ("Starting new display for automatic guest login");
 
451
        else if (username)
 
452
            g_debug ("Starting new display for automatic login as user %s", username);
 
453
        else
 
454
            g_debug ("Starting new display for greeter");
 
455
    }
 
456
    else
 
457
    {
 
458
        if (is_guest)
 
459
            g_debug ("Starting new display for greeter with guest selected");
 
460
        else if (username)
 
461
            g_debug ("Starting new display for greeter with user %s selected", username);
 
462
        else if (is_lock)
 
463
            g_debug ("Starting new display for greeter (lock screen)");
 
464
        else
 
465
            g_debug ("Starting new display for greeter");
 
466
    }
 
467
 
 
468
    display_server = SEAT_GET_CLASS (seat)->create_display_server (seat);
 
469
    display = display_new (display_server);
 
470
    g_object_unref (display_server);
 
471
 
 
472
    g_signal_connect (display, "display-server-ready", G_CALLBACK (display_display_server_ready_cb), seat);  
 
473
    g_signal_connect (display, "switch-to-user", G_CALLBACK (display_switch_to_user_cb), seat);
 
474
    g_signal_connect (display, "switch-to-guest", G_CALLBACK (display_switch_to_guest_cb), seat);
 
475
    g_signal_connect (display, "get-guest-username", G_CALLBACK (display_get_guest_username_cb), seat);
 
476
    g_signal_connect (display, "create-session", G_CALLBACK (display_create_session_cb), seat);
 
477
    g_signal_connect (display, "start-greeter", G_CALLBACK (display_start_greeter_cb), seat);
 
478
    g_signal_connect (display, "start-session", G_CALLBACK (display_start_session_cb), seat);
 
479
    g_signal_connect_after (display, "start-session", G_CALLBACK (display_session_started_cb), seat);
 
480
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
 
481
    g_signal_connect (display, "stopped", G_CALLBACK (display_stopped_cb), seat);
 
482
    display_set_greeter_session (display, seat_get_string_property (seat, "greeter-session"));
 
483
    display_set_session_wrapper (display, seat_get_string_property (seat, "session-wrapper"));
 
484
    display_set_hide_users_hint (display, seat_get_boolean_property (seat, "greeter-hide-users"));
 
485
    display_set_show_manual_login_hint (display, seat_get_boolean_property (seat, "greeter-show-manual-login"));
 
486
    display_set_show_remote_login_hint (display, seat_get_boolean_property (seat, "greeter-show-remote-login"));
 
487
    if (is_lock)
 
488
        display_set_lock_hint (display, TRUE);
 
489
    display_set_allow_guest (display, seat_get_allow_guest (seat));
 
490
    display_set_greeter_allow_guest (display, seat_get_greeter_allow_guest (seat));
 
491
    if (autologin)
 
492
        display_set_autologin_user (display, username, is_guest, autologin_timeout);
 
493
    else
 
494
        display_set_select_user_hint (display, username, is_guest);
 
495
    if (!session_name)
 
496
        session_name = seat_get_string_property (seat, "user-session");
 
497
    display_set_user_session (display, SESSION_TYPE_LOCAL, session_name);
 
498
 
 
499
    seat->priv->displays = g_list_append (seat->priv->displays, display);
 
500
    g_signal_emit (seat, signals[DISPLAY_ADDED], 0, display);
 
501
 
 
502
    /* Switch to this display if currently not looking at anything */
 
503
    if (!seat->priv->active_display)
 
504
        seat_set_active_display (seat, display);
 
505
 
 
506
    return display_start (display);
 
507
}
 
508
 
 
509
gboolean
 
510
seat_switch_to_greeter (Seat *seat)
 
511
{
 
512
    g_return_val_if_fail (seat != NULL, FALSE);
 
513
 
 
514
    if (!seat->priv->can_switch)
 
515
        return FALSE;
 
516
 
 
517
    g_debug ("Switching to greeter");
 
518
    return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE, 0);
 
519
}
 
520
 
 
521
gboolean
 
522
seat_switch_to_user (Seat *seat, const gchar *username, const gchar *session_name)
 
523
{
 
524
    g_return_val_if_fail (seat != NULL, FALSE);
 
525
    g_return_val_if_fail (username != NULL, FALSE);
 
526
 
 
527
    if (!seat->priv->can_switch)
 
528
        return FALSE;
 
529
 
 
530
    g_debug ("Switching to user %s", username);
 
531
    return switch_to_user_or_start_greeter (seat, username, TRUE, FALSE, session_name, FALSE, FALSE, 0);
 
532
}
 
533
 
 
534
gboolean
 
535
seat_switch_to_guest (Seat *seat, const gchar *session_name)
 
536
{
 
537
    g_return_val_if_fail (seat != NULL, FALSE);
 
538
 
 
539
    if (!seat->priv->can_switch || !seat_get_allow_guest (seat))
 
540
        return FALSE;
 
541
 
 
542
    if (seat->priv->guest_username)
 
543
        g_debug ("Switching to existing guest account %s", seat->priv->guest_username);
 
544
    else
 
545
        g_debug ("Switching to new guest account");
 
546
    return switch_to_user_or_start_greeter (seat, seat->priv->guest_username, TRUE, TRUE, session_name, FALSE, TRUE, 0);
 
547
}
 
548
 
 
549
gboolean
 
550
seat_lock (Seat *seat, const gchar *username)
 
551
{
 
552
    g_return_val_if_fail (seat != NULL, FALSE);
 
553
 
 
554
    if (!seat->priv->can_switch)
 
555
        return FALSE;
 
556
 
 
557
    g_debug ("Locking seat");
 
558
    return switch_to_user_or_start_greeter (seat, username, FALSE, FALSE, NULL, TRUE, FALSE, 0);
 
559
}
 
560
 
 
561
void
 
562
seat_stop (Seat *seat)
 
563
{
 
564
    g_return_if_fail (seat != NULL);
 
565
 
 
566
    if (seat->priv->stopping)
 
567
        return;
 
568
 
 
569
    g_debug ("Stopping seat");
 
570
    seat->priv->stopping = TRUE;
 
571
    SEAT_GET_CLASS (seat)->stop (seat);
 
572
}
 
573
 
 
574
gboolean
 
575
seat_get_is_stopping (Seat *seat)
 
576
{
 
577
    g_return_val_if_fail (seat != NULL, FALSE);
 
578
    return seat->priv->stopping;
 
579
}
 
580
 
 
581
static void
 
582
seat_real_setup (Seat *seat)
 
583
{
 
584
}
 
585
 
 
586
static gboolean
 
587
seat_real_start (Seat *seat)
 
588
{
 
589
    const gchar *autologin_username;
 
590
    int autologin_timeout;
 
591
 
 
592
    g_debug ("Starting seat");
 
593
 
 
594
    /* Start showing a greeter */
 
595
    autologin_username = seat_get_string_property (seat, "autologin-user");
 
596
    if (g_strcmp0 (autologin_username, "") == 0)
 
597
        autologin_username = NULL;
 
598
    autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
 
599
 
 
600
    if (autologin_username)
 
601
        return switch_to_user_or_start_greeter (seat, autologin_username, TRUE, FALSE, NULL, FALSE, TRUE, autologin_timeout);
 
602
    else if (seat_get_boolean_property (seat, "autologin-guest"))
 
603
        return switch_to_user_or_start_greeter (seat, NULL, TRUE, TRUE, NULL, FALSE, TRUE, autologin_timeout);
 
604
    else
 
605
        return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE, 0);
 
606
}
 
607
 
 
608
static void
 
609
seat_real_set_active_display (Seat *seat, Display *display)
 
610
{
 
611
    if (display == seat->priv->active_display)
 
612
        return;
 
613
 
 
614
    if (seat->priv->active_display)
 
615
    {
 
616
        /* Stop the existing display if it is a greeter */
 
617
        if (!display_get_username (seat->priv->active_display))
 
618
        {
 
619
            g_debug ("Stopping greeter display being switched from");
 
620
            display_stop (seat->priv->active_display);
 
621
        }
 
622
        /* Otherwise lock it */
 
623
        else
 
624
        {
 
625
            display_lock (seat->priv->active_display);
 
626
        }
 
627
        g_object_unref (seat->priv->active_display);
 
628
    }
 
629
    seat->priv->active_display = g_object_ref (display);
 
630
}
 
631
 
 
632
static void
 
633
seat_real_stop (Seat *seat)
 
634
{
 
635
    GList *link;
 
636
 
 
637
    check_stopped (seat);
 
638
    if (seat->priv->stopped)
 
639
        return;
 
640
 
 
641
    for (link = seat->priv->displays; link; link = link->next)
 
642
    {
 
643
        Display *display = link->data;
 
644
        display_stop (display);
 
645
    }
 
646
}
 
647
 
 
648
static void
 
649
seat_init (Seat *seat)
 
650
{
 
651
    seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_TYPE, SeatPrivate);
 
652
    seat->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
653
}
 
654
 
 
655
static void
 
656
seat_finalize (GObject *object)
 
657
{
 
658
    Seat *self;
 
659
 
 
660
    self = SEAT (object);
 
661
 
 
662
    g_hash_table_unref (self->priv->properties);
 
663
    g_free (self->priv->guest_username);
 
664
    g_list_free_full (self->priv->displays, g_object_unref);
 
665
    if (self->priv->active_display)
 
666
        g_object_unref (self->priv->active_display);
 
667
 
 
668
    G_OBJECT_CLASS (seat_parent_class)->finalize (object);
 
669
}
 
670
 
 
671
static void
 
672
seat_class_init (SeatClass *klass)
 
673
{
 
674
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
675
 
 
676
    klass->setup = seat_real_setup;
 
677
    klass->start = seat_real_start;
 
678
    klass->set_active_display = seat_real_set_active_display;
 
679
    klass->run_script = seat_real_run_script;
 
680
    klass->stop = seat_real_stop;
 
681
 
 
682
    object_class->finalize = seat_finalize;
 
683
 
 
684
    g_type_class_add_private (klass, sizeof (SeatPrivate));
 
685
 
 
686
    signals[DISPLAY_ADDED] =
 
687
        g_signal_new ("display-added",
 
688
                      G_TYPE_FROM_CLASS (klass),
 
689
                      G_SIGNAL_RUN_LAST,
 
690
                      G_STRUCT_OFFSET (SeatClass, display_added),
 
691
                      NULL, NULL,
 
692
                      g_cclosure_marshal_VOID__OBJECT,
 
693
                      G_TYPE_NONE, 1, DISPLAY_TYPE);
 
694
    signals[DISPLAY_REMOVED] =
 
695
        g_signal_new ("display-removed",
 
696
                      G_TYPE_FROM_CLASS (klass),
 
697
                      G_SIGNAL_RUN_LAST,
 
698
                      G_STRUCT_OFFSET (SeatClass, display_removed),
 
699
                      NULL, NULL,
 
700
                      g_cclosure_marshal_VOID__OBJECT,
 
701
                      G_TYPE_NONE, 1, DISPLAY_TYPE);
 
702
    signals[STOPPED] =
 
703
        g_signal_new ("stopped",
 
704
                      G_TYPE_FROM_CLASS (klass),
 
705
                      G_SIGNAL_RUN_LAST,
 
706
                      G_STRUCT_OFFSET (SeatClass, stopped),
 
707
                      NULL, NULL,
 
708
                      g_cclosure_marshal_VOID__VOID,
 
709
                      G_TYPE_NONE, 0);
 
710
}