From 11879eac6a14d084a6296040f43270d3886714c8 Mon Sep 17 00:00:00 2001
From: Crony Akatsuki <crony@cronyakatsuki.xyz>
Date: Sun, 2 Feb 2025 19:55:22 +0100
Subject: [PATCH] Install hyprland and additionals.

---
 modules/home-manager/default.nix  |   2 +
 modules/home-manager/hyprland.nix | 217 ++++++++++++++++++++++++++++++
 modules/nixos/default.nix         |   2 +
 modules/nixos/hyprland.nix        |  30 +++++
 4 files changed, 251 insertions(+)
 create mode 100644 modules/home-manager/hyprland.nix
 create mode 100644 modules/nixos/hyprland.nix

diff --git a/modules/home-manager/default.nix b/modules/home-manager/default.nix
index 84d8e2d..b692ffa 100644
--- a/modules/home-manager/default.nix
+++ b/modules/home-manager/default.nix
@@ -9,6 +9,7 @@
     ./obs-studio.nix
     ./nh.nix
     ./restic.nix
+    ./hyprland.nix
   ];
 
   crony.mangohud.enable = lib.mkDefault true;
@@ -20,4 +21,5 @@
   crony.obs-studio.enable = lib.mkDefault true;
   crony.nh.enable = lib.mkDefault true;
   crony.restic.enable = lib.mkDefault true;
+  crony.hyprland.enable = lib.mkDefault true;
 }
