Atoll/DynamicIsland/components/Settings/SettingsWindowController.swift
2026-01-29 12:26:04 +05:30

147 lines
4.6 KiB
Swift

/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* Originally from boring.notch project
* Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit
import SwiftUI
import Sparkle
class SettingsWindowController: NSWindowController {
static let shared = SettingsWindowController()
private var updaterController: SPUStandardUpdaterController?
private init() {
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 700, height: 600),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered,
defer: false
)
super.init(window: window)
setupWindow()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setUpdaterController(_ controller: SPUStandardUpdaterController) {
self.updaterController = controller
// Recreate the content view with the proper updater controller
setupWindow()
}
private func setupWindow() {
guard let window = window else { return }
window.title = "Atoll Settings"
window.titlebarAppearsTransparent = false
window.titleVisibility = .visible
window.toolbarStyle = .unified
window.isMovableByWindowBackground = true
// Make it behave like a regular app window with proper Spaces support
window.collectionBehavior = [.managed, .participatesInCycle, .fullScreenAuxiliary]
// Ensure proper window behavior
window.hidesOnDeactivate = false
window.isExcludedFromWindowsMenu = false
// Configure window to be a standard document-style window
window.isRestorable = true
window.identifier = NSUserInterfaceItemIdentifier("DynamicIslandSettingsWindow")
// Create the SwiftUI content
let settingsView = SettingsView(updaterController: updaterController)
let hostingView = NSHostingView(rootView: settingsView)
window.contentView = hostingView
// Handle window closing
window.delegate = self
ScreenCaptureVisibilityManager.shared.register(window, scope: .panelsOnly)
}
func showWindow() {
// Ensure window exists
_ = window
// If window is already visible, bring it to front properly
if window?.isVisible == true {
NSApp.activate(ignoringOtherApps: true)
window?.orderFrontRegardless()
window?.makeKeyAndOrderFront(nil)
return
}
// Show the window with proper ordering
window?.orderFrontRegardless()
window?.makeKeyAndOrderFront(nil)
window?.center()
// Activate the app and ensure window gets focus
NSApp.activate(ignoringOtherApps: true)
// Force window to front after activation
DispatchQueue.main.async { [weak self] in
self?.window?.makeKeyAndOrderFront(nil)
}
}
override func close() {
super.close()
relinquishFocus()
}
private func relinquishFocus() {
window?.orderOut(nil)
// Set app back to accessory mode immediately
NSApp.setActivationPolicy(.accessory)
}
deinit {
if let window = window {
ScreenCaptureVisibilityManager.shared.unregister(window)
}
}
}
extension SettingsWindowController: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
relinquishFocus()
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
return true
}
func windowDidBecomeKey(_ notification: Notification) {
// Ensure app is in regular mode when window becomes key
NSApp.setActivationPolicy(.regular)
}
func windowDidResignKey(_ notification: Notification) {
}
}