As a side effect, lightdm is now aware of session changes performed using VT switching.
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
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
g_free (config_section);
g_object_unref (seat);
-
+
return started;
}
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)
{
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
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;
+ }
}
}
}
#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,
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
{
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,
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;
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);
}
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
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);
}
/*
* 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
#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
{
GObjectClass parent_class;
void (*can_graphical_changed)(Login1Seat *seat);
+ void (*active_session_changed)(Login1Seat *seat, const gchar *login1_session);
} Login1SeatClass;
typedef struct Login1ServicePrivate Login1ServicePrivate;
/*
* 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
/* The session to set active when it starts */
Session *session_to_activate;
-
+
/* TRUE once we have started */
gboolean started;
{
Seat *seat;
SeatModule *m = NULL;
-
+
g_return_val_if_fail (module_name != NULL, NULL);
if (seat_modules)
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)
{
{
Process *script;
gboolean result = FALSE;
-
+
script = process_new (NULL, NULL);
process_set_command (script, script_name);
static void
seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
-{
+{
}
static void
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");
g_free (argv[0]);
argv[0] = path;
}
-
+
return argv;
}
session_set_argv (session, argv);
g_strfreev (argv);
g_object_unref (session_config);
-
+
return session;
}
gchar **argv;
session = greeter_get_authentication_session (greeter);
-
+
/* Get session command to run */
switch (type)
{
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);
background_session = session;
session = NULL;
}
-
+
if (session)
{
DisplayServer *display_server;
{
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)
{
/*
* 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
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);
link = find_env_entry (session, name);
if (!link)
return NULL;
-
+
entry = link->data;
return entry + strlen (name) + 1;
GList *link;
g_return_if_fail (session != NULL);
-
+
link = find_env_entry (session, name);
if (!link)
return;
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)
{
/*
* 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
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);