diff --git a/modules/home-manager/hyprland.nix b/modules/home-manager/hyprland.nix
new file mode 100644
index 0000000..7a50ef9
--- /dev/null
+++ b/modules/home-manager/hyprland.nix
@@ -0,0 +1,217 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}: {
+  options = {
+    crony.hyprland.enable = lib.mkEnableOption "Enable hyprland and configure it for me";
+  };
+
+  config = lib.mkIf config.crony.hyprland.enable {
+    home.packages = with pkgs; [
+      (writeShellScriptBin "tofi-pass" ''
+        tofi --hide-input true --prompt-text 'Password: ' --require-match false --hidden-character '.' < /dev/null
+      '')
+      cliphist
+      wl-clipboard
+    ];
+
+    # Enable and setup tofi
+    programs.tofi = {
+      enable = true;
+      settings = {
+        anchor = "top";
+        width = "100%";
+        height = "28";
+        horizontal = true;
+        history = false;
+        require-match = false;
+        terminal = "foot";
+        outline-width = 0;
+        border-width = 0;
+        min-input-width = 120;
+        result-spacing = 15;
+        padding-top = 4;
+        padding-bottom = 0;
+        padding-left = 5;
+        padding-right = 5;
+      };
+    };
+
+    # Enable hyprpaper
+    services.hyprpaper.enable = true;
+
+    # Enable hypridle
+    services.hypridle = {
+      enable = true;
+      settings = {
+        general = {
+          lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances.
+          before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
+          after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
+        };
+
+        listener = [
+          {
+            timeout = 300; # 5min
+            on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
+          }
+          {
+            timeout = 330; # 5.5min
+            on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
+            on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has fired.
+          }
+        ];
+      };
+    };
+
+    # Enable hyprlock
+    programs.hyprlock = {
+      enable = true;
+      settings = {
+        general = {
+          disable_loading_bar = true;
+          grace = 300;
+          hide_cursor = true;
+          no_fade_in = false;
+        };
+      };
+    };
+
+    # Setup and enable hyprland
+    wayland.windowManager.hyprland = {
+      enable = true;
+
+      systemd.enable = false; # Using USWM globally
+
+      settings = {
+        "$mod" = "SUPER";
+        "$menu" = "tofi";
+        "$terminal" = "foot";
+
+        exec-once = [
+          "wl-paste --type text --watch cliphist store" # Stores only text data
+          "wl-paste --type image --watch cliphist store" # Stores only image data
+        ];
+
+        monitor = [
+          "HDMI-A-1, 1920x1080@144, 0x0, 1"
+        ];
+
+        animations = {
+          enabled = "yes";
+        };
+
+        decoration = {
+          blur = {
+            enabled = true;
+          };
+
+          shadow = {
+            enabled = true;
+          };
+
+          rounding = 10;
+        };
+
+        general = {
+          border_size = 5;
+          layout = "master";
+          allow_tearing = true;
+        };
+
+        input = {
+          kb_layout = "us";
+          kb_options = "caps:escape";
+        };
+
+        master = {
+          mfact = "0.5";
+          new_status = "slave";
+        };
+
+        binds = {
+          allow_workspace_cycles = true;
+        };
+
+        bind = [
+          "$mod,        Return, exec, $terminal"
+          "$mod SHIFT,  Q, killactive"
+          "$mod CTRL,   E, exit"
+          "$mod SHIFT,  Space, togglefloating"
+          "$mod,        D, exec, tofi-run | xargs hyprctl dispatch exec --"
+          "$mod SHIFT,  D, exec, tofi-drun | xargs hyprctl dispatch exec --"
+
+          "$mod,        V, exec, cliphist list | tofi --horizontal false --height 380 | cliphist decode | wl-copy"
+
+          "$mod,        j, layoutmsg, cyclenext"
+          "$mod,        k, layoutmsg, cycleprev"
+          "$mod SHIFT,  j, layoutmsg, swapnext"
+          "$mod SHIFT,  k, layoutmsg, swapprev"
+
+          "$mod,        h, layoutmsg, mfact -0.05"
+          "$mod,        l, layoutmsg, mfact +0.05"
+
+          "$mod,        Tab, workspace, previous"
+
+          "$mod,        1, workspace, 1"
+          "$mod,        2, workspace, 2"
+          "$mod,        3, workspace, 3"
+          "$mod,        4, workspace, 4"
+          "$mod,        5, workspace, 5"
+          "$mod,        6, workspace, 6"
+          "$mod,        7, workspace, 7"
+          "$mod,        8, workspace, 8"
+          "$mod,        9, workspace, 9"
+
+          "$mod SHIFT,  1, movetoworkspacesilent, 1"
+          "$mod SHIFT,  2, movetoworkspacesilent, 2"
+          "$mod SHIFT,  3, movetoworkspacesilent, 3"
+          "$mod SHIFT,  4, movetoworkspacesilent, 4"
+          "$mod SHIFT,  5, movetoworkspacesilent, 5"
+          "$mod SHIFT,  6, movetoworkspacesilent, 6"
+          "$mod SHIFT,  7, movetoworkspacesilent, 7"
+          "$mod SHIFT,  8, movetoworkspacesilent, 8"
+          "$mod SHIFT,  9, movetoworkspacesilent, 9"
+        ];
+
+        bindel = [
+          ", 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"
+        ];
+
+        # Requires playerctl
+        bindl = [
+          ", XF86AudioPlay, exec, playerctl play-pause"
+          ", XF86AudioPrev, exec, playerctl previous"
+          ", XF86AudioNext, exec, playerctl next"
+
+          '', switch:off:Lid Switch,exec,hyprctl keyword monitor "eDP-1, 1920x1080, 0x0, 1"''
+          '', switch:on:Lid Switch,exec,hyprctl keyword monitor "eDP-1, disable"''
+        ];
+
+        bindm = [
+          # mouse movements
+          "$mod, mouse:272, movewindow"
+          "$mod, mouse:273, resizewindow"
+          "$mod ALT, mouse:272, resizewindow"
+        ];
+
+        windowrulev2 = [
+          # Hide xwaylandvideobridge
+          "opacity 0.0 override, class:^(xwaylandvideobridge)$"
+          "noanim, class:^(xwaylandvideobridge)$"
+          "noinitialfocus, class:^(xwaylandvideobridge)$"
+          "maxsize 1 1, class:^(xwaylandvideobridge)$"
+          "noblur, class:^(xwaylandvideobridge)$"
+          "nofocus, class:^(xwaylandvideobridge)$"
+
+          # Allow tearing for sifu
+          "immediate, class:^(steam_app_2138710)$"
+        ];
+      };
+    };
+  };
+}
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
index d9f043d..83e7ab5 100644
--- a/modules/nixos/default.nix
+++ b/modules/nixos/default.nix
@@ -14,6 +14,7 @@
     ./nfs-share.nix
     ./auto-cpufreq.nix
     ./wireguard.nix
+    ./hyprland.nix
   ];
 
   crony.bluetooth.enable = lib.mkDefault true;
@@ -30,4 +31,5 @@
   crony.nfs-share.enable = lib.mkDefault true;
   crony.auto-cpufreq.enable = lib.mkDefault true;
   crony.wireguard.enable = lib.mkDefault true;
+  crony.hyprland-nixos.enable = lib.mkDefault true;
 }
diff --git a/modules/nixos/hyprland.nix b/modules/nixos/hyprland.nix
new file mode 100644
index 0000000..de62928
--- /dev/null
+++ b/modules/nixos/hyprland.nix
@@ -0,0 +1,30 @@
+{
+  config,
+  lib,
+  ...
+}: {
+  options = {
+    crony.hyprland-nixos.enable = lib.mkEnableOption "Enable hyprland globally";
+  };
+
+  config = lib.mkIf config.crony.hyprland-nixos.enable {
+    programs.uwsm = {
+      enable = true;
+
+      waylandCompositors = {
+        hyprland = {
+          prettyName = "Hyprland";
+          comment = "Hyprland compositor managed by UWSM";
+          binPath = "/run/current-system/sw/bin/Hyprland";
+        };
+      };
+    };
+
+    programs.hyprland = {
+      enable = true;
+      withUWSM = true;
+    };
+
+    security.pam.services.hyprlock = {};
+  };
+}