b4f893eb294883909759fc9fd825eade1a9f308c diff --git a/src/Makefile.am b/src/Makefile.am index cbe8a09..6ab05c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -205,5 +205,7 @@ MAINTAINERCLEANFILES = \ install-data-local: -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-session.d -mkdir -p $(DESTDIR)$(prefix)/lib/ConsoleKit/run-session.d + -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-seat.d + -mkdir -p $(DESTDIR)$(prefix)/lib/ConsoleKit/run-seat.d -mkdir -p $(DESTDIR)$(localstatedir)/run/ConsoleKit -mkdir -p $(DESTDIR)$(localstatedir)/log/ConsoleKit diff --git a/src/ck-manager.c b/src/ck-manager.c index 440163b..4b7200b 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -1228,29 +1228,50 @@ ck_manager_can_stop (CkManager *manager, } static void -on_seat_active_session_changed (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_active_session_changed_full (CkSeat *seat, + CkSession *old_session, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + if (session != NULL) { + ck_session_get_id (session, &ssid, NULL); + } + ck_manager_dump (manager); + ck_seat_run_programs (seat, old_session, session, "seat_active_session_changed"); + log_seat_active_session_changed_event (manager, seat, ssid); } static void -on_seat_session_added (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_session_added_full (CkSeat *seat, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + ck_session_get_id (session, &ssid, NULL); + ck_manager_dump (manager); + ck_session_run_programs (session, "session_added"); + log_seat_session_added_event (manager, seat, ssid); } static void -on_seat_session_removed (CkSeat *seat, - const char *ssid, - CkManager *manager) +on_seat_session_removed_full (CkSeat *seat, + CkSession *session, + CkManager *manager) { + char *ssid = NULL; + + ck_session_get_id (session, &ssid, NULL); + ck_manager_dump (manager); + ck_session_run_programs (session, "session_removed"); + log_seat_session_removed_event (manager, seat, ssid); } @@ -1276,9 +1297,9 @@ static void connect_seat_signals (CkManager *manager, CkSeat *seat) { - g_signal_connect (seat, "active-session-changed", G_CALLBACK (on_seat_active_session_changed), manager); - g_signal_connect (seat, "session-added", G_CALLBACK (on_seat_session_added), manager); - g_signal_connect (seat, "session-removed", G_CALLBACK (on_seat_session_removed), manager); + g_signal_connect (seat, "active-session-changed-full", G_CALLBACK (on_seat_active_session_changed_full), manager); + g_signal_connect (seat, "session-added-full", G_CALLBACK (on_seat_session_added_full), manager); + g_signal_connect (seat, "session-removed-full", G_CALLBACK (on_seat_session_removed_full), manager); g_signal_connect (seat, "device-added", G_CALLBACK (on_seat_device_added), manager); g_signal_connect (seat, "device-removed", G_CALLBACK (on_seat_device_removed), manager); } @@ -1287,9 +1308,9 @@ static void disconnect_seat_signals (CkManager *manager, CkSeat *seat) { - g_signal_handlers_disconnect_by_func (seat, on_seat_active_session_changed, manager); - g_signal_handlers_disconnect_by_func (seat, on_seat_session_added, manager); - g_signal_handlers_disconnect_by_func (seat, on_seat_session_removed, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_active_session_changed_full, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_session_added_full, manager); + g_signal_handlers_disconnect_by_func (seat, on_seat_session_removed_full, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_device_added, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_device_removed, manager); } @@ -1325,7 +1346,9 @@ add_new_seat (CkManager *manager, g_debug ("Added seat: %s kind:%d", sid, kind); ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_added"); + g_debug ("Emitting seat-added: %s", sid); g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); log_seat_added_event (manager, seat); @@ -1366,6 +1389,7 @@ remove_seat (CkManager *manager, } ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_removed"); g_debug ("Emitting seat-removed: %s", sid); g_signal_emit (manager, signals [SEAT_REMOVED], 0, sid); @@ -2429,7 +2453,9 @@ add_seat_for_file (CkManager *manager, g_debug ("Added seat: %s", sid); ck_manager_dump (manager); + ck_seat_run_programs (seat, NULL, NULL, "seat_added"); + g_debug ("Emitting seat-added: %s", sid); g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); log_seat_added_event (manager, seat); diff --git a/src/ck-marshal.list b/src/ck-marshal.list index f9eed10..7f60efc 100644 --- a/src/ck-marshal.list +++ b/src/ck-marshal.list @@ -1,2 +1,3 @@ VOID:UINT,STRING BOOLEAN:POINTER +VOID:OBJECT,OBJECT 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) diff --git a/src/ck-seat.h b/src/ck-seat.h index 47d10a7..fb9a955 100644 --- a/src/ck-seat.h +++ b/src/ck-seat.h @@ -93,6 +93,11 @@ CkSeat * ck_seat_new_with_devices (const char *sid, gboolean ck_seat_register (CkSeat *seat); +void ck_seat_run_programs (CkSeat *seat, + CkSession *old_session, + CkSession *new_session, + const char *action); + void ck_seat_dump (CkSeat *seat, GKeyFile *key_file);