]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/display-manager.c
Fix autologin use case and add a test for it
[sojka/lightdm.git] / src / display-manager.c
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 <config.h>
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/wait.h>
17
18 #include "display-manager.h"
19 #include "configuration.h"
20 #include "seat-xlocal.h"
21 #include "seat-xremote.h"
22 #include "seat-unity.h"
23 #include "seat-surfaceflinger.h"
24 #include "plymouth.h"
25
26 enum {
27     SEAT_ADDED,
28     SEAT_REMOVED,
29     STOPPED,
30     LAST_SIGNAL
31 };
32 static guint signals[LAST_SIGNAL] = { 0 };
33
34 struct DisplayManagerPrivate
35 {
36     /* The seats available */
37     GList *seats;
38
39     /* TRUE if stopping the display manager (waiting for seats to stop) */
40     gboolean stopping;
41
42     /* TRUE if stopped */
43     gboolean stopped;
44 };
45
46 G_DEFINE_TYPE (DisplayManager, display_manager, G_TYPE_OBJECT);
47
48 DisplayManager *
49 display_manager_new (void)
50 {
51     return g_object_new (DISPLAY_MANAGER_TYPE, NULL);
52 }
53
54 GList *
55 display_manager_get_seats (DisplayManager *manager)
56 {
57     return manager->priv->seats;
58 }
59
60 static void
61 check_stopped (DisplayManager *manager)
62 {
63     if (manager->priv->stopping &&
64         !manager->priv->stopped &&
65         g_list_length (manager->priv->seats) == 0)
66     {
67         manager->priv->stopped = TRUE;
68         g_debug ("Display manager stopped");
69         g_signal_emit (manager, signals[STOPPED], 0);
70     }
71 }
72
73 static void
74 seat_stopped_cb (Seat *seat, DisplayManager *manager)
75 {
76     manager->priv->seats = g_list_remove (manager->priv->seats, seat);
77     g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
78
79     if (!manager->priv->stopping)
80         g_signal_emit (manager, signals[SEAT_REMOVED], 0, seat);
81
82     g_object_unref (seat);
83
84     check_stopped (manager);
85 }
86
87 gboolean
88 display_manager_add_seat (DisplayManager *manager, Seat *seat)
89 {
90     gboolean result;
91
92     g_return_val_if_fail (!manager->priv->stopping, FALSE);
93
94     result = seat_start (SEAT (seat));
95     if (!result)
96         return FALSE;
97
98     manager->priv->seats = g_list_append (manager->priv->seats, g_object_ref (seat));
99     g_signal_connect (seat, "stopped", G_CALLBACK (seat_stopped_cb), manager);
100     g_signal_emit (manager, signals[SEAT_ADDED], 0, seat);
101
102     return TRUE;
103 }
104
105 void
106 display_manager_start (DisplayManager *manager)
107 {
108     g_return_if_fail (manager != NULL);
109
110     /* Disable Plymouth if no X servers are replacing it */
111     if (plymouth_get_is_active ())
112     {
113         g_debug ("Stopping Plymouth, no displays replace it");      
114         plymouth_quit (FALSE);
115     }
116 }
117
118 void
119 display_manager_stop (DisplayManager *manager)
120 {
121     GList *seats, *link;
122
123     g_return_if_fail (manager != NULL);
124
125     if (manager->priv->stopping)
126         return;
127
128     g_debug ("Stopping display manager");
129
130     manager->priv->stopping = TRUE;
131
132     /* Stop all the seats. Copy the list as it might be modified if a seat stops during this loop */
133     seats = g_list_copy (manager->priv->seats);
134     for (link = seats; link; link = link->next)
135     {
136         Seat *seat = link->data;
137         seat_stop (seat);
138     }
139     g_list_free (seats);
140
141     check_stopped (manager);
142 }
143   
144 static void
145 display_manager_init (DisplayManager *manager)
146 {
147     manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, DISPLAY_MANAGER_TYPE, DisplayManagerPrivate);
148
149     /* Load the seat modules */
150     seat_register_module ("xlocal", SEAT_XLOCAL_TYPE);
151     seat_register_module ("xremote", SEAT_XREMOTE_TYPE);
152     seat_register_module ("unity", SEAT_UNITY_TYPE);
153     seat_register_module ("surfaceflinger", SEAT_SURFACEFLINGER_TYPE);
154 }
155
156 static void
157 display_manager_finalize (GObject *object)
158 {
159     DisplayManager *self;
160     GList *link;
161
162     self = DISPLAY_MANAGER (object);
163
164     for (link = self->priv->seats; link; link = link->next)
165     {
166         Seat *seat = link->data;
167         g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
168     }
169     g_list_free_full (self->priv->seats, g_object_unref);
170
171     G_OBJECT_CLASS (display_manager_parent_class)->finalize (object);
172 }
173
174 static void
175 display_manager_class_init (DisplayManagerClass *klass)
176 {
177     GObjectClass *object_class = G_OBJECT_CLASS (klass);
178
179     object_class->finalize = display_manager_finalize;
180
181     g_type_class_add_private (klass, sizeof (DisplayManagerPrivate));
182
183     signals[SEAT_ADDED] =
184         g_signal_new ("seat-added",
185                       G_TYPE_FROM_CLASS (klass),
186                       G_SIGNAL_RUN_LAST,
187                       G_STRUCT_OFFSET (DisplayManagerClass, seat_added),
188                       NULL, NULL,
189                       NULL,
190                       G_TYPE_NONE, 1, SEAT_TYPE);
191     signals[SEAT_REMOVED] =
192         g_signal_new ("seat-removed",
193                       G_TYPE_FROM_CLASS (klass),
194                       G_SIGNAL_RUN_LAST,
195                       G_STRUCT_OFFSET (DisplayManagerClass, seat_removed),
196                       NULL, NULL,
197                       NULL,
198                       G_TYPE_NONE, 1, SEAT_TYPE);
199     signals[STOPPED] =
200         g_signal_new ("stopped",
201                       G_TYPE_FROM_CLASS (klass),
202                       G_SIGNAL_RUN_LAST,
203                       G_STRUCT_OFFSET (DisplayManagerClass, stopped),
204                       NULL, NULL,
205                       NULL,
206                       G_TYPE_NONE, 0);
207 }