diff --git a/flake.lock b/flake.lock index 891395c7..38e53308 100644 --- a/flake.lock +++ b/flake.lock @@ -161,7 +161,7 @@ }, "flake-utils": { "inputs": { - "systems": "systems_2" + "systems": "systems_3" }, "locked": { "lastModified": 1731533236, @@ -511,6 +511,27 @@ "type": "github" } }, + "hyprspace": { + "inputs": { + "hyprland": [ + "hyprland" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1752663231, + "narHash": "sha256-rTItuAWpzICMREF8Ww8cK4hYgNMRXJ4wjkN0akLlaWE=", + "owner": "KZDKM", + "repo": "Hyprspace", + "rev": "0a82e3724f929de8ad8fb04d2b7fa128493f24f7", + "type": "github" + }, + "original": { + "owner": "KZDKM", + "repo": "Hyprspace", + "type": "github" + } + }, "hyprutils": { "inputs": { "nixpkgs": [ @@ -733,7 +754,7 @@ "nixpkgs" ], "nuschtosSearch": "nuschtosSearch", - "systems": "systems_3" + "systems": "systems_4" }, "locked": { "lastModified": 1752762787, @@ -863,6 +884,7 @@ "hypr-dynamic-cursors": "hypr-dynamic-cursors", "hyprland": "hyprland", "hyprland-plugins": "hyprland-plugins", + "hyprspace": "hyprspace", "impermanence": "impermanence", "nix-alien": "nix-alien", "nix-flatpak": "nix-flatpak", @@ -910,6 +932,21 @@ } }, "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_3": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -924,7 +961,7 @@ "type": "github" } }, - "systems_3": { + "systems_4": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", diff --git a/flake.nix b/flake.nix index 1f997a3c..6148698c 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,9 @@ hypr-dynamic-cursors.url = "github:VirtCode/hypr-dynamic-cursors"; hypr-dynamic-cursors.inputs.nixpkgs.follows = "nixpkgs"; hypr-dynamic-cursors.inputs.hyprland.follows = "hyprland"; + hyprspace.url = "github:KZDKM/Hyprspace"; + hyprspace.inputs.nixpkgs.follows = "nixpkgs"; + hyprspace.inputs.hyprland.follows = "hyprland"; # NeoVim <3 nixvim.url = "github:nix-community/nixvim"; diff --git a/home/christoph/hyprland.nix b/home/christoph/hyprland.nix index 3f8cf9a1..09e69628 100644 --- a/home/christoph/hyprland.nix +++ b/home/christoph/hyprland.nix @@ -4,6 +4,10 @@ }: { enable = !headless; dunst.enable = !config.modules.hyprpanel.enable; # Disable for hyprpanel + bars.enable = false; + dynamicCursor.enable = true; + trails.enable = true; + hyprspace.enable = true; keybindings = { main-mod = "SUPER"; diff --git a/home/modules/hyprland/autostart.nix b/home/modules/hyprland/autostart.nix index ccca0635..82f6b41c 100644 --- a/home/modules/hyprland/autostart.nix +++ b/home/modules/hyprland/autostart.nix @@ -11,7 +11,7 @@ builtins.concatLists [ "wl-paste -t text --watch clipman store --no-persist" "wl-paste -p -t text --watch clipman store -P --histpath=\"~/.local/share/clipman-primary.json\"" - "hyprctl setcursor Bibata-Modern-Classic 16" + "hyprctl setcursor ${config.home.pointerCursor.name} ${builtins.toString config.home.pointerCursor.size}" "hyprsunset --identity" # HACK: Hyprland doesn't set the xwayland/x11 keymap correctly diff --git a/home/modules/hyprland/default.nix b/home/modules/hyprland/default.nix index 230a30d6..a3c7f9df 100644 --- a/home/modules/hyprland/default.nix +++ b/home/modules/hyprland/default.nix @@ -48,7 +48,7 @@ in { x11.enable = true; package = pkgs.bibata-cursors; name = "Bibata-Modern-Classic"; - size = 16; + size = 24; }; packages = with pkgs; [ @@ -145,9 +145,19 @@ in { systemd.variables = ["--all"]; # Import PATH into systemd xwayland.enable = true; - plugins = [ - inputs.hypr-dynamic-cursors.packages.${pkgs.system}.hypr-dynamic-cursors - inputs.hyprland-plugins.packages.${pkgs.system}.hyprbars + plugins = builtins.concatLists [ + (lib.optionals + hyprland.bars.enable + [inputs.hyprland-plugins.packages.${pkgs.system}.hyprbars]) + (lib.optionals + hyprland.dynamicCursor.enable + [inputs.hypr-dynamic-cursors.packages.${pkgs.system}.hypr-dynamic-cursors]) + (lib.optionals + hyprland.trails.enable + [inputs.hyprland-plugins.packages.${pkgs.system}.hyprtrails]) + (lib.optionals + hyprland.hyprspace.enable + [inputs.hyprspace.packages.${pkgs.system}.Hyprspace]) ]; settings = import ./settings.nix { diff --git a/home/modules/hyprland/options.nix b/home/modules/hyprland/options.nix index 13c77f11..fa661a31 100644 --- a/home/modules/hyprland/options.nix +++ b/home/modules/hyprland/options.nix @@ -2,9 +2,15 @@ lib, mylib, ... -}: rec { +}: { enable = lib.mkEnableOption "Hyprland Window Manager + Compositor"; + dunst.enable = lib.mkEnableOption "Enable dunst notification daemon"; + bars.enable = lib.mkEnableOption "Enable window bars"; + dynamicCursor.enable = lib.mkEnableOption "Enable dynamic cursors"; + trails.enable = lib.mkEnableOption "Enable dynamic window trails"; + hyprspace.enable = lib.mkEnableOption "Enable hyprspace workspace overview"; + keyboard = { layout = lib.mkOption { type = lib.types.str; @@ -25,128 +31,6 @@ }; }; - dunst.enable = lib.mkEnableOption "Enable dunst notification daemon"; - - monitors = lib.mkOption { - type = lib.types.attrs; - description = "Hyprland Monitor Configurations"; - example = '' - { - "HDMI-A-1" = { - width = 2560; - height = 1440; - rate = 144; - x = 1920; - y = 0; - scale = 1; - } - } - ''; - }; - - workspaces = lib.mkOption { - type = lib.types.attrs; - description = "How workspaces are distributed to monitors. These monitors will also receive a wallpaper."; - example = '' - { - "HDMI-A-1" = [1 2 3 4 5 6 7 8 9]; - "HDMI-A-2" = [0]; - } - ''; - }; - - autostart = { - immediate = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "Programs to launch when Hyprland starts"; - example = '' - [ - "kitty" - ] - ''; - default = []; - }; - - delayed = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "Programs to launch with a delay when Hyprland starts (e.g. to wait for the waybar tray)"; - example = '' - [ - "keepassxc" - "nextcloud --background" - ] - ''; - default = []; - }; - - special-silent = lib.mkOption { - type = lib.types.attrsOf (lib.types.listOf lib.types.str); - description = "Programs to silently launch on special workspaces"; - example = '' - { - "ferdium" = ["ferdium"]; - "btop" = ["kitty --title=Btop btop"]; - } - ''; - default = {}; - }; - }; - - workspacerules = lib.mkOption { - type = lib.types.attrs; - description = "Launch programs on specified workspaces, accepts window class."; - example = '' - { - "2" = [ - "jetbrains-clion" - "code-url-handler" - ]; - } - ''; - }; - - windowrules = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "Specify specific window rules."; - example = '' - [ - "suppressevent activate, class: Unity" - ] - ''; - }; - - transparent-opacity = lib.mkOption { - type = lib.types.str; - description = "The opacity transparent windows should have."; - example = "0.8"; - }; - - floating = lib.mkOption { - type = lib.types.listOf lib.types.attrs; - description = "What programs are floating down here?"; - example = '' - [ - { - class = "thunar"; - title = "File Operation Progress"; - } - { - class = "org.kde.polkit-kde-authentication-agent-1"; - } - ] - ''; - }; - - transparent = lib.mkOption { - type = lib.types.listOf lib.types.str; - description = "What programs should be transparent? Accepts window class."; - example = '' - [ - "kitty" - ] - ''; - }; - keybindings = { main-mod = lib.mkOption { type = lib.types.str; @@ -197,4 +81,124 @@ ''; }; }; + + monitors = lib.mkOption { + type = lib.types.attrs; + description = "Hyprland Monitor Configurations"; + example = '' + { + "HDMI-A-1" = { + width = 2560; + height = 1440; + rate = 144; + x = 1920; + y = 0; + scale = 1; + } + } + ''; + }; + + workspaces = lib.mkOption { + type = lib.types.attrs; + description = "How workspaces are distributed to monitors. These monitors will also receive a wallpaper."; + example = '' + { + "HDMI-A-1" = [1 2 3 4 5 6 7 8 9]; + "HDMI-A-2" = [0]; + } + ''; + }; + + workspacerules = lib.mkOption { + type = lib.types.attrs; + description = "Launch programs on specified workspaces, accepts window class."; + example = '' + { + "2" = [ + "jetbrains-clion" + "code-url-handler" + ]; + } + ''; + }; + + windowrules = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "Specify specific window rules."; + example = '' + [ + "suppressevent activate, class: Unity" + ] + ''; + }; + + transparent-opacity = lib.mkOption { + type = lib.types.str; + description = "The opacity transparent windows should have."; + example = "0.8"; + }; + + transparent = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "What programs should be transparent? Accepts window class."; + example = '' + [ + "kitty" + ] + ''; + }; + + floating = lib.mkOption { + type = lib.types.listOf lib.types.attrs; + description = "What programs are floating down here?"; + example = '' + [ + { + class = "thunar"; + title = "File Operation Progress"; + } + { + class = "org.kde.polkit-kde-authentication-agent-1"; + } + ] + ''; + }; + + autostart = { + immediate = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "Programs to launch when Hyprland starts"; + example = '' + [ + "kitty" + ] + ''; + default = []; + }; + + delayed = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "Programs to launch with a delay when Hyprland starts (e.g. to wait for the waybar tray)"; + example = '' + [ + "keepassxc" + "nextcloud --background" + ] + ''; + default = []; + }; + + special-silent = lib.mkOption { + type = lib.types.attrsOf (lib.types.listOf lib.types.str); + description = "Programs to silently launch on special workspaces"; + example = '' + { + "ferdium" = ["ferdium"]; + "btop" = ["kitty --title=Btop btop"]; + } + ''; + default = {}; + }; + }; } diff --git a/home/modules/hyprland/settings.nix b/home/modules/hyprland/settings.nix index 81732e3e..4fdf74be 100644 --- a/home/modules/hyprland/settings.nix +++ b/home/modules/hyprland/settings.nix @@ -205,4 +205,155 @@ "workspaces, 1, 6, default" ]; }; + + plugin = lib.mergeAttrsList [ + (lib.optionalAttrs hyprland.bars.enable { + hyprbars = { + enabled = true; + + bar_height = 25; + bar_blur = true; + bar_color = "rgb(${color.hex.base})"; + col.text = "rgb(${color.hex.text})"; + + bar_title_enabled = true; + bar_text_size = 12; + bar_text_font = color.font; + + bar_text_align = "center"; + bar_buttons_alignment = "left"; + + bar_part_of_window = true; + bar_precedence_over_border = false; + + # example buttons (R -> L) + # hyprbars-button = color, size, on-click + hyprbars-button = [ + "rgb(${color.hex.red}), 10, 󰖭, hyprctl dispatch killactive" + "rgb(${color.hex.green}), 10, , hyprctl dispatch fullscreen 1" + ]; + + # cmd to run on double click of the bar + on_double_click = "hyprctl dispatch fullscreen 1"; + }; + }) + + (lib.optionalAttrs hyprland.dynamicCursor.enable { + dynamic-cursors = { + # enables the plugin + enabled = true; + + # sets the cursor behaviour, supports these values: + # tilt - tilt the cursor based on x-velocity + # rotate - rotate the cursor based on movement direction + # stretch - stretch the cursor shape based on direction and velocity + # none - do not change the cursors behaviour + mode = "rotate"; + + # minimum angle difference in degrees after which the shape is changed + # smaller values are smoother, but more expensive for hw cursors + threshold = 2; + + # for mode = rotate + rotate = { + # length in px of the simulated stick used to rotate the cursor + # most realistic if this is your actual cursor size + length = 20; + + # clockwise offset applied to the angle in degrees + # this will apply to ALL shapes + offset = 0.0; + }; + + # for mode = tilt + tilt = { + # controls how powerful the tilt is, the lower, the more power + # this value controls at which speed (px/s) the full tilt is reached + # the full tilt being 60° in both directions + limit = 2500; + + # relationship between speed and tilt, supports these values: + # linear - a linear function is used + # quadratic - a quadratic function is used (most realistic to actual air drag) + # negative_quadratic - negative version of the quadratic one, feels more aggressive + # see `activation` in `src/mode/utils.cpp` for how exactly the calculation is done + function = "negative_quadratic"; + + # time window (ms) over which the speed is calculated + # higher values will make slow motions smoother but more delayed + window = 100; + }; + + # configure shake to find + # magnifies the cursor if its is being shaken + shake = { + # enables shake to find + enabled = true; + + # use nearest-neighbour (pixelated) scaling when shaking + # may look weird when effects are enabled + nearest = true; + + # controls how soon a shake is detected + # lower values mean sooner + threshold = 3.0; + + # magnification level immediately after shake start + base = 1.5; + # magnification increase per second when continuing to shake + speed = 0.0; + # how much the speed is influenced by the current shake intensitiy + influence = 0.0; + + # maximal magnification the cursor can reach + # values below 1 disable the limit (e.g. 0) + limit = 0.0; + + # time in millseconds the cursor will stay magnified after a shake has ended + timeout = 1000; + + # show cursor behaviour `tilt`, `rotate`, etc. while shaking + effects = true; + + # enable ipc events for shake + # see the `ipc` section below + ipc = false; + }; + + # use hyprcursor to get a higher resolution texture when the cursor is magnified + # see the `hyprcursor` section below + hyprcursor = { + # use nearest-neighbour (pixelated) scaling when magnifing beyond texture size + # this will also have effect without hyprcursor support being enabled + # 0 / false - never use pixelated scaling + # 1 / true - use pixelated when no highres image + # 2 - always use pixleated scaling + nearest = true; + + # enable dedicated hyprcursor support + enabled = true; + + # resolution in pixels to load the magnified shapes at + # be warned that loading a very high-resolution image will take a long time and might impact memory consumption + # -1 means we use [normal cursor size] * [shake:base option] + resolution = -1; + + # shape to use when clientside cursors are being magnified + # see the shape-name property of shape rules for possible names + # specifying clientside will use the actual shape, but will be pixelated + fallback = "clientside"; + }; + }; + }) + + (lib.optionalAttrs hyprland.trails.enable { + hyprtrails = { + color = "rgb(${color.hex.accent})"; + }; + }) + + (lib.optionalAttrs hyprland.hyprspace.enable { + overview = {}; + }) + ]; }