summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2014-08-22 13:12:25 +1200
committerRobert Ancell <robert.ancell@canonical.com>2014-08-22 13:12:25 +1200
commit9966903c17a74ec7b265c9b25afabaa7af4d42e5 (patch)
tree7a3aa2ce58b983d1311cd23b3a3a637d206f79fc
parent377567a5e05a25c57cb87a4c4ad9e21122d16a30 (diff)
downloadlightdm-9966903c17a74ec7b265c9b25afabaa7af4d42e5.tar.gz
Make a login1 service object (not currently required, but will be used for automatic multi-seat support)
-rw-r--r--src/login1.c266
-rw-r--r--src/login1.h48
-rw-r--r--tests/src/test-runner.c2
3 files changed, 309 insertions, 7 deletions
diff --git a/src/login1.c b/src/login1.c
index cd780c58..f5d5a798 100644
--- a/src/login1.c
+++ b/src/login1.c
@@ -10,10 +10,46 @@
* license.
*/
+#include <string.h>
#include <gio/gio.h>
#include "login1.h"
+#define LOGIN1_SERVICE_NAME "org.freedesktop.login1"
+
+enum {
+ SEAT_ADDED,
+ SEAT_REMOVED,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct Login1ServicePrivate
+{
+ /* Connection to bus service is running on */
+ GDBusConnection *connection;
+
+ /* Seats the service is reporting */
+ GList *seats;
+
+ /* Handle to signal subscription */
+ guint signal_id;
+};
+
+struct Login1SeatPrivate
+{
+ /* Seat Id */
+ gchar *id;
+
+ /* D-Bus path for this seat */
+ gchar *path;
+};
+
+G_DEFINE_TYPE (Login1Service, login1_service, G_TYPE_OBJECT);
+G_DEFINE_TYPE (Login1Seat, login1_seat, G_TYPE_OBJECT);
+
+static Login1Service *singleton = NULL;
+
static gboolean
check_login1 (void)
{
@@ -24,7 +60,7 @@ check_login1 (void)
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
- "org.freedesktop.login1",
+ LOGIN1_SERVICE_NAME,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
NULL,
@@ -50,7 +86,7 @@ login1_is_running (void)
if (!have_checked)
{
have_checked = TRUE;
- is_running = check_login1();
+ is_running = check_login1 ();
}
return is_running;
@@ -71,7 +107,7 @@ login1_get_session_id (void)
if (!bus)
return NULL;
result = g_dbus_connection_call_sync (bus,
- "org.freedesktop.login1",
+ LOGIN1_SERVICE_NAME,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"GetSessionByPID",
@@ -118,7 +154,7 @@ login1_lock_session (const gchar *session_path)
GVariant *result;
result = g_dbus_connection_call_sync (bus,
- "org.freedesktop.login1",
+ LOGIN1_SERVICE_NAME,
session_path,
"org.freedesktop.login1.Session",
"Lock",
@@ -159,7 +195,7 @@ login1_unlock_session (const gchar *session_path)
GVariant *result;
result = g_dbus_connection_call_sync (bus,
- "org.freedesktop.login1",
+ LOGIN1_SERVICE_NAME,
session_path,
"org.freedesktop.login1.Session",
"Unlock",
@@ -200,7 +236,7 @@ login1_activate_session (const gchar *session_path)
GVariant *result;
result = g_dbus_connection_call_sync (bus,
- "org.freedesktop.login1",
+ LOGIN1_SERVICE_NAME,
session_path,
"org.freedesktop.login1.Session",
"Activate",
@@ -218,3 +254,221 @@ login1_activate_session (const gchar *session_path)
}
g_object_unref (bus);
}
+
+Login1Service *
+login1_service_get_instance (void)
+{
+ if (!singleton)
+ singleton = g_object_new (LOGIN1_SERVICE_TYPE, NULL);
+ return singleton;
+}
+
+static Login1Seat *
+add_seat (Login1Service *service, const gchar *id, const gchar *path)
+{
+ Login1Seat *seat;
+
+ seat = g_object_new (LOGIN1_SEAT_TYPE, NULL);
+ seat->priv->id = g_strdup (id);
+ seat->priv->path = g_strdup (path);
+ service->priv->seats = g_list_append (service->priv->seats, seat);
+
+ return seat;
+}
+
+static void
+signal_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ Login1Service *service = user_data;
+
+ if (strcmp (signal_name, "SeatNew") == 0)
+ {
+ const gchar *id, *path;
+ Login1Seat *seat;
+
+ g_variant_get (parameters, "(&s&o)", &id, &path);
+ seat = login1_service_get_seat (service, id);
+ if (!seat)
+ {
+ seat = add_seat (service, id, path);
+ g_signal_emit (service, signals[SEAT_ADDED], 0, seat);
+ }
+ }
+ else if (strcmp (signal_name, "SeatRemoved") == 0)
+ {
+ const gchar *id, *path;
+ Login1Seat *seat;
+
+ g_variant_get (parameters, "(&s&o)", &id, &path);
+ seat = login1_service_get_seat (service, id);
+ if (seat)
+ {
+ service->priv->seats = g_list_remove (service->priv->seats, seat);
+ g_signal_emit (service, signals[SEAT_REMOVED], 0, seat);
+ g_object_unref (seat);
+ }
+ }
+}
+
+gboolean
+login1_service_connect (Login1Service *service)
+{
+ GVariant *result;
+ GVariantIter *seat_iter;
+ const gchar *id, *path;
+ GError *error = NULL;
+
+ g_return_val_if_fail (service != NULL, FALSE);
+
+ service->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (error)
+ g_warning ("Failed to get system bus: %s", error->message);
+ g_clear_error (&error);
+ if (!service->priv->connection)
+ return FALSE;
+
+ service->priv->signal_id = g_dbus_connection_signal_subscribe (service->priv->connection,
+ LOGIN1_SERVICE_NAME,
+ "org.freedesktop.login1.Manager",
+ NULL,
+ "/org/freedesktop/login1",
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ signal_cb,
+ service,
+ NULL);
+
+ result = g_dbus_connection_call_sync (service->priv->connection,
+ LOGIN1_SERVICE_NAME,
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "ListSeats",
+ g_variant_new ("()"),
+ G_VARIANT_TYPE ("(a(so))"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (error)
+ g_warning ("Failed to get list of logind seats: %s", error->message);
+ g_clear_error (&error);
+ if (!result)
+ return FALSE;
+
+ g_variant_get (result, "(a(so))", &seat_iter);
+ while (g_variant_iter_loop (seat_iter, "(&s&o)", &id, &path))
+ add_seat (service, id, path);
+ g_variant_iter_free (seat_iter);
+ g_variant_unref (result);
+
+ return TRUE;
+}
+
+GList *
+login1_service_get_seats (Login1Service *service)
+{
+ g_return_val_if_fail (service != NULL, NULL);
+ return service->priv->seats;
+}
+
+Login1Seat *
+login1_service_get_seat (Login1Service *service, const gchar *id)
+{
+ GList *link;
+
+ g_return_val_if_fail (service != NULL, NULL);
+
+ for (link = service->priv->seats; link; link = link->next)
+ {
+ Login1Seat *seat = link->data;
+ if (strcmp (seat->priv->id, id) == 0)
+ return seat;
+ }
+
+ return NULL;
+}
+
+static void
+login1_service_init (Login1Service *service)
+{
+ service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service, LOGIN1_SERVICE_TYPE, Login1ServicePrivate);
+}
+
+static void
+login1_service_finalize (GObject *object)
+{
+ Login1Service *self = LOGIN1_SERVICE (object);
+
+ g_list_free_full (self->priv->seats, g_object_unref);
+ g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->signal_id);
+ g_object_unref (self->priv->connection);
+
+ G_OBJECT_CLASS (login1_service_parent_class)->finalize (object);
+}
+
+static void
+login1_service_class_init (Login1ServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = login1_service_finalize;
+
+ g_type_class_add_private (klass, sizeof (Login1ServicePrivate));
+
+ signals[SEAT_ADDED] =
+ g_signal_new ("seat-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (Login1ServiceClass, seat_added),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
+ signals[SEAT_REMOVED] =
+ g_signal_new ("seat-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (Login1ServiceClass, seat_removed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
+}
+
+const gchar *
+login1_seat_get_id (Login1Seat *seat)
+{
+ g_return_val_if_fail (seat != NULL, NULL);
+ return seat->priv->id;
+}
+
+static void
+login1_seat_init (Login1Seat *seat)
+{
+ seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, LOGIN1_SEAT_TYPE, Login1SeatPrivate);
+}
+
+static void
+login1_seat_finalize (GObject *object)
+{
+ Login1Seat *self = LOGIN1_SEAT (object);
+
+ g_free (self->priv->id);
+ g_free (self->priv->path);
+
+ G_OBJECT_CLASS (login1_seat_parent_class)->finalize (object);
+}
+
+static void
+login1_seat_class_init (Login1SeatClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = login1_seat_finalize;
+
+ g_type_class_add_private (klass, sizeof (Login1SeatPrivate));
+}
diff --git a/src/login1.h b/src/login1.h
index 55b9b5db..9161becf 100644
--- a/src/login1.h
+++ b/src/login1.h
@@ -26,6 +26,54 @@ void login1_unlock_session (const gchar *session_path);
void login1_activate_session (const gchar *session_path);
+#define LOGIN1_SEAT_TYPE (login1_seat_get_type())
+#define LOGIN1_SEAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGIN1_SEAT_TYPE, Login1Seat));
+
+#define LOGIN1_SERVICE_TYPE (login1_service_get_type())
+#define LOGIN1_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGIN1_SERVICE_TYPE, Login1Service));
+
+typedef struct Login1SeatPrivate Login1SeatPrivate;
+
+typedef struct
+{
+ GObject parent_instance;
+ Login1SeatPrivate *priv;
+} Login1Seat;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} Login1SeatClass;
+
+typedef struct Login1ServicePrivate Login1ServicePrivate;
+
+typedef struct
+{
+ GObject parent_instance;
+ Login1ServicePrivate *priv;
+} Login1Service;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (*seat_added)(Login1Service *service, Login1Seat *seat);
+ void (*seat_removed)(Login1Service *service, Login1Seat *seat);
+} Login1ServiceClass;
+
+GType login1_service_get_type (void);
+
+GType login1_seat_get_type (void);
+
+Login1Service *login1_service_get_instance (void);
+
+gboolean login1_service_connect (Login1Service *service);
+
+GList *login1_service_get_seats (Login1Service *service);
+
+Login1Seat *login1_service_get_seat (Login1Service *service, const gchar *id);
+
+const gchar *login1_seat_get_id (Login1Seat *seat);
+
G_END_DECLS
#endif /* _LOGIN1_H_ */
diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c
index f02bcc28..8bab571a 100644
--- a/tests/src/test-runner.c
+++ b/tests/src/test-runner.c
@@ -1626,7 +1626,7 @@ handle_login1_call (GDBusConnection *connection,
Login1Seat *seat = link->data;
g_variant_builder_add (&seats, "(so)", seat->id, seat->path);
}
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", g_variant_builder_end (&seats)));
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", &seats));
}
else if (strcmp (method_name, "GetSessionByPID") == 0)
{