{ config, lib, ... }: # The Hyprland compositor. { options.modules.desktop.session.hyprland.enable = lib.mkEnableOption "the Hyprland compositor"; config = lib.mkIf config.modules.desktop.session.hyprland.enable { # This program integration owns the session, portals, and polkit, launched # through the universal Wayland session manager. programs.hyprland = { enable = true; withUWSM = true; }; home-manager.users.${config.user.name}.wayland.windowManager.hyprland = { enable = true; # One package drives the whole session, so there is never a version split. # The program integration above installs it and the portal, leaving home- # manager to write only the config. package = null; portalPackage = null; # uwsm owns the systemd graphical-session targets. systemd.enable = false; # Write the native Lua Hyprland config. Home Manager renders the Nix # settings below as hl.* calls. configType = "lua"; settings = { config = { input = { kb_layout = config.services.xserver.xkb.layout; repeat_delay = 250; repeat_rate = 45; accel_profile = "flat"; touchpad = { natural_scroll = true; tap_to_click = true; disable_while_typing = true; }; }; general = { gaps_in = 4; gaps_out = 8; border_size = 2; layout = "dwindle"; }; decoration = { rounding = 6; blur.enabled = false; }; xwayland.force_zero_scaling = true; dwindle.preserve_split = true; }; bind = lib.mapAttrsToList (_name: keybind: { _args = [ keybind.keys (lib.generators.mkLuaInline ( { exec = "hl.dsp.exec_cmd(${lib.generators.toLua { } keybind.action.command})"; focus = "hl.dsp.focus(${ lib.generators.toLua { } { inherit (keybind.action) direction workspace; } })"; "move-window" = "hl.dsp.window.move(${ lib.generators.toLua { } { inherit (keybind.action) direction workspace; } })"; "resize-window" = "hl.dsp.window.resize(${ lib.generators.toLua { } ( { down = { x = 0; y = 10; relative = true; }; left = { x = -10; y = 0; relative = true; }; right = { x = 10; y = 0; relative = true; }; up = { x = 0; y = -10; relative = true; }; } .${keybind.action.direction} ) })"; "toggle-floating" = ''hl.dsp.window.float({ action = "toggle" })''; "toggle-fullscreen" = "hl.dsp.window.fullscreen()"; "close-window" = "hl.dsp.window.close()"; } .${keybind.action.kind} )) ] ++ lib.optional keybind.repeating { repeating = true; }; }) (lib.attrByPath [ config.networking.hostName ] { } config.registry.keybind); }; }; registry.keybind.${config.networking.hostName} = lib.mkMerge [ # Generate numeric workspace keybinds. (lib.listToAttrs ( lib.concatMap (workspace: [ { name = "hyprland-workspace-${toString workspace}"; value = { keys = "SUPER + ${toString workspace}"; action = { kind = "focus"; inherit workspace; }; }; } { name = "hyprland-move-to-workspace-${toString workspace}"; value = { keys = "SUPER + SHIFT + ${toString workspace}"; action = { kind = "move-window"; inherit workspace; }; }; } ]) (lib.range 1 9) )) # Generate directional keybinds. (lib.listToAttrs ( lib.concatMap ( { direction, key }: [ { name = "hyprland-focus-${direction}"; value = { keys = "SUPER + ${key}"; action = { kind = "focus"; inherit direction; }; }; } { name = "hyprland-move-${direction}"; value = { keys = "SUPER + SHIFT + ${key}"; action = { kind = "move-window"; inherit direction; }; }; } { name = "hyprland-resize-${direction}"; value = { keys = "SUPER + ALT + ${key}"; repeating = true; action = { kind = "resize-window"; inherit direction; }; }; } ] ) [ { key = "H"; direction = "left"; } { key = "J"; direction = "down"; } { key = "K"; direction = "up"; } { key = "L"; direction = "right"; } ] )) { hyprland-toggle-floating = { keys = "SUPER + Space"; action.kind = "toggle-floating"; }; hyprland-toggle-fullscreen = { keys = "SUPER + F"; action.kind = "toggle-fullscreen"; }; hyprland-close-window = { keys = "SUPER + SHIFT + Q"; action.kind = "close-window"; }; } ]; }; }