139 lines
4 KiB
Nix
139 lines
4 KiB
Nix
{config, pkgs, lib, ...}:
|
|
|
|
{
|
|
# === Wayland + Hyprland ===
|
|
programs.hyprland = {
|
|
enable = true;
|
|
xwayland.enable = true;
|
|
};
|
|
|
|
# Session variables
|
|
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
|
|
|
# === Lid close behavior ===
|
|
# Don't suspend when lid closes — external display stays active
|
|
services.logind = {
|
|
lidSwitch = "ignore";
|
|
lidSwitchExternalPower = "ignore";
|
|
lidSwitchDocked = "ignore";
|
|
};
|
|
|
|
# Fallback ACPI handler for lid events outside Hyprland session
|
|
# Primary handling is done via Hyprland bindl in hyprland.conf
|
|
services.acpid = {
|
|
enable = true;
|
|
handlers.lid = {
|
|
event = "button/lid.*";
|
|
action = ''
|
|
${pkgs.bash}/bin/bash -c '
|
|
LID_STATE=$(cat /proc/acpi/button/lid/LID0/state 2>/dev/null || cat /proc/acpi/button/lid/LID/state 2>/dev/null || echo "open")
|
|
if echo "$LID_STATE" | grep -qi "closed"; then
|
|
EVENT="close"
|
|
else
|
|
EVENT="open"
|
|
fi
|
|
for user_dir in /run/user/*/hypr/; do
|
|
[ -d "$user_dir" ] || continue
|
|
SIG=$(ls "$user_dir" 2>/dev/null | head -1)
|
|
[ -z "$SIG" ] && continue
|
|
UID=$(basename $(dirname "$user_dir"))
|
|
USER=$(id -nu $UID 2>/dev/null || echo "sscoble")
|
|
HOME_DIR=$(getent passwd "$USER" | cut -d: -f6)
|
|
USER_SCRIPT="$HOME_DIR/.config/hypr/scripts/lid-handler.sh"
|
|
if [ -x "$USER_SCRIPT" ]; then
|
|
sudo -u "$USER" \
|
|
XDG_RUNTIME_DIR="/run/user/$UID" \
|
|
HYPRLAND_INSTANCE_SIGNATURE="$SIG" \
|
|
"$USER_SCRIPT" "$EVENT"
|
|
fi
|
|
break
|
|
done
|
|
'
|
|
'';
|
|
};
|
|
};
|
|
|
|
# Security — required for hyprlock
|
|
security.pam.services.hyprlock = {};
|
|
|
|
# Polkit for GUI auth prompts
|
|
security.polkit.enable = true;
|
|
systemd.user.services.polkit-gnome-authentication-agent-1 = {
|
|
description = "polkit-gnome-authentication-agent-1";
|
|
wantedBy = [ "graphical-session.target" ];
|
|
wants = [ "graphical-session.target" ];
|
|
after = [ "graphical-session.target" ];
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
|
|
Restart = "on-failure";
|
|
RestartSec = 1;
|
|
};
|
|
};
|
|
|
|
# Display manager — greetd (minimal, Wayland-native)
|
|
services.greetd = {
|
|
enable = true;
|
|
settings = {
|
|
default_session = {
|
|
command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd start-hyprland";
|
|
user = "greeter";
|
|
};
|
|
};
|
|
};
|
|
|
|
# Clear TTY before greetd starts to avoid boot message overlap
|
|
systemd.services.greetd.serviceConfig = {
|
|
TTYVTDisallocate = true;
|
|
Type = "idle";
|
|
};
|
|
|
|
# Create greeter user for greetd
|
|
users.users.greeter = {
|
|
description = "Greeter";
|
|
group = "greeter";
|
|
isSystemUser = true;
|
|
};
|
|
users.groups.greeter = {};
|
|
|
|
# Suppress kernel boot messages on console
|
|
boot.consoleLogLevel = 0;
|
|
|
|
# XDG portal for Wayland
|
|
xdg.portal = {
|
|
enable = true;
|
|
extraPortals = [ pkgs.xdg-desktop-portal-hyprland ];
|
|
config.common.default = "*";
|
|
};
|
|
|
|
# Fonts
|
|
fonts.packages = with pkgs; [
|
|
font-awesome
|
|
nerd-fonts.jetbrains-mono
|
|
nerd-fonts.fira-code
|
|
];
|
|
|
|
# Audio (pipewire)
|
|
services.pipewire = {
|
|
enable = true;
|
|
alsa.enable = true;
|
|
alsa.support32Bit = true;
|
|
pulse.enable = true;
|
|
};
|
|
|
|
# Bluetooth
|
|
hardware.bluetooth.enable = true;
|
|
hardware.bluetooth.powerOnBoot = true;
|
|
|
|
# Bluetooth manager (GUI pairing, tray applet)
|
|
# Note: using manual setup instead of services.blueman.enable to avoid
|
|
# a systemd unit bug (duplicate ExecStart in blueman-applet.service).
|
|
# The applet is launched via exec-once in hyprland.conf instead.
|
|
environment.systemPackages = with pkgs; [ blueman ];
|
|
services.dbus.packages = with pkgs; [ blueman ];
|
|
systemd.user.services.blueman-applet = { enable = false; };
|
|
systemd.user.services.blueman-manager = { enable = false; };
|
|
|
|
# NetworkManager applet
|
|
programs.nm-applet.enable = true;
|
|
}
|