From c589cef163fddefcca977f130319f6b5e3657621 Mon Sep 17 00:00:00 2001 From: Ryan Schanzenbacher Date: Sat, 29 Aug 2026 11:32:16 -0400 Subject: Added vorsaint and settings file, refactor yabai --- files/darwin-settings/vorssaint_settings.plist | 787 +++++++++++++++++++++++++ hosts/RyanMac/configuration.nix | 93 +-- modules/darwin/yabai/default.nix | 237 ++++++++ 3 files changed, 1032 insertions(+), 85 deletions(-) create mode 100644 files/darwin-settings/vorssaint_settings.plist create mode 100644 modules/darwin/yabai/default.nix diff --git a/files/darwin-settings/vorssaint_settings.plist b/files/darwin-settings/vorssaint_settings.plist new file mode 100644 index 0000000..44a5daa --- /dev/null +++ b/files/darwin-settings/vorssaint_settings.plist @@ -0,0 +1,787 @@ + + + + + settings + + appAppearance + system + appUpdatesCheckFrequency + off + appUpdatesIncludeAppStore + + appUpdatesNotify + + autoCheckUpdates + + autoQuitEnabled + + autoQuitExceptions + + com.apple.finder + + batteryLimitPercent + 10 + brightnessControlEnabled + + brightnessKeysEnabled + + brightnessOSDEnabled + + cameraPreviewShortcut + control+option+command:13 + cameraPreviewShortcutEnabled + + clamshellPreferred + + cleanerScheduleFrequency + off + cleanerScheduleHour + 9 + cleanerScheduleMinute + 0 + cleanerScheduleNotify + + cleanerScheduleWeekday + 2 + clipboardHistoryEnabled + + clipboardHistoryIncludeImagesFiles + + clipboardHistoryLimit + 50 + clipboardHistoryShortcut + control+option+command:9 + clipboardHistoryShortcutEnabled + + clipboardHistorySkipSensitive + + colorPickerBareHex + + colorPickerFormat + hex + colorPickerShortcut + control+option+command:8 + colorPickerShortcutEnabled + + commandBarAliases + + commandBarDisabledSources + + commandBarHidden + + commandBarPins + + commandBarShortcut + option:49 + commandBarShortcutEnabled + + defaultDurationMinutes + 0 + dockClickCycleWindows + + dockClickMinimize + + dockPreviewEnabled + + extraBrightnessEnabled + + extraBrightnessLevel + 100 + featureAvailable.appUpdates + + featureAvailable.autoQuit + + featureAvailable.brightness + + featureAvailable.cameraPreview + + featureAvailable.cleaner + + featureAvailable.cleaningMode + + featureAvailable.clipboardHistory + + featureAvailable.colorPicker + + featureAvailable.commandBar + + featureAvailable.dockClick + + featureAvailable.dockPreview + + featureAvailable.extraBrightness + + featureAvailable.finderCutPaste + + featureAvailable.homebrew + + featureAvailable.keepAwake + + featureAvailable.keyboardDebounce + + featureAvailable.mediaTools + + featureAvailable.micMute + + featureAvailable.middleClick + + featureAvailable.mixer + + featureAvailable.monitorCPU + + featureAvailable.monitorDisk + + featureAvailable.monitorGPU + + featureAvailable.monitorMemory + + featureAvailable.monitorNetwork + + featureAvailable.monitorPower + + featureAvailable.mouseButtonShortcuts + + featureAvailable.mouseNavigation + + featureAvailable.musicBlock + + featureAvailable.pastePlain + + featureAvailable.quickLauncher + + featureAvailable.quickToggles + + featureAvailable.radialMenu + + featureAvailable.scratchpad + + featureAvailable.screenOCR + + featureAvailable.screenshot + + featureAvailable.scrollInverter + + featureAvailable.shelf + + featureAvailable.smoothScroll + + featureAvailable.soundOutputSwitcher + + featureAvailable.superKey + + featureAvailable.switcher + + featureAvailable.textSnippets + + featureAvailable.uninstaller + + featureAvailable.urlCleaner + + featureAvailable.windowLayout + + featureAvailable.windowMaximizer + + featuresOnboardingVersion + 4 + finderCutPasteEnabled + + hasOnboarded + + hotkeyEnabled + + keepAwakeActiveIcon + vorssaint + keepAwakeAutoStart + + keepAwakeConnectedToPower + + keepAwakeExternalDisplay + + keepAwakeIconTint + orange + keepAwakeMouseJiggleEnabled + + keepAwakeMouseJiggleIntervalMinutes + 5 + keepAwakeShortcut + control+option+command:40 + keyboardDebounceEnabled + + keyboardDebounceKeyWindows + + keyboardDebounceWindowMs + 5 + lastUpdateIntroVersion + 3.2.0 + launchAtLoginWanted + + mediaGIFEnd + 0.0 + mediaGIFFPS + 12 + mediaGIFLoops + + mediaGIFQuality + 0.73999999999999999 + mediaGIFStart + 0.0 + mediaGIFWidth + 720 + mediaImageFormat + jpeg + mediaImageMaxDimension + 1600 + mediaImageQuality + 0.71999999999999997 + mediaImageStripMetadata + + mediaLastTool + videoCompressor + mediaTextAccurate + + mediaTextLanguageCorrection + + mediaVideoCodec + h264 + mediaVideoEnd + 0.0 + mediaVideoFPS + 30 + mediaVideoKeepAudio + + mediaVideoMaxDimension + 1280 + mediaVideoQuality + 0.68000000000000005 + mediaVideoStart + 0.0 + menuBarBatteryTemperature + + menuBarBatteryTime + + menuBarCPU + + menuBarCPUTemperature + + menuBarCombineTemperatures + + menuBarDiskActivity + + menuBarDiskUsage + + menuBarGPU + + menuBarGPUTemperature + + menuBarHideIconWithMetrics + + menuBarLabelStyle + compact + menuBarMemoryStyle + percent + menuBarMetricAppearance + values + menuBarMetricOrder + cpu,cpuTemperature,gpu,gpuTemperature,memory,battery,batteryTime,batteryTemperature,peripheralBattery,network,diskUsage,diskActivity,power + menuBarMetricSpacing + compact + menuBarNetworkUploadFirst + + menuBarPeripheralBattery + + menuBarPreset + dense + menuBarSeparateMetrics + + menuBarUsageBarCriticalColor + #FF453A + menuBarUsageBarElevatedColor + #FFD60A + menuBarUsageBarHighThreshold + 90 + menuBarUsageBarMediumThreshold + 70 + menuBarUsageBarNormalColor + #64D2FF + micMuteMenuBarIndicator + + micMuteShortcut + control+option+command:46 + micMuteShortcutEnabled + + middleClickEnabled + + middleClickExceptions + + middleClickTapFingers + 0 + mixerHeadphonesDisconnectVolumePercent + 25 + mixerLowerVolumeOnHeadphonesDisconnect + + mixerShowFinder + + monitorAlertBattery + + monitorAlertBatteryPercent + 15 + monitorAlertCPU + + monitorAlertCPUTemperature + + monitorAlertCPUTemperatureThreshold + 90 + monitorAlertCPUThreshold + 90 + monitorAlertCooldownMinutes + 15 + monitorAlertDisk + + monitorAlertDiskFreePercent + 10 + monitorAlertMemory + + monitorDiskActivity + + monitorDiskProtection + + monitorDiskSMART + + monitorDiskTools + + monitorDiskUsage + + monitorGraphBattery + + monitorGraphCPU + + monitorGraphDisk + + monitorGraphGPU + + monitorGraphMemory + + monitorGraphNetwork + + monitorGraphPower + + monitorIntervalSeconds + 2 + monitorNetApps + + monitorNetSpeed + + monitorNetTest + + monitorNetTotals + + monitorPwrAdapter + + monitorPwrBattery + + monitorPwrHealth + + monitorPwrSystem + + monitorPwrTimeRemaining + + monitorShowDisk + + monitorShowFanControlBeta + + monitorShowMixer + + monitorShowNetwork + + monitorShowPower + + monitorShowSystem + + monitorSysAlerts + + monitorSysBattery + + monitorSysCPU + + monitorSysGPU + + monitorSysMemory + + monitorSysTemps + + monitorSysUptime + + mouseButtonExceptions + + mouseButtonShortcuts + + mouseButtonShortcutsEnabled + + mouseNavigationEnabled + + mouseNavigationExceptions + + musicBlockEnabled + + musicBlockReplacementPath + + onboardingStep + 0 + panelCollapsedResetVersion + 2.15.1 + panelControlAutoQuit + + panelControlCutPaste + + panelControlDockClick + + panelControlDockClickCycle + + panelControlDockPreview + + panelControlFilesExpanded + + panelControlInputExpanded + + panelControlKeyDebounce + + panelControlMiddleClick + + panelControlMouseButtonShortcuts + + panelControlMouseNavigation + + panelControlMouseScroll + + panelControlRadialMenu + + panelControlShelf + + panelControlSuperKey + + panelControlSwitcher + + panelControlTextSnippets + + panelControlWindowMaximize + + panelControlWindowsExpanded + + panelNavigationEnabled + + panelPowerOrder + system,adapter,battery,remaining,health + panelShowBrightness + + panelShowControls + + panelShowKeepAwake + + panelShowToggles + + panelShowUtilities + + panelToggleDarkMode + + panelToggleDesktopIcons + + panelToggleDisplayOff + + panelToggleEjectDisks + + panelToggleEmptyTrash + + panelToggleHiddenFiles + + panelToggleLockScreen + + panelToggleScreenSaver + + panelUtilityAppUpdates + + panelUtilityCameraPreview + + panelUtilityCleaner + + panelUtilityCleaning + + panelUtilityClipboard + + panelUtilityColorPicker + + panelUtilityCommandBar + + panelUtilityHomebrew + + panelUtilityMedia + + panelUtilityMicMute + + panelUtilityQuickLauncher + + panelUtilityScratchpad + + panelUtilityScreenOCR + + panelUtilityScreenshot + + panelUtilityURLCleaner + + panelUtilityUninstaller + + panelUtilityWindowLayout + + pastePlainEnabled + + pastePlainShortcut + option+shift+command:9 + previewSize + normal + quickLauncherHiddenItems + + quickLauncherShortcut + control+command:9 + quickLauncherShortcutEnabled + + radialMenuActivationMode + pressOrHold + radialMenuAtPointer + + radialMenuEnabled + + radialMenuItems + + W3sicGF5bG9hZCI6InNjcmVlbnNob3QiLCJjaGlsZHJlbiI6W10sIm5hbWUi + OiIiLCJpZCI6IjU1N0M5QjY0LURBRUQtNEY0OS1CMjAyLUE2RTRFMjg3QkE3 + MSIsImtpbmQiOiJ0b29sIiwic3ltYm9sTmFtZSI6IiJ9LHsicGF5bG9hZCI6 + ImNvbG9yUGlja2VyIiwiY2hpbGRyZW4iOltdLCJuYW1lIjoiIiwiaWQiOiI4 + NDc1RTg2OS0yNjFELTQ2OEUtODJEOC1BMjFGM0VFN0VGQjgiLCJraW5kIjoi + dG9vbCIsInN5bWJvbE5hbWUiOiIifSx7InBheWxvYWQiOiJjYW1lcmFQcmV2 + aWV3IiwiY2hpbGRyZW4iOltdLCJuYW1lIjoiIiwiaWQiOiIzRTNCRUU3MS05 + QzgxLTQ5QjMtOTEzNS03OTA5RkY5MDc4QUQiLCJraW5kIjoidG9vbCIsInN5 + bWJvbE5hbWUiOiIifV0= + + radialMenuMouseButton + off + radialMenuShortcut + control+option+command:49 + releaseNotesOnUpdate + + scratchpadCloseOnClickOutside + + scratchpadRetention + never + scratchpadShortcut + control+option+command:45 + scratchpadShortcutEnabled + + screenOCRDetectQRCodes + + screenOCRShortcut + control+option+command:17 + screenOCRShortcutEnabled + + screenshotAnnotationShadows + + screenshotBackdropPresets + [] + screenshotBackdropStyle + + screenshotCopyToClipboard + + screenshotDefaultAction + + screenshotDelay + 0 + screenshotDownscale + + screenshotFileNamePattern + + screenshotFileNumberNext + 1 + screenshotFileNumberStart + 1 + screenshotFreeze + + screenshotIncludePointer + + screenshotLastColor + red + screenshotLastSticker + check + screenshotLastStroke + medium + screenshotLastTool + select + screenshotOpenEditorDirectly + + screenshotSaveFolder + + screenshotSaveSubfolder + + screenshotShortcut + control+option+command:21 + screenshotShortcutEnabled + + screenshotShowLastRegion + + screenshotToolOrder + select,arrow,pixelate,crop,text,sticker,rect,highlight,freehand,line,ellipse,counter,redact + screenshotToolShortcutsEnabled + + scrollInverterEnabled + + scrollInverterExceptions + + shelfAutomaticExclusions + + shelfCloseAfterDrop + + shelfDropZoneEnabled + + shelfEnabled + + shelfRemoveAfterDrop + + shelfShakeToOpen + + shelfShortcut + control+option+command:2 + shelfShortcutEnabled + + showCountdownInMenuBar + + smoothScrollEnabled + + smoothScrollExceptions + + smoothScrollStep + 40 + snippetLibraryEnabled + + snippetLibraryShortcut + control+option+command:37 + soundOutputSwitcherEnabled + + soundOutputSwitcherShortcut + control+option+command:1 + superKeyEnabled + + superKeySoloAction + none + supportUpdateIntroVersion + 3.1.13 + switcherCurrentSpaceOnly + + switcherEnabled + + switcherIconRowMode + + switcherMergeTabs + + switcherShortcut + command:48 + switcherShowWindowlessFinder + + switcherSimpleMode + + switcherWindowShortcut + command:50 + switcherWindowlessApps + finder + temperatureUnit + celsius + textSnippetsEnabled + + updateHighlightsSeenVersion + 3.2.0 + urlCleanerEnabled + + whatsAppDownloadsAutomaticEnabled + + whatsAppDownloadsCategories + image,video,audio + whatsAppDownloadsIncludeExisting + + whatsAppDownloadsNotify + + whatsAppDownloadsRetentionDays + 7 + whatsAppOrganizerCategories + image,video,audio,document,archive,other + whatsAppOrganizerDelayMinutes + 5 + whatsAppOrganizerDuplicateAction + trashNew + whatsAppOrganizerEnabled + + whatsAppOrganizerLayout + flat + windowGestureEnabled + + windowGestureModifiers + control+command + windowGestureRaiseWindow + + windowLayoutHiddenActions + + windowLayoutShortcutBottom + control+option:125 + windowLayoutShortcutBottomCenterSixth + none + windowLayoutShortcutBottomLeft + control+option:38 + windowLayoutShortcutBottomLeftSixth + none + windowLayoutShortcutBottomRight + control+option:40 + windowLayoutShortcutBottomRightSixth + none + windowLayoutShortcutCenter + control+option:8 + windowLayoutShortcutCenterThird + control+option:3 + windowLayoutShortcutFullScreen + none + windowLayoutShortcutLeft + control+option:123 + windowLayoutShortcutLeftThird + control+option:2 + windowLayoutShortcutLeftTwoThirds + control+option:14 + windowLayoutShortcutMaximize + control+option:36 + windowLayoutShortcutNextDisplay + control+option+command:124 + windowLayoutShortcutRestore + control+option:15 + windowLayoutShortcutRight + control+option:124 + windowLayoutShortcutRightThird + control+option:5 + windowLayoutShortcutRightTwoThirds + control+option:17 + windowLayoutShortcutTop + control+option:126 + windowLayoutShortcutTopCenterSixth + none + windowLayoutShortcutTopLeft + control+option:32 + windowLayoutShortcutTopLeftSixth + none + windowLayoutShortcutTopRight + control+option:34 + windowLayoutShortcutTopRightSixth + none + windowLayoutShortcutsEnabled + + windowMaximizeEnabled + + + vorssaintBackupAppVersion + 3.2.0 + vorssaintBackupVersion + 1 + + diff --git a/hosts/RyanMac/configuration.nix b/hosts/RyanMac/configuration.nix index e8339e6..307c7f0 100644 --- a/hosts/RyanMac/configuration.nix +++ b/hosts/RyanMac/configuration.nix @@ -24,20 +24,6 @@ let ]; }); - mkSpace = i: { - name = toString (117+i); - value = { - enabled = true; - value = { - type = "standard"; - parameters = [ (48 + i) (builtins.elemAt [ 18 19 20 21 22 23 25 26 28 ] (i - 1)) 524288 ]; # opt + num - #parameters = [ (48 + i) (builtins.elemAt [ 18 19 20 21 22 23 25 26 28 ] (i - 1)) 1048576 ]; # cmd + num - }; - }; - }; - - spaceHotkeys = builtins.listToAttrs (map mkSpace (lib.range 1 9)); - manualHotkeys = { "64" = { enabled = true; @@ -49,6 +35,7 @@ in { imports = [ inputs.nix-homebrew.darwinModules.nix-homebrew ../../modules/darwin/random-wallpaper + ../../modules/darwin/yabai ]; # Define the system's user and home dir location @@ -69,43 +56,14 @@ in { }; # Configure yabai - services.yabai = { + local.yabai = { enable = true; - enableScriptingAddition = false; - config = { - mouse_follows_focus = "on"; - layout = "bsp"; - window_placement = "second_child"; - top_padding = "10"; - bottom_padding = "10"; - left_padding = "10"; - right_padding = "10"; - window_gap = "10"; - mouse_modifier = "alt"; - mouse_drop_action = "swap"; - mouse_action1 = "move"; - mouse_action2 = "resize"; - focus_follows_mouse = "autofocus"; + defaultPadding = 10; + defaultTopPadding = 10; + displayTopPadding = { + "6131F10F-6020-4D7E-8222-8702B5AEF45E" = 40; }; - extraConfig = '' - yabai -m rule --add app='System Settings' manage=off - yabai -m rule --add app="^Zen$" title="^Picture-in-Picture$" manage=off - '' - # Add simple-bar signals if enabled - + lib.optionalString config.home-manager.users.${username}.ryan.simple-bar.enable '' - yabai -m signal --add event=window_focused action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows when focused application changes" - yabai -m signal --add event=window_resized action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows when a window is resized" - yabai -m signal --add event=window_destroyed action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-ba spaces & windows when an application window is closed" - yabai -m signal --add event=space_changed action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows on space change" - yabai -m signal --add event=display_changed action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows on display focus change" - yabai -m signal --add event=window_title_changed action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows when current window title changes" - yabai -m signal --add event=space_destroyed action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows on space removal" - yabai -m signal --add event=space_created action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows on space creation" - yabai -m signal --add event=application_activated action="curl http://localhost:7776/yabai/spaces/refresh && curl http://localhost:7776/yabai/windows/refresh" label="Refresh simple-bar spaces & windows when application is activated" - yabai -m signal --add event=display_added action="curl http://localhost:7776/yabai/displays/refresh" label="Refresh simple-bar displays when a new dispay is added" - yabai -m signal --add event=display_removed action="curl http://localhost:7776/yabai/displays/refresh" label="Refresh simple-bar displays when a dispay is removed" - yabai -m signal --add event=display_moved action="curl http://localhost:7776/yabai/displays/refresh" label="Refresh simple-bar displays when a dispay is moved" - ''; + extraSymbolicHotkeys = manualHotkeys; }; # Configure JankyBorders @@ -200,6 +158,7 @@ in { "gimp" "kdenlive" "rustdesk" + "vorssaint" ]; }; @@ -209,35 +168,6 @@ in { skhdConfig = '' alt - d : osascript -e 'tell application "System Events" to key code 49 using {command down}' alt - return : osascript -e 'tell application "Ghostty"' -e 'new window' -e 'activate' -e 'end tell' - - shift + alt - q : ${pkgs.yabai}/bin/yabai -m window --close - - alt - up : ${pkgs.yabai}/bin/yabai -m window --focus north || ${pkgs.yabai}/bin/yabai -m display --focus north - shift + alt - up : ${pkgs.yabai}/bin/yabai -m window --swap north || ${pkgs.yabai}/bin/yabai -m window --display north - alt - down : ${pkgs.yabai}/bin/yabai -m window --focus south || ${pkgs.yabai}/bin/yabai -m display --focus south - shift + alt - down : ${pkgs.yabai}/bin/yabai -m window --swap south || ${pkgs.yabai}/bin/yabai -m window --display south - alt - right : ${pkgs.yabai}/bin/yabai -m window --focus east || ${pkgs.yabai}/bin/yabai -m display --focus east - shift + alt - right : ${pkgs.yabai}/bin/yabai -m window --swap east || ${pkgs.yabai}/bin/yabai -m window --display east - alt - left : ${pkgs.yabai}/bin/yabai -m window --focus west || ${pkgs.yabai}/bin/yabai -m display --focus west - shift + alt - left: ${pkgs.yabai}/bin/yabai -m window --swap west || ${pkgs.yabai}/bin/yabai -m window --display west - - shift + alt - space: ${pkgs.yabai}/bin/yabai -m window --toggle float - - shift + alt - return: ${pkgs.yabai}/bin/yabai -m window --toggle sticky - - alt - f : ${pkgs.yabai}/bin/yabai -m window --toggle zoom-fullscreen - - shift + alt - f: ${pkgs.yabai}/bin/yabai -m window --toggle native-fullscreen - - shift + alt - 1 : ${pkgs.yabai}/bin/yabai -m window --space 1 - shift + alt - 2 : ${pkgs.yabai}/bin/yabai -m window --space 2 - shift + alt - 3 : ${pkgs.yabai}/bin/yabai -m window --space 3 - shift + alt - 4 : ${pkgs.yabai}/bin/yabai -m window --space 4 - shift + alt - 5 : ${pkgs.yabai}/bin/yabai -m window --space 5 - shift + alt - 6 : ${pkgs.yabai}/bin/yabai -m window --space 6 - shift + alt - 7 : ${pkgs.yabai}/bin/yabai -m window --space 7 - shift + alt - 8 : ${pkgs.yabai}/bin/yabai -m window --space 8 - shift + alt - 9 : ${pkgs.yabai}/bin/yabai -m window --space 9 ''; }; @@ -250,9 +180,6 @@ in { }; system.defaults = { - WindowManager = { - EnableTilingOptionAccelerator = false; - }; NSGlobalDomain = { # 24 hour time AppleICUForce24HourTime = true; @@ -391,10 +318,6 @@ in { "com.apple.Accessibility" = { ReduceMotionEnabled = 1; }; - - "com.apple.symbolichotkeys" = { - AppleSymbolicHotKeys = manualHotkeys // spaceHotkeys; - }; }; universalaccess.reduceMotion = true; }; diff --git a/modules/darwin/yabai/default.nix b/modules/darwin/yabai/default.nix new file mode 100644 index 0000000..8e64dd1 --- /dev/null +++ b/modules/darwin/yabai/default.nix @@ -0,0 +1,237 @@ +# modules/darwin/yabai/default.nix +{ config, lib, pkgs, ... }: + +let + cfg = config.local.yabai; + + # symbolic hotkey IDs 118..126 == "Switch to Desktop 1".."Switch to Desktop 9" + spaceKeycodes = [ 18 19 20 21 22 23 25 26 28 ]; + + mkSpaceHotkey = i: { + name = toString (117 + i); + value = { + enabled = true; + value = { + type = "standard"; + parameters = [ + (48 + i) # ASCII '1'..'9' + (builtins.elemAt spaceKeycodes (i - 1)) # virtual keycode + cfg.spaceHotkeys.modifierMask + ]; + }; + }; + }; + + spaceHotkeys = builtins.listToAttrs + (map mkSpaceHotkey (lib.range 1 cfg.spaceHotkeys.count)); + + padArms = lib.concatStringsSep "\n" (lib.mapAttrsToList + (uuid: pad: " ${uuid}) pad=${toString pad} ;;") + cfg.displayTopPadding); + + displayPaddingScript = pkgs.writeShellScript "yabai-display-padding" '' + set -eu + yabai="${cfg.package}/bin/yabai" + + "$yabai" -m query --displays \ + | ${lib.getExe pkgs.jq} -r '.[] | "\(.uuid) \(.spaces | map(tostring) | join(" "))"' \ + | while read -r uuid spaces; do + case "$uuid" in +${padArms} + *) pad=${toString cfg.defaultPadding} ;; + esac + for s in $spaces; do + for k in top_padding; do + "$yabai" -m config --space "$s" "$k" "$pad" || true + done + done + done + ''; + + yabaiBin = "${cfg.package}/bin/yabai"; + + directionBinds = lib.concatStringsSep "\n" (map (d: '' + alt - ${d.key} : ${yabaiBin} -m window --focus ${d.dir} || ${yabaiBin} -m display --focus ${d.dir} + shift + alt - ${d.key} : ${yabaiBin} -m window --swap ${d.dir} || ${yabaiBin} -m window --display ${d.dir} + '') [ + { key = "up"; dir = "north"; } + { key = "down"; dir = "south"; } + { key = "right"; dir = "east"; } + { key = "left"; dir = "west"; } + ]); + + spaceMoveBinds = lib.concatStringsSep "\n" + (map (i: "shift + alt - ${toString i} : ${yabaiBin} -m window --space ${toString i}") + (lib.range 1 cfg.spaceHotkeys.count)); + +in { + options.local.yabai = { + enable = lib.mkEnableOption "yabai tiling window manager setup"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.yabai; + description = "yabai package. Referenced by keybindings and the padding script."; + }; + + enableScriptingAddition = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Only gates space creation/destruction and moving windows between + spaces. Window geometry and padding work without it. + ''; + }; + + defaultPadding = lib.mkOption { + type = lib.types.int; + default = 10; + description = '' + Padding and window_gap for any display not listed in displayTopPadding. + Sized for Retina (2x) panels. + ''; + }; + + defaultTopPadding = lib.mkOption { + type = lib.types.int; + default = 10; + description = '' + Padding for top edge of screen + ''; + }; + + displayTopPadding = lib.mkOption { + type = lib.types.attrsOf lib.types.int; + default = { }; + example = lib.literalExpression '' + { "37D8832A-2D66-02CA-B9F7-8F30A301B230" = 40; } + ''; + description = '' + Display UUID -> padding value. The value is applied to all four + paddings and to window_gap for every space on that display. + + Get UUIDs with: + yabai -m query --displays | jq -r '.[] | "\(.uuid) \(.frame)"' + + Do not key off frame dimensions: yabai reports points, not pixels, + so a scaled 1080p panel will not report 1920x1080. + ''; + }; + + manageKeybindings = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Emit yabai skhd bindings into services.skhd.skhdConfig."; + }; + + spaceHotkeys = { + enable = lib.mkEnableOption "opt+ macOS space-switching hotkeys" // { + default = true; + }; + + count = lib.mkOption { + type = lib.types.ints.between 1 9; + default = 9; + description = "Number of spaces to bind. macOS exposes 9 symbolic hotkeys."; + }; + + modifierMask = lib.mkOption { + type = lib.types.int; + default = 524288; # option + description = "Carbon modifier mask. 524288 = option, 1048576 = command."; + }; + }; + + extraSymbolicHotkeys = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = '' + Merged into com.apple.symbolichotkeys alongside the space hotkeys. + Put non-yabai symbolic hotkeys here rather than defining + CustomUserPreferences."com.apple.symbolichotkeys" in the host config -- + CustomUserPreferences is types.attrs and merges shallowly, so a second + definition of that domain silently clobbers this one. + ''; + }; + + extraSettings = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = "Extra keys merged into services.yabai.config."; + }; + + extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + description = "Extra shell appended to yabairc (rules, signals)."; + }; + }; + + config = lib.mkIf cfg.enable { + services.yabai = { + enable = true; + inherit (cfg) package enableScriptingAddition; + + config = { + mouse_follows_focus = "on"; + layout = "bsp"; + window_placement = "second_child"; + top_padding = toString cfg.defaultTopPadding; + bottom_padding = toString cfg.defaultPadding; + left_padding = toString cfg.defaultPadding; + right_padding = toString cfg.defaultPadding; + window_gap = toString cfg.defaultPadding; + mouse_modifier = "alt"; + mouse_drop_action = "swap"; + mouse_action1 = "move"; + mouse_action2 = "resize"; + focus_follows_mouse = "autofocus"; + } // cfg.extraSettings; + + extraConfig = '' + yabai -m rule --add app='System Settings' manage=off + yabai -m rule --add app="^Zen$" title="^Picture-in-Picture$" manage=off + '' + + lib.optionalString (cfg.displayTopPadding != { }) '' + + # Per-display padding. space_created is required, not redundant: + # display_added fires when yabai sees the display, which can precede + # macOS finishing space creation on it, so the first pass may find + # zero or one space. display_removed is required because yabai + # reindexes spaces on disconnect and the overrides are keyed by index. + yabai -m signal --add event=display_added action="${displayPaddingScript}" label="per-display padding (added)" + yabai -m signal --add event=display_removed action="${displayPaddingScript}" label="per-display padding (removed)" + yabai -m signal --add event=space_created action="${displayPaddingScript}" label="per-display padding (space)" + ${displayPaddingScript} + '' + + cfg.extraConfig; + }; + + services.skhd = lib.mkIf cfg.manageKeybindings { + enable = true; + skhdConfig = '' + shift + alt - q : ${yabaiBin} -m window --close + + ${directionBinds} + + shift + alt - space : ${yabaiBin} -m window --toggle float + shift + alt - return : ${yabaiBin} -m window --toggle sticky + alt - f : ${yabaiBin} -m window --toggle zoom-fullscreen + shift + alt - f : ${yabaiBin} -m window --toggle native-fullscreen + + ${spaceMoveBinds} + ''; + }; + + # Prerequisites, not preferences: yabai requires per-display spaces, and + # macOS's own tiling fights it for window placement. + system.defaults = { + spaces."spans-displays" = false; + WindowManager.EnableTilingOptionAccelerator = false; + + CustomUserPreferences."com.apple.symbolichotkeys".AppleSymbolicHotKeys = + cfg.extraSymbolicHotkeys + // (lib.optionalAttrs cfg.spaceHotkeys.enable spaceHotkeys); + }; + }; +} -- cgit v1.3.1