Age | Commit message (Collapse) | Author |
|
logind has no concept of session ordering. Sessions have a unique name,
some attributes about the capabilities and that's already it. There is
currently no stable+total order on sessions. If we use the logind API to
switch between sessions, we are faced with an unordered list of sessions
we have no clue of.
This used to be no problem on seats with VTs or on seats with only a
single active session. However, with the introduction of multi-session
capability for seats without VTs, we need to find a way to order sessions
in a stable way.
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).
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).
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.
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).
|
|
Fix the whole code to use "unsigned int" for vtnr. 0 is an invalid vtnr so
we don't need negative numbers at all.
Note that most code already assumes it's unsigned so in case there's a
negative vtnr, our code may, under special circumstances, silently break.
So this patch makes sure all sources of vtnrs verify the validity. Also
note that the dbus api already uses unsigned ints.
|
|
Just in order to bring things inline with the method and property
callbacks.
|
|
|
|
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.
|
|
We currently use seat_can_multi_session() to test for two things:
* whether the seat can handle session-switching
* whether the seat has VTs
As both are currently logically equivalent, we didn't care. However, we
want to allow session-switching on seats without VTs, so split this helper
into:
* seat_can_multi_session(): whether session-switching is supported
* seat_has_vts(): whether the seat has VTs
Note that only one seat on a system can have VTs. There is only one set of
them. We automatically assign them to seat0 as usual.
With this patch in place, we can easily add new session-switching/tracking
methods without breaking any VT code as it is now protected by has_vts(),
no longer by can_multi_session().
|
|
The seat->vtconsole member always points to the default seat seat0. Even
if VTs are disabled, it's used as default seat. Therefore, rename it to
seat0 to correctly state what it is.
This also changes the seat files in /run from IS_VTCONSOLE to IS_SEAT0. It
wasn't used by any code, yet, so this seems fine.
While we are at it, we also remove every "if (s->vtconsole)" as this
pointer is always valid!
|
|
Session compositors need access to fbdev, DRM and evdev devices if they
control a session. To make logind pass them to sessions, we need to
listen for them actively.
However, we avoid creating new seats for non master-of-seat devices. Only
once a seat is created, we start remembering all other session devices. If
the last master-device is removed (even if there are other non-master
devices still available), we destroy the seat. This is the current
behavior, but we need to explicitly implement it now as there may be
non-master devices in the seat->devices list.
Unlike master devices, we don't care whether our list of non-master
devices is complete. We don't export this list but use it only as cache if
sessions request these devices. Hence, if a session requests a device that
is not in the list, we will simply look it up. However, once a session
requested a device, we must be notified of "remove" udev events. So we
must link the devices somehow into the device-list.
Regarding the implementation, we now sort the device list by the "master"
flag. This guarantees that master devices are at the front and non-master
devices at the tail of the list. Thus, we can easily test whether a seat
has a master device attached.
|
|
#pragma once has been "un-deprecated" in gcc since 3.3, and is widely supported
in other compilers.
I've been using and maintaining (rebasing) this patch for a while now, as
it annoyed me to see #ifndef fooblahfoo, etc all over the place,
almost arrogant about the annoyance of having to define all these names to
perform a commen but neccicary functionality, when a completely superior
alternative exists.
I havn't sent it till now, cause its kindof a style change, and it is bad
voodoo to mess with style that has been established by more established
editors. So feel free to lambast me as a crazy bafoon.
v2 - preserve externally used headers
|
|
Since we boot so fast now that gdm might get started before the
graphics drivers are properly loaded and probed we might end up
announcing seat0 to gdm before it has graphics capabilities. Which will
cause gdm/X11 cause to fail later on.
To fix this race, let's expose CanGraphical and CanTTY fields on all
seats, which clarify whether a seat is suitable for gdm resp, suitable
for text logins. gdm then needs to watch CanGraphical and spawn X11 on
it only if it is true.
This way:
USB graphics seats will expose CanGraphical=yes, CanTTY=no
Machines with no graphics drivers at all, but a text console:
CanGraphical=no, CanTTY=yes
Machines with CONFIG_VT turned off: CanGraphical=yes, CanTTY=no
And the most important case: seat0 where the graphics driver has not
been probed yet boot up with CanGraphical=no, CanTTY=yes first, which
then changes to CanGraphical=yes as soon as the probing is complete.
|
|
We finally got the OK from all contributors with non-trivial commits to
relicense systemd from GPL2+ to LGPL2.1+.
Some udev bits continue to be GPL2+ for now, but we are looking into
relicensing them too, to allow free copy/paste of all code within
systemd.
The bits that used to be MIT continue to be MIT.
The big benefit of the relicensing is that closed source code may now
link against libsystemd-login.so and friends.
|
|
don't pretend we could do VT switching
|
|
|