1 /* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
3 * Copyright (C) 2010-2011 Robert Ancell.
4 * Author: Robert Ancell <robert.ancell@canonical.com>
6 * This program is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
18 #define LOGIN1_SERVICE_NAME "org.freedesktop.login1"
25 static guint signals[LAST_SIGNAL] = { 0 };
27 struct Login1ServicePrivate
29 /* Connection to bus service is running on */
30 GDBusConnection *connection;
32 /* TRUE if have connected to service */
35 /* Seats the service is reporting */
38 /* Handle to signal subscription */
42 struct Login1SeatPrivate
47 /* D-Bus path for this seat */
51 G_DEFINE_TYPE (Login1Service, login1_service, G_TYPE_OBJECT);
52 G_DEFINE_TYPE (Login1Seat, login1_seat, G_TYPE_OBJECT);
54 static Login1Service *singleton = NULL;
57 login1_get_session_id (void)
64 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
66 g_warning ("Failed to get system bus: %s", error->message);
67 g_clear_error (&error);
70 result = g_dbus_connection_call_sync (bus,
72 "/org/freedesktop/login1",
73 "org.freedesktop.login1.Manager",
75 g_variant_new ("(u)", getpid()),
76 G_VARIANT_TYPE ("(o)"),
77 G_DBUS_CALL_FLAGS_NONE,
84 g_warning ("Failed to open login1 session: %s", error->message);
85 g_clear_error (&error);
89 g_variant_get (result, "(o)", &session_path);
90 g_variant_unref (result);
91 g_debug ("Got login1 session id: %s", session_path);
97 login1_lock_session (const gchar *session_path)
100 GError *error = NULL;
102 g_return_if_fail (session_path != NULL);
104 g_debug ("Locking login1 session %s", session_path);
106 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
108 g_warning ("Failed to get system bus: %s", error->message);
109 g_clear_error (&error);
117 result = g_dbus_connection_call_sync (bus,
120 "org.freedesktop.login1.Session",
122 g_variant_new ("()"),
123 G_VARIANT_TYPE ("()"),
124 G_DBUS_CALL_FLAGS_NONE,
129 g_warning ("Error locking login1 session: %s", error->message);
130 g_clear_error (&error);
132 g_variant_unref (result);
134 g_object_unref (bus);
138 login1_unlock_session (const gchar *session_path)
140 GDBusConnection *bus;
141 GError *error = NULL;
143 g_return_if_fail (session_path != NULL);
145 g_debug ("Unlocking login1 session %s", session_path);
147 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
149 g_warning ("Failed to get system bus: %s", error->message);
150 g_clear_error (&error);
158 result = g_dbus_connection_call_sync (bus,
161 "org.freedesktop.login1.Session",
163 g_variant_new ("()"),
164 G_VARIANT_TYPE ("()"),
165 G_DBUS_CALL_FLAGS_NONE,
170 g_warning ("Error unlocking login1 session: %s", error->message);
171 g_clear_error (&error);
173 g_variant_unref (result);
175 g_object_unref (bus);
179 login1_activate_session (const gchar *session_path)
181 GDBusConnection *bus;
182 GError *error = NULL;
184 g_return_if_fail (session_path != NULL);
186 g_debug ("Activating login1 session %s", session_path);
188 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
190 g_warning ("Failed to get system bus: %s", error->message);
191 g_clear_error (&error);
199 result = g_dbus_connection_call_sync (bus,
202 "org.freedesktop.login1.Session",
204 g_variant_new ("()"),
205 G_VARIANT_TYPE ("()"),
206 G_DBUS_CALL_FLAGS_NONE,
211 g_warning ("Error activating login1 session: %s", error->message);
212 g_clear_error (&error);
214 g_variant_unref (result);
216 g_object_unref (bus);
220 login1_service_get_instance (void)
223 singleton = g_object_new (LOGIN1_SERVICE_TYPE, NULL);
228 add_seat (Login1Service *service, const gchar *id, const gchar *path)
232 seat = g_object_new (LOGIN1_SEAT_TYPE, NULL);
233 seat->priv->id = g_strdup (id);
234 seat->priv->path = g_strdup (path);
235 service->priv->seats = g_list_append (service->priv->seats, seat);
241 signal_cb (GDBusConnection *connection,
242 const gchar *sender_name,
243 const gchar *object_path,
244 const gchar *interface_name,
245 const gchar *signal_name,
246 GVariant *parameters,
249 Login1Service *service = user_data;
251 if (strcmp (signal_name, "SeatNew") == 0)
253 const gchar *id, *path;
256 g_variant_get (parameters, "(&s&o)", &id, &path);
257 seat = login1_service_get_seat (service, id);
260 seat = add_seat (service, id, path);
261 g_signal_emit (service, signals[SEAT_ADDED], 0, seat);
264 else if (strcmp (signal_name, "SeatRemoved") == 0)
266 const gchar *id, *path;
269 g_variant_get (parameters, "(&s&o)", &id, &path);
270 seat = login1_service_get_seat (service, id);
273 service->priv->seats = g_list_remove (service->priv->seats, seat);
274 g_signal_emit (service, signals[SEAT_REMOVED], 0, seat);
275 g_object_unref (seat);
281 login1_service_connect (Login1Service *service)
284 GVariantIter *seat_iter;
285 const gchar *id, *path;
286 GError *error = NULL;
288 g_return_val_if_fail (service != NULL, FALSE);
290 if (service->priv->connected)
293 service->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
295 g_warning ("Failed to get system bus: %s", error->message);
296 g_clear_error (&error);
297 if (!service->priv->connection)
300 service->priv->signal_id = g_dbus_connection_signal_subscribe (service->priv->connection,
302 "org.freedesktop.login1.Manager",
304 "/org/freedesktop/login1",
306 G_DBUS_SIGNAL_FLAGS_NONE,
311 result = g_dbus_connection_call_sync (service->priv->connection,
313 "/org/freedesktop/login1",
314 "org.freedesktop.login1.Manager",
316 g_variant_new ("()"),
317 G_VARIANT_TYPE ("(a(so))"),
318 G_DBUS_CALL_FLAGS_NONE,
323 g_warning ("Failed to get list of logind seats: %s", error->message);
324 g_clear_error (&error);
328 g_variant_get (result, "(a(so))", &seat_iter);
329 while (g_variant_iter_loop (seat_iter, "(&s&o)", &id, &path))
330 add_seat (service, id, path);
331 g_variant_iter_free (seat_iter);
332 g_variant_unref (result);
334 service->priv->connected = TRUE;
340 login1_service_get_is_connected (Login1Service *service)
342 g_return_val_if_fail (service != NULL, FALSE);
343 return service->priv->connected;
347 login1_service_get_seats (Login1Service *service)
349 g_return_val_if_fail (service != NULL, NULL);
350 return service->priv->seats;
354 login1_service_get_seat (Login1Service *service, const gchar *id)
358 g_return_val_if_fail (service != NULL, NULL);
360 for (link = service->priv->seats; link; link = link->next)
362 Login1Seat *seat = link->data;
363 if (strcmp (seat->priv->id, id) == 0)
371 login1_service_init (Login1Service *service)
373 service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service, LOGIN1_SERVICE_TYPE, Login1ServicePrivate);
377 login1_service_finalize (GObject *object)
379 Login1Service *self = LOGIN1_SERVICE (object);
381 g_list_free_full (self->priv->seats, g_object_unref);
382 g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->signal_id);
383 g_object_unref (self->priv->connection);
385 G_OBJECT_CLASS (login1_service_parent_class)->finalize (object);
389 login1_service_class_init (Login1ServiceClass *klass)
391 GObjectClass *object_class = G_OBJECT_CLASS (klass);
393 object_class->finalize = login1_service_finalize;
395 g_type_class_add_private (klass, sizeof (Login1ServicePrivate));
397 signals[SEAT_ADDED] =
398 g_signal_new ("seat-added",
399 G_TYPE_FROM_CLASS (klass),
401 G_STRUCT_OFFSET (Login1ServiceClass, seat_added),
404 G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
405 signals[SEAT_REMOVED] =
406 g_signal_new ("seat-removed",
407 G_TYPE_FROM_CLASS (klass),
409 G_STRUCT_OFFSET (Login1ServiceClass, seat_removed),
412 G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
416 login1_seat_get_id (Login1Seat *seat)
418 g_return_val_if_fail (seat != NULL, NULL);
419 return seat->priv->id;
423 login1_seat_init (Login1Seat *seat)
425 seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, LOGIN1_SEAT_TYPE, Login1SeatPrivate);
429 login1_seat_finalize (GObject *object)
431 Login1Seat *self = LOGIN1_SEAT (object);
433 g_free (self->priv->id);
434 g_free (self->priv->path);
436 G_OBJECT_CLASS (login1_seat_parent_class)->finalize (object);
440 login1_seat_class_init (Login1SeatClass *klass)
442 GObjectClass *object_class = G_OBJECT_CLASS (klass);
444 object_class->finalize = login1_seat_finalize;
446 g_type_class_add_private (klass, sizeof (Login1SeatPrivate));