]> rtime.felk.cvut.cz Git - sojka/lightdm.git/commitdiff
Fixes a bug that prevents session locking if the session was unlocked after changing...
authorJesús González <jgonzalez@gdr-sistemas.com>
Fri, 19 Sep 2014 01:44:10 +0000 (03:44 +0200)
committerJesús González <jgonzalez@gdr-sistemas.com>
Fri, 19 Sep 2014 01:44:10 +0000 (03:44 +0200)
As a side effect, lightdm is now aware of session changes performed using VT switching.

src/lightdm.c
src/login1.c
src/login1.h
src/seat.c
src/seat.h
src/session.c
src/session.h

index a5c1e017cd6f4ca83d41d13f4614da107ad63ae3..0d161ed58660735e9f68da29c663728715459880 100644 (file)
@@ -569,7 +569,7 @@ emit_object_value_changed (GDBusConnection *bus, const gchar *path, const gchar
                                         g_variant_new ("(sa{sv}as)", interface_name, &builder, NULL),
                                         &error))
         g_warning ("Failed to emit PropertiesChanged signal: %s", error->message);
-    g_clear_error (&error); 
+    g_clear_error (&error);
 }
 
 static void
@@ -585,7 +585,7 @@ emit_object_signal (GDBusConnection *bus, const gchar *path, const gchar *signal
                                         g_variant_new ("(o)", object_path),
                                         &error))
         g_warning ("Failed to emit %s signal on %s: %s", signal_name, path, error->message);
-    g_clear_error (&error); 
+    g_clear_error (&error);
 }
 
 static void
@@ -1001,7 +1001,7 @@ add_login1_seat (Login1Seat *login1_seat)
 
     g_free (config_section);
     g_object_unref (seat);
-  
+
     return started;
 }
 
@@ -1055,6 +1055,54 @@ login1_can_graphical_changed_cb (Login1Seat *login1_seat)
     update_login1_seat (login1_seat);
 }
 
+static void
+login1_active_session_changed_cb (Login1Seat *login1_seat, const gchar *login1_session)
+{
+    g_debug ("Seat %s changes active session to %s", login1_seat_get_id (login1_seat), login1_session);
+
+    Seat *seat;
+    seat = display_manager_get_seat (display_manager, login1_seat_get_id (login1_seat));
+
+    if (seat)
+    {
+        Session *active_session;
+        active_session = seat_get_expected_active_session (seat);
+
+        if (g_strcmp0 (login1_session, session_get_login1_session (active_session)) == 0)
+        {
+            // Session is already active
+            g_debug ("Session %s is already active", login1_session);
+            return;
+        }
+
+        GList *session_link;
+        for (session_link = seat_get_sessions (seat); session_link; session_link = session_link->next)
+        {
+            Session *session = session_link->data;
+
+            if (g_strcmp0 (login1_session, session_get_login1_session (session)) == 0)
+            {
+                g_debug ("Activating session %s", login1_session);
+                seat_set_externally_activated_session (seat, session);
+                return;
+            }
+        }
+    }
+}
+
+static gboolean
+login1_add_seat (Login1Seat *login1_seat)
+{
+    if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
+    {
+        g_signal_connect (login1_seat, SIGNAL_LOGIN1_CAN_GRAPHICAL_CHANGED, G_CALLBACK (login1_can_graphical_changed_cb), NULL);
+    }
+
+    g_signal_connect (login1_seat, SIGNAL_LOGIN1_ACTIVE_SESION_CHANGED, G_CALLBACK (login1_active_session_changed_cb), NULL);
+
+    return update_login1_seat (login1_seat);
+}
+
 static void
 login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat)
 {
@@ -1063,9 +1111,7 @@ login1_service_seat_added_cb (Login1Service *service, Login1Seat *login1_seat)
     else
         g_debug ("Seat %s added from logind without graphical output", login1_seat_get_id (login1_seat));
 
-    if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
-        g_signal_connect (login1_seat, "can-graphical-changed", G_CALLBACK (login1_can_graphical_changed_cb), NULL);
-    update_login1_seat (login1_seat);
+    login1_add_seat (login1_seat);
 }
 
 static void
@@ -1420,10 +1466,10 @@ main (int argc, char **argv)
             for (link = login1_service_get_seats (login1_service_get_instance ()); link; link = link->next)
             {
                 Login1Seat *login1_seat = link->data;
-                if (config_get_boolean (config_get_instance (), "LightDM", "logind-check-graphical"))
-                    g_signal_connect (login1_seat, "can-graphical-changed", G_CALLBACK (login1_can_graphical_changed_cb), NULL);
-                if (!update_login1_seat (login1_seat))
+                if (!login1_add_seat (login1_seat))
+                {
                     return EXIT_FAILURE;
+                }
             }
         }
     }
