[systemd-devel] [RFC] logind: introduce session "positions"

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Sun Dec 1 07:13:47 PST 2013


On Sun, Dec 01, 2013 at 12:43:35PM +0100, David Herrmann wrote:
> This patch introduces session "positions". A position is a simple integer
> assigned to a session which is never changed implicitly (currently, we
> also don't change it explicitly, but that may be changed someday). For
> seats with VTs, we force the position to be the same as the VTnr. Without
> VTs, we simply find the lowest unassigned number and use it as position.
> If position-assignment fails or if, for any reason, we decide to not
> assign a position to a session, the position is set to 0 (which is treated
> as invalid position).
I like the idea. Stable ordering is good when switching back and forth.

> During session_load() or if two sessions have the same VTnr, we may end up
> with two sessions with the same position (this shouldn't happen, but lets
> be fail-safe in case some other part of the stack fails). This case is
> dealt with gracefully by ignoring any session but the first session
> assigned to the position. Thus, session->pos is a hint, seat->positions[i]
> is the definite position-assignment. Always verify both match in case you
> need to modify them!
> 
> Additionally, we introduce SwitchTo(unsigned int) on the seat-dbus-API.
> You can call it with any integer value != 0 and logind will try to switch
> to the request position. If you implement a compositor or any other
> session-controller, you simply watch for ctrl+alt+F1 to F12 and call
> SwitchTo(Fx). logind will figure a way out deal with this number.
> For convenience, we also introduce SwitchToNext/Previous(). It should be
> called on ctrl+alt+Left/Right (like the kernel-console used to support).
Is this necessary? If positions are known, then the compositor can ask
which session is at this position and ask for the switch to the session.
The advantage is that if there's no session at this position, the compositor
can display an error immedatiely.

> Note that the public API (SwitchTo*()) is *not* bound to the underlying
> logic that is implemented now. We don't export "session-positions" on the
> dbus/C API! They are an implementation detail. Instead, the SwitchTo*()
> API is supposed to be a hint to let logind choose the session-switching
> logic. Any foreground session-controller is free to enumerate/order
> existing sessions according to their needs and call Session.Activate()
> manually. But the SwitchTo*() API provides a uniform behavior across
> session-controllers.
Hm, this add a lot of complexity. But below you argue that a different
behaviour (with F1, F2 being special) might be implemented soon. And
then one compositor would be using F3 to switch to the third session,
and another to switch to the first user session, so there'd be no consistency
anyway. Maybe it's better to just let compositors handle this?

> Background: Session-switching keys depend on the active keymap. The XKB
> specification provides the XKB_KEY_XF86Switch_VT_1-12 key-symbols which
> have to be mapped by all keymaps to allow session-switching. It is usually
> bound to ctrl+alt+Fx but may be set differently. A compositor passes any
> keyboard input to XKB before passing it to clients. In case a key-press
> invokes the XKB_KEY_XF86Switch_VT_x action, the keypress is *not*
> forwarded to clients, but instead a session-switch is scheduled.
> 
> This actually prevents us from handling these keys outside of the session.
> If an active compositor has a keymap with a different mapping of these
> keys, and logind itself tries to catch these combinations, we end up with
> the key-press sent to the compositor's clients *and* handled by logind.
> This is *bad* and we must avoid this. The only situation where a
> background process is allowed to handle key-presses is debugging and
> emergency-keys. In these cases, we don't care for keymap mismatches and
> accept the double-event. Another exception is unmapped keys like
> PowerOff/Suspend (even though this one is controversial).
> 
> Future ideas: As this commit-msg isn't long enough, yet, some notes on
> future ideas. The current position-assignment is compatible with the
> legacy VT numbers. However, it is a rather outdated way of addressing
> sessions. Instead, we can make use of session-classes of logind. We
> already tag session with one of the classes "greeter", "user",
> "background", "lock-screen". So one of my ideas is to make
> "position-assignment" a "per-class" thing. And instead of mapping F1-F12
> directly to the positions, we map it as follows:
>  - F1: Activate the last-spawned session in the "greeter" class. Usually,
>        only a single greeter should be active, but in case
>        systemd-welcomed runs and gdm is spawned later, this will switch to
>        gdm (actually gdm.service should stop systemd-welcomed.service but
>        lets be overly pedantic here).
>  - F2: Activate the session from the "user" class which has been active
>        last. So if you switch to F1 and back to F2, you're guaranteed to
>        get back to your last active user-session.
>  - F3-F11: Direct mapping to "user" sessions. So F3 maps to the
>            user-session with position 3, F11 to position 11 (or apply a
>            "-2" offset, so F3=>1 and F11=>9..)
>  - F12: Switch to the last-spawned session in the "emergency" class. This
>         doesn't exist, yet, but we could start sessions showing the
>         kernel-log or an emergency-console here.
> 
> Inside of each group, you can use SwitchToNext/Previous() to switch to the
> next/previous session. As only the "user" group has a way of directly
> addressing sessions, this is needed for the "greeter" and "emergency"
> groups. Note that both groups are expected to only have one session, so
> this is really just a fallback for odd cases. However, for the "user"
> group the Next/Previous can come in quite handy.
> 
> Comments?

> @@ -231,6 +232,9 @@ int session_save(Session *s) {
>          if (s->seat && seat_has_vts(s->seat))
>                  fprintf(f, "VTNR=%u\n", s->vtnr);
>  
> +        if (!s->vtnr)
> +                fprintf(f, "POS=%u\n", s->pos);
> +
Is there any reason not to use "POSITION="?

Zbyszek


More information about the systemd-devel mailing list