]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Correctly work out the active display from the active VT when it exits so a greeter...
authorRobert Ancell <robert.ancell@canonical.com>
Wed, 28 Nov 2012 03:59:16 +0000 (16:59 +1300)
committerRobert Ancell <robert.ancell@canonical.com>
Wed, 28 Nov 2012 03:59:16 +0000 (16:59 +1300)
src/display.c
src/display.h
src/seat-xdmcp-session.c
src/seat-xlocal.c
src/seat-xremote.c
src/seat-xvnc.c
src/seat.c
src/seat.h
src/xserver-local.c

index 13b87d5d70ed7d6b05b64b24d811efd63564e97a..d86f81392cd89a7098525e3e5a496393826eb1bd 100644 (file)
@@ -112,8 +112,11 @@ static void user_session_stopped_cb (Session *session, Display *display);
 Display *
 display_new (DisplayServer *display_server)
 {
-    Display *display = g_object_new (DISPLAY_TYPE, NULL);
+    Display *display;
 
+    g_return_val_if_fail (display_server != NULL, NULL);
+  
+    display = g_object_new (DISPLAY_TYPE, NULL);
     display->priv->display_server = g_object_ref (display_server);
 
     return display;
@@ -601,7 +604,7 @@ greeter_session_stopped_cb (Session *session, Display *display)
         return;
     }
 
-    if (!display->priv->display_server)
+    if (display_server_get_is_stopped (display->priv->display_server))
         return;
 
     /* Start the session for the authenticated user */
@@ -752,10 +755,6 @@ display_server_stopped_cb (DisplayServer *server, Display *display)
 {
     g_debug ("Display server stopped");
 
-    g_signal_handlers_disconnect_matched (display->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
-    g_object_unref (display->priv->display_server);
-    display->priv->display_server = NULL;
-
     /* Stop this display, it will be restarted by the seat if necessary */
     display_stop (display);
 }
@@ -820,6 +819,40 @@ display_start (Display *display)
     return TRUE;
 }
 
+gboolean
+display_get_is_ready (Display *display)
+{
+    g_return_val_if_fail (display != NULL, FALSE);
+
+    return display->priv->is_ready;
+}
+
+void
+display_lock (Display *display)
+{
+    g_return_if_fail (display != NULL);
+
+    if (!display->priv->session)
+        return;
+
+    g_debug ("Locking display");
+
+    session_lock (display->priv->session);
+}
+
+void
+display_unlock (Display *display)
+{
+    g_return_if_fail (display != NULL);
+
+    if (!display->priv->session)
+        return;
+
+    g_debug ("Unlocking display");
+
+    session_unlock (display->priv->session);
+}
+
 void
 display_stop (Display *display)
 {
@@ -846,14 +879,11 @@ display_stop (Display *display)
     }
 
     /* Stop the display server after that */
-    if (display->priv->display_server)
+    if (!display_server_get_is_stopped (display->priv->display_server))
     {
         display_server_stop (display->priv->display_server);
-        if (display->priv->display_server && !display_server_get_is_stopped (display->priv->display_server))
+        if (!display_server_get_is_stopped (display->priv->display_server))
             return;
-        g_signal_handlers_disconnect_matched (display->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
-        g_object_unref (display->priv->display_server);
-        display->priv->display_server = NULL;
     }
 
     display->priv->stopped = TRUE;
@@ -862,37 +892,10 @@ display_stop (Display *display)
 }
 
 gboolean
-display_get_is_ready (Display *display)
+display_get_is_stopped (Display *display)
 {
     g_return_val_if_fail (display != NULL, FALSE);
-
-    return display->priv->is_ready;
-}
-
-void
-display_lock (Display *display)
-{
-    g_return_if_fail (display != NULL);
-
-    if (!display->priv->session)
-        return;
-
-    g_debug ("Locking display");
-
-    session_lock (display->priv->session);
-}
-
-void
-display_unlock (Display *display)
-{
-    g_return_if_fail (display != NULL);
-
-    if (!display->priv->session)
-        return;
-
-    g_debug ("Unlocking display");
-
-    session_unlock (display->priv->session);
+    return display->priv->stopped;
 }
 
 static gboolean
@@ -926,11 +929,8 @@ display_finalize (GObject *object)
 
     self = DISPLAY (object);
 