index ad922a5a6a892be826f52d04f0cf15a752c15cdf..9e9ae87f98d0fd6bd794d834867eb4de9042889b 100644 (file)
@@ -18,6 +18,9 @@
 #define LOGIN1_SERVICE_NAME "org.freedesktop.login1"
 #define LOGIN1_OBJECT_NAME "/org/freedesktop/login1"
 #define LOGIN1_MANAGER_INTERFACE_NAME "org.freedesktop.login1.Manager"
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define DBUS_PROPERTIES_GET_METHOD "Get"
+#define LOGIN1_SEAT_INTERFACE "org.freedesktop.login1.Seat"
 
 enum {
     SEAT_ADDED,
@@ -43,9 +46,10 @@ struct Login1ServicePrivate
 
 enum {
     CAN_GRAPHICAL_CHANGED,
+    ACTIVE_SESSION_CHANGED,
     LAST_SEAT_SIGNAL
 };
-static guint seat_signals[LAST_SEAT_SIGNAL] = { 0 };
+static guint seat_signals[LAST_SEAT_SIGNAL] = { 0, 0 };
 
 struct Login1SeatPrivate
 {
@@ -81,6 +85,32 @@ login1_service_get_instance (void)
     return singleton;
 }
 
+static GVariant *
+seat_get_property (GDBusConnection *connection,
+                   Login1Seat *seat,
+                   const gchar *property_name)
+{
+    GVariant *result;
+    GError *error = NULL;
+
+    result = g_dbus_connection_call_sync (connection,
+                                          LOGIN1_SERVICE_NAME,
+                                          seat->priv->path,
+                                          DBUS_PROPERTIES_INTERFACE,
+                                          DBUS_PROPERTIES_GET_METHOD,
+                                          g_variant_new ("(ss)", LOGIN1_SEAT_INTERFACE, property_name),
+                                          G_VARIANT_TYPE ("(v)"),
+                                          G_DBUS_CALL_FLAGS_NONE,
+                                          -1,
+                                          NULL,
+                                          &error);
+    if (error)
+        g_warning ("Error updating %s: %s", property_name, error->message);
+    g_clear_error (&error);
+
+    return result;
+}
+
 static void
 seat_properties_changed_cb (GDBusConnection *connection,
                             const gchar *sender_name,
@@ -100,22 +130,8 @@ seat_properties_changed_cb (GDBusConnection *connection,
         if (strcmp (property_name, "CanGraphical") == 0)
         {
             GVariant *result;
-            GError *error = NULL;
-
-            result = g_dbus_connection_call_sync (connection,
-                                                  LOGIN1_SERVICE_NAME,
-                                                  seat->priv->path,
-                                                  "org.freedesktop.DBus.Properties",
-                                                  "Get",
-                                                  g_variant_new ("(ss)", "org.freedesktop.login1.Seat", property_name),
-                                                  G_VARIANT_TYPE ("(v)"),
-                                                  G_DBUS_CALL_FLAGS_NONE,
-                                                  -1,
-                                                  NULL,
-                                                  &error);
-            if (error)
-                g_warning ("Error updating CanGraphical: %s", error->message);
-            g_clear_error (&error);
+
+            result = seat_get_property (connection, seat, property_name);
             if (result)
             {
                 GVariant *value;
@@ -129,6 +145,37 @@ seat_properties_changed_cb (GDBusConnection *connection,
                 g_variant_unref (result);
             }
         }
+        if (strcmp (property_name, "ActiveSession") == 0)
+        {
+            GVariant *result;
+
+            result = seat_get_property (connection, seat, property_name);
+            if (result)
+            {
+                GVariant *value1, *value2;
+                const gchar *login1_session;
+
+                g_variant_get (result, "(v)", &value1);
+
+                // returned value should be of type (so)
+                value2 = g_variant_get_child_value (value1, 0);
+
+                if (value2)
+                {
+                    login1_session = g_variant_get_string (value2, NULL);
+
+                    if (login1_session)
+                    {
+                        g_signal_emit (seat, seat_signals[ACTIVE_SESSION_CHANGED], 0, login1_session);
+                    }
+
+                    g_variant_unref (value2);
+                }
+
+                g_variant_unref (value1);
+                g_variant_unref (result);
+            }
+        }
     }
     g_variant_iter_free (invalidated_properties);
 }
@@ -227,11 +274,11 @@ signal_cb (GDBusConnection *connection,
         seat = login1_service_get_seat (service, id);
         if (seat)
         {
-            service->priv->seats = g_list_remove (service->priv->seats, seat);            
+            service->priv->seats = g_list_remove (service->priv->seats, seat);
             g_signal_emit (service, service_signals[SEAT_REMOVED], 0, seat);
             g_object_unref (seat);
-        }                        
-    } 
+        }
+    }
 }
 
 gboolean
