# shellcheck shell=bash #------------------------------------------ # lib/session.sh — display manager and graphical session wiring # # DM policy: # * A DE module leaves its native DM alone (GNOME→gdm, Plasma→sddm, XFCE→sddm). # * A TWM module enforces SDDM, because SDDM is the only DM that presents both # Wayland compositors and X11 sessions in one menu. One greeter, no surprises. #------------------------------------------ if [[ -n "${_SB_SESSION_LOADED:-}" ]]; then return 0 fi _SB_SESSION_LOADED=1 # Name of the active display manager ("sddm", "gdm", "lightdm"), or "" if none. detect_display_manager() { local link=/etc/systemd/system/display-manager.service if [[ -L "$link" ]]; then basename "$(readlink "$link")" | sed 's/\.service$//' else echo "" fi } enable_graphical_target() { sudo systemctl set-default graphical.target } # Make $1 the display manager, disabling whatever is active now. switch_display_manager() { local target="$1" local current current=$(detect_display_manager) if [[ "$current" == "$target" ]]; then ok "Display manager already $target." else if [[ -n "$current" ]]; then info "Disabling current display manager: $current" # disable may fail if the unit vanished; that is not fatal sudo systemctl disable "$current" 2>/dev/null || true fi info "Enabling display manager: $target" sudo systemctl enable "$target" fi enable_graphical_target } # Register a Wayland session so the DM can list it. # $1 = identifier, $2 = display name, $3 = command write_wayland_session() { local id="$1" name="$2" exec_cmd="$3" local file="/usr/share/wayland-sessions/${id}.desktop" if [[ -f "$file" ]]; then ok "Wayland session already registered: $id" return 0 fi info "Registering Wayland session: $id" sudo mkdir -p "$(dirname "$file")" printf '[Desktop Entry]\nName=%s\nComment=%s\nExec=%s\nType=Application\nDesktopNames=%s\n' \ "$name" "$name session" "$exec_cmd" "$id" | sudo tee "$file" >/dev/null sudo chmod 644 "$file" } # Register an X11 session so the DM can list it. write_x11_session() { local id="$1" name="$2" exec_cmd="$3" local file="/usr/share/xsessions/${id}.desktop" if [[ -f "$file" ]]; then ok "X11 session already registered: $id" return 0 fi info "Registering X11 session: $id" # A bare Fedora has no X session yet, so the directory may not exist. sudo mkdir -p "$(dirname "$file")" printf '[Desktop Entry]\nName=%s\nComment=%s\nExec=%s\nType=Application\n' \ "$name" "$name session" "$exec_cmd" | sudo tee "$file" >/dev/null sudo chmod 644 "$file" } # Common login-time plumbing every Wayland compositor wants on a bare install. install_session_prereqs() { install_packages \ xdg-desktop-portal \ polkit \ polkit-gnome \ pipewire \ pipewire-pulseaudio \ wireplumber # A bare compositor (niri, MangoWC, Hyprland) has NO polkit agent: without # one, anything needing privilege elevation (virt-manager's libvirt access, # disks, network settings) fails with "no polkit agent available to # authenticate". Autostart it for every graphical session via the XDG # autostart dir the session runs. local autostart="${XDG_AUTOSTART_DIR:-/etc/xdg/autostart}" local desktop_src="${POLKIT_AGENT_DESKTOP:-/usr/share/applications/polkit-gnome-authentication-agent-1.desktop}" if [[ -f "$desktop_src" ]] && [[ ! -e "$autostart/$(basename "$desktop_src")" ]]; then info "Enabling polkit agent for compositor sessions..." sudo mkdir -p "$autostart" sudo ln -sf "$desktop_src" "$autostart/$(basename "$desktop_src")" fi }