feat: implement the managed Hyprland desktop with Kitty and stable updates
This commit is contained in:
+380
@@ -0,0 +1,380 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
c = import ./colors.nix;
|
||||
wallpaper = pkgs.runCommand "quiet-orbit.png" { nativeBuildInputs = [ pkgs.resvg ]; } ''
|
||||
resvg ${./wallpaper.svg} "$out"
|
||||
'';
|
||||
screenshot = pkgs.writeShellApplication {
|
||||
name = "desktop-screenshot";
|
||||
runtimeInputs = with pkgs; [
|
||||
grim
|
||||
slurp
|
||||
satty
|
||||
coreutils
|
||||
];
|
||||
text = ''
|
||||
geometry=$(slurp) || exit 0
|
||||
[ -n "$geometry" ] || exit 0
|
||||
mkdir -p "$HOME/Pictures/Screenshots"
|
||||
grim -g "$geometry" - | satty --filename - --copy-command wl-copy \
|
||||
--output-filename "$HOME/Pictures/Screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
|
||||
'';
|
||||
};
|
||||
launcherExec = pkgs.writeShellScript "anyrun-uwsm" ''
|
||||
kind=$1
|
||||
shift
|
||||
if [ "$kind" = term ]; then
|
||||
printf '%s\n' "$*"
|
||||
else
|
||||
printf 'uwsm app -- %s\n' "$*"
|
||||
fi
|
||||
'';
|
||||
networkManager = config.networking.networkmanager.enable;
|
||||
bluetooth = config.hardware.bluetooth.enable;
|
||||
power = config.services.upower.enable;
|
||||
in
|
||||
{
|
||||
programs.hyprland = {
|
||||
enable = true;
|
||||
withUWSM = true;
|
||||
};
|
||||
programs.hyprlock.enable = true;
|
||||
services.hypridle.enable = true;
|
||||
hardware.graphics.enable = true;
|
||||
security.polkit.enable = true;
|
||||
security.rtkit.enable = true;
|
||||
programs.dconf.enable = true;
|
||||
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
wireplumber.enable = true;
|
||||
};
|
||||
|
||||
# NixOS's Hyprland module already installs the Hyprland and GTK portals.
|
||||
xdg.portal.config.hyprland = {
|
||||
default = [
|
||||
"hyprland"
|
||||
"gtk"
|
||||
];
|
||||
"org.freedesktop.impl.portal.FileChooser" = [ "gtk" ];
|
||||
};
|
||||
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
environment.systemPackages = with pkgs; [
|
||||
wl-clipboard
|
||||
grim
|
||||
slurp
|
||||
satty
|
||||
screenshot
|
||||
pavucontrol
|
||||
playerctl
|
||||
brightnessctl
|
||||
xdg-utils
|
||||
libnotify
|
||||
];
|
||||
services.udev.packages = [ pkgs.brightnessctl ];
|
||||
fonts.packages = with pkgs; [
|
||||
inter
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-color-emoji
|
||||
];
|
||||
fonts.fontconfig.defaultFonts = {
|
||||
sansSerif = [
|
||||
"Inter"
|
||||
"Noto Sans"
|
||||
];
|
||||
serif = [ "Noto Serif" ];
|
||||
emoji = [ "Noto Color Emoji" ];
|
||||
};
|
||||
|
||||
home-manager.users.dev = {
|
||||
xdg.enable = true;
|
||||
xdg.userDirs = {
|
||||
enable = true;
|
||||
createDirectories = true;
|
||||
};
|
||||
xdg.autostart.enable = true;
|
||||
home.pointerCursor = {
|
||||
package = pkgs.bibata-cursors;
|
||||
name = "Bibata-Modern-Ice";
|
||||
size = 24;
|
||||
gtk.enable = true;
|
||||
x11.enable = true;
|
||||
};
|
||||
gtk = {
|
||||
enable = true;
|
||||
font = {
|
||||
name = "Inter";
|
||||
size = 11;
|
||||
};
|
||||
theme = {
|
||||
name = "Adwaita-dark";
|
||||
package = pkgs.gnome-themes-extra;
|
||||
};
|
||||
iconTheme = {
|
||||
name = "Papirus-Dark";
|
||||
package = pkgs.papirus-icon-theme;
|
||||
};
|
||||
gtk3.extraConfig.gtk-application-prefer-dark-theme = true;
|
||||
gtk4.extraConfig.gtk-application-prefer-dark-theme = true;
|
||||
};
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme.name = "gtk3";
|
||||
style = {
|
||||
name = "adwaita-dark";
|
||||
package = pkgs.adwaita-qt;
|
||||
};
|
||||
};
|
||||
dconf.settings."org/gnome/desktop/interface" = {
|
||||
color-scheme = "prefer-dark";
|
||||
font-name = "Inter 11";
|
||||
monospace-font-name = "JetBrainsMono Nerd Font 13";
|
||||
};
|
||||
|
||||
wayland.windowManager.hyprland = {
|
||||
enable = true;
|
||||
package = null;
|
||||
portalPackage = null;
|
||||
systemd.enable = false; # UWSM owns the session and environment.
|
||||
configType = "lua";
|
||||
extraConfig = builtins.readFile ./hyprland.lua;
|
||||
};
|
||||
services.hyprpolkitagent.enable = true;
|
||||
services.awww.enable = true;
|
||||
systemd.user.services.awww.Service = {
|
||||
Type = "notify"; # awww 0.12 signals socket readiness; no guessed sleep.
|
||||
ExecStartPost = "${pkgs.awww}/bin/awww img ${wallpaper} --transition-type fade --transition-duration 0.5";
|
||||
};
|
||||
|
||||
programs.ashell = {
|
||||
enable = true;
|
||||
systemd.enable = true;
|
||||
settings = {
|
||||
log_level = "warn";
|
||||
position = "Top";
|
||||
modules = {
|
||||
left = [
|
||||
[
|
||||
"appLauncher"
|
||||
"Workspaces"
|
||||
]
|
||||
];
|
||||
center = [ "Tempo" ];
|
||||
right = [
|
||||
"SystemInfo"
|
||||
[
|
||||
"Tray"
|
||||
"Privacy"
|
||||
"Settings"
|
||||
]
|
||||
];
|
||||
};
|
||||
CustomModule = [
|
||||
{
|
||||
name = "appLauncher";
|
||||
icon = "";
|
||||
command = "uwsm app -- anyrun";
|
||||
}
|
||||
];
|
||||
tempo.clock_format = "%a %d %b %H:%M";
|
||||
workspaces = {
|
||||
visibility_mode = "MonitorSpecific";
|
||||
enable_workspace_filling = true;
|
||||
};
|
||||
system_info = {
|
||||
indicators = [
|
||||
"Cpu"
|
||||
"Memory"
|
||||
];
|
||||
interval = 5;
|
||||
};
|
||||
settings = {
|
||||
lock_cmd = "loginctl lock-session";
|
||||
logout_cmd = "uwsm stop";
|
||||
audio_sinks_more_cmd = "uwsm app -- pavucontrol -t 3";
|
||||
audio_sources_more_cmd = "uwsm app -- pavucontrol -t 4";
|
||||
wifi_more_cmd = "uwsm app -- nm-connection-editor";
|
||||
vpn_more_cmd = "uwsm app -- nm-connection-editor";
|
||||
bluetooth_more_cmd = "uwsm app -- blueman-manager";
|
||||
indicators = [
|
||||
"IdleInhibitor"
|
||||
"Audio"
|
||||
"Microphone"
|
||||
]
|
||||
++ lib.optionals networkManager [
|
||||
"Network"
|
||||
"Vpn"
|
||||
]
|
||||
++ lib.optionals bluetooth [ "Bluetooth" ]
|
||||
++ lib.optionals power [
|
||||
"PowerProfile"
|
||||
"Battery"
|
||||
"Brightness"
|
||||
];
|
||||
audio_indicator_format = "IconAndPercentage";
|
||||
};
|
||||
appearance = {
|
||||
font_name = "Inter";
|
||||
scale_factor = 1.15;
|
||||
style = "Islands";
|
||||
opacity = 1.0;
|
||||
primary_color = c.blue;
|
||||
text_color = c.text;
|
||||
success_color = c.green;
|
||||
danger_color = c.red;
|
||||
background_color = {
|
||||
base = c.background;
|
||||
weak = c.surface;
|
||||
strong = c.raised;
|
||||
};
|
||||
secondary_color.base = c.surface;
|
||||
workspace_colors = [
|
||||
c.blue
|
||||
c.purple
|
||||
c.cyan
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.user.services.ashell.Unit.PartOf = [ "graphical-session.target" ];
|
||||
|
||||
programs.anyrun = {
|
||||
enable = true;
|
||||
config = {
|
||||
plugins = [
|
||||
"${pkgs.anyrun}/lib/libapplications.so"
|
||||
"${pkgs.anyrun}/lib/librink.so"
|
||||
];
|
||||
width.fraction = 0.42;
|
||||
y.fraction = 0.2;
|
||||
hidePluginInfo = true;
|
||||
closeOnClick = true;
|
||||
maxEntries = 8;
|
||||
};
|
||||
extraCss = builtins.readFile ./anyrun.css;
|
||||
extraConfigFiles."applications.ron".text = ''
|
||||
(
|
||||
desktop_actions: false,
|
||||
max_entries: 8,
|
||||
terminal: Some((command: "uwsm", args: "app -- kitty -e {}")),
|
||||
preprocess_exec_script: Some("${launcherExec}"),
|
||||
)
|
||||
'';
|
||||
};
|
||||
|
||||
services.mako = {
|
||||
enable = true;
|
||||
settings = {
|
||||
font = "Inter 11";
|
||||
width = 360;
|
||||
height = 160;
|
||||
margin = "12";
|
||||
padding = "14";
|
||||
border-size = 2;
|
||||
border-radius = 12;
|
||||
background-color = c.background;
|
||||
text-color = c.text;
|
||||
border-color = c.border;
|
||||
default-timeout = 6000;
|
||||
max-visible = 4;
|
||||
max-icon-size = 48;
|
||||
"urgency=critical" = {
|
||||
border-color = c.red;
|
||||
default-timeout = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
package = null;
|
||||
settings = {
|
||||
general = {
|
||||
hide_cursor = true;
|
||||
ignore_empty_input = true;
|
||||
};
|
||||
background = [
|
||||
{
|
||||
monitor = "";
|
||||
path = "${wallpaper}";
|
||||
blur_passes = 2;
|
||||
}
|
||||
];
|
||||
label = [
|
||||
{
|
||||
monitor = "";
|
||||
text = "cmd[update:1000] date +'%H:%M'";
|
||||
font_size = 84;
|
||||
font_family = "Inter";
|
||||
color = "rgb(f2f4f8)";
|
||||
position = "0,100";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
}
|
||||
{
|
||||
monitor = "";
|
||||
text = "$USER";
|
||||
font_size = 18;
|
||||
font_family = "Inter";
|
||||
color = "rgb(a2a9b0)";
|
||||
position = "0,0";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
}
|
||||
];
|
||||
input-field = [
|
||||
{
|
||||
monitor = "";
|
||||
size = "320,60";
|
||||
position = "0,-100";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
outline_thickness = 2;
|
||||
dots_center = true;
|
||||
font_family = "Inter";
|
||||
inner_color = "rgb(262626)";
|
||||
outer_color = "rgb(78a9ff)";
|
||||
font_color = "rgb(f2f4f8)";
|
||||
check_color = "rgb(3ddbd9)";
|
||||
fail_color = "rgb(ff6b7a)";
|
||||
capslock_color = "rgb(f1c21b)";
|
||||
placeholder_text = "<i>Password</i>";
|
||||
fail_text = "<i>Try again ($ATTEMPTS)</i>";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
services.hypridle = {
|
||||
enable = true;
|
||||
package = null; # NixOS owns the service and PAM integration.
|
||||
settings = {
|
||||
general = {
|
||||
lock_cmd = "pidof hyprlock || hyprlock";
|
||||
before_sleep_cmd = "loginctl lock-session";
|
||||
after_sleep_cmd = "hyprctl dispatch 'hl.dsp.dpms({ action = \"enable\" })'";
|
||||
inhibit_sleep = 3;
|
||||
};
|
||||
listener = [
|
||||
{
|
||||
timeout = 600;
|
||||
on-timeout = "loginctl lock-session";
|
||||
}
|
||||
{
|
||||
timeout = 900;
|
||||
on-timeout = "hyprctl dispatch 'hl.dsp.dpms({ action = \"disable\" })'";
|
||||
on-resume = "hyprctl dispatch 'hl.dsp.dpms({ action = \"enable\" })'";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user