@@ -518,11 +565,20 @@ login1_seat_class_init (Login1SeatClass *klass)
     g_type_class_add_private (klass, sizeof (Login1SeatPrivate));
 
     seat_signals[CAN_GRAPHICAL_CHANGED] =
-        g_signal_new ("can-graphical-changed",
+        g_signal_new (SIGNAL_LOGIN1_CAN_GRAPHICAL_CHANGED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (Login1SeatClass, can_graphical_changed),
                       NULL, NULL,
                       NULL,
                       G_TYPE_NONE, 0);
+
+    seat_signals[ACTIVE_SESSION_CHANGED] =
+        g_signal_new (SIGNAL_LOGIN1_ACTIVE_SESION_CHANGED,
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (Login1SeatClass, active_session_changed),
+                      NULL, NULL,
+                      NULL,
+                      G_TYPE_NONE, 1, G_TYPE_STRING);
 }
index 416632f7a840302be68dfb0e046124dab438dae3..3295ceba18e7d6a4a12fa02e7989b4390ecaea50 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@canonical.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -22,6 +22,9 @@ G_BEGIN_DECLS
 #define LOGIN1_SERVICE_TYPE (login1_service_get_type())
 #define LOGIN1_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGIN1_SERVICE_TYPE, Login1Service));
 
+#define SIGNAL_LOGIN1_ACTIVE_SESION_CHANGED "active-session-changed"
+#define SIGNAL_LOGIN1_CAN_GRAPHICAL_CHANGED "can-graphical-changed"
+
 typedef struct Login1SeatPrivate Login1SeatPrivate;
 
 typedef struct
@@ -34,6 +37,7 @@ typedef struct
 {
     GObjectClass parent_class;
     void (*can_graphical_changed)(Login1Seat *seat);
+    void (*active_session_changed)(Login1Seat *seat, const gchar *login1_session);
 } Login1SeatClass;
 
 typedef struct Login1ServicePrivate Login1ServicePrivate;
index c115aa18a597eb8f9bf086e53f2ac5b50dd636fb..b3563a25702fab054816bfb1a8eb9cf2ea692b7c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@canonical.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -56,7 +56,7 @@ struct SeatPrivate
 
     /* The session to set active when it starts */
     Session *session_to_activate;
-  
+
     /* TRUE once we have started */
     gboolean started;
 
@@ -106,7 +106,7 @@ seat_new (const gchar *module_name, const gchar *name)
 {
     Seat *seat;
     SeatModule *m = NULL;
-  
+
     g_return_val_if_fail (module_name != NULL, NULL);
 
     if (seat_modules)
@@ -269,6 +269,37 @@ seat_get_next_session (Seat *seat)
     return seat->priv->next_session;
 }
 
