Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions LilAgents/DockVisibility.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
import AppKit
import CoreGraphics
import Foundation

enum AppPreferences {
static let showOnAllDesktopsKey = "showOnAllDesktops"

static var showOnAllDesktops: Bool {
get {
UserDefaults.standard.bool(forKey: showOnAllDesktopsKey)
}
set {
UserDefaults.standard.set(newValue, forKey: showOnAllDesktopsKey)
}
}
}

enum DockVisibility {
static func collectionBehavior(showOnAllDesktops: Bool = AppPreferences.showOnAllDesktops) -> NSWindow.CollectionBehavior {
showOnAllDesktops
? [.canJoinAllSpaces, .fullScreenAuxiliary, .stationary]
: [.moveToActiveSpace, .stationary]
}

static func screenHasVisibleDockReservedArea(
screenFrame: CGRect,
visibleFrame: CGRect
Expand Down
22 changes: 21 additions & 1 deletion LilAgents/LilAgentsApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let displayItem = NSMenuItem(title: "Display", action: nil, keyEquivalent: "")
let displayMenu = NSMenu()
displayMenu.delegate = self
let allDesktopsItem = NSMenuItem(title: "Show on All Desktops", action: #selector(toggleShowOnAllDesktops(_:)), keyEquivalent: "")
allDesktopsItem.state = AppPreferences.showOnAllDesktops ? .on : .off
displayMenu.addItem(allDesktopsItem)
displayMenu.addItem(NSMenuItem.separator())
let autoItem = NSMenuItem(title: "Auto (Main Display)", action: #selector(switchDisplay(_:)), keyEquivalent: "")
autoItem.tag = -1
autoItem.state = .on
displayMenu.addItem(autoItem)
displayMenu.addItem(NSMenuItem.separator())
for (i, screen) in NSScreen.screens.enumerated() {
let name = screen.localizedName
let item = NSMenuItem(title: name, action: #selector(switchDisplay(_:)), keyEquivalent: "")
Expand Down Expand Up @@ -210,6 +213,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

@objc func toggleShowOnAllDesktops(_ sender: NSMenuItem) {
let enabled = !AppPreferences.showOnAllDesktops
AppPreferences.showOnAllDesktops = enabled
sender.state = enabled ? .on : .off
syncWindowCollectionBehaviors()
}

@objc func toggleChar1(_ sender: NSMenuItem) {
guard let chars = controller?.characters, chars.count > 0 else { return }
let char = chars[0]
Expand Down Expand Up @@ -242,6 +252,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@objc func quitApp() {
NSApp.terminate(nil)
}

private func syncWindowCollectionBehaviors() {
let behavior = DockVisibility.collectionBehavior()

controller?.characters.forEach { character in
character.window.collectionBehavior = behavior
character.popoverWindow?.collectionBehavior = behavior
character.thinkingBubbleWindow?.collectionBehavior = behavior
}
}
}

extension AppDelegate: NSMenuDelegate {}
4 changes: 4 additions & 0 deletions LilAgents/LilAgentsController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ class LilAgentsController {
}

private func shouldShowCharacters(on screen: NSScreen) -> Bool {
if AppPreferences.showOnAllDesktops {
return true
}

// User explicitly pinned to this screen — always show
if pinnedScreenIndex >= 0, pinnedScreenIndex < NSScreen.screens.count {
return true
Expand Down
10 changes: 7 additions & 3 deletions LilAgents/WalkerCharacter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class WalkerCharacter {
window.hasShadow = false
window.level = .statusBar
window.ignoresMouseEvents = false
window.collectionBehavior = [.moveToActiveSpace, .stationary]
window.collectionBehavior = windowCollectionBehavior

let hostView = CharacterContentView(frame: CGRect(x: 0, y: 0, width: displayWidth, height: displayHeight))
hostView.character = self
Expand Down Expand Up @@ -405,6 +405,10 @@ class WalkerCharacter {
(themeOverride ?? PopoverTheme.current).withCharacterColor(characterColor).withCustomFont()
}

private var windowCollectionBehavior: NSWindow.CollectionBehavior {
DockVisibility.collectionBehavior()
}

func createPopoverWindow() {
let t = resolvedTheme
let popoverWidth: CGFloat = 420
Expand All @@ -420,7 +424,7 @@ class WalkerCharacter {
win.backgroundColor = .clear
win.hasShadow = true
win.level = NSWindow.Level(rawValue: NSWindow.Level.statusBar.rawValue + 10)
win.collectionBehavior = [.moveToActiveSpace, .stationary]
win.collectionBehavior = windowCollectionBehavior
let brightness = t.popoverBg.redComponent * 0.299 + t.popoverBg.greenComponent * 0.587 + t.popoverBg.blueComponent * 0.114
win.appearance = NSAppearance(named: brightness < 0.5 ? .darkAqua : .aqua)

Expand Down Expand Up @@ -792,7 +796,7 @@ class WalkerCharacter {
win.hasShadow = true
win.level = NSWindow.Level(rawValue: NSWindow.Level.statusBar.rawValue + 5)
win.ignoresMouseEvents = true
win.collectionBehavior = [.moveToActiveSpace, .stationary]
win.collectionBehavior = windowCollectionBehavior

let container = NSView(frame: NSRect(x: 0, y: 0, width: w, height: h))
container.wantsLayer = true
Expand Down
22 changes: 22 additions & 0 deletions Tests/AppPreferencesTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Foundation

func runAppPreferencesTests() {
let defaults = UserDefaults.standard
let key = AppPreferences.showOnAllDesktopsKey
let originalValue = defaults.object(forKey: key)

defer {
defaults.removeObject(forKey: key)
if let originalValue {
defaults.set(originalValue, forKey: key)
}
}

defaults.removeObject(forKey: key)
expect(AppPreferences.showOnAllDesktops == false, "show on all desktops defaults to off")

AppPreferences.showOnAllDesktops = true
expect(defaults.bool(forKey: key) == true, "show on all desktops persists on")

print("AppPreferences tests passed")
}
20 changes: 11 additions & 9 deletions Tests/DockVisibilityTests.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import Foundation
import CoreGraphics
import AppKit

func runDockVisibilityTests() {
func expect(
_ condition: @autoclosure () -> Bool,
_ message: String
) {
if !condition() {
fputs("FAIL: \(message)\n", stderr)
exit(1)
}
}

let screenFrame = CGRect(x: 0, y: 0, width: 1440, height: 900)

Expand Down Expand Up @@ -74,5 +66,15 @@ func runDockVisibilityTests() {
"keeps characters hidden on non-main screens when only the menu bar is visible"
)

expect(
DockVisibility.collectionBehavior(showOnAllDesktops: false) == [.moveToActiveSpace, .stationary],
"uses active-space behavior when show on all desktops is off"
)

expect(
DockVisibility.collectionBehavior(showOnAllDesktops: true) == [.canJoinAllSpaces, .fullScreenAuxiliary, .stationary],
"uses all-spaces behavior when show on all desktops is on"
)

print("DockVisibility tests passed")
}
10 changes: 10 additions & 0 deletions Tests/main.swift
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
import Foundation

func expect(_ condition: @autoclosure () -> Bool, _ message: String) {
if !condition() {
fputs("FAIL: \(message)\n", stderr)
exit(1)
}
}

runDockVisibilityTests()
runAppPreferencesTests()