2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
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
18 #include "display-manager.h"
19 #include "configuration.h"
20 #include "seat-xlocal.h"
21 #include "seat-xremote.h"
22 #include "seat-unity.h"
31 static guint signals[LAST_SIGNAL] = { 0 };
33 struct DisplayManagerPrivate
35 /* The seats available */
38 /* TRUE if stopping the display manager (waiting for seats to stop) */
45 G_DEFINE_TYPE (DisplayManager, display_manager, G_TYPE_OBJECT);
48 display_manager_new (void)
50 return g_object_new (DISPLAY_MANAGER_TYPE, NULL);
54 display_manager_get_seats (DisplayManager *manager)
56 return manager->priv->seats;
60 display_manager_get_seat (DisplayManager *manager, const gchar *name)
64 for (link = manager->priv->seats; link; link = link->next)
66 Seat *seat = link->data;
68 if (strcmp (seat_get_name (seat), name) == 0)
76 check_stopped (DisplayManager *manager)
78 if (manager->priv->stopping &&
79 !manager->priv->stopped &&
80 g_list_length (manager->priv->seats) == 0)
82 manager->priv->stopped = TRUE;
83 g_debug ("Display manager stopped");
84 g_signal_emit (manager, signals[STOPPED], 0);
89 seat_stopped_cb (Seat *seat, DisplayManager *manager)
91 manager->priv->seats = g_list_remove (manager->priv->seats, seat);
92 g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
94 if (!manager->priv->stopping)
95 g_signal_emit (manager, signals[SEAT_REMOVED], 0, seat);
97 g_object_unref (seat);
99 check_stopped (manager);
103 display_manager_add_seat (DisplayManager *manager, Seat *seat)
107 g_return_val_if_fail (!manager->priv->stopping, FALSE);
109 result = seat_start (SEAT (seat));
113 manager->priv->seats = g_list_append (manager->priv->seats, g_object_ref (seat));
114 g_signal_connect (seat, SEAT_SIGNAL_STOPPED, G_CALLBACK (seat_stopped_cb), manager);
115 g_signal_emit (manager, signals[SEAT_ADDED], 0, seat);
121 display_manager_start (DisplayManager *manager)
123 g_return_if_fail (manager != NULL);
125 /* Disable Plymouth if no X servers are replacing it */
126 if (plymouth_get_is_active ())
128 g_debug ("Stopping Plymouth, no displays replace it");
129 plymouth_quit (FALSE);
134 display_manager_stop (DisplayManager *manager)
138 g_return_if_fail (manager != NULL);
140 if (manager->priv->stopping)
143 g_debug ("Stopping display manager");
145 manager->priv->stopping = TRUE;
147 /* Stop all the seats. Copy the list as it might be modified if a seat stops during this loop */
148 seats = g_list_copy (manager->priv->seats);
149 for (link = seats; link; link = link->next)
151 Seat *seat = link->data;
156 check_stopped (manager);
160 display_manager_init (DisplayManager *manager)
162 manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, DISPLAY_MANAGER_TYPE, DisplayManagerPrivate);
164 /* Load the seat modules */
165 seat_register_module ("xlocal", SEAT_XLOCAL_TYPE);
166 seat_register_module ("xremote", SEAT_XREMOTE_TYPE);
167 seat_register_module ("unity", SEAT_UNITY_TYPE);
171 display_manager_finalize (GObject *object)
173 DisplayManager *self = DISPLAY_MANAGER (object);
176 for (link = self->priv->seats; link; link = link->next)
178 Seat *seat = link->data;
179 g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
181 g_list_free_full (self->priv->seats, g_object_unref);
183 G_OBJECT_CLASS (display_manager_parent_class)->finalize (object);
187 display_manager_class_init (DisplayManagerClass *klass)
189 GObjectClass *object_class = G_OBJECT_CLASS (klass);
191 object_class->finalize = display_manager_finalize;
193 g_type_class_add_private (klass, sizeof (DisplayManagerPrivate));
195 signals[SEAT_ADDED] =
196 g_signal_new (DISPLAY_MANAGER_SIGNAL_SEAT_ADDED,
197 G_TYPE_FROM_CLASS (klass),
199 G_STRUCT_OFFSET (DisplayManagerClass, seat_added),
202 G_TYPE_NONE, 1, SEAT_TYPE);
203 signals[SEAT_REMOVED] =
204 g_signal_new (DISPLAY_MANAGER_SIGNAL_SEAT_REMOVED,
205 G_TYPE_FROM_CLASS (klass),
207 G_STRUCT_OFFSET (DisplayManagerClass, seat_removed),
210 G_TYPE_NONE, 1, SEAT_TYPE);
212 g_signal_new (DISPLAY_MANAGER_SIGNAL_STOPPED,
213 G_TYPE_FROM_CLASS (klass),
215 G_STRUCT_OFFSET (DisplayManagerClass, stopped),