Back to index

lightdm  1.3.2
display-manager.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010-2011 Robert Ancell.
00003  * Author: Robert Ancell <robert.ancell@canonical.com>
00004  * 
00005  * This program is free software: you can redistribute it and/or modify it under
00006  * the terms of the GNU General Public License as published by the Free Software
00007  * Foundation, either version 3 of the License, or (at your option) any later
00008  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
00009  * license.
00010  */
00011 
00012 #include <config.h>
00013 
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <sys/wait.h>
00017 
00018 #include "display-manager.h"
00019 #include "configuration.h"
00020 #include "display.h"
00021 #include "seat-xlocal.h"
00022 #include "seat-xremote.h"
00023 #include "plymouth.h"
00024 
00025 enum {
00026     SEAT_ADDED,
00027     SEAT_REMOVED,
00028     STOPPED,
00029     LAST_SIGNAL
00030 };
00031 static guint signals[LAST_SIGNAL] = { 0 };
00032 
00033 struct DisplayManagerPrivate
00034 {
00035     /* The seats available */
00036     GList *seats;
00037 
00038     /* TRUE if stopping the display manager (waiting for seats to stop) */
00039     gboolean stopping;
00040 
00041     /* TRUE if stopped */
00042     gboolean stopped;
00043 };
00044 
00045 G_DEFINE_TYPE (DisplayManager, display_manager, G_TYPE_OBJECT);
00046 
00047 DisplayManager *
00048 display_manager_new (void)
00049 {
00050     return g_object_new (DISPLAY_MANAGER_TYPE, NULL);
00051 }
00052 
00053 GList *
00054 display_manager_get_seats (DisplayManager *manager)
00055 {
00056     return manager->priv->seats;
00057 }
00058 
00059 static void
00060 check_stopped (DisplayManager *manager)
00061 {
00062     if (manager->priv->stopping &&
00063         !manager->priv->stopped &&
00064         g_list_length (manager->priv->seats) == 0)
00065     {
00066         manager->priv->stopped = TRUE;
00067         g_debug ("Display manager stopped");
00068         g_signal_emit (manager, signals[STOPPED], 0);
00069     }
00070 }
00071 
00072 static void
00073 seat_stopped_cb (Seat *seat, DisplayManager *manager)
00074 {
00075     manager->priv->seats = g_list_remove (manager->priv->seats, seat);
00076     g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
00077 
00078     if (!manager->priv->stopping)
00079         g_signal_emit (manager, signals[SEAT_REMOVED], 0, seat);
00080 
00081     g_object_unref (seat);
00082 
00083     check_stopped (manager);
00084 }
00085 
00086 gboolean
00087 display_manager_add_seat (DisplayManager *manager, Seat *seat)
00088 {
00089     gboolean result;
00090 
00091     g_return_val_if_fail (!manager->priv->stopping, FALSE);
00092 
00093     result = seat_start (SEAT (seat));
00094     if (!result)
00095         return FALSE;
00096 
00097     manager->priv->seats = g_list_append (manager->priv->seats, g_object_ref (seat));
00098     g_signal_connect (seat, "stopped", G_CALLBACK (seat_stopped_cb), manager);
00099     g_signal_emit (manager, signals[SEAT_ADDED], 0, seat);
00100 
00101     return TRUE;
00102 }
00103 
00104 void
00105 display_manager_start (DisplayManager *manager)
00106 {
00107     g_return_if_fail (manager != NULL);
00108 
00109     /* Disable Plymouth if no X servers are replacing it */
00110     if (plymouth_get_is_active ())
00111     {
00112         g_debug ("Stopping Plymouth, no displays replace it");      
00113         plymouth_quit (FALSE);
00114     }
00115 }
00116 
00117 void
00118 display_manager_stop (DisplayManager *manager)
00119 {
00120     GList *link;
00121 
00122     g_return_if_fail (manager != NULL);
00123 
00124     if (manager->priv->stopping)
00125         return;
00126 
00127     g_debug ("Stopping display manager");
00128 
00129     manager->priv->stopping = TRUE;
00130 
00131     for (link = manager->priv->seats; link; link = link->next)
00132     {
00133         Seat *seat = link->data;
00134         seat_stop (seat);
00135     }
00136 
00137     check_stopped (manager);
00138 }
00139   
00140 static void
00141 display_manager_init (DisplayManager *manager)
00142 {
00143     manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, DISPLAY_MANAGER_TYPE, DisplayManagerPrivate);
00144 
00145     /* Load the seat modules */
00146     seat_register_module ("xlocal", SEAT_XLOCAL_TYPE);
00147     seat_register_module ("xremote", SEAT_XREMOTE_TYPE);
00148 }
00149 
00150 static void
00151 display_manager_finalize (GObject *object)
00152 {
00153     DisplayManager *self;
00154     GList *link;
00155 
00156     self = DISPLAY_MANAGER (object);
00157 
00158     for (link = self->priv->seats; link; link = link->next)
00159     {
00160         Seat *seat = link->data;
00161         g_signal_handlers_disconnect_matched (seat, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
00162     }
00163     g_list_free_full (self->priv->seats, g_object_unref);
00164 
00165     G_OBJECT_CLASS (display_manager_parent_class)->finalize (object);
00166 }
00167 
00168 static void
00169 display_manager_class_init (DisplayManagerClass *klass)
00170 {
00171     GObjectClass *object_class = G_OBJECT_CLASS (klass);
00172 
00173     object_class->finalize = display_manager_finalize;
00174 
00175     g_type_class_add_private (klass, sizeof (DisplayManagerPrivate));
00176 
00177     signals[SEAT_ADDED] =
00178         g_signal_new ("seat-added",
00179                       G_TYPE_FROM_CLASS (klass),
00180                       G_SIGNAL_RUN_LAST,
00181                       G_STRUCT_OFFSET (DisplayManagerClass, seat_added),
00182                       NULL, NULL,
00183                       g_cclosure_marshal_VOID__OBJECT,
00184                       G_TYPE_NONE, 1, SEAT_TYPE);
00185     signals[SEAT_REMOVED] =
00186         g_signal_new ("seat-removed",
00187                       G_TYPE_FROM_CLASS (klass),
00188                       G_SIGNAL_RUN_LAST,
00189                       G_STRUCT_OFFSET (DisplayManagerClass, seat_removed),
00190                       NULL, NULL,
00191                       g_cclosure_marshal_VOID__OBJECT,
00192                       G_TYPE_NONE, 1, SEAT_TYPE);
00193     signals[STOPPED] =
00194         g_signal_new ("stopped",
00195                       G_TYPE_FROM_CLASS (klass),
00196                       G_SIGNAL_RUN_LAST,
00197                       G_STRUCT_OFFSET (DisplayManagerClass, stopped),
00198                       NULL, NULL,
00199                       g_cclosure_marshal_VOID__VOID,
00200                       G_TYPE_NONE, 0);
00201 }