2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2012-07-18 19:07:51 +02:00
|
|
|
#pragma once
|
2011-05-24 00:19:22 +02:00
|
|
|
|
|
|
|
typedef struct Seat Seat;
|
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
#include "logind-session.h"
|
|
|
|
|
|
|
|
struct Seat {
|
|
|
|
Manager *manager;
|
|
|
|
char *id;
|
|
|
|
|
|
|
|
char *state_file;
|
|
|
|
|
|
|
|
LIST_HEAD(Device, devices);
|
|
|
|
|
|
|
|
Session *active;
|
2013-09-17 23:40:19 +02:00
|
|
|
Session *pending_switch;
|
2011-05-24 00:19:22 +02:00
|
|
|
LIST_HEAD(Session, sessions);
|
2011-05-25 00:55:58 +02:00
|
|
|
|
logind: introduce session "positions"
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).
2013-11-30 11:39:48 +01:00
|
|
|
Session **positions;
|
|
|
|
size_t position_count;
|
|
|
|
|
2011-05-25 00:55:58 +02:00
|
|
|
bool in_gc_queue:1;
|
2011-05-26 02:21:16 +02:00
|
|
|
bool started:1;
|
2011-05-25 00:55:58 +02:00
|
|
|
|
|
|
|
LIST_FIELDS(Seat, gc_queue);
|
2011-05-24 00:19:22 +02:00
|
|
|
};
|
|
|
|
|
2018-08-03 18:53:09 +02:00
|
|
|
int seat_new(Seat **ret, Manager *m, const char *id);
|
|
|
|
Seat* seat_free(Seat *s);
|
|
|
|
|
|
|
|
DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free);
|
2011-05-25 00:55:58 +02:00
|
|
|
|
2011-05-24 00:19:22 +02:00
|
|
|
int seat_save(Seat *s);
|
|
|
|
int seat_load(Seat *s);
|
|
|
|
|
2011-05-25 00:55:58 +02:00
|
|
|
int seat_apply_acls(Seat *s, Session *old_active);
|
2011-06-21 21:46:13 +02:00
|
|
|
int seat_set_active(Seat *s, Session *session);
|
2018-10-19 20:00:46 +02:00
|
|
|
int seat_switch_to(Seat *s, unsigned num);
|
logind: introduce session "positions"
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).
2013-11-30 11:39:48 +01:00
|
|
|
int seat_switch_to_next(Seat *s);
|
|
|
|
int seat_switch_to_previous(Seat *s);
|
2018-10-19 20:00:46 +02:00
|
|
|
int seat_active_vt_changed(Seat *s, unsigned vtnr);
|
2011-05-25 00:55:58 +02:00
|
|
|
int seat_read_active_vt(Seat *s);
|
2011-06-28 03:21:14 +02:00
|
|
|
int seat_preallocate_vts(Seat *s);
|
2011-05-25 00:55:58 +02:00
|
|
|
|
2011-06-17 15:59:18 +02:00
|
|
|
int seat_attach_session(Seat *s, Session *session);
|
2013-09-17 23:40:19 +02:00
|
|
|
void seat_complete_switch(Seat *s);
|
logind: introduce session "positions"
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).
2013-11-30 11:39:48 +01:00
|
|
|
void seat_evict_position(Seat *s, Session *session);
|
2018-10-19 20:00:46 +02:00
|
|
|
void seat_claim_position(Seat *s, Session *session, unsigned pos);
|
2011-06-17 15:59:18 +02:00
|
|
|
|
2013-09-17 17:40:02 +02:00
|
|
|
bool seat_has_vts(Seat *s);
|
2013-09-17 17:39:59 +02:00
|
|
|
bool seat_is_seat0(Seat *s);
|
2012-01-03 21:47:54 +01:00
|
|
|
bool seat_can_multi_session(Seat *s);
|
2012-06-21 13:48:01 +02:00
|
|
|
bool seat_can_tty(Seat *s);
|
logind: listen actively for session devices
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.
2013-09-17 17:39:54 +02:00
|
|
|
bool seat_has_master_device(Seat *s);
|
2012-06-21 13:48:01 +02:00
|
|
|
bool seat_can_graphical(Seat *s);
|
|
|
|
|
2011-06-17 15:59:18 +02:00
|
|
|
int seat_get_idle_hint(Seat *s, dual_timestamp *t);
|
|
|
|
|
2011-05-25 00:55:58 +02:00
|
|
|
int seat_start(Seat *s);
|
2014-02-09 02:29:56 +01:00
|
|
|
int seat_stop(Seat *s, bool force);
|
|
|
|
int seat_stop_sessions(Seat *s, bool force);
|
2011-05-25 00:55:58 +02:00
|
|
|
|
2018-02-15 13:14:35 +01:00
|
|
|
bool seat_may_gc(Seat *s, bool drop_not_started);
|
2011-05-25 00:55:58 +02:00
|
|
|
void seat_add_to_gc_queue(Seat *s);
|
|
|
|
|
2011-05-26 02:21:16 +02:00
|
|
|
bool seat_name_is_valid(const char *name);
|
|
|
|
|
logind: make "self" and "auto" magic strings when operating on seats + sessions
Most of the operations one can do on sessions so far accepted an empty
session name as a shortcut for the caller's session. This is quite
useful traditionally, but much less useful than it used to be, since
most user code now (rightfully) runs in --user context, not in a
session.
With this change we tweak the logic a bit: we introduce the two special
session and seat names "self" and "auto". The former refers to the
session/seat the client is in, and is hence mostly equivalent to te
empty string "" as before. However, the latter refers to the
session/seat the client is in if that exists, with a fallback of the
user's display session if not. Clients can hence reference "auto"
instead of the empty string if they really don't want to think much
about sessions.
Why "self" btw? Previously, we'd already expose a special dbus object
with the path /org/freedesktop/login1/session/self (and similar for the
seat), matching what the empty string did for bus calls that took a
session name. With this scheme we reuse this identifier and introduce
"auto" in a similar way.
Of course this means real-life seats and sessions can never be named
"self" or "auto", but they aren't anyway: valid seat names have to start
with "seat" anyway, and sessions are generated server-side as either a
numeric value or "c" suffixed with a counter ID.
Fixes: #12399
2019-04-28 17:55:36 +02:00
|
|
|
static inline bool SEAT_IS_SELF(const char *name) {
|
|
|
|
return isempty(name) || streq(name, "self");
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool SEAT_IS_AUTO(const char *name) {
|
|
|
|
return streq_ptr(name, "auto");
|
|
|
|
}
|