{ lib, config, ... }: let inherit (lib) mkOption types mkIf recursiveUpdate trivial strings lists; inherit (builtins) concatStringsSep elem genList elemAt length; inherit (trivial) boolToString; inherit (strings) floatToString; inherit (lists) remove; # v0.49.0 cfg = config.horseman.wm.hyprland; homeCfg = config.horseman; keybinding = types.submodule { options = { flags = mkOption { type = types.listOf (types.enum ["l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p"]); }; mods = mkOption { type = types.listOf types.str; }; key = mkOption { type = types.str; }; dispatcher = mkOption { type = types.str; }; params = mkOption { type = types.str; }; }; }; submapKeybinding = types.submodule { options = { flags = mkOption { type = types.listOf (types.enum ["l" "r" "c" "g" "o" "e" "m" "t" "i" "s" "d" "p"]); }; mods = mkOption { type = types.listOf types.str; }; key = mkOption { type = types.str; }; }; }; vec2 = types.submodule { options = { x = mkOption {type = types.int;}; y = mkOption {type = types.int;}; }; }; fontWeight = types.enum ["thin" "ultralight" "light" "semilight" "book" "normal" "medium" "semibold" "bold" "ultrabold" "heavy" "ultraheavy"]; in { options.horseman.wm.hyprland.config = { execOnce = mkOption { type = types.listOf types.str; default = []; }; env = mkOption { type = types.listOf types.str; default = []; }; windowrules = mkOption { type = types.listOf types.str; default = []; }; workspaces = mkOption { type = types.listOf types.str; default = []; }; general = { borderSize = mkOption { type = types.int; default = 1; }; noBorderOnFloating = mkOption { type = types.bool; default = false; }; gapsIn = mkOption { type = types.int; default = 5; }; gapsOut = mkOption { type = types.int; default = 20; }; gapsWorkspaces = mkOption { type = types.int; default = 0; }; col.inactiveBorder = mkOption { type = types.str; default = "0xff444444"; }; col.activeBorder = mkOption { type = types.str; default = "0xffffffff"; }; col.nogroupBorder = mkOption { type = types.str; default = "0xffffaaff"; }; col.nogroupBorderActive = mkOption { type = types.str; default = "0xffff00ff"; }; layout = mkOption { type = types.enum ["dwindle" "master"]; default = "dwindle"; }; noFocusFallback = mkOption { type = types.bool; default = false; }; resizeOnBorder = mkOption { type = types.bool; default = false; }; extendBorderGrabArea = mkOption { type = types.int; default = 15; }; hoverIconOnBorder = mkOption { type = types.bool; default = true; }; allowTearing = mkOption { type = types.bool; default = false; }; resizeCorner = mkOption { type = types.ints.between 0 4; default = 0; }; snap = { enabled = mkOption { type = types.bool; default = false; }; windowGap = mkOption { type = types.int; default = 10; }; monitorGap = mkOption { type = types.int; default = 10; }; borderOverlap = mkOption { type = types.bool; default = false; }; }; }; decoration = { rounding = mkOption { type = types.int; default = 0; }; roundingPower = mkOption { type = types.numbers.between 2 10; default = 2.0; }; activeOpacity = mkOption { type = types.numbers.between 0 1; default = 1.0; }; inactiveOpacity = mkOption { type = types.numbers.between 0 1; default = 1.0; }; fullscreenOpacity = mkOption { type = types.numbers.between 0 1; default = 1.0; }; dimInactive = mkOption { type = types.bool; default = false; }; dimStrength = mkOption { type = types.numbers.between 0 1; default = 0.5; }; dimSpecial = mkOption { type = types.numbers.between 0 1; default = 0.2; }; dimAround = mkOption { type = types.numbers.between 0 1; default = 0.4; }; screenShader = mkOption { type = types.str; default = ""; }; borderPartOfWindow = mkOption { type = types.bool; default = true; }; blur = { enabled = mkOption { type = types.bool; default = true; }; size = mkOption { type = types.int; default = 8; }; passes = mkOption { type = types.int; default = 1; }; ignoreOpacity = mkOption { type = types.bool; default = true; }; newOptimizations = mkOption { type = types.bool; default = true; }; xray = mkOption { type = types.bool; default = false; }; noise = mkOption { type = types.numbers.between 0 1; default = 0.0117; }; contrast = mkOption { type = types.numbers.between 0 2; default = 0.8916; }; brightness = mkOption { type = types.numbers.between 0 2; default = 0.8172; }; vibrancy = mkOption { type = types.numbers.between 0 1; default = 0.1696; }; vibrancyDarkness = mkOption { type = types.numbers.between 0 1; default = 0.0; }; special = mkOption { type = types.bool; default = false; }; popups = mkOption { type = types.bool; default = false; }; popupsIgnorealpha = mkOption { type = types.numbers.between 0 1; default = 0.2; }; inputMethods = mkOption { type = types.bool; default = false; }; inputMethodsIgnorealpha = mkOption { type = types.numbers.between 0 1; default = 0.2; }; }; shadow = { enabled = mkOption { type = types.bool; default = true; }; range = mkOption { type = types.int; default = 4; }; renderPower = mkOption { type = types.ints.between 1 4; default = 3; }; sharp = mkOption { type = types.bool; default = false; }; ignoreWindow = mkOption { type = types.bool; default = true; }; color = mkOption { type = types.str; default = "0xee1a1a1a"; }; colorInactive = mkOption { type = types.nullOr types.str; default = null; }; offset = mkOption { type = vec2; default = { x = 0; y = 0; }; }; scale = mkOption { type = types.numbers.between 0 1; default = 1.0; }; }; }; animations = { enabled = mkOption { type = types.bool; default = true; }; workspaceWraparound = mkOption { type = types.bool; default = false; }; beziers = mkOption { type = types.listOf (types.submodule { options = { name = mkOption {type = types.str;}; startX = mkOption {type = types.number;}; startY = mkOption {type = types.number;}; endX = mkOption {type = types.number;}; endY = mkOption {type = types.number;}; }; }); }; animations = mkOption { type = types.listOf (types.submodule { options = { name = mkOption {type = types.str;}; on = mkOption {type = types.bool;}; speed = mkOption { type = types.number; default = 0; }; curve = mkOption { type = types.str; default = ""; }; style = mkOption { type = types.str; default = ""; }; }; }); }; }; input = { kbModel = mkOption { type = types.str; default = ""; }; kbLayout = mkOption { type = types.str; default = "us"; }; kbVariant = mkOption { type = types.str; default = ""; }; kbOptions = mkOption { type = types.str; default = ""; }; kbRules = mkOption { type = types.str; default = ""; }; kbFile = mkOption { type = types.str; default = ""; }; numlockByDefault = mkOption { type = types.bool; default = false; }; resolveBindsBySym = mkOption { type = types.bool; default = false; }; repeatRate = mkOption { type = types.int; default = 25; }; repeatDelay = mkOption { type = types.int; default = 600; }; sensitivity = mkOption { type = types.numbers.between 0 1; default = 0.0; }; accelProfile = mkOption { type = types.enum ["" "adaptive" "flat"]; default = ""; }; forceNoAccel = mkOption { type = types.bool; default = false; }; leftHanded = mkOption { type = types.bool; default = false; }; scrollPoints = mkOption { type = types.str; default = ""; }; scrollMethod = mkOption { type = types.enum ["" "2fg" "edge" "on_button_down" "no_scroll"]; default = ""; }; scrollButton = mkOption { type = types.int; default = 0; }; scrollButtonLock = mkOption { type = types.bool; default = false; }; scrollFactor = mkOption { type = types.float; default = 1.0; }; naturalScroll = mkOption { type = types.bool; default = false; }; followMouse = mkOption { type = types.enum [0 1 2 3]; default = 1; }; followMouseThreshold = mkOption { type = types.float; default = 0.0; }; focusOnClose = mkOption { type = types.enum [0 1]; default = 0; }; mouseRefocus = mkOption { type = types.bool; default = true; }; floatSwitchOverrideFocus = mkOption { type = types.enum [1 2]; default = 1; }; specialFallthrough = mkOption { type = types.bool; default = false; }; offWindowAxisEvents = mkOption { type = types.enum [0 1 2 3]; default = 1; }; emulateDiscreteScroll = mkOption { type = types.enum [0 1 2]; default = 1; }; touchpad = { disableWhileTyping = mkOption { type = types.bool; default = true; }; naturalScroll = mkOption { type = types.bool; default = false; }; scrollFactor = mkOption { type = types.float; default = 1.0; }; middleButtonEmulation = mkOption { type = types.bool; default = false; }; tapButtonMap = mkOption { type = types.enum ["lrm" "lmr"]; default = "lrm"; }; clickfingerBehavior = mkOption { type = types.bool; default = false; }; tapToClick = mkOption { type = types.bool; default = true; }; dragLock = mkOption { type = types.bool; default = false; }; tapAndDrag = mkOption { type = types.bool; default = true; }; flipX = mkOption { type = types.bool; default = false; }; flipY = mkOption { type = types.bool; default = false; }; }; touchdevice = { transform = mkOption { type = types.ints.between (-1) 7; default = -1; }; output = mkOption { type = types.str; default = "[[Auto]]"; }; enabled = mkOption { type = types.bool; default = true; }; }; tablet = { transform = mkOption { type = types.ints.between (-1) 7; default = -1; }; output = mkOption { type = types.str; default = ""; }; regionPosition = mkOption { type = vec2; default = { x = 0; y = 0; }; }; absoluteRegionPosition = mkOption { type = types.bool; default = false; }; regionSize = mkOption { type = vec2; default = { x = 0; y = 0; }; }; relativeInput = mkOption { type = types.bool; default = false; }; leftHanded = mkOption { type = types.bool; default = false; }; activeAreaSize = mkOption { type = vec2; default = { x = 0; y = 0; }; }; activeAreaPosition = mkOption { type = vec2; default = { x = 0; y = 0; }; }; }; }; gestures = { workspaceSwipe = mkOption { type = types.bool; default = false; }; workspaceSwipeFingers = mkOption { type = types.int; default = 3; }; workspaceSwipeMinFingers = mkOption { type = types.bool; default = false; }; workspaceSwipeDistance = mkOption { type = types.int; default = 300; }; workspaceSwipeTouch = mkOption { type = types.bool; default = false; }; workspaceSwipeInvert = mkOption { type = types.bool; default = true; }; workspaceSwipeTouchInvert = mkOption { type = types.bool; default = false; }; workspaceSwipeMinSpeedToForce = mkOption { type = types.int; default = 30; }; workspaceSwipeCancelRatio = mkOption { type = types.numbers.between 0 1; default = 0.5; }; workspaceSwipeCreateNew = mkOption { type = types.bool; default = true; }; workspaceSwipeDirectionLock = mkOption { type = types.bool; default = true; }; workspaceSwipeDirectionLockThreshold = mkOption { type = types.int; default = 10; }; workspaceSwipeForever = mkOption { type = types.bool; default = false; }; workspaceSwipeUseR = mkOption { type = types.bool; default = false; }; }; group = { autoGroup = mkOption { type = types.bool; default = true; }; insertAfterCurrent = mkOption { type = types.bool; default = true; }; focusRemovedWindow = mkOption { type = types.bool; default = true; }; dragIntoGroup = mkOption { type = types.enum [0 1 2]; default = 1; }; mergeGroupsOnDrag = mkOption { type = types.bool; default = true; }; mergeGroupsOnGroupbar = mkOption { type = types.bool; default = true; }; mergeFloatedIntoTiledOnGroupbar = mkOption { type = types.bool; default = false; }; groupOnMovetoworkspace = mkOption { type = types.bool; default = false; }; col.borderActive = mkOption { type = types.str; default = "0x66ffff00"; }; col.borderInactive = mkOption { type = types.str; default = "0x66777700"; }; col.borderLockedActive = mkOption { type = types.str; default = "0x66ff5500"; }; col.borderLockedInactive = mkOption { type = types.str; default = "0x66775500"; }; groupbar = { enabled = mkOption { type = types.bool; default = true; }; fontFamily = mkOption { type = types.str; default = ""; }; fontSize = mkOption { type = types.int; default = 8; }; fontWeightActive = mkOption { type = fontWeight; default = "normal"; }; fontWeightInactive = mkOption { type = fontWeight; default = "normal"; }; gradients = mkOption { type = types.bool; default = false; }; height = mkOption { type = types.int; default = 14; }; indicatorGap = mkOption { type = types.int; default = 0; }; indicatorHeight = mkOption { type = types.int; default = 3; }; stacked = mkOption { type = types.bool; default = false; }; priority = mkOption { type = types.int; default = 3; }; renderTitles = mkOption { type = types.bool; default = true; }; textOffset = mkOption { type = types.int; default = 0; }; scrolling = mkOption { type = types.bool; default = true; }; rounding = mkOption { type = types.int; default = 1; }; gradientRounding = mkOption { type = types.int; default = 2; }; roundOnlyEdges = mkOption { type = types.bool; default = true; }; gradientRoundOnlyEdges = mkOption { type = types.bool; default = true; }; textColor = mkOption { type = types.str; default = "0xffffffff"; }; col.active = mkOption { type = types.str; default = "0x66ffff00"; }; col.inactive = mkOption { type = types.str; default = "0x66777700"; }; col.lockedActive = mkOption { type = types.str; default = "0x66ff5500"; }; col.lockedInactive = mkOption { type = types.str; default = "0x66775500"; }; gapsIn = mkOption { type = types.int; default = 2; }; gapsOut = mkOption { type = types.int; default = 2; }; keepUpperGap = mkOption { type = types.bool; default = true; }; }; }; misc = { disableHyprlandLogo = mkOption { type = types.bool; default = false; }; disableSplashRendering = mkOption { type = types.bool; default = false; }; col.splash = mkOption { type = types.str; default = "0xffffffff"; }; fontFamily = mkOption { type = types.str; default = "Sans"; }; splashFontFamily = mkOption { type = types.str; default = ""; }; forceDefaultWallpaper = mkOption { type = types.enum [(-1) 0 1 2]; default = -1; }; vfr = mkOption { type = types.bool; default = true; }; vrr = mkOption { type = types.enum [0 1 2 3]; default = 0; }; mouseMoveEnablesDPMS = mkOption { type = types.bool; default = false; }; keyPressEnablesDPMS = mkOption { type = types.bool; default = false; }; alwaysFollowOnDnd = mkOption { type = types.bool; default = true; }; layersHogKeyboardFocus = mkOption { type = types.bool; default = true; }; animateManualResizes = mkOption { type = types.bool; default = false; }; animateMouseWindowdragging = mkOption { type = types.bool; default = false; }; disableAutoreload = mkOption { type = types.bool; default = false; }; enableSwallow = mkOption { type = types.bool; default = false; }; swallowRegex = mkOption { type = types.str; default = ""; }; swallowExceptionRegex = mkOption { type = types.str; default = ""; }; focusOnActivate = mkOption { type = types.bool; default = false; }; mouseMoveFocusesMonitor = mkOption { type = types.bool; default = true; }; allowSessionLockRestore = mkOption { type = types.bool; default = false; }; backgroundColor = mkOption { type = types.str; default = "0x111111"; }; closeSpecialOnEmpty = mkOption { type = types.bool; default = true; }; newWindowTakesOverFullscreen = mkOption { type = types.enum [0 1 2]; default = 0; }; exitWindowRetainsFullscreen = mkOption { type = types.bool; default = false; }; initialWorkspaceTracking = mkOption { type = types.enum [0 1 2]; default = 1; }; middleClickPaste = mkOption { type = types.bool; default = true; }; renderUnfocusedFps = mkOption { type = types.int; default = 15; }; disableXdgEnvChecks = mkOption { type = types.bool; default = false; }; disableHyprlandQtutilsCheck = mkOption { type = types.bool; default = false; }; lockdeadScreenDelay = mkOption { type = types.int; default = 1000; }; enableAnrDialog = mkOption { type = types.bool; default = true; }; anrMissedPings = mkOption { type = types.int; default = 1; }; }; binds = { passMouseWhenBound = mkOption { type = types.bool; default = false; }; scrollEventDelay = mkOption { type = types.int; default = 300; }; workspaceBackAndForth = mkOption { type = types.bool; default = false; }; hideSpecialOnWorkspaceChange = mkOption { type = types.bool; default = false; }; allowWorkspaceCycles = mkOption { type = types.bool; default = false; }; workspaceCenterOn = mkOption { type = types.enum [0 1]; default = 0; }; focusPreferredMethod = mkOption { type = types.enum [0 1]; default = 0; }; ignoreGroupLock = mkOption { type = types.bool; default = false; }; movefocusCyclesFullscreen = mkOption { type = types.bool; default = false; }; movefocusCyclesGroupfirst = mkOption { type = types.bool; default = false; }; disableKeybindGrabbing = mkOption { type = types.bool; default = false; }; windowDirectionMonitorFallback = mkOption { type = types.bool; default = true; }; allowPinFullscreen = mkOption { type = types.bool; default = false; }; dragThreshold = mkOption { type = types.int; default = 0; }; }; xwayland = { enabled = mkOption { type = types.bool; default = true; }; useNearestNeighbor = mkOption { type = types.bool; default = true; }; forceZeroScaling = mkOption { type = types.bool; default = false; }; createAbstractSocket = mkOption { type = types.bool; default = false; }; }; opengl = { nvidiaAntiFlicker = mkOption { type = types.bool; default = true; }; }; render = { directScanout = mkOption { type = types.enum [0 1 2]; default = 0; }; expandUndersizedTextures = mkOption { type = types.bool; default = true; }; xpMode = mkOption { type = types.bool; default = false; }; ctmAnimation = mkOption { type = types.enum [0 1 2]; default = 2; }; cmFsPassthrough = mkOption { type = types.enum [0 1 2]; default = 2; }; cmEnabled = mkOption { type = types.bool; default = true; }; sendContentType = mkOption { type = types.bool; default = true; }; }; cursor = { syncGsettingsTheme = mkOption { type = types.bool; default = true; }; noHardwareCursors = mkOption { type = types.enum [0 1 2]; default = 2; }; noBreakFsVrr = mkOption { type = types.enum [0 1 2]; default = 2; }; minRefreshRate = mkOption { type = types.int; default = 24; }; hotspotPadding = mkOption { type = types.int; default = 1; }; inactiveTimeout = mkOption { type = types.number; default = 0; }; noWarps = mkOption { type = types.bool; default = false; }; persistentWarps = mkOption { type = types.bool; default = false; }; warpOnChangeWorkspace = mkOption { type = types.enum [0 1 2]; default = 0; }; warpOnToggleSpecial = mkOption { type = types.enum [0 1 2]; default = 0; }; defaultMonitor = mkOption { type = types.str; default = ""; }; zoomFactor = mkOption { type = types.float; default = 1.0; }; zoomRigid = mkOption { type = types.bool; default = false; }; enableHyprcursor = mkOption { type = types.bool; default = true; }; hideOnKeyPress = mkOption { type = types.bool; default = false; }; hideOnTouch = mkOption { type = types.bool; default = true; }; useCpuBuffer = mkOption { type = types.enum [0 1 2]; default = 2; }; warpBackAfterNonMouseInput = mkOption { type = types.bool; default = false; }; }; ecosystem = { noUpdateNews = mkOption { type = types.bool; default = false; }; noDonationNag = mkOption { type = types.bool; default = false; }; enforcePermissions = mkOption { type = types.bool; default = false; }; }; dwindle = { pseudotile = mkOption {type = types.bool;}; preserveSplit = mkOption {type = types.bool;}; }; master = { newStatus = mkOption {type = types.enum ["master" "slave" "inherit"];}; }; monitors = { defaultMonitor = mkOption {type = types.bool;}; bindWorkspaces = mkOption { type = types.enum ["no" "interlaced"]; default = "no"; }; displays = mkOption { type = types.listOf (types.submodule { options = { output = mkOption {type = types.str;}; resolution = mkOption { type = types.str; default = "highres"; }; refreshRate = mkOption { type = types.str; default = "highrr"; }; x = mkOption {type = types.int;}; y = mkOption {type = types.int;}; scale = mkOption { type = types.number; default = 1; }; transform = mkOption { type = types.enum [0 1 2 3 4 5 6 7]; default = 0; }; wallpaper = mkOption { type = types.nullOr types.path; default = null; }; bar = mkOption { type = types.enum ["" "left" "right" "top" "bottom"]; default = ""; }; }; }); }; }; keybindings = { binds = mkOption {type = types.listOf keybinding;}; submaps = mkOption { type = types.listOf (types.submodule { options = { name = mkOption {type = types.str;}; enterBind = mkOption {type = submapKeybinding;}; exitBind = mkOption {type = submapKeybinding;}; binds = mkOption {type = types.listOf keybinding;}; }; }); }; }; sleep = { lockCommand = mkOption {type = types.str;}; listeners = mkOption { type = types.listOf (types.submodule { options = { timeout = mkOption {type = types.ints.positive;}; onTimeout = mkOption {type = types.str;}; onResume = mkOption { type = types.str; default = ""; }; ignoreInhibit = mkOption { type = types.bool; default = false; }; }; }); }; }; waybar = { layout = { horizontal = { left = mkOption {type = types.listOf types.str;}; center = mkOption {type = types.listOf types.str;}; right = mkOption {type = types.listOf types.str;}; }; vertical = { left = mkOption {type = types.listOf types.str;}; center = mkOption {type = types.listOf types.str;}; right = mkOption {type = types.listOf types.str;}; }; }; formats = { horizontal = mkOption { type = types.attrs; }; vertical = mkOption { type = types.attrs; }; }; modules = mkOption { type = types.attrs; }; }; }; config = mkIf cfg.enable { home-manager.users.${homeCfg.username} = { xdg.configFile."hypr/hypridle.conf".text = '' # This file has been auto-generated. general { lock_cmd = ${cfg.config.sleep.lockCommand} } ${concatStringsSep "\n\n" (map (lis: '' listener { timeout = ${toString lis.timeout} on-timeout = ${lis.onTimeout} on-resume = ${lis.onResume} } '') cfg.config.sleep.listeners)} ''; xdg.configFile."hypr/hyprpaper.conf".text = '' # This file has been auto-generated. ${concatStringsSep "\n" (map (dis: if dis.wallpaper != null then '' preload = ${dis.wallpaper} wallpaper = ${dis.output}, ${dis.wallpaper} '' else "") cfg.config.monitors.displays)} preload = /home/horseman/nix-config/misc/wallpaper.jpg wallpaper = , /home/horseman/nix-config/misc/wallpaper.jpg ''; xdg.configFile."hypr/hyprlock.conf".text = '' $font = Monospace general { hide_cursor = false } animations { enabled = true bezier = linear, 1, 1, 0, 0 animation = fadeIn, 1, 5, linear animation = fadeOut, 1, 5, linear animation = inputFieldDots, 1, 2, linear } background { monitor = path = screenshot blur_passes = 3 } input-field { monitor = size = 20%, 5% outline_thickness = 3 inner_color = rgba(0, 0, 0, 0.0) # no fill outer_color = rgba(33ccffee) rgba(00ff99ee) 45deg check_color = rgba(00ff99ee) rgba(ff6633ee) 120deg fail_color = rgba(ff6633ee) rgba(ff0066ee) 40deg font_color = rgb(143, 143, 143) fade_on_empty = false rounding = 15 font_family = $font placeholder_text = Input password... fail_text = $PAMFAIL dots_spacing = 0.3 position = 0, -20 halign = center valign = center } label { monitor = text = $TIME font_size = 90 font_family = $font position = 0, -50 halign = center valign = top } ''; xdg.configFile."hypr/hyprland.conf".text = '' # This file has been auto-generated. ${concatStringsSep "\n" (map (kb: "bind${concatStringsSep "" kb.flags} = ${concatStringsSep " " kb.mods}, ${kb.key}, ${kb.dispatcher}${ if (elem "m" kb.flags) # Mouse binds take one argument less then "" else ", ${kb.params}" }") cfg.config.keybindings.binds)} ${concatStringsSep "\n\n" (map (sm: '' bind${concatStringsSep "" sm.enterBind.flags} = ${concatStringsSep " " sm.enterBind.mods}, ${sm.enterBind.key}, submap, ${sm.name} submap = ${sm.name} ${concatStringsSep "\n" (map (kb: "bind${concatStringsSep "" kb.flags} = ${concatStringsSep " " kb.mods}, ${kb.key}, ${kb.dispatcher}${ if (elem "m" kb.flags) # Mouse binds take one argument less then "" else ", ${kb.params}" }") sm.binds)} bind${concatStringsSep "" sm.exitBind.flags} = ${concatStringsSep " " sm.exitBind.mods}, ${sm.exitBind.key}, submap, reset submap = reset '') cfg.config.keybindings.submaps)} ${concatStringsSep "\n" (map (x: "exec-once = " + x) cfg.config.execOnce)} ${concatStringsSep "\n" (map (x: "env = " + x) cfg.config.env)} general { border_size = ${toString cfg.config.general.borderSize} no_border_on_floating = ${boolToString cfg.config.general.noBorderOnFloating} gaps_in = ${toString cfg.config.general.gapsIn} gaps_out = ${toString cfg.config.general.gapsOut} gaps_workspaces = ${toString cfg.config.general.gapsWorkspaces} col.inactive_border = ${cfg.config.general.col.inactiveBorder} col.active_border = ${cfg.config.general.col.activeBorder} col.nogroup_border = ${cfg.config.general.col.nogroupBorder} col.nogroup_border_active = ${cfg.config.general.col.nogroupBorderActive} layout = ${cfg.config.general.layout} no_focus_fallback = ${boolToString cfg.config.general.noFocusFallback} resize_on_border = ${boolToString cfg.config.general.resizeOnBorder} extend_border_grab_area = ${toString cfg.config.general.extendBorderGrabArea} hover_icon_on_border = ${boolToString cfg.config.general.hoverIconOnBorder} allow_tearing = ${boolToString cfg.config.general.allowTearing} resize_corner = ${toString cfg.config.general.resizeCorner} snap { enabled = ${boolToString cfg.config.general.snap.enabled} window_gap = ${toString cfg.config.general.snap.windowGap} monitor_gap = ${toString cfg.config.general.snap.monitorGap} border_overlap = ${boolToString cfg.config.general.snap.borderOverlap} } } decoration { rounding = ${toString cfg.config.decoration.rounding} rounding_power = ${toString cfg.config.decoration.roundingPower} active_opacity = ${toString cfg.config.decoration.activeOpacity} inactive_opacity = ${toString cfg.config.decoration.inactiveOpacity} fullscreen_opacity = ${toString cfg.config.decoration.fullscreenOpacity} dim_inactive = ${boolToString cfg.config.decoration.dimInactive} dim_strength = ${toString cfg.config.decoration.dimStrength} dim_special = ${toString cfg.config.decoration.dimSpecial} dim_around = ${toString cfg.config.decoration.dimAround} screen_shader = ${toString cfg.config.decoration.screenShader} border_part_of_window = ${boolToString cfg.config.decoration.borderPartOfWindow} blur { enabled = ${boolToString cfg.config.decoration.blur.enabled} size = ${toString cfg.config.decoration.blur.size} passes = ${toString cfg.config.decoration.blur.passes} ignore_opacity = ${boolToString cfg.config.decoration.blur.ignoreOpacity} new_optimizations = ${boolToString cfg.config.decoration.blur.newOptimizations} xray = ${boolToString cfg.config.decoration.blur.xray} noise = ${toString cfg.config.decoration.blur.noise} contrast = ${toString cfg.config.decoration.blur.contrast} brightness = ${toString cfg.config.decoration.blur.brightness} vibrancy = ${toString cfg.config.decoration.blur.vibrancy} vibrancy_darkness = ${toString cfg.config.decoration.blur.vibrancyDarkness} special = ${boolToString cfg.config.decoration.blur.special} popups = ${boolToString cfg.config.decoration.blur.popups} popups_ignorealpha = ${toString cfg.config.decoration.blur.popupsIgnorealpha} input_methods = ${boolToString cfg.config.decoration.blur.inputMethods} input_methods_ignorealpha = ${toString cfg.config.decoration.blur.inputMethodsIgnorealpha} } shadow { enabled = ${boolToString cfg.config.decoration.shadow.enabled} range = ${toString cfg.config.decoration.shadow.range} render_power = ${toString cfg.config.decoration.shadow.renderPower} sharp = ${boolToString cfg.config.decoration.shadow.sharp} ignore_window = ${boolToString cfg.config.decoration.shadow.ignoreWindow} color = ${toString cfg.config.decoration.shadow.color} ${ if (cfg.config.decoration.shadow.colorInactive == null) then "" else "color_inactive = ${toString cfg.config.decoration.shadow.colorInactive}" } offset = ${toString cfg.config.decoration.shadow.offset.x} ${toString cfg.config.decoration.shadow.offset.y} scale = ${toString cfg.config.decoration.shadow.scale} } } animations { enabled = ${boolToString cfg.config.animations.enabled} workspace_wraparound = ${boolToString cfg.config.animations.workspaceWraparound} ${concatStringsSep "\n " (map (bez: "bezier = ${bez.name}, ${floatToString bez.startX}, ${floatToString bez.startY}, ${floatToString bez.endX}, ${floatToString bez.endY}") cfg.config.animations.beziers)} ${concatStringsSep "\n " (map (anim: "animation = ${anim.name}, ${toString anim.on}, ${floatToString anim.speed}, ${anim.curve}, ${anim.style}") cfg.config.animations.animations)} } input { kb_model = ${toString cfg.config.input.kbModel} kb_layout = ${toString cfg.config.input.kbLayout} kb_variant = ${toString cfg.config.input.kbVariant} kb_options = ${toString cfg.config.input.kbOptions} kb_rules = ${toString cfg.config.input.kbRules} kb_file = ${toString cfg.config.input.kbFile} numlock_by_default = ${boolToString cfg.config.input.numlockByDefault} resolve_binds_by_sym = ${boolToString cfg.config.input.resolveBindsBySym} repeat_rate = ${toString cfg.config.input.repeatRate} repeat_delay = ${toString cfg.config.input.repeatDelay} sensitivity = ${toString cfg.config.input.sensitivity} accel_profile = ${toString cfg.config.input.accelProfile} force_no_accel = ${boolToString cfg.config.input.forceNoAccel} left_handed = ${boolToString cfg.config.input.leftHanded} scroll_points = ${toString cfg.config.input.scrollPoints} scroll_method = ${toString cfg.config.input.scrollMethod} scroll_button = ${toString cfg.config.input.scrollButton} scroll_button_lock = ${boolToString cfg.config.input.scrollButtonLock} scroll_factor = ${toString cfg.config.input.scrollFactor} natural_scroll = ${boolToString cfg.config.input.naturalScroll} follow_mouse = ${toString cfg.config.input.followMouse} follow_mouse_threshold = ${toString cfg.config.input.followMouseThreshold} focus_on_close = ${toString cfg.config.input.focusOnClose} mouse_refocus = ${boolToString cfg.config.input.mouseRefocus} float_switch_override_focus = ${toString cfg.config.input.floatSwitchOverrideFocus} special_fallthrough = ${boolToString cfg.config.input.specialFallthrough} off_window_axis_events = ${toString cfg.config.input.offWindowAxisEvents} emulate_discrete_scroll = ${toString cfg.config.input.emulateDiscreteScroll} touchpad { disable_while_typing = ${boolToString cfg.config.input.touchpad.disableWhileTyping} natural_scroll = ${boolToString cfg.config.input.touchpad.naturalScroll} scroll_factor = ${toString cfg.config.input.touchpad.scrollFactor} middle_button_emulation = ${boolToString cfg.config.input.touchpad.middleButtonEmulation} tap_button_map = ${toString cfg.config.input.touchpad.tapButtonMap} clickfinger_behavior = ${boolToString cfg.config.input.touchpad.clickfingerBehavior} tap-to-click = ${boolToString cfg.config.input.touchpad.tapToClick} drag_lock = ${toString cfg.config.input.touchpad.dragLock} tap-and-drag = ${toString cfg.config.input.touchpad.tapAndDrag} flip_x = ${boolToString cfg.config.input.touchpad.flipX} flip_y = ${boolToString cfg.config.input.touchpad.flipY} } touchdevice { transform = ${toString cfg.config.input.touchdevice.transform} output = ${toString cfg.config.input.touchdevice.output} enabled = ${boolToString cfg.config.input.touchdevice.enabled} } tablet { transform = ${toString cfg.config.input.tablet.transform} output = ${toString cfg.config.input.tablet.output} region_position = ${toString cfg.config.input.tablet.regionPosition.x} ${toString cfg.config.input.tablet.regionPosition.y} absolute_region_position = ${boolToString cfg.config.input.tablet.absoluteRegionPosition} region_size = ${toString cfg.config.input.tablet.regionSize.x} ${toString cfg.config.input.tablet.regionSize.y} relative_input = ${boolToString cfg.config.input.tablet.relativeInput} left_handed = ${boolToString cfg.config.input.tablet.leftHanded} active_area_size = ${toString cfg.config.input.tablet.activeAreaSize.x} ${toString cfg.config.input.tablet.activeAreaSize.y} active_area_position = ${toString cfg.config.input.tablet.activeAreaPosition.x} ${toString cfg.config.input.tablet.activeAreaPosition.y} } } gestures { workspace_swipe = ${boolToString cfg.config.gestures.workspaceSwipe} workspace_swipe_fingers = ${toString cfg.config.gestures.workspaceSwipeFingers} workspace_swipe_min_fingers = ${boolToString cfg.config.gestures.workspaceSwipeMinFingers} workspace_swipe_distance = ${toString cfg.config.gestures.workspaceSwipeDistance} workspace_swipe_touch = ${boolToString cfg.config.gestures.workspaceSwipeTouch} workspace_swipe_invert = ${boolToString cfg.config.gestures.workspaceSwipeInvert} workspace_swipe_touch_invert = ${boolToString cfg.config.gestures.workspaceSwipeTouchInvert} workspace_swipe_min_speed_to_force = ${toString cfg.config.gestures.workspaceSwipeMinSpeedToForce} workspace_swipe_cancel_ratio = ${floatToString cfg.config.gestures.workspaceSwipeCancelRatio} workspace_swipe_create_new = ${boolToString cfg.config.gestures.workspaceSwipeCreateNew} workspace_swipe_direction_lock = ${boolToString cfg.config.gestures.workspaceSwipeDirectionLock} workspace_swipe_direction_lock_threshold = ${toString cfg.config.gestures.workspaceSwipeDirectionLockThreshold} workspace_swipe_forever = ${boolToString cfg.config.gestures.workspaceSwipeForever} workspace_swipe_use_r = ${boolToString cfg.config.gestures.workspaceSwipeUseR} } group { auto_group = ${boolToString cfg.config.group.autoGroup} insert_after_current = ${boolToString cfg.config.group.insertAfterCurrent} focus_removed_window = ${boolToString cfg.config.group.focusRemovedWindow} drag_into_group = ${toString cfg.config.group.dragIntoGroup} merge_groups_on_drag = ${boolToString cfg.config.group.mergeGroupsOnDrag} merge_groups_on_groupbar = ${boolToString cfg.config.group.mergeGroupsOnGroupbar} merge_floated_into_tiled_on_groupbar = ${boolToString cfg.config.group.mergeFloatedIntoTiledOnGroupbar} group_on_movetoworkspace = ${boolToString cfg.config.group.groupOnMovetoworkspace} col.border_active = ${toString cfg.config.group.col.borderActive} col.border_inactive = ${toString cfg.config.group.col.borderInactive} col.border_locked_active = ${toString cfg.config.group.col.borderLockedActive} col.border_locked_inactive = ${toString cfg.config.group.col.borderLockedInactive} groupbar { enabled = ${boolToString cfg.config.group.groupbar.enabled} font_family = ${toString cfg.config.group.groupbar.fontFamily} font_size = ${toString cfg.config.group.groupbar.fontSize} font_weight_active = ${toString cfg.config.group.groupbar.fontWeightActive} font_weight_inactive = ${toString cfg.config.group.groupbar.fontWeightInactive} gradients = ${boolToString cfg.config.group.groupbar.gradients} height = ${toString cfg.config.group.groupbar.height} indicator_gap = ${toString cfg.config.group.groupbar.indicatorGap} indicator_height = ${toString cfg.config.group.groupbar.indicatorHeight} stacked = ${boolToString cfg.config.group.groupbar.stacked} priority = ${toString cfg.config.group.groupbar.priority} render_titles = ${boolToString cfg.config.group.groupbar.renderTitles} text_offset = ${toString cfg.config.group.groupbar.textOffset} scrolling = ${boolToString cfg.config.group.groupbar.scrolling} rounding = ${toString cfg.config.group.groupbar.rounding} gradient_rounding = ${toString cfg.config.group.groupbar.gradientRounding} round_only_edges = ${boolToString cfg.config.group.groupbar.roundOnlyEdges} gradient_round_only_edges = ${boolToString cfg.config.group.groupbar.gradientRoundOnlyEdges} text_color = ${toString cfg.config.group.groupbar.textColor} col.active = ${toString cfg.config.group.groupbar.col.active} col.inactive = ${toString cfg.config.group.groupbar.col.inactive} col.locked_active = ${toString cfg.config.group.groupbar.col.lockedActive} col.locked_inactive = ${toString cfg.config.group.groupbar.col.lockedInactive} gaps_in = ${toString cfg.config.group.groupbar.gapsIn} gaps_out = ${toString cfg.config.group.groupbar.gapsOut} keep_upper_gap = ${boolToString cfg.config.group.groupbar.keepUpperGap} } } misc { disable_hyprland_logo = ${boolToString cfg.config.misc.disableHyprlandLogo} disable_splash_rendering = ${boolToString cfg.config.misc.disableSplashRendering} col.splash = ${toString cfg.config.misc.col.splash} font_family = ${toString cfg.config.misc.fontFamily} splash_font_family = ${toString cfg.config.misc.splashFontFamily} force_default_wallpaper = ${toString cfg.config.misc.forceDefaultWallpaper} vfr = ${toString cfg.config.misc.vfr} vrr = ${toString cfg.config.misc.vrr} mouse_move_enables_dpms = ${boolToString cfg.config.misc.mouseMoveEnablesDPMS} key_press_enables_dpms = ${boolToString cfg.config.misc.keyPressEnablesDPMS} always_follow_on_dnd = ${boolToString cfg.config.misc.alwaysFollowOnDnd} layers_hog_keyboard_focus = ${boolToString cfg.config.misc.layersHogKeyboardFocus} animate_manual_resizes = ${boolToString cfg.config.misc.animateManualResizes} animate_mouse_windowdragging = ${boolToString cfg.config.misc.animateMouseWindowdragging} disable_autoreload = ${boolToString cfg.config.misc.disableAutoreload} enable_swallow = ${boolToString cfg.config.misc.enableSwallow} swallow_regex = ${toString cfg.config.misc.swallowRegex} swallow_exception_regex = ${toString cfg.config.misc.swallowExceptionRegex} focus_on_activate = ${boolToString cfg.config.misc.focusOnActivate} mouse_move_focuses_monitor = ${boolToString cfg.config.misc.mouseMoveFocusesMonitor} allow_session_lock_restore = ${boolToString cfg.config.misc.allowSessionLockRestore} background_color = ${toString cfg.config.misc.backgroundColor} close_special_on_empty = ${boolToString cfg.config.misc.closeSpecialOnEmpty} new_window_takes_over_fullscreen = ${toString cfg.config.misc.newWindowTakesOverFullscreen} exit_window_retains_fullscreen = ${boolToString cfg.config.misc.exitWindowRetainsFullscreen} initial_workspace_tracking = ${toString cfg.config.misc.initialWorkspaceTracking} middle_click_paste = ${boolToString cfg.config.misc.middleClickPaste} render_unfocused_fps = ${toString cfg.config.misc.renderUnfocusedFps} disable_xdg_env_checks = ${boolToString cfg.config.misc.disableXdgEnvChecks} disable_hyprland_qtutils_check = ${boolToString cfg.config.misc.disableHyprlandQtutilsCheck} lockdead_screen_delay = ${toString cfg.config.misc.lockdeadScreenDelay} enable_anr_dialog = ${boolToString cfg.config.misc.enableAnrDialog} anr_missed_pings = ${toString cfg.config.misc.anrMissedPings} } binds { pass_mouse_when_bound = ${boolToString cfg.config.binds.passMouseWhenBound} scroll_event_delay = ${toString cfg.config.binds.scrollEventDelay} workspace_back_and_forth = ${boolToString cfg.config.binds.workspaceBackAndForth} hide_special_on_workspace_change = ${boolToString cfg.config.binds.hideSpecialOnWorkspaceChange} allow_workspace_cycles = ${boolToString cfg.config.binds.allowWorkspaceCycles} workspace_center_on = ${toString cfg.config.binds.workspaceCenterOn} focus_preferred_method = ${toString cfg.config.binds.focusPreferredMethod} ignore_group_lock = ${boolToString cfg.config.binds.ignoreGroupLock} movefocus_cycles_fullscreen = ${boolToString cfg.config.binds.movefocusCyclesFullscreen} movefocus_cycles_groupfirst = ${boolToString cfg.config.binds.movefocusCyclesGroupfirst} disable_keybind_grabbing = ${boolToString cfg.config.binds.disableKeybindGrabbing} window_direction_monitor_fallback = ${boolToString cfg.config.binds.windowDirectionMonitorFallback} allow_pin_fullscreen = ${boolToString cfg.config.binds.allowPinFullscreen} drag_threshold = ${toString cfg.config.binds.dragThreshold} } xwayland { enabled = ${boolToString cfg.config.xwayland.enabled} use_nearest_neighbor = ${boolToString cfg.config.xwayland.useNearestNeighbor} force_zero_scaling = ${boolToString cfg.config.xwayland.forceZeroScaling} create_abstract_socket = ${boolToString cfg.config.xwayland.createAbstractSocket} } opengl { nvidia_anti_flicker = ${boolToString cfg.config.opengl.nvidiaAntiFlicker} } render { direct_scanout = ${toString cfg.config.render.directScanout} expand_undersized_textures = ${boolToString cfg.config.render.expandUndersizedTextures} xp_mode = ${boolToString cfg.config.render.xpMode} ctm_animation = ${toString cfg.config.render.ctmAnimation} cm_fs_passthrough = ${toString cfg.config.render.cmFsPassthrough} cm_enabled = ${boolToString cfg.config.render.cmEnabled} send_content_type = ${boolToString cfg.config.render.sendContentType} } cursor { sync_gsettings_theme = ${boolToString cfg.config.cursor.syncGsettingsTheme} no_hardware_cursors = ${toString cfg.config.cursor.noHardwareCursors} no_break_fs_vrr = ${toString cfg.config.cursor.noBreakFsVrr} min_refresh_rate = ${toString cfg.config.cursor.minRefreshRate} hotspot_padding = ${toString cfg.config.cursor.hotspotPadding} inactive_timeout = ${toString cfg.config.cursor.inactiveTimeout} no_warps = ${boolToString cfg.config.cursor.noWarps} persistent_warps = ${boolToString cfg.config.cursor.persistentWarps} warp_on_change_workspace = ${toString cfg.config.cursor.warpOnChangeWorkspace} warp_on_toggle_special = ${toString cfg.config.cursor.warpOnToggleSpecial} default_monitor = ${toString cfg.config.cursor.defaultMonitor} zoom_factor = ${toString cfg.config.cursor.zoomFactor} zoom_rigid = ${boolToString cfg.config.cursor.zoomRigid} enable_hyprcursor = ${boolToString cfg.config.cursor.enableHyprcursor} hide_on_key_press = ${boolToString cfg.config.cursor.hideOnKeyPress} hide_on_touch = ${boolToString cfg.config.cursor.hideOnTouch} use_cpu_buffer = ${toString cfg.config.cursor.useCpuBuffer} warp_back_after_non_mouse_input = ${boolToString cfg.config.cursor.warpBackAfterNonMouseInput} } ecosystem { no_update_news = ${boolToString cfg.config.ecosystem.noUpdateNews} no_donation_nag = ${boolToString cfg.config.ecosystem.noDonationNag} enforce_permissions = ${boolToString cfg.config.ecosystem.enforcePermissions} } dwindle { pseudotile = ${boolToString cfg.config.dwindle.pseudotile} preserve_split = ${boolToString cfg.config.dwindle.preserveSplit} } master { new_status = ${toString cfg.config.master.newStatus} } ${concatStringsSep "\n" (map (mon: "monitor = ${mon.output}, ${mon.resolution}@${mon.refreshRate}, ${toString mon.x}x${toString mon.y}, ${floatToString mon.scale}, transform, ${toString mon.transform}") cfg.config.monitors.displays)} ${ if cfg.config.monitors.defaultMonitor then "monitor = ,preferred, auto, auto" else "" } ${concatStringsSep "\n" (map (wr: "windowrule = " + wr) cfg.config.windowrules)} ${concatStringsSep "\n" (map (ws: "workspace = " + ws) cfg.config.workspaces)} ${ concatStringsSep "\n" ( if cfg.config.monitors.bindWorkspaces == "interlaced" then (map (x: "workspace = ${toString (x + 1)}, persistent:true, monitor:${(elemAt cfg.config.monitors.displays (x - ((length cfg.config.monitors.displays) * (x / (length cfg.config.monitors.displays))))).output}") (genList (x: x) 10)) else [] ) } ''; programs.waybar = { enable = true; settings = let outputMap = location: ( remove null ( map (disp: if (disp.bar == location) then disp.output else null) cfg.config.monitors.displays ) ); in { topBar = recursiveUpdate { layer = "top"; position = "top"; output = outputMap "top"; modules-left = cfg.config.waybar.layout.horizontal.left; modules-center = cfg.config.waybar.layout.horizontal.center; modules-right = cfg.config.waybar.layout.horizontal.right; } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.horizontal); bottomBar = recursiveUpdate { layer = "top"; position = "bottom"; output = outputMap "bottom"; modules-left = cfg.config.waybar.layout.horizontal.left; modules-center = cfg.config.waybar.layout.horizontal.center; modules-right = cfg.config.waybar.layout.horizontal.right; } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.horizontal); rightBar = recursiveUpdate { layer = "top"; position = "right"; output = outputMap "right"; modules-left = cfg.config.waybar.layout.vertical.left; modules-center = cfg.config.waybar.layout.vertical.center; modules-right = cfg.config.waybar.layout.vertical.right; } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.vertical); leftBar = recursiveUpdate { layer = "top"; position = "left"; output = outputMap "left"; modules-left = cfg.config.waybar.layout.vertical.left; modules-center = cfg.config.waybar.layout.vertical.center; modules-right = cfg.config.waybar.layout.vertical.right; } (recursiveUpdate cfg.config.waybar.modules cfg.config.waybar.formats.vertical); }; }; xdg.configFile."waybar/style.css".source = ./config/waybar/style.css; }; }; }