config: add vt_default_sessions option for per-VT default session

Add a vt_default_sessions config option that maps TTY numbers to session
names using a comma-separated list of vt:name or vt:type:name entries.
VT defaults take priority over the per-user save file so each TTY
reliably starts on the intended session regardless of prior login state.
Autologin is unaffected.

Refactor findSessionByName to delegate to a new findSessionByNameAndType
helper that accepts an optional DisplayServer filter, keeping existing
call sites unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jackson Delahunt 2026-03-29 14:56:19 +11:00
parent 142476041d
commit 09dcefde3b
3 changed files with 59 additions and 0 deletions

View File

@ -360,6 +360,18 @@ vi_default_mode = normal
# Enable vi keybindings
vi_mode = false
# Per-VT default session override
# Maps virtual terminal numbers to session names, separated by commas.
# Each entry is vt_number:session_name or vt_number:type:session_name
# where type is one of: wayland, x11, custom, shell, xinitrc
# Session names match the filename (without .desktop), the Name field, or DesktopNames.
# Specifying a type is recommended when multiple sessions share the same name across types
# (e.g. 1:x11:ubuntu to select the X11 Ubuntu session specifically).
# Without a type, the first matching session in list order (wayland, then x11, then custom) is used.
# VT defaults take priority over the per-user save file.
# If null, no VT-specific defaults are applied.
vt_default_sessions = null
# Wayland desktop environments
# You can specify multiple directories,
# e.g. $PREFIX_DIRECTORY/share/wayland-sessions:$PREFIX_DIRECTORY/local/share/wayland-sessions

View File

@ -92,6 +92,7 @@ start_cmd: ?[]const u8 = null,
text_in_center: bool = false,
vi_default_mode: ViMode = .normal,
vi_mode: bool = false,
vt_default_sessions: ?[]const u8 = null,
waylandsessions: []const u8 = build_options.prefix_directory ++ "/share/wayland-sessions",
x_cmd: []const u8 = build_options.prefix_directory ++ "/bin/X",
x_vt: ?u8 = null,

View File

@ -1058,6 +1058,45 @@ pub fn main() !void {
}
}
// Apply VT-specific default session if configured.
// Format: vt_default_sessions = 1:wayland:ubuntu,3:custom:desktop-environment
// The type field (wayland/x11/custom/shell/xinitrc) is optional:
// vt:type:name match session by type and name
// vt:name match first session with that name regardless of type
// VT defaults take priority over the per-user save file so each VT
// reliably starts on the intended session.
if (!state.is_autologin) {
if (state.config.vt_default_sessions) |vt_sessions_str| {
var vt_iter = std.mem.splitScalar(u8, vt_sessions_str, ',');
while (vt_iter.next()) |entry| {
const trimmed = std.mem.trim(u8, entry, " \t");
var parts = std.mem.splitScalar(u8, trimmed, ':');
const vt_str = parts.next() orelse continue;
const second = parts.next() orelse continue;
const vt_num = std.fmt.parseInt(u8, std.mem.trim(u8, vt_str, " \t"), 10) catch continue;
if (vt_num != state.active_tty) continue;
// Determine if second field is a type qualifier or the session name
const maybe_type_str = std.mem.trim(u8, second, " \t");
const maybe_name = parts.next();
const ds: ?DisplayServer = if (maybe_name != null) ds_parse: {
if (std.ascii.eqlIgnoreCase(maybe_type_str, "wayland")) break :ds_parse .wayland;
if (std.ascii.eqlIgnoreCase(maybe_type_str, "x11")) break :ds_parse .x11;
if (std.ascii.eqlIgnoreCase(maybe_type_str, "custom")) break :ds_parse .custom;
if (std.ascii.eqlIgnoreCase(maybe_type_str, "shell")) break :ds_parse .shell;
if (std.ascii.eqlIgnoreCase(maybe_type_str, "xinitrc")) break :ds_parse .xinitrc;
break :ds_parse null;
} else null;
const session_name = if (maybe_name) |n| std.mem.trim(u8, n, " \t") else maybe_type_str;
if (findSessionByNameAndType(&state.session, session_name, ds)) |idx| {
state.session.label.current = idx;
}
break;
}
}
}
const info_line_widget = state.info_line.widget();
const session_widget = state.session.widget();
const login_widget = state.login.widget();
@ -2093,7 +2132,14 @@ fn isValidUsername(username: []const u8, usernames: StringList) bool {
}
fn findSessionByName(session: *Session, name: []const u8) ?usize {
return findSessionByNameAndType(session, name, null);
}
fn findSessionByNameAndType(session: *Session, name: []const u8, display_server: ?DisplayServer) ?usize {
for (session.label.list.items, 0..) |env, i| {
if (display_server) |ds| {
if (env.environment.display_server != ds) continue;
}
if (std.ascii.eqlIgnoreCase(env.environment.file_name, name)) return i;
if (std.ascii.eqlIgnoreCase(env.environment.name, name)) return i;
if (env.environment.xdg_session_desktop) |session_desktop| {