+/**
+ * Obtains the active session which lightdm expects to be active.
+ *
+ * This function is different from seat_get_active_session() in that the
+ * later (in the case of xlocal seats) dynamically finds the session that is
+ * really active (based on the active VT), whereas this function returns the
+ * session that lightdm activated last by itself, which may not be the actual
+ * active session (i.e. VT changes).
+ */
+Session *
+seat_get_expected_active_session (Seat *seat)
+{
+    g_return_val_if_fail (seat != NULL, NULL);
+    return seat->priv->active_session;
+}
+
+/**
+ * Sets the active session which lightdm expects to be active.
+ *
+ * This function is different from seat_set_active_session() in that the
+ * later performs an actual session activation, whereas this function just
+ * updates the active session after the session has been activated by some
+ * means external to lightdm (i.e. VT changes).
+ */
+void
+seat_set_externally_activated_session (Seat *seat, Session *session)
+{
+    g_return_if_fail (seat != NULL);
+    seat->priv->active_session = session;
+}
+
 gboolean
 seat_get_can_switch (Seat *seat)
 {
@@ -288,7 +319,7 @@ run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name,
 {
     Process *script;
     gboolean result = FALSE;
-  
+
     script = process_new (NULL, NULL);
 
     process_set_command (script, script_name);
@@ -338,7 +369,7 @@ run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name,
 
 static void
 seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
-{  
+{
 }
 
 static void
@@ -476,7 +507,7 @@ find_resettable_greeter (Seat *seat)
 static void
 set_greeter_hints (Seat *seat, Greeter *greeter_session)
 {
-    greeter_clear_hints (greeter_session);    
+    greeter_clear_hints (greeter_session);
     greeter_set_hint (greeter_session, "default-session", seat_get_string_property (seat, "user-session"));
     greeter_set_hint (greeter_session, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
     greeter_set_hint (greeter_session, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
@@ -893,7 +924,7 @@ get_session_argv (Seat *seat, SessionConfig *session_config, const gchar *sessio
         g_free (argv[0]);
         argv[0] = path;
     }
-  
+
     return argv;
 }
 
@@ -1051,7 +1082,7 @@ create_guest_session (Seat *seat, const gchar *session_name)
     session_set_argv (session, argv);
     g_strfreev (argv);
     g_object_unref (session_config);
-  
+
     return session;
 }
 
@@ -1091,7 +1122,7 @@ greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *sessi
         gchar **argv;
 
         session = greeter_get_authentication_session (greeter);
-  
+
         /* Get session command to run */
         switch (type)
         {
@@ -1215,14 +1246,14 @@ create_greeter_session (Seat *seat)
     g_signal_connect (greeter_session, "notify::active-username", G_CALLBACK (greeter_active_username_changed_cb), seat);
     g_signal_connect (greeter_session, "authentication-complete", G_CALLBACK (session_authentication_complete_cb), seat);
     g_signal_connect (greeter_session, "stopped", G_CALLBACK (session_stopped_cb), seat);
-  
+
     set_session_env (SESSION (greeter_session));
     session_set_env (SESSION (greeter_session), "XDG_SESSION_CLASS", "greeter");
 
     session_set_pam_service (SESSION (greeter_session), seat_get_string_property (seat, "pam-greeter-service"));
     if (getuid () == 0)
     {
-        gchar *greeter_user;      
+        gchar *greeter_user;
         greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
         session_set_username (SESSION (greeter_session), greeter_user);
         g_free (greeter_user);
@@ -1634,7 +1665,7 @@ seat_real_start (Seat *seat)
             background_session = session;
             session = NULL;
         }
-      
+
         if (session)
         {
             DisplayServer *display_server;
@@ -1796,7 +1827,7 @@ seat_finalize (GObject *object)
     {
         DisplayServer *display_server = link->data;
         g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
-    }  
+    }
     g_list_free_full (self->priv->display_servers, g_object_unref);
     for (link = self->priv->sessions; link; link = link->next)
     {
index ef9c8cb0a111e43f435e10e7b19feb01c5063076..08dcce056c6bccdbb75dfd129c6c54b07bd0fcc1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@canonical.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -88,6 +88,10 @@ Session *seat_get_active_session (Seat *seat);
 
 Session *seat_get_next_session (Seat *seat);
 
+void seat_set_externally_activated_session (Seat *seat, Session *session);
+
+Session *seat_get_expected_active_session (Seat *seat);
+
 gboolean seat_get_can_switch (Seat *seat);
 
 gboolean seat_get_allow_guest (Seat *seat);
index 5169bbdaa759ad1aa64979750085483fc6f1d48a..10e369c30c704953b54e826d2a6b727b51831e91 100644 (file)
@@ -310,7 +310,7 @@ session_get_env (Session *session, const gchar *name)
     link = find_env_entry (session, name);
     if (!link)
         return NULL;
-  
+
     entry = link->data;
 
     return entry + strlen (name) + 1;
@@ -322,7 +322,7 @@ session_unset_env (Session *session, const gchar *name)
     GList *link;
 
     g_return_if_fail (session != NULL);
-  
+
     link = find_env_entry (session, name);
     if (!link)
         return;
@@ -652,6 +652,13 @@ session_get_username (Session *session)
     return session->priv->username;
 }
 
+const gchar *
+session_get_login1_session (Session *session)
+{
+    g_return_val_if_fail (session != NULL, NULL);
+    return session->priv->login1_session;
+}
+
 const gchar *
 session_get_console_kit_cookie (Session *session)
 {
index e820e137e07d051d35431aa3260c3cb49563c54d..5b6baa8d2559471449bb585dd841424ca9f2962b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@canonical.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -111,6 +111,8 @@ gboolean session_get_is_started (Session *session);
 
 const gchar *session_get_username (Session *session);
 
+const gchar *session_get_login1_session (Session *session);
+
 const gchar *session_get_console_kit_cookie (Session *session);
 
 void session_respond (Session *session, struct pam_response *response);