diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2014-08-22 13:12:25 +1200 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2014-08-22 13:12:25 +1200 |
commit | 9966903c17a74ec7b265c9b25afabaa7af4d42e5 (patch) | |
tree | 7a3aa2ce58b983d1311cd23b3a3a637d206f79fc | |
parent | 377567a5e05a25c57cb87a4c4ad9e21122d16a30 (diff) | |
download | lightdm-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.c | 266 | ||||
-rw-r--r-- | src/login1.h | 48 | ||||
-rw-r--r-- | tests/src/test-runner.c | 2 |
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) { |