feat(desktop): Hyprland, Waybar, autostart/bindings/idle
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b16707b2ab
commit
6e87d8e186
5 changed files with 1317 additions and 0 deletions
61
modules/desktop/hyprland/autostart.nix
Normal file
61
modules/desktop/hyprland/autostart.nix
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf optionals;
|
||||
cfg = config.omni.desktop;
|
||||
omni = config.omni.lib;
|
||||
user = config.omni.user;
|
||||
in
|
||||
{
|
||||
config = mkIf (cfg.enable) {
|
||||
home-manager.users.${user} = {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
exec-once = [
|
||||
# NOTE: do NOT add "waybar" here. Waybar is managed by the
|
||||
# systemd user service from `programs.waybar.systemd.enable
|
||||
# = true` in modules/desktop/hyprland.nix. Launching it
|
||||
# from `exec-once` AS WELL produces two stacked bars on
|
||||
# screen. The keybinding to restart waybar
|
||||
# (`systemctl --user restart waybar` in bindings.nix) also
|
||||
# assumes the systemd-managed instance.
|
||||
"gnome-keyring-daemon --start --components=secrets,pkcs11"
|
||||
"mako"
|
||||
"awww init"
|
||||
"nm-applet --indicator"
|
||||
"blueman-applet"
|
||||
"wl-paste --type text --watch cliphist store"
|
||||
"wl-paste --type image --watch cliphist store"
|
||||
"${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"
|
||||
"mkdir -p ~/Pictures/Screenshots"
|
||||
"hypridle"
|
||||
"swayosd-server"
|
||||
"[workspace 1 silent] ${cfg.defaultTerminal} -e tmux"
|
||||
"[workspace 1 silent] ${cfg.defaultBrowser}"
|
||||
]
|
||||
++ optionals (omni.isEnabled "media") [
|
||||
"[workspace 4 silent] spotify"
|
||||
]
|
||||
++ optionals (omni.isEnabled "communication") [
|
||||
"[workspace 5 silent] signal-desktop --password-store=gnome-libsecret"
|
||||
"[workspace 5 silent] element-desktop --password-store=gnome-libsecret"
|
||||
"[workspace 5 silent] ferdium --password-store=gnome-libsecret"
|
||||
# nixpkgs ships the binary as `Telegram` (capital T), not
|
||||
# `telegram-desktop`. It's Qt, so it doesn't take the
|
||||
# --password-store flag the Electron apps below use.
|
||||
"[workspace 5 silent] Telegram"
|
||||
];
|
||||
|
||||
exec =
|
||||
[ ]
|
||||
++ optionals (cfg.wallpaper != null) [
|
||||
"awww img ${toString cfg.wallpaper} --transition-type wipe"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
169
modules/desktop/hyprland/bindings.nix
Normal file
169
modules/desktop/hyprland/bindings.nix
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf optionals;
|
||||
cfg = config.omni.desktop;
|
||||
omni = config.omni.lib;
|
||||
user = config.omni.user;
|
||||
|
||||
terminal = cfg.defaultTerminal;
|
||||
browser = cfg.defaultBrowser;
|
||||
in
|
||||
{
|
||||
config = mkIf (cfg.enable) {
|
||||
home-manager.users.${user} = {
|
||||
wayland.windowManager.hyprland.settings = {
|
||||
"$mainMod" = "SUPER";
|
||||
|
||||
bind = [
|
||||
# Application launches
|
||||
"$mainMod, Return, exec, ${terminal}"
|
||||
"$mainMod, B, exec, ${browser}"
|
||||
"$mainMod, E, exec, thunar"
|
||||
"$mainMod, R, exec, walker"
|
||||
"$mainMod, D, exec, walker"
|
||||
|
||||
# Window management
|
||||
"$mainMod, Q, killactive"
|
||||
"$mainMod, F, fullscreen, 1"
|
||||
"$mainMod SHIFT, F, fullscreen, 0"
|
||||
"$mainMod, Space, togglefloating"
|
||||
"$mainMod, P, pseudo"
|
||||
"$mainMod, J, layoutmsg, togglesplit"
|
||||
"$mainMod, G, togglegroup"
|
||||
"$mainMod, Tab, changegroupactive"
|
||||
|
||||
# Focus (vim keys)
|
||||
"$mainMod, h, movefocus, l"
|
||||
"$mainMod, l, movefocus, r"
|
||||
"$mainMod, k, movefocus, u"
|
||||
"$mainMod, j, movefocus, d"
|
||||
|
||||
# Focus (arrow keys)
|
||||
"$mainMod, left, movefocus, l"
|
||||
"$mainMod, right, movefocus, r"
|
||||
"$mainMod, up, movefocus, u"
|
||||
"$mainMod, down, movefocus, d"
|
||||
|
||||
# Move windows (vim keys)
|
||||
"$mainMod SHIFT, h, movewindow, l"
|
||||
"$mainMod SHIFT, l, movewindow, r"
|
||||
"$mainMod SHIFT, k, movewindow, u"
|
||||
"$mainMod SHIFT, j, movewindow, d"
|
||||
|
||||
# Move windows (arrow keys)
|
||||
"$mainMod SHIFT, left, movewindow, l"
|
||||
"$mainMod SHIFT, right, movewindow, r"
|
||||
"$mainMod SHIFT, up, movewindow, u"
|
||||
"$mainMod SHIFT, down, movewindow, d"
|
||||
|
||||
# Workspaces
|
||||
"$mainMod, 1, workspace, 1"
|
||||
"$mainMod, 2, workspace, 2"
|
||||
"$mainMod, 3, workspace, 3"
|
||||
"$mainMod, 4, workspace, 4"
|
||||
"$mainMod, 5, workspace, 5"
|
||||
"$mainMod, 6, workspace, 6"
|
||||
"$mainMod, 7, workspace, 7"
|
||||
"$mainMod, 8, workspace, 8"
|
||||
"$mainMod, 9, workspace, 9"
|
||||
"$mainMod, 0, workspace, 10"
|
||||
|
||||
# Move to workspace
|
||||
"$mainMod SHIFT, 1, movetoworkspace, 1"
|
||||
"$mainMod SHIFT, 2, movetoworkspace, 2"
|
||||
"$mainMod SHIFT, 3, movetoworkspace, 3"
|
||||
"$mainMod SHIFT, 4, movetoworkspace, 4"
|
||||
"$mainMod SHIFT, 5, movetoworkspace, 5"
|
||||
"$mainMod SHIFT, 6, movetoworkspace, 6"
|
||||
"$mainMod SHIFT, 7, movetoworkspace, 7"
|
||||
"$mainMod SHIFT, 8, movetoworkspace, 8"
|
||||
"$mainMod SHIFT, 9, movetoworkspace, 9"
|
||||
"$mainMod SHIFT, 0, movetoworkspace, 10"
|
||||
|
||||
# Scroll workspaces
|
||||
"$mainMod, mouse_down, workspace, e+1"
|
||||
"$mainMod, mouse_up, workspace, e-1"
|
||||
|
||||
# Screenshots (grim + satty for annotation)
|
||||
", Print, exec, grim -g \"$(slurp)\" - | satty -f - --output-filename ~/Pictures/Screenshots/$(date +'screenshot_%Y-%m-%d-%H%M%S.png')"
|
||||
"SHIFT, Print, exec, grim - | satty -f - --output-filename ~/Pictures/Screenshots/$(date +'screenshot_%Y-%m-%d-%H%M%S.png')"
|
||||
"$mainMod, Print, exec, grim -g \"$(slurp)\" - | wl-copy"
|
||||
|
||||
# Screen recording
|
||||
"$mainMod SHIFT, R, exec, wf-recorder -g \"$(slurp)\" -f ~/Videos/recording_$(date +'%Y-%m-%d-%H%M%S.mp4')"
|
||||
|
||||
# Lock screen
|
||||
"$mainMod, L, exec, hyprlock"
|
||||
|
||||
# System / Power
|
||||
"$mainMod SHIFT, Q, exit,"
|
||||
"$mainMod SHIFT, P, exec, systemctl poweroff"
|
||||
"$mainMod SHIFT, B, exec, systemctl reboot"
|
||||
"$mainMod ALT, R, exec, systemctl --user restart waybar"
|
||||
|
||||
# Clipboard
|
||||
"$mainMod, Y, exec, cliphist list | walker --dmenu | cliphist decode | wl-copy"
|
||||
"$mainMod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy"
|
||||
|
||||
# Color picker
|
||||
"$mainMod SHIFT, C, exec, hyprpicker -a"
|
||||
|
||||
# Scratchpad
|
||||
"$mainMod, S, togglespecialworkspace, magic"
|
||||
"$mainMod SHIFT, S, movetoworkspace, special:magic"
|
||||
|
||||
# Theme cycling
|
||||
"$mainMod ALT, T, exec, omni-theme-bg-next"
|
||||
"$mainMod ALT SHIFT, T, exec, omni-theme-next"
|
||||
]
|
||||
# Coding shortcuts
|
||||
++ optionals (omni.isEnabled "coding") [
|
||||
"$mainMod, C, exec, code"
|
||||
"$mainMod SHIFT, C, exec, ${terminal} -e nvim"
|
||||
]
|
||||
# Communication shortcuts
|
||||
++ optionals (omni.isEnabled "communication") [
|
||||
"$mainMod CTRL, D, exec, discord"
|
||||
"$mainMod CTRL SHIFT, D, exec, slack"
|
||||
];
|
||||
|
||||
# Resize with vim/arrow keys
|
||||
binde = [
|
||||
"$mainMod CTRL, h, resizeactive, -50 0"
|
||||
"$mainMod CTRL, l, resizeactive, 50 0"
|
||||
"$mainMod CTRL, k, resizeactive, 0 -50"
|
||||
"$mainMod CTRL, j, resizeactive, 0 50"
|
||||
"$mainMod CTRL, left, resizeactive, -50 0"
|
||||
"$mainMod CTRL, right, resizeactive, 50 0"
|
||||
"$mainMod CTRL, up, resizeactive, 0 -50"
|
||||
"$mainMod CTRL, down, resizeactive, 0 50"
|
||||
];
|
||||
|
||||
# Mouse bindings
|
||||
bindm = [
|
||||
"$mainMod, mouse:272, movewindow"
|
||||
"$mainMod, mouse:273, resizewindow"
|
||||
];
|
||||
|
||||
# Media/brightness keys (locked — work even when input inhibited)
|
||||
bindl = [
|
||||
", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
|
||||
", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
|
||||
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
|
||||
", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
|
||||
", XF86MonBrightnessUp, exec, brightnessctl set 10%+"
|
||||
", XF86MonBrightnessDown, exec, brightnessctl set 10%-"
|
||||
", XF86AudioPlay, exec, playerctl play-pause"
|
||||
", XF86AudioNext, exec, playerctl next"
|
||||
", XF86AudioPrev, exec, playerctl previous"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
179
modules/desktop/hyprland/idle.nix
Normal file
179
modules/desktop/hyprland/idle.nix
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf optionals;
|
||||
cfg = config.omni.desktop;
|
||||
user = config.omni.user;
|
||||
in
|
||||
{
|
||||
config = mkIf (cfg.enable) {
|
||||
home-manager.users.${user} = {
|
||||
# Hypridle — screen dimming, locking, DPMS, optional suspend
|
||||
services.hypridle = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general = {
|
||||
lock_cmd = "pidof hyprlock || hyprlock";
|
||||
before_sleep_cmd = "loginctl lock-session";
|
||||
after_sleep_cmd = "hyprctl dispatch dpms on";
|
||||
};
|
||||
|
||||
listener = [
|
||||
# Dim screen after 5 minutes
|
||||
{
|
||||
timeout = 300;
|
||||
on-timeout = "brightnessctl -s set 10%";
|
||||
on-resume = "brightnessctl -r";
|
||||
}
|
||||
# Lock screen after 10 minutes
|
||||
{
|
||||
timeout = 600;
|
||||
on-timeout = "loginctl lock-session";
|
||||
}
|
||||
# Turn off screen after 15 minutes
|
||||
{
|
||||
timeout = 900;
|
||||
on-timeout = "hyprctl dispatch dpms off";
|
||||
on-resume = "hyprctl dispatch dpms on";
|
||||
}
|
||||
]
|
||||
++ optionals cfg.idleSuspend [
|
||||
# Suspend after 30 minutes
|
||||
{
|
||||
timeout = 1800;
|
||||
on-timeout = "systemctl suspend";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Hyprlock — lock screen appearance
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general = {
|
||||
disable_loading_bar = true;
|
||||
grace = 5;
|
||||
hide_cursor = false;
|
||||
no_fade_in = false;
|
||||
};
|
||||
|
||||
background = [
|
||||
{
|
||||
monitor = "";
|
||||
path = if cfg.wallpaper != null then toString cfg.wallpaper else "~/Pictures/wallpaper.jpg";
|
||||
blur_passes = 3;
|
||||
blur_size = 8;
|
||||
noise = 0.0117;
|
||||
contrast = 0.8916;
|
||||
brightness = 0.8172;
|
||||
vibrancy = 0.1696;
|
||||
vibrancy_darkness = 0.0;
|
||||
}
|
||||
];
|
||||
|
||||
image = [
|
||||
{
|
||||
monitor = "";
|
||||
path = "~/.face";
|
||||
size = 150;
|
||||
rounding = -1;
|
||||
border_size = 4;
|
||||
border_color = "rgb(221, 221, 221)";
|
||||
position = "0, 200";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
}
|
||||
];
|
||||
|
||||
label = [
|
||||
# Time
|
||||
{
|
||||
monitor = "";
|
||||
text = ''cmd[update:30000] echo "$TIME"'';
|
||||
color = "rgba(200, 200, 200, 1.0)";
|
||||
font_size = 55;
|
||||
font_family = "JetBrainsMono Nerd Font";
|
||||
position = "-100, -40";
|
||||
halign = "right";
|
||||
valign = "bottom";
|
||||
shadow_passes = 5;
|
||||
shadow_size = 10;
|
||||
}
|
||||
# Date
|
||||
{
|
||||
monitor = "";
|
||||
text = ''cmd[update:43200000] echo "$(date +"%A, %d %B %Y")"'';
|
||||
color = "rgba(200, 200, 200, 1.0)";
|
||||
font_size = 25;
|
||||
font_family = "JetBrainsMono Nerd Font";
|
||||
position = "-100, -150";
|
||||
halign = "right";
|
||||
valign = "bottom";
|
||||
shadow_passes = 5;
|
||||
shadow_size = 10;
|
||||
}
|
||||
# Username
|
||||
{
|
||||
monitor = "";
|
||||
text = user;
|
||||
color = "rgba(200, 200, 200, 1.0)";
|
||||
font_size = 20;
|
||||
font_family = "JetBrainsMono Nerd Font";
|
||||
position = "0, 80";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
shadow_passes = 5;
|
||||
shadow_size = 10;
|
||||
}
|
||||
# Hostname
|
||||
{
|
||||
monitor = "";
|
||||
text = ''cmd[update:60000] echo "$(uname -n)"'';
|
||||
color = "rgba(200, 200, 200, 0.8)";
|
||||
font_size = 16;
|
||||
font_family = "JetBrainsMono Nerd Font";
|
||||
position = "100, 40";
|
||||
halign = "left";
|
||||
valign = "bottom";
|
||||
shadow_passes = 5;
|
||||
shadow_size = 10;
|
||||
}
|
||||
];
|
||||
|
||||
input-field = [
|
||||
{
|
||||
monitor = "";
|
||||
size = "200, 50";
|
||||
outline_thickness = 3;
|
||||
dots_size = 0.33;
|
||||
dots_spacing = 0.15;
|
||||
dots_center = false;
|
||||
dots_rounding = -1;
|
||||
outer_color = "rgb(151515)";
|
||||
inner_color = "rgb(200, 200, 200)";
|
||||
font_color = "rgb(10, 10, 10)";
|
||||
fade_on_empty = true;
|
||||
fade_timeout = 1000;
|
||||
placeholder_text = "<i>Input Password...</i>";
|
||||
hide_input = false;
|
||||
rounding = -1;
|
||||
check_color = "rgb(204, 136, 34)";
|
||||
fail_color = "rgb(204, 34, 34)";
|
||||
fail_text = "<i>$FAIL <b>($ATTEMPTS)</b></i>";
|
||||
fail_timeout = 2000;
|
||||
position = "0, -20";
|
||||
halign = "center";
|
||||
valign = "center";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue