diff options
Diffstat (limited to 'Sources/phbar/Models/AppDelegate.swift')
| -rw-r--r-- | Sources/phbar/Models/AppDelegate.swift | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/Sources/phbar/Models/AppDelegate.swift b/Sources/phbar/Models/AppDelegate.swift new file mode 100644 index 0000000..a7ecb5a --- /dev/null +++ b/Sources/phbar/Models/AppDelegate.swift @@ -0,0 +1,47 @@ +import AppKit +import SwiftUI + +@MainActor +final class AppDelegate: NSObject, NSApplicationDelegate { + private var windows: [BarWindow] = [] + private var blocks: [Block] = Config.blocks.map(\.resolved) + private var tokens: [UnsafeMutableRawPointer] = [] + + func applicationDidFinishLaunching(_ notification: Notification) { + for screen in NSScreen.screens { + let frame = Screen.barFrame(screen, position: Config.position, height: Config.height) + let window = BarWindow(contentRect: frame) + window.contentView = NSHostingView(rootView: BarView(blocks: blocks)) + window.orderFrontRegardless() + windows.append(window) + } + + // Register one listener per unique name; a single post fans out to every + // block with that name (see Notifier). + for name in Set(blocks.map(\.name)) { + let token = Notifier.register(name) { [weak self] in + self?.handleRefresh(name) + } + tokens.append(token) + } + + for block in blocks { block.start() } + } + + func applicationWillTerminate(_ notification: Notification) { + for block in blocks { block.stop() } + for token in tokens { Notifier.cancel(token) } + } + + /// Called from a Darwin notification handler. Marked `nonisolated` because + /// libnotify's delivery contract isn't statically visible to Swift, so we + /// hop back to the main actor explicitly. + nonisolated func handleRefresh(_ name: String) { + Task { @MainActor [weak self] in + guard let self else { return } + for block in self.blocks where block.name == name { + block.runScript() + } + } + } +} |
