feat: standalone autodetect for DM Wayland sessions
This commit is contained in:
parent
2838a5a71e
commit
2a2aa2fbcb
3 changed files with 54 additions and 12 deletions
|
|
@ -323,9 +323,11 @@ composited onto the output in a second render pass instead of being drawn
|
|||
into a host window.
|
||||
|
||||
The auto-detection fires only when none of `KICK_MODE`, `WLR_BACKENDS`,
|
||||
`WAYLAND_DISPLAY` or `DISPLAY` is set **and** kick's stdin is a real VT
|
||||
(`/dev/tty<digits>`): there must be nothing to nest into, and SSH sessions,
|
||||
terminal emulators and pipes never match the VT shape test. The chosen mode
|
||||
`WAYLAND_DISPLAY` or `DISPLAY` is set **and** either kick's stdin is a real
|
||||
VT (`/dev/tty<digits>`) or the login advertises a Wayland session
|
||||
(`XDG_SESSION_TYPE=wayland`, as every display manager/greeter sets): there
|
||||
must be nothing to nest into, and SSH sessions, terminal emulators and
|
||||
pipes match neither test, so they keep the nested default. The chosen mode
|
||||
is logged at startup as `[mode] standalone|nested (reason)`. Escape hatches,
|
||||
in precedence order:
|
||||
|
||||
|
|
|
|||
29
kick.c
29
kick.c
|
|
@ -12141,16 +12141,22 @@ static bool parse_screen_mode(const char *val) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* True when this process was started from a Linux virtual console: our
|
||||
controlling terminal is a real VT (/dev/tty<digits>) and there is no
|
||||
ambient graphical session (neither WAYLAND_DISPLAY nor DISPLAY) that
|
||||
nested mode could open its window in. SSH sessions, terminal emulators
|
||||
and pipes all fail the tty shape test (/dev/pts/N, /dev/ttyS*, not a tty),
|
||||
so they keep the nested default. */
|
||||
/* True when this process is the graphical session itself (standalone) rather
|
||||
than a client of one (nested): our controlling terminal is a real VT
|
||||
(/dev/tty<digits>) and there is no ambient graphical session (neither
|
||||
WAYLAND_DISPLAY nor DISPLAY) that nested mode could open its window in --
|
||||
or a display manager launched us as its Wayland session (XDG_SESSION_TYPE
|
||||
says so; every major DM/greeter sets it, and the VT test can never fire
|
||||
there since stdin is no virtual console). SSH sessions, terminal
|
||||
emulators and pipes all fail both tests (/dev/pts/N, /dev/ttyS*, not a
|
||||
tty; no session type), so they keep the nested default. */
|
||||
static bool started_on_console(void) {
|
||||
char name[64];
|
||||
if (getenv("WAYLAND_DISPLAY") || getenv("DISPLAY"))
|
||||
return false;
|
||||
const char *session_type = getenv("XDG_SESSION_TYPE");
|
||||
if (session_type && strcmp(session_type, "wayland") == 0)
|
||||
return true;
|
||||
if (!isatty(STDIN_FILENO))
|
||||
return false;
|
||||
if (ttyname_r(STDIN_FILENO, name, sizeof(name)) != 0)
|
||||
|
|
@ -12511,13 +12517,15 @@ int main(int argc, char *argv[]) {
|
|||
drives a native output directly (DRM, or headless for tests); the
|
||||
default nested mode blits a headless output into a host window.
|
||||
With neither variable set, launching from a Linux virtual console
|
||||
picks standalone automatically so plain `kick` works at a TTY;
|
||||
KICK_MODE=nested pins the old behaviour there. */
|
||||
or as a display manager's Wayland session picks standalone
|
||||
automatically so plain `kick` works at a TTY and in lightdm/greetd
|
||||
entries; KICK_MODE=nested pins the old behaviour there. */
|
||||
server.standalone = false;
|
||||
const char *mode_reason = "default";
|
||||
{
|
||||
const char *mode = getenv("KICK_MODE");
|
||||
const char *wlr_backends = getenv("WLR_BACKENDS");
|
||||
const char *session_type = getenv("XDG_SESSION_TYPE");
|
||||
if (mode && strcmp(mode, "standalone") == 0) {
|
||||
server.standalone = true;
|
||||
mode_reason = "KICK_MODE";
|
||||
|
|
@ -12526,7 +12534,10 @@ int main(int argc, char *argv[]) {
|
|||
mode_reason = "KICK_MODE";
|
||||
} else if (!wlr_backends || !wlr_backends[0]) {
|
||||
server.standalone = started_on_console();
|
||||
mode_reason = server.standalone ? "console" : "default";
|
||||
if (server.standalone)
|
||||
mode_reason = (session_type &&
|
||||
strcmp(session_type, "wayland") == 0) ?
|
||||
"session" : "console";
|
||||
}
|
||||
if (wlr_backends && wlr_backends[0]) {
|
||||
server.standalone = true;
|
||||
|
|
|
|||
|
|
@ -4636,6 +4636,35 @@ def test_mode_autodetect_stays_nested_without_console():
|
|||
s.close()
|
||||
|
||||
|
||||
def test_mode_autodetect_standalone_wayland_session():
|
||||
"""A display manager launching kick as its Wayland session (no KICK_MODE,
|
||||
no WLR_BACKENDS, no displays, piped stdin like lightdm provides) must
|
||||
pick standalone via XDG_SESSION_TYPE: the VT shape test can never fire
|
||||
there, and without this the session tries to nest into nothing and the
|
||||
login loops back to the greeter."""
|
||||
env = dict(os.environ)
|
||||
log = _fresh_log()
|
||||
dump_dir = _mk_dump_dir()
|
||||
proc = subprocess.Popen(
|
||||
["env", "-i",
|
||||
"PATH=" + env["PATH"],
|
||||
"HOME=" + env.get("HOME", "/"),
|
||||
"XDG_RUNTIME_DIR=" + env.get("XDG_RUNTIME_DIR", "/tmp"),
|
||||
"XDG_SESSION_TYPE=wayland",
|
||||
"KICK_LOG=1",
|
||||
"KICK_DUMP_DIR=" + dump_dir,
|
||||
"stdbuf", "-oL", BIN],
|
||||
stdin=subprocess.PIPE, stdout=open(log, "ab"), stderr=subprocess.STDOUT,
|
||||
preexec_fn=_preexec_death(os.getpid()),
|
||||
)
|
||||
s = Session(proc, log, dump_dir)
|
||||
try:
|
||||
s.wait_for(r"\[mode\] standalone \(session\)")
|
||||
assert "[mode] nested" not in s.read_log()
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
def test_x11_leader_window_never_becomes_tab():
|
||||
"""A GTK-style X11 app (unmapped leader window created first, real frame
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue