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";