13
14
#include <gio/gio.h>
15
16
#include "login1.h"
18
#define LOGIN1_SERVICE_NAME "org.freedesktop.login1"
19
#define LOGIN1_OBJECT_NAME "/org/freedesktop/login1"
20
#define LOGIN1_MANAGER_INTERFACE_NAME "org.freedesktop.login1.Manager"
27
static guint service_signals[LAST_SERVICE_SIGNAL] = { 0 };
29
struct Login1ServicePrivate
31
/* Connection to bus service is running on */
32
GDBusConnection *connection;
34
/* TRUE if have connected to service */
37
/* Seats the service is reporting */
40
/* Handle to signal subscription */
45
CAN_GRAPHICAL_CHANGED,
46
ACTIVE_SESSION_CHANGED,
49
static guint seat_signals[LAST_SEAT_SIGNAL] = { 0 };
51
struct Login1SeatPrivate
53
/* Connection to bus seat is running on */
54
GDBusConnection *connection;
59
/* D-Bus path for this seat */
62
/* Handle to signal subscription */
65
/* TRUE if can run a graphical display on this seat */
66
gboolean can_graphical;
68
/* TRUE if can do session switching */
69
gboolean can_multi_session;
72
G_DEFINE_TYPE (Login1Service, login1_service, G_TYPE_OBJECT);
73
G_DEFINE_TYPE (Login1Seat, login1_seat, G_TYPE_OBJECT);
75
static Login1Service *singleton = NULL;
78
login1_service_get_instance (void)
81
singleton = g_object_new (LOGIN1_SERVICE_TYPE, NULL);
86
update_property (Login1Seat *seat, const gchar *name, GVariant *value)
88
if (strcmp (name, "CanGraphical") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
90
seat->priv->can_graphical = g_variant_get_boolean (value);
91
g_signal_emit (seat, seat_signals[CAN_GRAPHICAL_CHANGED], 0);
93
else if (strcmp (name, "ActiveSession") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE ("(so)")))
95
const gchar *login1_session_id;
96
g_variant_get (value, "(&so)", &login1_session_id, NULL);
97
g_signal_emit (seat, seat_signals[ACTIVE_SESSION_CHANGED], 0, login1_session_id);
102
seat_properties_changed_cb (GDBusConnection *connection,
103
const gchar *sender_name,
104
const gchar *object_path,
105
const gchar *interface_name,
106
const gchar *signal_name,
107
GVariant *parameters,
110
Login1Seat *seat = user_data;
112
GVariantIter *invalidated_properties;
116
g_variant_get (parameters, "(sa{sv}as)", NULL, &iter, &invalidated_properties);
117
while (g_variant_iter_loop (iter, "{&sv}", &name, &value))
118
update_property (seat, name, value);
119
g_variant_iter_free (iter);
120
while (g_variant_iter_loop (invalidated_properties, "&s", &name))
123
GError *error = NULL;
125
result = g_dbus_connection_call_sync (connection,
128
"org.freedesktop.DBus.Properties",
130
g_variant_new ("(ss)", "org.freedesktop.login1.Seat", name),
131
G_VARIANT_TYPE ("(v)"),
132
G_DBUS_CALL_FLAGS_NONE,
137
g_warning ("Error updating seat property %s: %s", name, error->message);
138
g_clear_error (&error);
141
g_variant_get (result, "(v)", &value);
142
update_property (seat, name, value);
143
g_variant_unref (value);
144
g_variant_unref (result);
147
g_variant_iter_free (invalidated_properties);
151
add_seat (Login1Service *service, const gchar *id, const gchar *path)
155
GError *error = NULL;
157
seat = g_object_new (LOGIN1_SEAT_TYPE, NULL);
158
seat->priv->connection = g_object_ref (service->priv->connection);
159
seat->priv->id = g_strdup (id);
160
seat->priv->path = g_strdup (path);
162
seat->priv->signal_id = g_dbus_connection_signal_subscribe (seat->priv->connection,
164
"org.freedesktop.DBus.Properties",
167
"org.freedesktop.login1.Seat",
168
G_DBUS_SIGNAL_FLAGS_NONE,
169
seat_properties_changed_cb,
173
/* Get properties for this seat */
174
result = g_dbus_connection_call_sync (seat->priv->connection,
177
"org.freedesktop.DBus.Properties",
179
g_variant_new ("(s)", "org.freedesktop.login1.Seat"),
180
G_VARIANT_TYPE ("(a{sv})"),
181
G_DBUS_CALL_FLAGS_NONE,
186
g_warning ("Failed to get seat properties: %s", error->message);
187
g_clear_error (&error);
190
GVariantIter *properties;
194
g_variant_get (result, "(a{sv})", &properties);
195
while (g_variant_iter_loop (properties, "{&sv}", &name, &value))
197
if (strcmp (name, "CanGraphical") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
198
seat->priv->can_graphical = g_variant_get_boolean (value);
199
else if (strcmp (name, "CanMultiSession") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
200
seat->priv->can_multi_session = g_variant_get_boolean (value);
202
g_variant_iter_free (properties);
203
g_variant_unref (result);
206
service->priv->seats = g_list_append (service->priv->seats, seat);
212
signal_cb (GDBusConnection *connection,
213
const gchar *sender_name,
214
const gchar *object_path,
215
const gchar *interface_name,
216
const gchar *signal_name,
217
GVariant *parameters,
220
Login1Service *service = user_data;
222
if (strcmp (signal_name, "SeatNew") == 0)
224
const gchar *id, *path;
227
g_variant_get (parameters, "(&s&o)", &id, &path);
228
seat = login1_service_get_seat (service, id);
231
seat = add_seat (service, id, path);
232
g_signal_emit (service, service_signals[SEAT_ADDED], 0, seat);
235
else if (strcmp (signal_name, "SeatRemoved") == 0)
237
const gchar *id, *path;
240
g_variant_get (parameters, "(&s&o)", &id, &path);
241
seat = login1_service_get_seat (service, id);
244
service->priv->seats = g_list_remove (service->priv->seats, seat);
245
g_signal_emit (service, service_signals[SEAT_REMOVED], 0, seat);
246
g_object_unref (seat);
18
login1_is_running (void)
20
return access ("/run/systemd/seats/", F_OK) >= 0;
24
login1_get_session_id (void)
252
login1_service_connect (Login1Service *service)
255
GVariantIter *seat_iter;
256
const gchar *id, *path;
29
257
GError *error = NULL;
31
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
259
g_return_val_if_fail (service != NULL, FALSE);
261
if (service->priv->connected)
264
service->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
33
266
g_warning ("Failed to get system bus: %s", error->message);
34
267
g_clear_error (&error);
37
result = g_dbus_connection_call_sync (bus,
38
"org.freedesktop.login1",
39
"/org/freedesktop/login1",
40
"org.freedesktop.login1.Manager",
42
g_variant_new ("(u)", getpid()),
43
G_VARIANT_TYPE ("(o)"),
268
if (!service->priv->connection)
271
service->priv->signal_id = g_dbus_connection_signal_subscribe (service->priv->connection,
273
LOGIN1_MANAGER_INTERFACE_NAME,
277
G_DBUS_SIGNAL_FLAGS_NONE,
279
g_object_ref (service),
282
result = g_dbus_connection_call_sync (service->priv->connection,
285
LOGIN1_MANAGER_INTERFACE_NAME,
287
g_variant_new ("()"),
288
G_VARIANT_TYPE ("(a(so))"),
44
289
G_DBUS_CALL_FLAGS_NONE,
51
g_warning ("Failed to open login1 session: %s", error->message);
294
g_warning ("Failed to get list of logind seats: %s", error->message);
52
295
g_clear_error (&error);
56
g_variant_get (result, "(o)", &session_path);
299
g_variant_get (result, "(a(so))", &seat_iter);
300
while (g_variant_iter_loop (seat_iter, "(&s&o)", &id, &path))
301
add_seat (service, id, path);
302
g_variant_iter_free (seat_iter);
57
303
g_variant_unref (result);
58
g_debug ("Got login1 session id: %s", session_path);
305
service->priv->connected = TRUE;
311
login1_service_get_is_connected (Login1Service *service)
313
g_return_val_if_fail (service != NULL, FALSE);
314
return service->priv->connected;
318
login1_service_get_seats (Login1Service *service)
320
g_return_val_if_fail (service != NULL, NULL);
321
return service->priv->seats;
325
login1_service_get_seat (Login1Service *service, const gchar *id)
329
g_return_val_if_fail (service != NULL, NULL);
331
for (link = service->priv->seats; link; link = link->next)
333
Login1Seat *seat = link->data;
334
if (strcmp (seat->priv->id, id) == 0)
64
login1_lock_session (const gchar *session_path)
342
login1_service_lock_session (Login1Service *service, const gchar *session_id)
67
344
GError *error = NULL;
69
g_return_if_fail (session_path != NULL);
71
g_debug ("Locking login1 session %s", session_path);
73
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
75
g_warning ("Failed to get system bus: %s", error->message);
76
g_clear_error (&error);
346
g_return_if_fail (service != NULL);
347
g_return_if_fail (session_id != NULL);
349
g_debug ("Locking login1 session %s", session_id);
84
result = g_dbus_connection_call_sync (bus,
85
"org.freedesktop.login1",
87
"org.freedesktop.login1.Session",
355
result = g_dbus_connection_call_sync (service->priv->connection,
358
LOGIN1_MANAGER_INTERFACE_NAME,
360
g_variant_new ("(s)", session_id),
90
361
G_VARIANT_TYPE ("()"),
91
362
G_DBUS_CALL_FLAGS_NONE,
181
436
g_variant_unref (result);
183
g_object_unref (bus);
441
login1_service_init (Login1Service *service)
443
service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service, LOGIN1_SERVICE_TYPE, Login1ServicePrivate);
447
login1_service_finalize (GObject *object)
449
Login1Service *self = LOGIN1_SERVICE (object);
451
g_list_free_full (self->priv->seats, g_object_unref);
452
g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->signal_id);
453
g_object_unref (self->priv->connection);
455
G_OBJECT_CLASS (login1_service_parent_class)->finalize (object);
459
login1_service_class_init (Login1ServiceClass *klass)
461
GObjectClass *object_class = G_OBJECT_CLASS (klass);
463
object_class->finalize = login1_service_finalize;
465
g_type_class_add_private (klass, sizeof (Login1ServicePrivate));
467
service_signals[SEAT_ADDED] =
468
g_signal_new (LOGIN1_SERVICE_SIGNAL_SEAT_ADDED,
469
G_TYPE_FROM_CLASS (klass),
471
G_STRUCT_OFFSET (Login1ServiceClass, seat_added),
474
G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
475
service_signals[SEAT_REMOVED] =
476
g_signal_new (LOGIN1_SERVICE_SIGNAL_SEAT_REMOVED,
477
G_TYPE_FROM_CLASS (klass),
479
G_STRUCT_OFFSET (Login1ServiceClass, seat_removed),
482
G_TYPE_NONE, 1, LOGIN1_SEAT_TYPE);
486
login1_seat_get_id (Login1Seat *seat)
488
g_return_val_if_fail (seat != NULL, NULL);
489
return seat->priv->id;
493
login1_seat_get_can_graphical (Login1Seat *seat)
495
g_return_val_if_fail (seat != NULL, FALSE);
496
return seat->priv->can_graphical;
500
login1_seat_get_can_multi_session (Login1Seat *seat)
502
g_return_val_if_fail (seat != NULL, FALSE);
503
return seat->priv->can_multi_session;
507
login1_seat_init (Login1Seat *seat)
509
seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, LOGIN1_SEAT_TYPE, Login1SeatPrivate);
513
login1_seat_finalize (GObject *object)
515
Login1Seat *self = LOGIN1_SEAT (object);
517
g_free (self->priv->id);
518
g_free (self->priv->path);
519
g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->signal_id);
520
g_object_unref (self->priv->connection);
522
G_OBJECT_CLASS (login1_seat_parent_class)->finalize (object);
526
login1_seat_class_init (Login1SeatClass *klass)
528
GObjectClass *object_class = G_OBJECT_CLASS (klass);
530
object_class->finalize = login1_seat_finalize;
532
g_type_class_add_private (klass, sizeof (Login1SeatPrivate));
534
seat_signals[CAN_GRAPHICAL_CHANGED] =
535
g_signal_new (LOGIN1_SEAT_SIGNAL_CAN_GRAPHICAL_CHANGED,
536
G_TYPE_FROM_CLASS (klass),
538
G_STRUCT_OFFSET (Login1SeatClass, can_graphical_changed),
543
seat_signals[ACTIVE_SESSION_CHANGED] =
544
g_signal_new (LOGIN1_SIGNAL_ACTIVE_SESION_CHANGED,
545
G_TYPE_FROM_CLASS (klass),
547
G_STRUCT_OFFSET (Login1SeatClass, active_session_changed),
550
G_TYPE_NONE, 1, G_TYPE_STRING);