diff --git a/home-manager/modules/desktop/common/wayland-wm/default.nix b/home-manager/modules/desktop/common/wayland-wm/default.nix new file mode 100644 index 0000000..7dd936b --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/default.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: +{ + imports = [ + ./hyprland-vnc.nix + ./gammastep.nix + ./kitty.nix + ./mako.nix + ./swayidle.nix + ./swaylock.nix + ./waybar.nix + ./wofi.nix + ./zathura.nix + ]; + + home.packages = with pkgs; [ + grim + imv + mimeo + primary-xwayland + pulseaudio + slurp + waypipe + wf-recorder + wl-clipboard + wl-mirror + wl-mirror-pick + ydotool + ]; + + home.sessionVariables = { + MOZ_ENABLE_WAYLAND = 1; + QT_QPA_PLATFORM = "wayland"; + LIBSEAT_BACKEND = "logind"; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/gammastep.nix b/home-manager/modules/desktop/common/wayland-wm/gammastep.nix new file mode 100644 index 0000000..498756e --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/gammastep.nix @@ -0,0 +1,13 @@ +{ + services.gammastep = { + enable = true; + provider = "geoclue2"; + temperature = { + day = 6000; + night = 4600; + }; + settings = { + general.adjustment-method = "wayland"; + }; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/hyprland-vnc.nix b/home-manager/modules/desktop/common/wayland-wm/hyprland-vnc.nix new file mode 100644 index 0000000..a920f88 --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/hyprland-vnc.nix @@ -0,0 +1,35 @@ +{ pkgs, lib, config, ... }: +let + enabledMonitors = lib.filter (m: m.enabled) config.monitors; + # A nice VNC script for remotes running hyprland + vncsh = pkgs.writeShellScriptBin "vnc.sh" '' + ssh $1 bash <<'EOF' + pgrep "wayvnc" && exit + export HYPRLAND_INSTANCE_SIGNATURE="$(ls /tmp/hypr/ -lt | head -2 | tail -1 | rev | cut -d ' ' -f1 | rev)" + export WAYLAND_DISPLAY="wayland-1" + ip="$(ip addr show dev tailscale0 | grep 'inet ' | xargs | cut -d ' ' -f2 | cut -d '/' -f1)" + xpos="$(hyprctl monitors -j | jq -r 'sort_by(.x)[-1] | .x + .width')" + + ${lib.concatLines (lib.forEach enabledMonitors (m: '' + hyprctl output create headless + monitor="$(hyprctl monitors -j | jq -r 'map(.name)[-1]')" + hyprctl keyword monitor $monitor,${toString m.width}x${toString m.height}@${toString m.refreshRate},$(($xpos + ${toString m.x}))x${toString m.y},1 + screen -d -m wayvnc -k br -S /tmp/vnc-${m.workspace} -f 60 -o $monitor $ip 590${m.workspace} + sudo iptables -I INPUT -j ACCEPT -p tcp --dport 590${m.workspace} + ''))} + EOF + + ${lib.concatLines (lib.forEach enabledMonitors (m: '' + vncviewer $1::590${m.workspace} & + ''))} + + wait + ''; +in +{ + home.packages = with pkgs; [ + vncsh + wayvnc + tigervnc + ]; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/kitty.nix b/home-manager/modules/desktop/common/wayland-wm/kitty.nix new file mode 100644 index 0000000..3528e1f --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/kitty.nix @@ -0,0 +1,66 @@ +{ config, pkgs, ... }: + +let + inherit (config.colorscheme) colors; + kitty-xterm = pkgs.writeShellScriptBin "xterm" '' + ${config.programs.kitty.package}/bin/kitty -1 "$@" + ''; +in +{ + home = { + packages = [ kitty-xterm ]; + sessionVariables = { + TERMINAL = "kitty -1"; + }; + }; + + + programs.kitty = { + enable = true; + font = { + name = config.fontProfiles.monospace.family; + size = 12; + }; + settings = { + shell_integration = "no-rc"; # I prefer to do it manually + scrollback_lines = 4000; + scrollback_pager_history_size = 2048; + window_padding_width = 15; + foreground = "#${colors.base05}"; + background = "#${colors.base00}"; + selection_background = "#${colors.base05}"; + selection_foreground = "#${colors.base00}"; + url_color = "#${colors.base04}"; + cursor = "#${colors.base05}"; + active_border_color = "#${colors.base03}"; + inactive_border_color = "#${colors.base01}"; + active_tab_background = "#${colors.base00}"; + active_tab_foreground = "#${colors.base05}"; + inactive_tab_background = "#${colors.base01}"; + inactive_tab_foreground = "#${colors.base04}"; + tab_bar_background = "#${colors.base01}"; + color0 = "#${colors.base00}"; + color1 = "#${colors.base08}"; + color2 = "#${colors.base0B}"; + color3 = "#${colors.base0A}"; + color4 = "#${colors.base0D}"; + color5 = "#${colors.base0E}"; + color6 = "#${colors.base0C}"; + color7 = "#${colors.base05}"; + color8 = "#${colors.base03}"; + color9 = "#${colors.base08}"; + color10 = "#${colors.base0B}"; + color11 = "#${colors.base0A}"; + color12 = "#${colors.base0D}"; + color13 = "#${colors.base0E}"; + color14 = "#${colors.base0C}"; + color15 = "#${colors.base07}"; + color16 = "#${colors.base09}"; + color17 = "#${colors.base0F}"; + color18 = "#${colors.base01}"; + color19 = "#${colors.base02}"; + color20 = "#${colors.base04}"; + color21 = "#${colors.base06}"; + }; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/mako.nix b/home-manager/modules/desktop/common/wayland-wm/mako.nix new file mode 100644 index 0000000..52b003c --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/mako.nix @@ -0,0 +1,22 @@ +{ config, ... }: +let inherit (config.colorscheme) colors kind; +in { + programs.mako = { + enable = true; + iconPath = + if kind == "dark" then + "${config.gtk.iconTheme.package}/share/icons/Papirus-Dark" + else + "${config.gtk.iconTheme.package}/share/icons/Papirus-Light"; + font = "${config.fontProfiles.regular.family} 12"; + padding = "10,20"; + anchor = "top-center"; + width = 400; + height = 150; + borderSize = 2; + defaultTimeout = 12000; + backgroundColor = "#${colors.base00}dd"; + borderColor = "#${colors.base03}dd"; + textColor = "#${colors.base05}dd"; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/swayidle.nix b/home-manager/modules/desktop/common/wayland-wm/swayidle.nix new file mode 100644 index 0000000..707a7e3 --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/swayidle.nix @@ -0,0 +1,35 @@ +{ pkgs, lib, config, ... }: + +let + swaylock = "${config.programs.swaylock.package}/bin/swaylock"; + pactl = "${pkgs.pulseaudio}/bin/pactl"; + pgrep = "${pkgs.procps}/bin/pgrep"; + + isLocked = "${pgrep} -x ${swaylock}"; + actionLock = "${swaylock} -S --daemonize"; + + lockTime = 4 * 60; # TODO: configurable desktop (10 min)/laptop (4 min) + + mkEvent = time: start: resume: '' + timeout ${toString (lockTime + time)} '${start}' ${lib.optionalString (resume != null) "resume '${resume}'"} + timeout ${toString time} '${isLocked} && ${start}' ${lib.optionalString (resume != null) "resume '${isLocked} && ${resume}'"} + ''; +in +{ + xdg.configFile."swayidle/config".text = '' + timeout ${toString lockTime} '${actionLock}' + '' + + # After 10 seconds of locked, mute mic + (mkEvent 10 "${pactl} set-source-mute @DEFAULT_SOURCE@ yes" "${pactl} set-source-mute @DEFAULT_SOURCE@ no") + + # If has RGB, turn it off 20 seconds after locked + lib.optionalString config.services.rgbdaemon.enable + (mkEvent 20 "systemctl --user stop rgbdaemon" "systemctl --user start rgbdaemon") + + # Hyprland - Turn off screen (DPMS) + lib.optionalString config.wayland.windowManager.hyprland.enable + (let hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl"; + in mkEvent 40 "${hyprctl} dispatch dpms off" "${hyprctl} dispatch dpms on") + + # Sway - Turn off screen (DPMS) + lib.optionalString config.wayland.windowManager.sway.enable + (let swaymsg = "${config.wayland.windowManager.sway.package}/bin/swaymsg"; + in mkEvent 40 "${swaymsg} 'output * dpms off'" "${swaymsg} 'output * dpms on'"); +} diff --git a/home-manager/modules/desktop/common/wayland-wm/swaylock.nix b/home-manager/modules/desktop/common/wayland-wm/swaylock.nix new file mode 100644 index 0000000..738bbfd --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/swaylock.nix @@ -0,0 +1,43 @@ +{ config, pkgs, ... }: + +let inherit (config.colorscheme) colors; +in +{ + programs.swaylock = { + enable = true; + package = pkgs.swaylock-effects; + settings = { + effect-blur = "20x3"; + fade-in = 0.1; + + font = config.fontProfiles.regular.family; + font-size = 15; + + line-uses-inside = true; + disable-caps-lock-text = true; + indicator-caps-lock = true; + indicator-radius = 40; + indicator-idle-visible = true; + indicator-y-position = 1000; + + ring-color = "#${colors.base02}"; + inside-wrong-color = "#${colors.base08}"; + ring-wrong-color = "#${colors.base08}"; + key-hl-color = "#${colors.base0B}"; + bs-hl-color = "#${colors.base08}"; + ring-ver-color = "#${colors.base09}"; + inside-ver-color = "#${colors.base09}"; + inside-color = "#${colors.base01}"; + text-color = "#${colors.base07}"; + text-clear-color = "#${colors.base01}"; + text-ver-color = "#${colors.base01}"; + text-wrong-color = "#${colors.base01}"; + text-caps-lock-color = "#${colors.base07}"; + inside-clear-color = "#${colors.base0C}"; + ring-clear-color = "#${colors.base0C}"; + inside-caps-lock-color = "#${colors.base09}"; + ring-caps-lock-color = "#${colors.base02}"; + separator-color = "#${colors.base02}"; + }; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/waybar.nix b/home-manager/modules/desktop/common/wayland-wm/waybar.nix new file mode 100644 index 0000000..4104e18 --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/waybar.nix @@ -0,0 +1,425 @@ +{ outputs, config, lib, pkgs, ... }: + +let + # Dependencies + jq = "${pkgs.jq}/bin/jq"; + xml = "${pkgs.xmlstarlet}/bin/xml"; + gamemoded = "${pkgs.gamemode}/bin/gamemoded"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + journalctl = "${pkgs.systemd}/bin/journalctl"; + playerctl = "${pkgs.playerctl}/bin/playerctl"; + playerctld = "${pkgs.playerctl}/bin/playerctld"; + neomutt = "${pkgs.neomutt}/bin/neomutt"; + pavucontrol = "${pkgs.pavucontrol}/bin/pavucontrol"; + btm = "${pkgs.bottom}/bin/btm"; + wofi = "${pkgs.wofi}/bin/wofi"; + ikhal = "${pkgs.khal}/bin/ikhal"; + + terminal = "${pkgs.kitty}/bin/kitty"; + terminal-spawn = cmd: "${terminal} $SHELL -i -c ${cmd}"; + + calendar = terminal-spawn ikhal; + systemMonitor = terminal-spawn btm; + mail = terminal-spawn neomutt; + + # Function to simplify making waybar outputs + jsonOutput = name: { pre ? "", text ? "", tooltip ? "", alt ? "", class ? "", percentage ? "" }: "${pkgs.writeShellScriptBin "waybar-${name}" '' + set -euo pipefail + ${pre} + ${jq} -cn \ + --arg text "${text}" \ + --arg tooltip "${tooltip}" \ + --arg alt "${alt}" \ + --arg class "${class}" \ + --arg percentage "${percentage}" \ + '{text:$text,tooltip:$tooltip,alt:$alt,class:$class,percentage:$percentage}' + ''}/bin/waybar-${name}"; +in +{ + programs.waybar = { + enable = true; + settings = { + + secondary = { + mode = "dock"; + layer = "top"; + height = 32; + width = 100; + margin = "6"; + position = "bottom"; + modules-center = (lib.optionals config.wayland.windowManager.sway.enable [ + "sway/workspaces" + "sway/mode" + ]) ++ (lib.optionals config.wayland.windowManager.hyprland.enable [ + "wlr/workspaces" + ]); + + "wlr/workspaces" = { + on-click = "activate"; + }; + }; + + primary = { + mode = "dock"; + layer = "top"; + height = 40; + margin = "6"; + position = "top"; + output = builtins.map (m: m.name) (builtins.filter (m: ! m.noBar) config.monitors); + modules-left = [ + "custom/menu" + "custom/currentplayer" + "custom/player" + ]; + modules-center = [ + "cpu" + "custom/gpu" + "memory" + "clock" + "pulseaudio" + "custom/unread-mail" + "custom/gammastep" + "custom/gpg-agent" + ]; + modules-right = [ + "custom/gamemode" + "network" + "custom/tailscale-ping" + "battery" + "tray" + "custom/hostname" + ]; + + clock = { + format = "{:%d/%m %H:%M}"; + tooltip-format = '' + {:%Y %B} + {calendar}''; + on-click = calendar; + }; + cpu = { + format = " {usage}%"; + on-click = systemMonitor; + }; + "custom/gpu" = { + interval = 5; + return-type = "json"; + exec = jsonOutput "gpu" { + text = "$(cat /sys/class/drm/card0/device/gpu_busy_percent)"; + tooltip = "GPU Usage"; + }; + format = "󰒋 {}%"; + on-click = systemMonitor; + }; + memory = { + format = "󰍛 {}%"; + interval = 5; + on-click = systemMonitor; + }; + pulseaudio = { + format = "{icon} {volume}%"; + format-muted = " 0%"; + format-icons = { + headphone = "󰋋"; + headset = "󰋎"; + portable = ""; + default = [ "" "" "" ]; + }; + on-click = pavucontrol; + }; + idle_inhibitor = { + format = "{icon}"; + format-icons = { + activated = "󰒳"; + deactivated = "󰒲"; + }; + }; + battery = { + bat = "BAT0"; + interval = 10; + format-icons = [ "󰁺" "󰁻" "󰁼" "󰁽" "󰁾" "󰁿" "󰂀" "󰂁" "󰂂" "󰁹" ]; + format = "{icon} {capacity}%"; + format-charging = "󰂄 {capacity}%"; + onclick = ""; + }; + "sway/window" = { + max-length = 20; + }; + network = { + interval = 3; + format-wifi = " {essid}"; + format-ethernet = "󰈁 Connected"; + format-disconnected = ""; + tooltip-format = '' + {ifname} + {ipaddr}/{cidr} + Up: {bandwidthUpBits} + Down: {bandwidthDownBits}''; + on-click = ""; + }; + "custom/tailscale-ping" = { + interval = 2; + return-type = "json"; + exec = + let + inherit (builtins) concatStringsSep attrNames; + hosts = attrNames outputs.nixosConfigurations; + homeMachine = "merope"; + remoteMachine = "alcyone"; + in + jsonOutput "tailscale-ping" { + # Build variables for each host + pre = '' + set -o pipefail + ${concatStringsSep "\n" (map (host: '' + ping_${host}="$(timeout 2 ping -c 1 -q ${host} 2>/dev/null | tail -1 | cut -d '/' -f5 | cut -d '.' -f1)ms" || ping_${host}="Disconnected" + '') hosts)} + ''; + # Access a remote machine's and a home machine's ping + text = " $ping_${remoteMachine} /  $ping_${homeMachine}"; + # Show pings from all machines + tooltip = concatStringsSep "\n" (map (host: "${host}: $ping_${host}") hosts); + }; + format = "{}"; + on-click = ""; + }; + "custom/menu" = { + return-type = "json"; + exec = jsonOutput "menu" { + text = ""; + tooltip = ''$(cat /etc/os-release | grep PRETTY_NAME | cut -d '"' -f2)''; + }; + on-click = "${wofi} -S drun -x 10 -y 10 -W 25% -H 60%"; + }; + "custom/hostname" = { + exec = "echo $USER@$(hostname)"; + on-click = terminal; + }; + "custom/unread-mail" = { + interval = 5; + return-type = "json"; + exec = jsonOutput "unread-mail" { + pre = '' + count=$(find ~/Mail/*/Inbox/new -type f | wc -l) + if [ "$count" == "0" ]; then + subjects="No new mail" + status="read" + else + subjects=$(\ + grep -h "Subject: " -r ~/Mail/*/Inbox/new | cut -d ':' -f2- | \ + perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | ${xml} esc | sed -e 's/^/\-/'\ + ) + status="unread" + fi + if pgrep mbsync &>/dev/null; then + status="syncing" + fi + ''; + text = "$count"; + tooltip = "$subjects"; + alt = "$status"; + }; + format = "{icon} ({})"; + format-icons = { + "read" = "󰇯"; + "unread" = "󰇮"; + "syncing" = "󰁪"; + }; + on-click = mail; + }; + "custom/gpg-agent" = { + interval = 2; + return-type = "json"; + exec = + let gpgCmds = import ../../../cli/gpg-commands.nix { inherit pkgs; }; + in + jsonOutput "gpg-agent" { + pre = ''status=$(${gpgCmds.isUnlocked} && echo "unlocked" || echo "locked")''; + alt = "$status"; + tooltip = "GPG is $status"; + }; + format = "{icon}"; + format-icons = { + "locked" = ""; + "unlocked" = ""; + }; + on-click = ""; + }; + "custom/gamemode" = { + exec-if = "${gamemoded} --status | grep 'is active' -q"; + interval = 2; + return-type = "json"; + exec = jsonOutput "gamemode" { + tooltip = "Gamemode is active"; + }; + format = " "; + }; + "custom/gammastep" = { + interval = 5; + return-type = "json"; + exec = jsonOutput "gammastep" { + pre = '' + if unit_status="$(${systemctl} --user is-active gammastep)"; then + status="$unit_status ($(${journalctl} --user -u gammastep.service -g 'Period: ' | tail -1 | cut -d ':' -f6 | xargs))" + else + status="$unit_status" + fi + ''; + alt = "\${status:-inactive}"; + tooltip = "Gammastep is $status"; + }; + format = "{icon}"; + format-icons = { + "activating" = "󰁪 "; + "deactivating" = "󰁪 "; + "inactive" = "? "; + "active (Night)" = " "; + "active (Nighttime)" = " "; + "active (Transition (Night)" = " "; + "active (Transition (Nighttime)" = " "; + "active (Day)" = " "; + "active (Daytime)" = " "; + "active (Transition (Day)" = " "; + "active (Transition (Daytime)" = " "; + }; + on-click = "${systemctl} --user is-active gammastep && ${systemctl} --user stop gammastep || ${systemctl} --user start gammastep"; + }; + "custom/currentplayer" = { + interval = 2; + return-type = "json"; + exec = jsonOutput "currentplayer" { + pre = '' + player="$(${playerctl} status -f "{{playerName}}" 2>/dev/null || echo "No player active" | cut -d '.' -f1)" + count="$(${playerctl} -l | wc -l)" + if ((count > 1)); then + more=" +$((count - 1))" + else + more="" + fi + ''; + alt = "$player"; + tooltip = "$player ($count available)"; + text = "$more"; + }; + format = "{icon}{}"; + format-icons = { + "No player active" = " "; + "Celluloid" = "󰎁 "; + "spotify" = " 󰓇"; + "ncspot" = " 󰓇"; + "qutebrowser" = "󰖟"; + "firefox" = " "; + "discord" = " 󰙯 "; + "sublimemusic" = " "; + "kdeconnect" = "󰄡 "; + }; + on-click = "${playerctld} shift"; + on-click-right = "${playerctld} unshift"; + }; + "custom/player" = { + exec-if = "${playerctl} status"; + exec = ''${playerctl} metadata --format '{"text": "{{artist}} - {{title}}", "alt": "{{status}}", "tooltip": "{{title}} ({{artist}} - {{album}})"}' ''; + return-type = "json"; + interval = 2; + max-length = 30; + format = "{icon} {}"; + format-icons = { + "Playing" = "󰐊"; + "Paused" = "󰏤 "; + "Stopped" = "󰓛"; + }; + on-click = "${playerctl} play-pause"; + }; + }; + + }; + # Cheatsheet: + # x -> all sides + # x y -> vertical, horizontal + # x y z -> top, horizontal, bottom + # w x y z -> top, right, bottom, left + style = let inherit (config.colorscheme) colors; in /* css */ '' + * { + font-family: ${config.fontProfiles.regular.family}, ${config.fontProfiles.monospace.family}; + font-size: 12pt; + padding: 0 8px; + } + + .modules-right { + margin-right: -15px; + } + + .modules-left { + margin-left: -15px; + } + + window#waybar.top { + opacity: 0.95; + padding: 0; + background-color: #${colors.base00}; + border: 2px solid #${colors.base0C}; + border-radius: 10px; + } + window#waybar.bottom { + opacity: 0.90; + background-color: #${colors.base00}; + border: 2px solid #${colors.base0C}; + border-radius: 10px; + } + + window#waybar { + color: #${colors.base05}; + } + + #workspaces button { + background-color: #${colors.base01}; + color: #${colors.base05}; + margin: 4px; + } + #workspaces button.hidden { + background-color: #${colors.base00}; + color: #${colors.base04}; + } + #workspaces button.focused, + #workspaces button.active { + background-color: #${colors.base0A}; + color: #${colors.base00}; + } + + #clock { + background-color: #${colors.base0C}; + color: #${colors.base00}; + padding-left: 15px; + padding-right: 15px; + margin-top: 0; + margin-bottom: 0; + border-radius: 10px; + } + + #custom-menu { + background-color: #${colors.base0C}; + color: #${colors.base00}; + padding-left: 15px; + padding-right: 22px; + margin-left: 0; + margin-right: 10px; + margin-top: 0; + margin-bottom: 0; + border-radius: 10px; + } + #custom-hostname { + background-color: #${colors.base0C}; + color: #${colors.base00}; + padding-left: 15px; + padding-right: 18px; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; + border-radius: 10px; + } + #tray { + color: #${colors.base05}; + } + ''; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/wezterm.nix b/home-manager/modules/desktop/common/wayland-wm/wezterm.nix new file mode 100644 index 0000000..692f5fb --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/wezterm.nix @@ -0,0 +1,54 @@ +{ config, pkgs, ... }: + +let + inherit (config) colorscheme; + inherit (colorscheme) colors; +in +{ + programs.wezterm = { + enable = true; + colorSchemes = { + "${colorscheme.slug}" = { + foreground = "#${colors.base05}"; + background = "#${colors.base00}"; + + ansi = [ + "#${colors.base08}" + "#${colors.base09}" + "#${colors.base0A}" + "#${colors.base0B}" + "#${colors.base0C}" + "#${colors.base0D}" + "#${colors.base0E}" + "#${colors.base0F}" + ]; + brights = [ + "#${colors.base00}" + "#${colors.base01}" + "#${colors.base02}" + "#${colors.base03}" + "#${colors.base04}" + "#${colors.base05}" + "#${colors.base06}" + "#${colors.base07}" + ]; + cursor_fg = "#${colors.base00}"; + cursor_bg = "#${colors.base05}"; + selection_fg = "#${colors.base00}"; + selection_bg = "#${colors.base05}"; + }; + }; + extraConfig = /* lua */ '' + return { + font = wezterm.font("${config.fontProfiles.monospace.family}"), + font_size = 12.0, + color_scheme = "${colorscheme.slug}", + hide_tab_bar_if_only_one_tab = true, + window_close_confirmation = "NeverPrompt", + set_environment_variables = { + TERM = 'wezterm', + }, + } + ''; + }; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/wofi-run-shell.patch b/home-manager/modules/desktop/common/wayland-wm/wofi-run-shell.patch new file mode 100644 index 0000000..930563b --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/wofi-run-shell.patch @@ -0,0 +1,20 @@ +--- a/src/wofi.c Mon Feb 22 23:53:57 2021 -0800 ++++ b/src/wofi.c Wed Aug 11 13:49:13 2021 -0300 +@@ -881,12 +881,15 @@ + } + + void wofi_term_run(const char* cmd) { ++ char *shell = getenv("SHELL"); ++ if (!shell) shell = "sh"; ++ + if(terminal != NULL) { +- execlp(terminal, terminal, "-e", cmd, NULL); ++ execlp(terminal, terminal, "-e", shell, "-c", cmd, NULL); + } + size_t term_count = sizeof(terminals) / sizeof(char*); + for(size_t count = 0; count < term_count; ++count) { +- execlp(terminals[count], terminals[count], "-e", cmd, NULL); ++ execlp(terminals[count], terminals[count], "-e", shell, "-c", cmd, NULL); + } + fprintf(stderr, "No terminal emulator found please set term in config or use --term\n"); + exit(1); diff --git a/home-manager/modules/desktop/common/wayland-wm/wofi.nix b/home-manager/modules/desktop/common/wayland-wm/wofi.nix new file mode 100644 index 0000000..c851788 --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/wofi.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: +let + wofi = pkgs.wofi.overrideAttrs (oa: { + patches = (oa.patches or [ ]) ++ [ + ./wofi-run-shell.patch # Fix for https://todo.sr.ht/~scoopta/wofi/174 + ]; + }); + + pass = config.programs.password-store.package; + passEnabled = config.programs.password-store.enable; + pass-wofi = pkgs.pass-wofi.override { inherit pass; }; +in +{ + home.packages = [ wofi ] ++ + (lib.optional passEnabled pass-wofi); + + xdg.configFile."wofi/config".text = '' + image_size=48 + columns=3 + allow_images=true + insensitive=true + + run-always_parse_args=true + run-cache_file=/dev/null + run-exec_search=true + ''; +} diff --git a/home-manager/modules/desktop/common/wayland-wm/zathura.nix b/home-manager/modules/desktop/common/wayland-wm/zathura.nix new file mode 100644 index 0000000..8348cc1 --- /dev/null +++ b/home-manager/modules/desktop/common/wayland-wm/zathura.nix @@ -0,0 +1,32 @@ +{ config, ... }: +let inherit (config.colorscheme) colors; +in { + programs.zathura = { + enable = true; + options = { + selection-clipboard = "clipboard"; + font = "${config.fontProfiles.regular.family} 12"; + recolor = true; + default-bg = "#${colors.base00}"; + default-fg = "#${colors.base01}"; + statusbar-bg = "#${colors.base02}"; + statusbar-fg = "#${colors.base04}"; + inputbar-bg = "#${colors.base00}"; + inputbar-fg = "#${colors.base07}"; + notification-bg = "#${colors.base00}"; + notification-fg = "#${colors.base07}"; + notification-error-bg = "#${colors.base00}"; + notification-error-fg = "#${colors.base08}"; + notification-warning-bg = "#${colors.base00}"; + notification-warning-fg = "#${colors.base08}"; + highlight-color = "#${colors.base0A}"; + highlight-active-color = "#${colors.base0D}"; + completion-bg = "#${colors.base01}"; + completion-fg = "#${colors.base05}"; + completions-highlight-bg = "#${colors.base0D}"; + completions-highlight-fg = "#${colors.base07}"; + recolor-lightcolor = "#${colors.base00}"; + recolor-darkcolor = "#${colors.base06}"; + }; + }; +} diff --git a/home-manager/modules/desktop/hprland/config.nix b/home-manager/modules/desktop/hprland/config.nix new file mode 100644 index 0000000..4059055 --- /dev/null +++ b/home-manager/modules/desktop/hprland/config.nix @@ -0,0 +1,251 @@ +{ home, colorscheme, wallpaper }: +let + inherit (home.sessionVariables) TERMINAL BROWSER EDITOR; +in +'' + general { + gaps_in=15 + gaps_out=20 + border_size=2.7 + col.active_border=0xff${colorscheme.colors.base0C} + col.inactive_border=0xff${colorscheme.colors.base02} + col.group_border_active=0xff${colorscheme.colors.base0B} + col.group_border=0xff${colorscheme.colors.base04} + cursor_inactive_timeout=4 + } + + decoration { + active_opacity=0.94 + inactive_opacity=0.84 + fullscreen_opacity=1.0 + rounding=5 + blur=true + blur_size=5 + blur_passes=3 + blur_new_optimizations=true + blur_ignore_opacity=true + drop_shadow=true + shadow_range=12 + shadow_offset=3 3 + col.shadow=0x44000000 + col.shadow_inactive=0x66000000 + } + + animations { + enabled=true + + bezier=easein,0.11, 0, 0.5, 0 + bezier=easeout,0.5, 1, 0.89, 1 + bezier=easeinout,0.45, 0, 0.55, 1 + + animation=windowsIn,1,3,easeout,slide + animation=windowsOut,1,3,easein,slide + animation=windowsMove,1,3,easeout + + animation=fadeIn,1,3,easeout + animation=fadeOut,1,3,easein + animation=fadeSwitch,1,3,easeout + animation=fadeShadow,1,3,easeout + animation=fadeDim,1,3,easeout + animation=border,1,3,easeout + + animation=workspaces,1,2,easeout,slide + } + + dwindle { + split_width_multiplier=1.35 + } + + misc { + vfr=on + } + + input { + kb_layout=br,us + touchpad { + disable_while_typing=false + } + } + + # Passthrough mode (e.g. for VNC) + bind=SUPER,P,submap,passthrough + submap=passthrough + bind=SUPER,P,submap,reset + submap=reset + + + # Startup + exec-once=waybar + exec=swaybg -i ${wallpaper} --mode fill + exec-once=mako + exec-once=swayidle -w + + # Mouse binding + bindm=SUPER,mouse:272,movewindow + bindm=SUPER,mouse:273,resizewindow + + # Program bindings + bind=SUPER,Return,exec,${TERMINAL} + bind=SUPER,w,exec,makoctl dismiss + bind=SUPER,v,exec,${TERMINAL} $SHELL -ic ${EDITOR} + bind=SUPER,b,exec,${BROWSER} + + bind=SUPER,x,exec,wofi -S drun -x 10 -y 10 -W 25% -H 60% + bind=SUPER,d,exec,wofi -S run + bind=,Scroll_Lock,exec,pass-wofi # fn+k + bind=,XF86Calculator,exec,pass-wofi # fn+f12 + + # Toggle waybar + bind=,XF86Tools,exec,pkill -USR1 waybar # profile button + + # Lock screen + bind=,XF86Launch5,exec,swaylock -S + bind=,XF86Launch4,exec,swaylock -S + bind=SUPER,backspace,exec,swaylock -S + + # Screenshots + bind=,Print,exec,grimblast --notify copy output + bind=SHIFT,Print,exec,grimblast --notify copy active + bind=CONTROL,Print,exec,grimblast --notify copy screen + bind=SUPER,Print,exec,grimblast --notify copy window + bind=ALT,Print,exec,grimblast --notify copy area + + # Keyboard controls (brightness, media, sound, etc) + bind=,XF86MonBrightnessUp,exec,light -A 10 + bind=,XF86MonBrightnessDown,exec,light -U 10 + + bind=,XF86AudioNext,exec,playerctl next + bind=,XF86AudioPrev,exec,playerctl previous + bind=,XF86AudioPlay,exec,playerctl play-pause + bind=,XF86AudioStop,exec,playerctl stop + bind=ALT,XF86AudioNext,exec,playerctld shift + bind=ALT,XF86AudioPrev,exec,playerctld unshift + bind=ALT,XF86AudioPlay,exec,systemctl --user restart playerctld + + bind=,XF86AudioRaiseVolume,exec,pactl set-sink-volume @DEFAULT_SINK@ +5% + bind=,XF86AudioLowerVolume,exec,pactl set-sink-volume @DEFAULT_SINK@ -5% + bind=,XF86AudioMute,exec,pactl set-sink-mute @DEFAULT_SINK@ toggle + + bind=SHIFT,XF86AudioMute,exec,pactl set-source-mute @DEFAULT_SOURCE@ toggle + bind=,XF86AudioMicMute,exec,pactl set-source-mute @DEFAULT_SOURCE@ toggle + + + # Window manager controls + bind=SUPERSHIFT,q,killactive + bind=SUPERSHIFT,e,exit + + bind=SUPER,s,togglesplit + bind=SUPER,f,fullscreen,1 + bind=SUPERSHIFT,f,fullscreen,0 + bind=SUPERSHIFT,space,togglefloating + + bind=SUPER,minus,splitratio,-0.25 + bind=SUPERSHIFT,minus,splitratio,-0.3333333 + + bind=SUPER,equal,splitratio,0.25 + bind=SUPERSHIFT,equal,splitratio,0.3333333 + + bind=SUPER,g,togglegroup + bind=SUPER,apostrophe,changegroupactive,f + bind=SUPERSHIFT,apostrophe,changegroupactive,b + + bind=SUPER,left,movefocus,l + bind=SUPER,right,movefocus,r + bind=SUPER,up,movefocus,u + bind=SUPER,down,movefocus,d + bind=SUPER,h,movefocus,l + bind=SUPER,l,movefocus,r + bind=SUPER,k,movefocus,u + bind=SUPER,j,movefocus,d + + bind=SUPERSHIFT,left,swapwindow,l + bind=SUPERSHIFT,right,swapwindow,r + bind=SUPERSHIFT,up,swapwindow,u + bind=SUPERSHIFT,down,swapwindow,d + bind=SUPERSHIFT,h,swapwindow,l + bind=SUPERSHIFT,l,swapwindow,r + bind=SUPERSHIFT,k,swapwindow,u + bind=SUPERSHIFT,j,swapwindow,d + + bind=SUPERCONTROL,left,focusmonitor,l + bind=SUPERCONTROL,right,focusmonitor,r + bind=SUPERCONTROL,up,focusmonitor,u + bind=SUPERCONTROL,down,focusmonitor,d + bind=SUPERCONTROL,h,focusmonitor,l + bind=SUPERCONTROL,l,focusmonitor,r + bind=SUPERCONTROL,k,focusmonitor,u + bind=SUPERCONTROL,j,focusmonitor,d + + bind=SUPERCONTROL,1,focusmonitor,DP-1 + bind=SUPERCONTROL,2,focusmonitor,DP-2 + bind=SUPERCONTROL,3,focusmonitor,DP-3 + + bind=SUPERCONTROLSHIFT,left,movewindow,mon:l + bind=SUPERCONTROLSHIFT,right,movewindow,mon:r + bind=SUPERCONTROLSHIFT,up,movewindow,mon:u + bind=SUPERCONTROLSHIFT,down,movewindow,mon:d + bind=SUPERCONTROLSHIFT,h,movewindow,mon:l + bind=SUPERCONTROLSHIFT,l,movewindow,mon:r + bind=SUPERCONTROLSHIFT,k,movewindow,mon:u + bind=SUPERCONTROLSHIFT,j,movewindow,mon:d + + bind=SUPERALT,left,movecurrentworkspacetomonitor,l + bind=SUPERALT,right,movecurrentworkspacetomonitor,r + bind=SUPERALT,up,movecurrentworkspacetomonitor,u + bind=SUPERALT,down,movecurrentworkspacetomonitor,d + bind=SUPERALT,h,movecurrentworkspacetomonitor,l + bind=SUPERALT,l,movecurrentworkspacetomonitor,r + bind=SUPERALT,k,movecurrentworkspacetomonitor,u + bind=SUPERALT,j,movecurrentworkspacetomonitor,d + + bind=SUPER,u,togglespecialworkspace + bind=SUPERSHIFT,u,movetoworkspace,special + + bind=SUPER,1,workspace,01 + bind=SUPER,2,workspace,02 + bind=SUPER,3,workspace,03 + bind=SUPER,4,workspace,04 + bind=SUPER,5,workspace,05 + bind=SUPER,6,workspace,06 + bind=SUPER,7,workspace,07 + bind=SUPER,8,workspace,08 + bind=SUPER,9,workspace,09 + bind=SUPER,0,workspace,10 + bind=SUPER,f1,workspace,11 + bind=SUPER,f2,workspace,12 + bind=SUPER,f3,workspace,13 + bind=SUPER,f4,workspace,14 + bind=SUPER,f5,workspace,15 + bind=SUPER,f6,workspace,16 + bind=SUPER,f7,workspace,17 + bind=SUPER,f8,workspace,18 + bind=SUPER,f9,workspace,19 + bind=SUPER,f10,workspace,20 + bind=SUPER,f11,workspace,21 + bind=SUPER,f12,workspace,22 + + bind=SUPERSHIFT,1,movetoworkspacesilent,01 + bind=SUPERSHIFT,2,movetoworkspacesilent,02 + bind=SUPERSHIFT,3,movetoworkspacesilent,03 + bind=SUPERSHIFT,4,movetoworkspacesilent,04 + bind=SUPERSHIFT,5,movetoworkspacesilent,05 + bind=SUPERSHIFT,6,movetoworkspacesilent,06 + bind=SUPERSHIFT,7,movetoworkspacesilent,07 + bind=SUPERSHIFT,8,movetoworkspacesilent,08 + bind=SUPERSHIFT,9,movetoworkspacesilent,09 + bind=SUPERSHIFT,0,movetoworkspacesilent,10 + bind=SUPERSHIFT,f1,movetoworkspacesilent,11 + bind=SUPERSHIFT,f2,movetoworkspacesilent,12 + bind=SUPERSHIFT,f3,movetoworkspacesilent,13 + bind=SUPERSHIFT,f4,movetoworkspacesilent,14 + bind=SUPERSHIFT,f5,movetoworkspacesilent,15 + bind=SUPERSHIFT,f6,movetoworkspacesilent,16 + bind=SUPERSHIFT,f7,movetoworkspacesilent,17 + bind=SUPERSHIFT,f8,movetoworkspacesilent,18 + bind=SUPERSHIFT,f9,movetoworkspacesilent,19 + bind=SUPERSHIFT,f10,movetoworkspacesilent,20 + bind=SUPERSHIFT,f11,movetoworkspacesilent,21 + bind=SUPERSHIFT,f12,movetoworkspacesilent,22 + + blurls=waybar +'' diff --git a/home-manager/modules/desktop/hprland/default.nix b/home-manager/modules/desktop/hprland/default.nix new file mode 100644 index 0000000..1c34cee --- /dev/null +++ b/home-manager/modules/desktop/hprland/default.nix @@ -0,0 +1,51 @@ +{ inputs, lib, config, pkgs, ... }: { + imports = [ + ../common + ../common/wayland-wm + inputs.hyprland.homeManagerModules.default + ]; + + programs = { + fish.loginShellInit = '' + if test (tty) = "/dev/tty1" + exec Hyprland &> /dev/null + end + ''; + zsh.loginExtra = '' + if [ "$(tty)" = "/dev/tty1" ]; then + exec Hyprland &> /dev/null + fi + ''; + zsh.profileExtra = '' + if [ "$(tty)" = "/dev/tty1" ]; then + exec Hyprland &> /dev/null + fi + ''; + }; + + home.packages = with pkgs; [ + inputs.hyprwm-contrib.packages.${system}.grimblast + swaybg + swayidle + # TODO + # inputs.hyprland.packages.${system}.xdg-desktop-portal-hyprland + ]; + + programs.waybar.package = pkgs.waybar.overrideAttrs (oa: { + mesonFlags = (oa.mesonFlags or [ ]) ++ [ "-Dexperimental=true" ]; + }); + + wayland.windowManager.hyprland = { + enable = true; + package = inputs.hyprland.packages.${pkgs.system}.default; + extraConfig = + (import ./monitors.nix { + inherit lib; + inherit (config) monitors; + }) + + (import ./config.nix { + inherit (config) home colorscheme wallpaper; + }); + }; +} + diff --git a/home-manager/modules/desktop/hprland/monitors.nix b/home-manager/modules/desktop/hprland/monitors.nix new file mode 100644 index 0000000..edd7d95 --- /dev/null +++ b/home-manager/modules/desktop/hprland/monitors.nix @@ -0,0 +1,9 @@ +# Convert config.monitors into hyprland's format +{ lib, monitors }: +let enabledMonitors = lib.filter (m: m.enabled) monitors; +in + +lib.concatStringsSep "\n" (lib.forEach enabledMonitors (m: '' + monitor=${m.name},${toString m.width}x${toString m.height}@${toString m.refreshRate},${toString m.x}x${toString m.y},1 + ${lib.optionalString (m.workspace != null)"workspace=${m.name},${m.workspace}"} +'')) diff --git a/home-manager/pfke_at_errol.nix b/home-manager/pfke_at_errol.nix index 5dcd86e..843077a 100644 --- a/home-manager/pfke_at_errol.nix +++ b/home-manager/pfke_at_errol.nix @@ -7,9 +7,21 @@ let in { imports = [ ./modules/cli/bat.nix + ./modules/cli/starship.nix ./modules/cli/zsh.nix + ./modules/desktop/hprland ./modules/keychain.nix - ./modules/cli/starship.nix + ]; + monitors = [ + { + name = "DP-0"; + width = 3440; + height = 1440; + noBar = true; + x = 0; + workspace = "1"; + enabled = true; + } ]; home.file.".config/nvim".source = mkPersistentLink "dot_files/.config/nvim";