From 7af406f3150b043b8830688a43d2562af564ecd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=BChl?= Date: Thu, 19 Feb 2026 10:53:30 +0100 Subject: [PATCH] feat: add Hyprland as an additional compositor alongside Niri Enables programs.hyprland at the system level, adds xdg-desktop-portal-hyprland with per-compositor portal routing, and wires up a home-manager config for endurance mirroring the Niri layout (same keybinds, monitors, window rules). Niri remains the default SDDM session. Co-Authored-By: Claude Sonnet 4.5 --- flake.lock | 6 +- home/by-host/endurance/config/dev.nix | 1 + home/by-host/endurance/default.nix | 1 + home/by-host/endurance/hyprland/default.nix | 15 ++++ home/by-host/endurance/hyprland/keybinds.nix | 59 ++++++++++++ home/by-host/endurance/hyprland/settings.nix | 85 ++++++++++++++++++ .../endurance/hyprland/window-rules.nix | 28 ++++++ modules/nixos/profiles/graphical/wm.nix | 8 +- overlays/unstable.nix | 2 +- ...7faeb894fd776d38be4e-nix-cache-privkey.age | 7 ++ ...ba1595d566934c2ea6ba-nix-cache-privkey.age | Bin 475 -> 0 bytes 11 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 home/by-host/endurance/hyprland/default.nix create mode 100644 home/by-host/endurance/hyprland/keybinds.nix create mode 100644 home/by-host/endurance/hyprland/settings.nix create mode 100644 home/by-host/endurance/hyprland/window-rules.nix create mode 100644 secrets/rekeyed/endurance/0f723801d4717faeb894fd776d38be4e-nix-cache-privkey.age delete mode 100644 secrets/rekeyed/endurance/b26d17749592ba1595d566934c2ea6ba-nix-cache-privkey.age diff --git a/flake.lock b/flake.lock index 5691021..ec03fee 100644 --- a/flake.lock +++ b/flake.lock @@ -778,11 +778,11 @@ }, "master": { "locked": { - "lastModified": 1767143992, - "narHash": "sha256-c3jlq36uxltxGLuQ3KPYfxZkue/LLD0Ct3NdhBUsRyo=", + "lastModified": 1771456066, + "narHash": "sha256-CLuGt3yg70gnhSam+0qpcWgPnUdY98wVeH4lByklol4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5830d8dfe6ae79365987d78bda3dd4152c271d8b", + "rev": "be6cf55e819f4d362aa6be60254bbb2537f9a5cb", "type": "github" }, "original": { diff --git a/home/by-host/endurance/config/dev.nix b/home/by-host/endurance/config/dev.nix index 406e13f..8e4f253 100644 --- a/home/by-host/endurance/config/dev.nix +++ b/home/by-host/endurance/config/dev.nix @@ -15,6 +15,7 @@ rfc # TUI-based RFC reader nix-init # Generate Nix packages from URLs install-nothing + marimo # Language Servers lua-language-server diff --git a/home/by-host/endurance/default.nix b/home/by-host/endurance/default.nix index 2e4830f..855fc15 100644 --- a/home/by-host/endurance/default.nix +++ b/home/by-host/endurance/default.nix @@ -15,6 +15,7 @@ ./wakatime.nix ./gpg ./niri + ./hyprland ./stylix.nix ./default-applications.nix ./misc/launcher.nix diff --git a/home/by-host/endurance/hyprland/default.nix b/home/by-host/endurance/hyprland/default.nix new file mode 100644 index 0000000..3aade58 --- /dev/null +++ b/home/by-host/endurance/hyprland/default.nix @@ -0,0 +1,15 @@ +{pkgs, ...}: { + imports = [ + ./settings.nix + ./keybinds.nix + ./window-rules.nix + ]; + + wayland.windowManager.hyprland.enable = true; + + home.packages = with pkgs; [ + wl-clipboard + cliphist + hyprpicker + ]; +} diff --git a/home/by-host/endurance/hyprland/keybinds.nix b/home/by-host/endurance/hyprland/keybinds.nix new file mode 100644 index 0000000..b99cac0 --- /dev/null +++ b/home/by-host/endurance/hyprland/keybinds.nix @@ -0,0 +1,59 @@ +{pkgs, ...}: { + wayland.windowManager.hyprland.settings = { + "$mod" = "SUPER"; + + bind = [ + # Apps + "$mod, space, exec, fuzzel" + "$mod, c, exec, ${pkgs.harbor.spawn-term}/bin/spawn-term" + "$mod, e, exec, nautilus" + "$mod, d, exec, zeal" + "$mod, g, exec, ${pkgs.harbor.hg-picker}/bin/hg-picker" + + # Window management + "$mod, q, killactive" + "$mod, f, fullscreen, 1" + "$mod, t, togglefloating" + "$mod, p, pseudo" + "$mod SHIFT, j, togglesplit" + + # Focus (vim-style, matching niri keybinds) + "$mod, h, movefocus, l" + "$mod, l, movefocus, r" + "$mod, k, movefocus, u" + "$mod, j, movefocus, d" + + # Move windows + "$mod CTRL, h, movewindow, l" + "$mod CTRL, l, movewindow, r" + "$mod CTRL, k, movewindow, u" + "$mod CTRL, j, movewindow, d" + + # Workspaces + "$mod, 1, workspace, 1" + "$mod, 2, workspace, 2" + "$mod, 3, workspace, 3" + "$mod, 4, workspace, 4" + "$mod, 5, workspace, 5" + + # Move to workspace silently + "$mod CTRL, 1, movetoworkspacesilent, 1" + "$mod CTRL, 2, movetoworkspacesilent, 2" + "$mod CTRL, 3, movetoworkspacesilent, 3" + "$mod CTRL, 4, movetoworkspacesilent, 4" + "$mod CTRL, 5, movetoworkspacesilent, 5" + ]; + + bindm = [ + # Mouse: move and resize windows + "$mod, mouse:272, movewindow" + "$mod, mouse:273, resizewindow" + ]; + + bindl = [ + # Scroll through workspaces + "$mod, mouse_down, workspace, e+1" + "$mod, mouse_up, workspace, e-1" + ]; + }; +} diff --git a/home/by-host/endurance/hyprland/settings.nix b/home/by-host/endurance/hyprland/settings.nix new file mode 100644 index 0000000..60e7a6c --- /dev/null +++ b/home/by-host/endurance/hyprland/settings.nix @@ -0,0 +1,85 @@ +{pkgs, ...}: { + wayland.windowManager.hyprland.settings = { + monitor = [ + # Main ultrawide (left) + "HDMI-A-1,3840x1080,0x0,1" + # Vertical display (right) + "DP-3,1920x1080,3840x-430,1,transform,1" + # Fallback for any other monitor + ",preferred,auto,1" + ]; + + exec-once = [ + # Clipboard history + "wl-paste --type text --watch cliphist store" + "wl-paste --type image --watch cliphist store" + # Automount USB drives + "udiskie" + ]; + + env = [ + "MOZ_ENABLE_WAYLAND,1" + "QT_WAYLAND_DISABLE_WINDOWDECORATION,1" + "ELECTRON_OZONE_PLATFORM_HINT,auto" + "NIXOS_OZONE_WL,1" + "XDG_SESSION_TYPE,wayland" + "XDG_CURRENT_DESKTOP,Hyprland" + ]; + + input = { + kb_layout = "us"; + kb_variant = "intl"; + follow_mouse = 2; + sensitivity = 0; + }; + + general = { + gaps_in = 8; + gaps_out = 15; + border_size = 2; + layout = "dwindle"; + }; + + decoration = { + rounding = 8; + blur = { + enabled = true; + size = 4; + passes = 2; + noise = 0.3; + }; + shadow = { + enabled = true; + range = 4; + render_power = 3; + }; + }; + + animations = { + enabled = true; + bezier = "myBezier, 0.05, 0.9, 0.1, 1.05"; + animation = [ + "windows, 1, 7, myBezier" + "windowsOut, 1, 7, default, popin 80%" + "border, 1, 10, default" + "fade, 1, 7, default" + "workspaces, 1, 6, default" + ]; + }; + + # Single tiled window on main monitor: give it breathing room + workspace = [ + "w[t1] m[HDMI-A-1], gapsout:15 840 15 840" + ]; + + dwindle = { + pseudotile = true; + preserve_split = true; + }; + + misc = { + disable_hyprland_logo = true; + disable_splash_rendering = true; + }; + }; +} diff --git a/home/by-host/endurance/hyprland/window-rules.nix b/home/by-host/endurance/hyprland/window-rules.nix new file mode 100644 index 0000000..b45d29d --- /dev/null +++ b/home/by-host/endurance/hyprland/window-rules.nix @@ -0,0 +1,28 @@ +{...}: { + wayland.windowManager.hyprland.settings = { + windowrulev2 = [ + # Privacy: block from screen capture + "noscreenshare, class:^(1password)$" + "noscreenshare, class:^(thunderbird)$" + "noscreenshare, title:^(ld\\.toph\\.so)$" + + # Floating windows + "float, class:^(org\\.zealdocs\\.zeal)$" + "center 1, class:^(org\\.zealdocs\\.zeal)$" + "size 50% 80%, class:^(org\\.zealdocs\\.zeal)$" + "minsize 1400 500, class:^(org\\.zealdocs\\.zeal)$" + + "float, class:^(speedcrunch)$" + "center 1, class:^(speedcrunch)$" + "size 30% 60%, class:^(speedcrunch)$" + + "float, title:^(DevTools)$" + + # Kitty: slight transparency + "opacity 0.97 0.97, class:^(kitty)$" + + # JetBrains: suppress phantom windows + "nofocus, class:^jetbrains-(?!toolbox), floating:1, title:^win\\d+$" + ]; + }; +} diff --git a/modules/nixos/profiles/graphical/wm.nix b/modules/nixos/profiles/graphical/wm.nix index 9408dc3..3f2b5ad 100644 --- a/modules/nixos/profiles/graphical/wm.nix +++ b/modules/nixos/profiles/graphical/wm.nix @@ -32,6 +32,8 @@ in { package = pkgs.niri; # TODO: Use input niri pkgs/overlay! }; + programs.hyprland.enable = true; + services = { xserver = { enable = true; @@ -62,11 +64,15 @@ in { xdg.portal = { enable = true; # xdgOpenUsePortal = true; - config.common.default = "gtk"; + config = { + common.default = "gtk"; + hyprland.default = ["hyprland" "gtk"]; + }; extraPortals = with pkgs; [ xdg-desktop-portal-gnome xdg-desktop-portal-gtk + xdg-desktop-portal-hyprland ]; }; diff --git a/overlays/unstable.nix b/overlays/unstable.nix index e4fec34..e72e7a2 100644 --- a/overlays/unstable.nix +++ b/overlays/unstable.nix @@ -17,5 +17,5 @@ # open-webui ; - inherit (channels.master) install-nothing; + inherit (channels.master) install-nothing marimo; } diff --git a/secrets/rekeyed/endurance/0f723801d4717faeb894fd776d38be4e-nix-cache-privkey.age b/secrets/rekeyed/endurance/0f723801d4717faeb894fd776d38be4e-nix-cache-privkey.age new file mode 100644 index 0000000..752d1b2 --- /dev/null +++ b/secrets/rekeyed/endurance/0f723801d4717faeb894fd776d38be4e-nix-cache-privkey.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 /u/eYA jAj/U8H5mR2k4JV8FEckBb8vmpGP9LLCFCFATVZd4yA +WyXJPAyZS2Dq93pK2GuVYNbBIxNyvEVJuVWrpZS89Zs +-> @W-grease _ +Gd35VA +--- 6blY/MMnEQunu/tWdJv/oGaqf1i6Pv+xdrqLV0EZNes +g/M02P!9XUxK(nʓׅ/j[`fÁ.Nff1V!r}h`es/&8ۥS2!oNjpL?X]v8C \ No newline at end of file diff --git a/secrets/rekeyed/endurance/b26d17749592ba1595d566934c2ea6ba-nix-cache-privkey.age b/secrets/rekeyed/endurance/b26d17749592ba1595d566934c2ea6ba-nix-cache-privkey.age deleted file mode 100644 index de73162170e6f208112cbef98cbc1fbc91adcb63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 475 zcmV<10VMumXJsvAZewzJaCB*JZZ2#bt^JKZbWZ-Qf*jjQ+hdNR&HWSF<4J>S7>iiP&5iHJ|H-5Lqk$UMsF==a%Ew2 zWgvYiAX`8nU~VgKL}(&c3Qb~8HB&cdLsB?YcXKpRL~t^1Y*06PHgrZgcWY8*ZB9#7 zPBD6EPe)@{GI>v7aWPm@d1_)xT2OL!aZO`GP6}%)XhuYMFE)60Nl8m7yNi^Ulu9<(jeV@9AV_`D?koTo?CBcLya_-Z)F=w18g|=M*q7ect#@*- RI5(Ka$NaBsT^eLX+@SNwvS$DQ