diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lightdm.c | 58 | ||||
-rw-r--r-- | src/login1.c | 92 | ||||
-rw-r--r-- | src/login1.h | 4 | ||||
-rw-r--r-- | src/seat.c | 31 | ||||
-rw-r--r-- | src/seat.h | 4 | ||||
-rw-r--r-- | src/session.c | 7 | ||||
-rw-r--r-- | src/session.h | 2 |
7 files changed, 174 insertions, 24 deletions
diff --git a/src/lightdm.c b/src/lightdm.c index f48af8bb..0d161ed5 100644 --- a/src/lightdm.c +++ b/src/lightdm.c @@ -1056,6 +1056,54 @@ login1_can_graphical_changed_cb (Login1Seat *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) { if (login1_seat_get_can_graphical (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; + } } } } diff --git a/src/login1.c b/src/login1.c index f799e3ed..9e9ae87f 100644 --- a/src/login1.c +++ b/src/login1.c @@ -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); } @@ -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); } diff --git a/src/login1.h b/src/login1.h index af9f2a96..3295ceba 100644 --- a/src/login1.h +++ b/src/login1.h @@ -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; @@ -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) { @@ -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); diff --git a/src/session.c b/src/session.c index a1e88937..10e369c3 100644 --- a/src/session.c +++ b/src/session.c @@ -653,6 +653,13 @@ session_get_username (Session *session) } 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) { g_return_val_if_fail (session != NULL, NULL); diff --git a/src/session.h b/src/session.h index b79a53d8..5b6baa8d 100644 --- a/src/session.h +++ b/src/session.h @@ -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); |