118 lines
3.9 KiB
Swift
118 lines
3.9 KiB
Swift
import AppKit
|
|
import Combine
|
|
|
|
/// Application delegate that bootstraps the notch overlay system.
|
|
@MainActor
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
private enum UITestLaunchArgument {
|
|
static let regularActivation = "--uitest-regular-activation"
|
|
static let showSettings = "--uitest-show-settings"
|
|
static let openNotch = "--uitest-open-notch"
|
|
}
|
|
|
|
private var cancellables = Set<AnyCancellable>()
|
|
private let settingsController = AppSettingsController.shared
|
|
|
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
|
NotchSettings.registerDefaults()
|
|
|
|
if isRunningUITests {
|
|
NSApp.setActivationPolicy(.regular)
|
|
} else {
|
|
NSApp.setActivationPolicy(.accessory)
|
|
}
|
|
|
|
// Sync the launch-at-login toggle with the actual system state
|
|
// in case the user toggled it from System Settings.
|
|
settingsController.update {
|
|
$0.display.launchAtLogin = LaunchAtLoginHelper.isEnabled
|
|
}
|
|
|
|
ScreenManager.shared.start()
|
|
observeDisplayPreference()
|
|
observeSizePreferences()
|
|
observeFontSizeChanges()
|
|
observeTerminalThemeChanges()
|
|
applyUITestLaunchBehaviorIfNeeded()
|
|
}
|
|
|
|
func applicationWillTerminate(_ notification: Notification) {
|
|
ScreenManager.shared.stop()
|
|
}
|
|
|
|
// MARK: - Preference observers
|
|
|
|
/// Only rebuild windows when the display-count preference changes.
|
|
private func observeDisplayPreference() {
|
|
settingsController.$settings
|
|
.map(\.display.showOnAllDisplays)
|
|
.removeDuplicates()
|
|
.dropFirst()
|
|
.sink { _ in
|
|
ScreenManager.shared.rebuildWindows()
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
/// Reposition (not rebuild) when any sizing preference changes.
|
|
private func observeSizePreferences() {
|
|
settingsController.$settings
|
|
.map(\.display.layoutSignature)
|
|
.removeDuplicates()
|
|
.dropFirst()
|
|
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
|
|
.sink { _ in
|
|
ScreenManager.shared.repositionWindows()
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
/// Live-update terminal font size across all sessions.
|
|
private func observeFontSizeChanges() {
|
|
settingsController.$settings
|
|
.map(\.terminal.fontSize)
|
|
.removeDuplicates()
|
|
.sink { newSize in
|
|
guard newSize > 0 else { return }
|
|
WorkspaceRegistry.shared.updateAllWorkspacesFontSizes(CGFloat(newSize))
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
/// Live-update terminal colors across all sessions.
|
|
private func observeTerminalThemeChanges() {
|
|
settingsController.$settings
|
|
.map(\.terminal.themeRawValue)
|
|
.removeDuplicates()
|
|
.sink { newTheme in
|
|
WorkspaceRegistry.shared.updateAllWorkspacesThemes(TerminalTheme.resolve(newTheme))
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
private var launchArguments: [String] {
|
|
ProcessInfo.processInfo.arguments
|
|
}
|
|
|
|
private var isRunningUITests: Bool {
|
|
launchArguments.contains(UITestLaunchArgument.regularActivation)
|
|
|| launchArguments.contains(UITestLaunchArgument.showSettings)
|
|
|| launchArguments.contains(UITestLaunchArgument.openNotch)
|
|
}
|
|
|
|
private func applyUITestLaunchBehaviorIfNeeded() {
|
|
guard isRunningUITests else { return }
|
|
|
|
DispatchQueue.main.async { @MainActor in
|
|
if self.launchArguments.contains(UITestLaunchArgument.showSettings) {
|
|
SettingsWindowController.shared.showSettings()
|
|
}
|
|
|
|
if self.launchArguments.contains(UITestLaunchArgument.openNotch),
|
|
let screenID = ScreenRegistry.shared.activeScreenID() {
|
|
ScreenManager.shared.openNotch(screenID: screenID)
|
|
}
|
|
}
|
|
}
|
|
}
|