summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lightdm.c58
-rw-r--r--src/login1.c92
-rw-r--r--src/login1.h4
-rw-r--r--src/seat.c31
-rw-r--r--src/seat.h4
-rw-r--r--src/session.c7
-rw-r--r--src/session.h2
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;
diff --git a/src/seat.c b/src/seat.c
index 529774e9..b3563a25 100644
--- a/src/seat.c
+++ b/src/seat.c
@@ -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)
{
diff --git a/src/seat.h b/src/seat.h
index 50de1eb4..08dcce05 100644
--- a/src/seat.h
+++ b/src/seat.h
@@ -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);