diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-09-17 23:40:19 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-09-17 17:15:30 -0500 |
commit | d7bd01b547bd91353513131561de9cc7d9f7d405 (patch) | |
tree | cf914215fd4aae73761cc77149bfa227cc596d5d /src/login/logind-session.c | |
parent | 118ecf32425a590ea266b5c2b6de7962bb242356 (diff) |
logind: implement generic multi-session
This enables the multi-session capability for seats that don't have VTs.
For legacy seats with VTs, everything stays the same. However, all other
seats now also get the multi-session capability.
The only feature that was missing was session-switching. As logind can
force a session-switch and signal that via the "Active" property, we only
need a way to allow synchronized/delayed session switches. Compositors
need to cleanup some devices before acknowledging the session switch.
Therefore, we use the session-devices to give compositors a chance to
block a session-switch until they cleaned everything up.
If you activate a session on a seat without VTs, we send a PauseDevice
signal to the active session for every active device. Only once the
session acknowledged all these with a PauseDeviceComplete() call, we
perform the final session switch.
One important note is that delayed session-switching is meant for
backwards compatibility. New compositors or other sessions should really
try to deal correctly with forced session switches! They only need to
handle EACCES/EPERM from syscalls and treat them as "PauseDevice" signal.
Following logind patches will add a timeout to session-switches which
forces the switch if the active session does not react in a timely
fashion. Moreover, explicit ForceActivate() calls might also be supported.
Hence, sessions must not crash if their devices get paused.
Diffstat (limited to 'src/login/logind-session.c')
-rw-r--r-- | src/login/logind-session.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/src/login/logind-session.c b/src/login/logind-session.c index fcc1901ed6..eea0bfb85b 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -100,6 +100,8 @@ void session_free(Session *s) { if (s->seat) { if (s->seat->active == s) s->seat->active = NULL; + if (s->seat->pending_switch == s) + s->seat->pending_switch = NULL; LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s); } @@ -375,21 +377,40 @@ int session_load(Session *s) { } int session_activate(Session *s) { + unsigned int num_pending; + assert(s); assert(s->user); - if (s->vtnr <= 0) - return -ENOTSUP; - if (!s->seat) return -ENOTSUP; if (s->seat->active == s) return 0; - assert(seat_has_vts(s->seat)); + /* on seats with VTs, we let VTs manage session-switching */ + if (seat_has_vts(s->seat)) { + if (s->vtnr <= 0) + return -ENOTSUP; + + return chvt(s->vtnr); + } - return chvt(s->vtnr); + /* On seats without VTs, we implement session-switching in logind. We + * try to pause all session-devices and wait until the session + * controller acknowledged them. Once all devices are asleep, we simply + * switch the active session and be done. + * We save the session we want to switch to in seat->pending_switch and + * seat_complete_switch() will perform the final switch. */ + + s->seat->pending_switch = s; + + /* if no devices are running, immediately perform the session switch */ + num_pending = session_device_try_pause_all(s); + if (!num_pending) + seat_complete_switch(s->seat); + + return 0; } static int session_link_x11_socket(Session *s) { |