2026-06-02 07:40:25 -07:00
|
|
|
{
|
|
|
|
|
config,
|
|
|
|
|
lib,
|
|
|
|
|
pkgs,
|
|
|
|
|
...
|
|
|
|
|
}:
|
2025-05-21 19:53:56 +01:00
|
|
|
|
2026-06-02 07:40:25 -07:00
|
|
|
let
|
|
|
|
|
cfg = config.features.swayDesktop;
|
2026-06-09 19:41:17 +01:00
|
|
|
# Catppuccin Mocha (shared with the Sway desktop, see lyrathorpe/home/sway.nix).
|
|
|
|
|
ctp = import ./catppuccin-mocha.nix;
|
2025-05-21 19:53:56 +01:00
|
|
|
in
|
|
|
|
|
{
|
2026-06-16 13:29:15 +01:00
|
|
|
# The features.swayDesktop.enable option is declared in
|
|
|
|
|
# system/modules/features.nix (so headless hosts can read/set it without
|
|
|
|
|
# importing this module). This module only provides its implementation.
|
2026-06-02 07:40:25 -07:00
|
|
|
config = lib.mkIf cfg.enable {
|
|
|
|
|
programs.sway = {
|
|
|
|
|
enable = true;
|
|
|
|
|
wrapperFeatures.gtk = true;
|
|
|
|
|
extraSessionCommands = ''
|
2026-06-04 13:34:44 +00:00
|
|
|
# QT
|
|
|
|
|
export QT_QPA_PLATFORM="wayland;xcb"
|
|
|
|
|
export QT_QPA_PLATFORMTHEME=qt5ct
|
|
|
|
|
# SDL
|
|
|
|
|
export SDL_VIDEODRIVER=wayland
|
|
|
|
|
# Java
|
|
|
|
|
export _JAVA_AWT_WM_NONREPARENTING=1
|
|
|
|
|
# Misc
|
|
|
|
|
export CLUTTER_BACKEND=wayland
|
|
|
|
|
export WINIT_UNIX_BACKEND=wayland
|
|
|
|
|
export MOZ_ENABLE_WAYLAND=1
|
|
|
|
|
'';
|
2026-06-02 07:40:25 -07:00
|
|
|
# Core Wayland utilities. The lock screen, idle daemon, status bar and
|
|
|
|
|
# notification daemon are configured per-user in home/sway.nix.
|
|
|
|
|
extraPackages = with pkgs; [
|
|
|
|
|
brightnessctl
|
|
|
|
|
foot
|
|
|
|
|
grim
|
2026-06-09 20:49:36 +01:00
|
|
|
slurp # region selection for screenshots
|
|
|
|
|
swappy # screenshot annotation/save
|
|
|
|
|
jq # used by the focused-window screenshot bind
|
|
|
|
|
playerctl # MPRIS media keys
|
2026-06-02 07:40:25 -07:00
|
|
|
sway-launcher-desktop
|
|
|
|
|
pavucontrol
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
fonts.packages = with pkgs; [
|
|
|
|
|
noto-fonts
|
|
|
|
|
noto-fonts-color-emoji
|
|
|
|
|
font-awesome
|
|
|
|
|
];
|
|
|
|
|
|
2026-06-09 18:10:08 +01:00
|
|
|
# Wayland login screen (replaces console/getty login on every Sway host).
|
|
|
|
|
# greetd runs ReGreet inside the cage kiosk compositor; the Sway session is
|
|
|
|
|
# offered automatically because programs.sway registers itself via
|
|
|
|
|
# services.displayManager.sessionPackages. Hosts that turn off
|
|
|
|
|
# features.swayDesktop (e.g. EDaaS) keep plain TTY login.
|
|
|
|
|
programs.regreet.enable = true;
|
2026-06-09 19:41:17 +01:00
|
|
|
# Theme the greeter to match the Sway desktop (Catppuccin Mocha). ReGreet is
|
|
|
|
|
# GTK; recolour via CSS (covering both libadwaita named colours and plain
|
|
|
|
|
# GTK node selectors) and use the same Noto Sans as the bar/notifications.
|
|
|
|
|
programs.regreet.font = {
|
|
|
|
|
name = "Noto Sans";
|
|
|
|
|
package = pkgs.noto-fonts;
|
|
|
|
|
size = 16;
|
|
|
|
|
};
|
|
|
|
|
programs.regreet.extraCss = ''
|
2026-06-09 19:49:13 +01:00
|
|
|
/* GTK4 Adwaita legacy names (what plain GTK4 actually references). */
|
|
|
|
|
@define-color theme_bg_color #${ctp.base};
|
|
|
|
|
@define-color theme_fg_color #${ctp.text};
|
|
|
|
|
@define-color theme_base_color #${ctp.mantle};
|
|
|
|
|
@define-color theme_text_color #${ctp.text};
|
|
|
|
|
@define-color theme_selected_bg_color #${ctp.blue};
|
|
|
|
|
@define-color theme_selected_fg_color #${ctp.base};
|
|
|
|
|
@define-color insensitive_bg_color #${ctp.mantle};
|
|
|
|
|
@define-color insensitive_fg_color #${ctp.overlay0};
|
|
|
|
|
@define-color borders #${ctp.surface1};
|
|
|
|
|
@define-color warning_color #${ctp.peach};
|
|
|
|
|
@define-color error_color #${ctp.red};
|
|
|
|
|
@define-color success_color #${ctp.green};
|
|
|
|
|
|
|
|
|
|
/* libadwaita names (inert on plain GTK4, kept for forward-compat). */
|
2026-06-09 19:41:17 +01:00
|
|
|
@define-color window_bg_color #${ctp.base};
|
|
|
|
|
@define-color window_fg_color #${ctp.text};
|
|
|
|
|
@define-color view_bg_color #${ctp.mantle};
|
|
|
|
|
@define-color view_fg_color #${ctp.text};
|
|
|
|
|
@define-color card_bg_color #${ctp.surface0};
|
|
|
|
|
@define-color card_fg_color #${ctp.text};
|
|
|
|
|
@define-color accent_bg_color #${ctp.blue};
|
|
|
|
|
@define-color accent_fg_color #${ctp.base};
|
|
|
|
|
@define-color accent_color #${ctp.blue};
|
|
|
|
|
@define-color destructive_bg_color #${ctp.red};
|
|
|
|
|
@define-color destructive_fg_color #${ctp.base};
|
|
|
|
|
|
|
|
|
|
window {
|
|
|
|
|
background-color: #${ctp.base};
|
|
|
|
|
color: #${ctp.text};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
label {
|
|
|
|
|
color: #${ctp.text};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entry {
|
|
|
|
|
background-color: #${ctp.surface0};
|
|
|
|
|
color: #${ctp.text};
|
|
|
|
|
border: 1px solid #${ctp.surface1};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entry:focus-within {
|
|
|
|
|
border-color: #${ctp.blue};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button,
|
|
|
|
|
combobox button {
|
|
|
|
|
background-color: #${ctp.surface0};
|
|
|
|
|
color: #${ctp.text};
|
|
|
|
|
border: 1px solid #${ctp.surface1};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button:hover {
|
|
|
|
|
background-color: #${ctp.surface1};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button:active,
|
|
|
|
|
button:checked {
|
|
|
|
|
background-color: #${ctp.blue};
|
|
|
|
|
color: #${ctp.base};
|
|
|
|
|
}
|
|
|
|
|
'';
|
2026-06-09 18:10:08 +01:00
|
|
|
# cage reads the XKB_* environment at startup, so force the greeter onto the
|
2026-06-09 18:31:47 +01:00
|
|
|
# same Dvorak layout as the Sway session (home/sway.nix) -- otherwise the
|
|
|
|
|
# password field would be QWERTY. Dvorak is the "us" layout's variant, NOT a
|
|
|
|
|
# layout of its own: "dvorak" alone has no symbols/ file, so the keymap
|
|
|
|
|
# fails to compile and the greeter ends up with no keyboard at all (the
|
|
|
|
|
# greeter has no fallback, unlike a running Sway session). This overrides the
|
|
|
|
|
# greetd command regreet sets with mkDefault.
|
2026-06-09 18:10:08 +01:00
|
|
|
services.greetd.settings.default_session.command =
|
|
|
|
|
let
|
|
|
|
|
greeter = pkgs.writeShellScript "regreet-cage" ''
|
2026-06-09 18:31:47 +01:00
|
|
|
export XKB_DEFAULT_LAYOUT=us
|
|
|
|
|
export XKB_DEFAULT_VARIANT=dvorak
|
2026-06-09 19:49:13 +01:00
|
|
|
# ReGreet is plain GTK4 (no libadwaita); force the dark Adwaita variant
|
|
|
|
|
# so the extraCss accents sit on a dark base instead of light Adwaita.
|
|
|
|
|
export GTK_THEME=Adwaita:dark
|
2026-06-09 18:10:08 +01:00
|
|
|
exec ${pkgs.dbus}/bin/dbus-run-session ${lib.getExe pkgs.cage} -s -- ${lib.getExe config.programs.regreet.package}
|
|
|
|
|
'';
|
|
|
|
|
in
|
|
|
|
|
"${greeter}";
|
|
|
|
|
|
2026-06-02 07:40:25 -07:00
|
|
|
# Desktop portals: enables screen sharing (wlroots) and native file pickers
|
|
|
|
|
# for Wayland apps such as Element and Firefox.
|
|
|
|
|
xdg.portal = {
|
|
|
|
|
enable = true;
|
|
|
|
|
wlr.enable = true;
|
|
|
|
|
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
|
|
|
|
config.common.default = "*";
|
|
|
|
|
};
|
|
|
|
|
};
|
2025-05-21 19:53:56 +01:00
|
|
|
}
|