diff options
Diffstat (limited to 'src/ck-seat.c')
-rw-r--r-- | src/ck-seat.c | 161 |
1 files changed, 151 insertions, 10 deletions
diff --git a/src/ck-seat.c b/src/ck-seat.c index 27ccf14..4f5e63f 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); @@ -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, @@ -1134,6 +1184,97 @@ ck_seat_new_from_file (const char *sid, } 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); + g_free (s); + } + + 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) |