diff options
Diffstat (limited to 'src/ck-seat.c')
-rw-r--r-- | src/ck-seat.c | 196 |
1 files changed, 163 insertions, 33 deletions
diff --git a/src/ck-seat.c b/src/ck-seat.c index c2f70da..fedd900 100644 --- a/src/ck-seat.c +++ b/src/ck-seat.c @@ -67,8 +67,11 @@ struct CkSeatPrivate enum { ACTIVE_SESSION_CHANGED, - SESSION_ADDED, + ACTIVE_SESSION_CHANGED_FULL, + SESSION_ADDED, /* Carries the session as path for D-Bus */ + SESSION_ADDED_FULL, /* Carries the session as CkSession for other uses */ SESSION_REMOVED, + SESSION_REMOVED_FULL, DEVICE_ADDED, DEVICE_REMOVED, LAST_SIGNAL @@ -480,15 +483,17 @@ static void change_active_session (CkSeat *seat, CkSession *session) { - char *ssid; + char *ssid; + CkSession *old_session; if (seat->priv->active_session == session) { return; } - if (seat->priv->active_session != NULL) { - ck_session_set_active (seat->priv->active_session, FALSE, NULL); - g_object_unref (seat->priv->active_session); + old_session = seat->priv->active_session; + + if (old_session != NULL) { + ck_session_set_active (old_session, FALSE, NULL); } seat->priv->active_session = session; @@ -502,8 +507,21 @@ change_active_session (CkSeat *seat, g_debug ("Active session changed: %s", ssid ? ssid : "(null)"); + /* The order of signal emission matters here. The manager + * dumps the database when receiving the + * 'active-session-changed-full' signal and does callout + * handling. dbus-glib will then send out a D-Bus on the + * 'active-session-changed' signal. Since the D-Bus signal + * must be sent when the database dump is finished it is + * important that the '-full' signalled is emitted first. */ + + g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED_FULL], 0, old_session, session); g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED], 0, ssid); + if (old_session != NULL) { + g_object_unref (old_session); + } + g_free (ssid); } @@ -586,9 +604,13 @@ ck_seat_remove_session (CkSeat *seat, * unref until the signal is emitted */ g_hash_table_steal (seat->priv->sessions, ssid); - ck_session_run_programs (session, "session_removed"); - g_debug ("Emitting session-removed: %s", ssid); + + /* The order of signal emission matters here, too, for similar + * reasons as for 'session-added'/'session-added-full'. See + * above. */ + + g_signal_emit (seat, signals [SESSION_REMOVED_FULL], 0, session); g_signal_emit (seat, signals [SESSION_REMOVED], 0, ssid); /* try to change the active session */ @@ -624,10 +646,12 @@ ck_seat_add_session (CkSeat *seat, g_signal_connect_object (session, "activate", G_CALLBACK (session_activate), seat, 0); /* FIXME: attach to property notify signals? */ - ck_session_run_programs (session, "session_added"); - g_debug ("Emitting added signal: %s", ssid); + /* The order of signal emission matters here, too. See + * above. */ + + g_signal_emit (seat, signals [SESSION_ADDED_FULL], 0, session); g_signal_emit (seat, signals [SESSION_ADDED], 0, ssid); maybe_update_active_session (seat); @@ -741,8 +765,8 @@ active_vt_changed (CkVtMonitor *vt_monitor, update_active_vt (seat, num); } -static gboolean -register_seat (CkSeat *seat) +gboolean +ck_seat_register (CkSeat *seat) { GError *error = NULL; @@ -920,6 +944,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + signals [ACTIVE_SESSION_CHANGED_FULL] = g_signal_new ("active-session-changed-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + ck_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, + 2, CK_TYPE_SESSION, CK_TYPE_SESSION); signals [SESSION_ADDED] = g_signal_new ("session-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -929,6 +962,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH); + signals [SESSION_ADDED_FULL] = g_signal_new ("session-added-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CK_TYPE_SESSION); signals [SESSION_REMOVED] = g_signal_new ("session-removed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -938,7 +980,15 @@ ck_seat_class_init (CkSeatClass *klass) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_OBJECT_PATH); - + signals [SESSION_REMOVED_FULL] = g_signal_new ("session-removed-full", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CK_TYPE_SESSION); signals [DEVICE_ADDED] = g_signal_new ("device-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, @@ -1023,19 +1073,12 @@ ck_seat_new (const char *sid, CkSeatKind kind) { GObject *object; - gboolean res; object = g_object_new (CK_TYPE_SEAT, "id", sid, "kind", kind, NULL); - res = register_seat (CK_SEAT (object)); - if (! res) { - g_object_unref (object); - return NULL; - } - return CK_SEAT (object); } @@ -1045,7 +1088,6 @@ ck_seat_new_with_devices (const char *sid, GPtrArray *devices) { GObject *object; - gboolean res; int i; object = g_object_new (CK_TYPE_SEAT, @@ -1059,12 +1101,6 @@ ck_seat_new_with_devices (const char *sid, } } - res = register_seat (CK_SEAT (object)); - if (! res) { - g_object_unref (object); - return NULL; - } - return CK_SEAT (object); } @@ -1083,6 +1119,8 @@ ck_seat_new_from_file (const char *sid, gsize ndevices; gsize i; + seat = NULL; + key_file = g_key_file_new (); error = NULL; res = g_key_file_load_from_file (key_file, @@ -1092,24 +1130,24 @@ ck_seat_new_from_file (const char *sid, if (! res) { g_warning ("Unable to load seats from file %s: %s", path, error->message); g_error_free (error); - return NULL; + goto out; } group = g_key_file_get_start_group (key_file); if (group == NULL || strcmp (group, "Seat Entry") != 0) { g_warning ("Not a seat file: %s", path); - return NULL; + goto out; } hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL); if (hidden) { g_debug ("Seat is hidden"); - return NULL; + goto out; } device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL); - g_debug ("Creating seat %s with %d devices", sid, ndevices); + g_debug ("Creating seat %s with %zd devices", sid, ndevices); devices = g_ptr_array_sized_new (ndevices); @@ -1137,17 +1175,110 @@ ck_seat_new_from_file (const char *sid, g_strfreev (split); } - + g_strfreev (device_list); g_free (group); seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices); - g_ptr_array_free (devices, TRUE); +out: + + g_key_file_free (key_file); + return seat; } static void +env_add_session_info (CkSession *session, + const char *prefix, + char **extra_env, + int *n) +{ + char *s; + gboolean b; + guint u; + + if (session == NULL) { + return; + } + + if (ck_session_get_id (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sID=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_session_type (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sTYPE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_unix_user (session, &u, NULL)) { + extra_env[(*n)++] = g_strdup_printf ("%sUSER_UID=%u", prefix, u); + } + + if (ck_session_get_display_device (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sDISPLAY_DEVICE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_x11_display_device (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY_DEVICE=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_x11_display (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY=%s", prefix, s); + g_free (s); + } + + if (ck_session_get_remote_host_name (session, &s, NULL) && s != NULL && *s != '\0') { + extra_env[(*n)++] = g_strdup_printf ("%sREMOTE_HOST_NAME=%s", prefix, s); + g_free (s); + } + + if (ck_session_is_local (session, &b, NULL)) + extra_env[(*n)++] = g_strdup_printf ("%sIS_LOCAL=%s", prefix, b ? "true" : "false"); +} + +void +ck_seat_run_programs (CkSeat *seat, + CkSession *old_session, + CkSession *new_session, + const char *action) +{ + int n; + char *extra_env[18]; /* be sure to adjust this as needed when + * you add more variables to the callout's + * environment */ + + n = 0; + + extra_env[n++] = g_strdup_printf ("CK_SEAT_ID=%s", seat->priv->id); + + /* Callout scripts/binaries should check if CK_SEAT_SESSION_ID + * resp. CK_SEAT_OLD_SESSON_ID is set to figure out if there + * will be an active session after the switch, or if there was + * one before. At least one of those environment variables + * will be set, possibly both. Only after checking these + * variables the script should check for the other session + * property variables. */ + + env_add_session_info (old_session, "CK_SEAT_OLD_SESSION_", extra_env, &n); + env_add_session_info (new_session, "CK_SEAT_SESSION_", extra_env, &n); + + extra_env[n++] = NULL; + + g_assert(n <= G_N_ELEMENTS(extra_env)); + + ck_run_programs (SYSCONFDIR "/ConsoleKit/run-seat.d", action, extra_env); + ck_run_programs (PREFIX "/lib/ConsoleKit/run-seat.d", action, extra_env); + + for (n = 0; extra_env[n] != NULL; n++) { + g_free (extra_env[n]); + } +} + +static void dump_seat_session_iter (char *id, CkSession *session, GString *str) @@ -1232,4 +1363,3 @@ ck_seat_dump (CkSeat *seat, g_free (group_name); } - |