-    if (self->priv->display_server)
-    {
-        g_signal_handlers_disconnect_matched (self->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
-        g_object_unref (self->priv->display_server);
-    }
+    g_signal_handlers_disconnect_matched (self->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
+    g_object_unref (self->priv->display_server);
     g_free (self->priv->greeter_session);
     if (self->priv->greeter)
     {
index e8a6027aa7a5f00a183523b5f91cb5ec827500a1..6da1b1a5a7625d302c4cd45a819c318b5579c30b 100644 (file)
@@ -90,6 +90,8 @@ void display_unlock (Display *display);
 
 void display_stop (Display *display);
 
+gboolean display_get_is_stopped (Display *display);
+
 G_END_DECLS
 
 #endif /* _DISPLAY_H_ */
index 720a3704b35e9a5d245069aa95495d92b5c65563..84ad8d47c6fb521828db162c271d5a104561b737 100644 (file)
@@ -63,12 +63,6 @@ seat_xdmcp_session_create_session (Seat *seat, Display *display)
     return SESSION (session);
 }
 
-static void
-seat_xdmcp_session_display_removed (Seat *seat, Display *display)
-{
-   seat_stop (seat);
-}
-
 static void
 seat_xdmcp_session_init (SeatXDMCPSession *seat)
 {
@@ -95,7 +89,6 @@ seat_xdmcp_session_class_init (SeatXDMCPSessionClass *klass)
 
     seat_class->create_display_server = seat_xdmcp_session_create_display_server;
     seat_class->create_session = seat_xdmcp_session_create_session;
-    seat_class->display_removed = seat_xdmcp_session_display_removed;
     object_class->finalize = seat_xdmcp_session_finalize;
 
     g_type_class_add_private (klass, sizeof (SeatXDMCPSessionPrivate));
index a1fb2e019f4714aec4e4e4ca77ab4ff27940ca95..678329874a4ab7fd09404a3e6c0f763a417b1c24 100644 (file)
@@ -124,13 +124,36 @@ seat_xlocal_create_session (Seat *seat, Display *display)
 static void
 seat_xlocal_set_active_display (Seat *seat, Display *display)
 {
-    gint number = xserver_local_get_vt (XSERVER_LOCAL (XSERVER (display_get_display_server (display))));
-    if (number >= 0)
-        vt_set_active (number);
+    gint vt = xserver_local_get_vt (XSERVER_LOCAL (display_get_display_server (display)));
+    if (vt >= 0)
+        vt_set_active (vt);
 
     SEAT_CLASS (seat_xlocal_parent_class)->set_active_display (seat, display);
 }
 
+static Display *
+seat_xlocal_get_active_display (Seat *seat)
+{
+    gint vt;
+    GList *link;
+
+    vt = vt_get_active ();
+    if (vt < 0)
+        return NULL;
+
+    for (link = seat_get_displays (seat); link; link = link->next)
+    {
+        Display *display = link->data;
+        XServerLocal *xserver;
+
+        xserver = XSERVER_LOCAL (display_get_display_server (display));
+        if (xserver_local_get_vt (xserver) == vt)
+            return display;
+    }
+
+    return NULL;
+}
+
 static void
 seat_xlocal_run_script (Seat *seat, Display *display, Process *script)
 {
@@ -146,28 +169,6 @@ seat_xlocal_run_script (Seat *seat, Display *display, Process *script)
     SEAT_CLASS (seat_xlocal_parent_class)->run_script (seat, display, script);
 }
 
-static void
-seat_xlocal_display_removed (Seat *seat, Display *display)
-{
-    if (seat_get_is_stopping (seat))
-        return;
-
-    /* If this is the only display and it failed to start then stop this seat */
-    if (g_list_length (seat_get_displays (seat)) == 0 && !display_get_is_ready (display))
-    {
-        g_debug ("Stopping X local seat, failed to start a display");
-        seat_stop (seat);
-        return;
-    }
-
-    /* Show a new greeter */  
-    if (display == seat_get_active_display (seat))
-    {
-        g_debug ("Active display stopped, switching to greeter");
-        seat_switch_to_greeter (seat);
-    }
-}
-
 static void
 seat_xlocal_init (SeatXLocal *seat)
 {
@@ -182,6 +183,6 @@ seat_xlocal_class_init (SeatXLocalClass *klass)
     seat_class->create_display_server = seat_xlocal_create_display_server;
     seat_class->create_session = seat_xlocal_create_session;
     seat_class->set_active_display = seat_xlocal_set_active_display;
+    seat_class->get_active_display = seat_xlocal_get_active_display;
     seat_class->run_script = seat_xlocal_run_script;
-    seat_class->display_removed = seat_xlocal_display_removed;
 }
index 252f0cc4fe5456a7242e78d9caa6d174234d9239..e6e999d8fc4669a9f86383e4a65fa5fb0f90148b 100644 (file)
@@ -70,13 +70,6 @@ seat_xremote_run_script (Seat *seat, Display *display, Process *script)
     SEAT_CLASS (seat_xremote_parent_class)->run_script (seat, display, script);
 }
 
-static void
-seat_xremote_display_removed (Seat *seat, Display *display)
-{
-    /* Can't restart the display, so remove this seat */
-    seat_stop (seat);
-}
-
 static void
 seat_xremote_init (SeatXRemote *seat)
 {
@@ -91,5 +84,4 @@ seat_xremote_class_init (SeatXRemoteClass *klass)
     seat_class->create_display_server = seat_xremote_create_display_server;
     seat_class->create_session = seat_xremote_create_session;
     seat_class->run_script = seat_xremote_run_script;
-    seat_class->display_removed = seat_xremote_display_removed;
 }
index eb150c31da46c944720bfdb5c38b23b35b42f290..a3e4f3c1e77ed29450b6432b1819041d87b487c0 100644 (file)
@@ -103,12 +103,6 @@ seat_xvnc_run_script (Seat *seat, Display *display, Process *script)
     SEAT_CLASS (seat_xvnc_parent_class)->run_script (seat, display, script);
 }
 
-static void
-seat_xvnc_display_removed (Seat *seat, Display *display)
-{
-    seat_stop (seat);
-}
-
 static void
 seat_xvnc_init (SeatXVNC *seat)
 {
@@ -136,7 +130,6 @@ seat_xvnc_class_init (SeatXVNCClass *klass)
     seat_class->create_display_server = seat_xvnc_create_display_server;
     seat_class->create_session = seat_xvnc_create_session;
     seat_class->run_script = seat_xvnc_run_script;
-    seat_class->display_removed = seat_xvnc_display_removed;
     object_class->finalize = seat_xdmcp_session_finalize;
 
     g_type_class_add_private (klass, sizeof (SeatXVNCPrivate));
index 4b736200196c1d0cbcf85ff9b634123f18d8011e..5e543f391c7ee50ad7ffa8d84f2254d26ab6f554 100644 (file)
@@ -38,9 +38,6 @@ struct SeatPrivate
     /* The displays for this seat */
     GList *displays;
 
-    /* The active display */
-    Display *active_display;
-
     /* TRUE if stopping this seat (waiting for displays to stop) */
     gboolean stopping;
 
@@ -162,7 +159,7 @@ Display *
 seat_get_active_display (Seat *seat)
 {
     g_return_val_if_fail (seat != NULL, NULL);
-    return seat->priv->active_display;
+    return SEAT_GET_CLASS (seat)->get_active_display (seat);
 }
 
 gboolean
@@ -196,6 +193,9 @@ switch_to_user (Seat *seat, const gchar *username, gboolean unlock)
     {
         Display *display = link->data;
 
+        if (display_get_is_stopped (display))
+            continue;
+
         /* If already logged in, then switch to that display */
         if (g_strcmp0 (display_get_username (display), username) == 0)        
         {
@@ -427,11 +427,51 @@ check_stopped (Seat *seat)
 static void
 display_stopped_cb (Display *display, Seat *seat)
 {
-    seat->priv->displays = g_list_remove (seat->priv->displays, display);
+    gboolean is_active;
+
+    is_active = display == seat_get_active_display (seat);
+
     g_signal_handlers_disconnect_matched (display, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
-    g_signal_emit (seat, signals[DISPLAY_REMOVED], 0, display);
+    seat->priv->displays = g_list_remove (seat->priv->displays, display);
     g_object_unref (display);
 
+    g_signal_emit (seat, signals[DISPLAY_REMOVED], 0, display);
+
+    /* If no more displays running either start a greeter or stop the seat */
+    if (!seat->priv->stopping)
+    {
+        if (g_list_length (seat->priv->displays) == 0)
+        {
+            /* If failed to start then stop this seat */
+            if (!display_get_is_ready (display))
+            {
+                g_debug ("Stopping seat, failed to start a display");
+                seat_stop (seat);
+            }
+            /* Attempt to start a greeter */
+            else if (!seat->priv->can_switch)
+            {
+                g_debug ("Stopping seat, display stopped");
+                seat_stop (seat);             
+            }
+            
+            else if (!seat_switch_to_greeter (seat))
+            {
+                g_debug ("Stopping seat, unable to start greeter");
+                seat_stop (seat);
+            }        
+        }
+        else if (is_active)
+        {
+            g_debug ("Active display stopped, switching to greeter");
+            if (!seat_switch_to_greeter (seat))
+            {
+                g_debug ("Stopping seat, unable to start greeter");
+                seat_stop (seat);              
+            }
+        }
+    }
+  
     check_stopped (seat);
 }
 
@@ -502,7 +542,7 @@ switch_to_user_or_start_greeter (Seat *seat, const gchar *username, gboolean use
     g_signal_emit (seat, signals[DISPLAY_ADDED], 0, display);
 
     /* Switch to this display if currently not looking at anything */
-    if (!seat->priv->active_display)
+    if (seat_get_active_display (seat) == NULL)
         seat_set_active_display (seat, display);
 
     return display_start (display);
@@ -610,25 +650,30 @@ seat_real_start (Seat *seat)
 static void
 seat_real_set_active_display (Seat *seat, Display *display)
 {
-    if (display == seat->priv->active_display)
-        return;
+    GList *link;
 
-    if (seat->priv->active_display)
+    for (link = seat->priv->displays; link; link = link->next)
     {
-        /* Stop the existing display if it is a greeter */
-        if (!display_get_username (seat->priv->active_display))
+        Display *d = link->data;
+
+        if (d == display)
+            continue;
+
+        /* Stop any greeters and lock any other sessions */
+        if (!display_get_username (d))
         {
-            g_debug ("Stopping greeter display being switched from");
-            display_stop (seat->priv->active_display);
+            g_debug ("Stopping background greeter");
+            display_stop (d);
         }
-        /* Otherwise lock it */
         else
-        {
-            display_lock (seat->priv->active_display);
-        }
-        g_object_unref (seat->priv->active_display);
-    }
-    seat->priv->active_display = g_object_ref (display);
+            display_lock (d);
+    }  
+}
+
+static Display *
+seat_real_get_active_display (Seat *seat)
+{
+    return NULL;
 }
 
 static void
@@ -664,8 +709,6 @@ seat_finalize (GObject *object)
     g_hash_table_unref (self->priv->properties);
     g_free (self->priv->guest_username);
     g_list_free_full (self->priv->displays, g_object_unref);
-    if (self->priv->active_display)
-        g_object_unref (self->priv->active_display);
 
     G_OBJECT_CLASS (seat_parent_class)->finalize (object);
 }
@@ -678,6 +721,7 @@ seat_class_init (SeatClass *klass)
     klass->setup = seat_real_setup;
     klass->start = seat_real_start;
     klass->set_active_display = seat_real_set_active_display;
+    klass->get_active_display = seat_real_get_active_display;
     klass->run_script = seat_real_run_script;
     klass->stop = seat_real_stop;
 
index 4760268f969b4eb00a746adec513c0b93e0d7dcf..fefb5b670f1099df321efb07470669e773234cc9 100644 (file)
@@ -40,6 +40,7 @@ typedef struct
     DisplayServer *(*create_display_server) (Seat *seat);
     Session *(*create_session) (Seat *seat, Display *display);
     void (*set_active_display)(Seat *seat, Display *display);
+    Display *(*get_active_display)(Seat *seat);
     void (*run_script)(Seat *seat, Display *display, Process *script);
     void (*stop)(Seat *seat);
 
index b0bf7b8ac7e0105cc632b20ecd6b07ce2d7b22ee..10981050622c8576d6adbcf8395e581e9ae1073d 100644 (file)
@@ -60,6 +60,9 @@ struct XServerLocalPrivate
     /* VT to run on */
     gint vt;
   
+    /* TRUE if holding a reference to the VT */
+    gboolean have_vt_ref;
+  
     /* TRUE if replacing Plymouth */
     gboolean replacing_plymouth;
 };
@@ -147,7 +150,10 @@ xserver_local_new (void)
     if (self->priv->vt < 0)
         self->priv->vt = vt_get_unused ();
     if (self->priv->vt >= 0)
+    {
         vt_ref (self->priv->vt);
+        self->priv->have_vt_ref = TRUE;
+    }
 
     return self;
 }
@@ -315,9 +321,6 @@ stopped_cb (Process *process, XServerLocal *server)
 {
     g_debug ("X server stopped");
 
-    g_object_unref (server->priv->xserver_process);
-    server->priv->xserver_process = NULL;
-
     xserver_local_release_display_number (xserver_get_display_number (XSERVER (server)));
   
     if (xserver_get_authority (XSERVER (server)) && server->priv->authority_file)
@@ -338,11 +341,11 @@ stopped_cb (Process *process, XServerLocal *server)
         server->priv->authority_file = NULL;
     }
 
-    if (server->priv->vt >= 0)
+    if (server->priv->have_vt_ref)
     {
         vt_unref (server->priv->vt);
-        server->priv->vt = -1;
-    }
+        server->priv->have_vt_ref = FALSE;
+    }  
 
     if (server->priv->replacing_plymouth && plymouth_get_is_running ())
     {
@@ -543,7 +546,7 @@ xserver_local_finalize (GObject *object)
     g_free (self->priv->xdmcp_key);
     if (self->priv->authority_file)
         g_object_unref (self->priv->authority_file);
-    if (self->priv->vt >= 0)
+    if (self->priv->have_vt_ref)
         vt_unref (self->priv->vt);
 
     G_OBJECT_CLASS (xserver_local_parent_class)->finalize (object);