{ lib, config, ... }: let inherit (lib) mkOption types mkIf recursiveUpdate lists; 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 { horseman.dots = { wofi.enable = true; waybar.enable = true; hypr = { hyprland.enable = true; hypridle.enable = true; hyprpaper.enable = true; hyprlock.enable = true; }; }; home-manager.users.${homeCfg.username} = { 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); }; }; }; }; }