Merge pull request #350 from Beingpax/refactor-window-management
Refactor window management
This commit is contained in:
commit
2dedff0c84
@ -3,46 +3,30 @@ import SwiftUI
|
|||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
weak var menuBarManager: MenuBarManager?
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
updateActivationPolicy()
|
menuBarManager?.applyActivationPolicy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||||
updateActivationPolicy()
|
menuBarManager?.applyActivationPolicy()
|
||||||
|
|
||||||
if !flag {
|
if !flag, let menuBarManager = menuBarManager, !menuBarManager.isMenuBarOnly {
|
||||||
createMainWindowIfNeeded()
|
if WindowManager.shared.showMainWindow() != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidBecomeActive(_ notification: Notification) {
|
func applicationDidBecomeActive(_ notification: Notification) {
|
||||||
updateActivationPolicy()
|
menuBarManager?.applyActivationPolicy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateActivationPolicy() {
|
|
||||||
let isMenuBarOnly = UserDefaults.standard.bool(forKey: "IsMenuBarOnly")
|
|
||||||
if isMenuBarOnly {
|
|
||||||
NSApp.setActivationPolicy(.accessory)
|
|
||||||
} else {
|
|
||||||
NSApp.setActivationPolicy(.regular)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createMainWindowIfNeeded() {
|
|
||||||
if NSApp.windows.isEmpty {
|
|
||||||
let contentView = ContentView()
|
|
||||||
let hostingView = NSHostingView(rootView: contentView)
|
|
||||||
let window = WindowManager.shared.createMainWindow(contentView: hostingView)
|
|
||||||
window.makeKeyAndOrderFront(nil)
|
|
||||||
} else {
|
|
||||||
NSApp.windows.first?.makeKeyAndOrderFront(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stash URL when app cold-starts to avoid spawning a new window/tab
|
// Stash URL when app cold-starts to avoid spawning a new window/tab
|
||||||
var pendingOpenFileURL: URL?
|
var pendingOpenFileURL: URL?
|
||||||
@ -52,15 +36,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||||
|
|
||||||
if NSApp.windows.isEmpty {
|
if WindowManager.shared.currentMainWindow() == nil {
|
||||||
// Cold start: do NOT create a window here to avoid extra window/tab.
|
// Cold start: do NOT create a window here to avoid extra window/tab.
|
||||||
// Defer to SwiftUI’s WindowGroup-created ContentView and let it process this later.
|
// Defer to SwiftUI’s WindowGroup-created ContentView and let it process this later.
|
||||||
pendingOpenFileURL = url
|
pendingOpenFileURL = url
|
||||||
} else {
|
} else {
|
||||||
// Running: focus current window and route in-place to Transcribe Audio
|
// Running: focus current window and route in-place to Transcribe Audio
|
||||||
NSApp.windows.first?.makeKeyAndOrderFront(nil)
|
menuBarManager?.focusMainWindow()
|
||||||
NotificationCenter.default.post(name: .navigateToDestination, object: nil, userInfo: ["destination": "Transcribe Audio"])
|
NotificationCenter.default.post(name: .navigateToDestination, object: nil, userInfo: ["destination": "Transcribe Audio"])
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
NotificationCenter.default.post(name: .openFileForTranscription, object: nil, userInfo: ["url": url])
|
NotificationCenter.default.post(name: .openFileForTranscription, object: nil, userInfo: ["url": url])
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import LaunchAtLogin
|
|
||||||
import SwiftData
|
|
||||||
import AppKit
|
import AppKit
|
||||||
|
|
||||||
class MenuBarManager: ObservableObject {
|
class MenuBarManager: ObservableObject {
|
||||||
@ -11,27 +9,9 @@ class MenuBarManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var updaterViewModel: UpdaterViewModel
|
|
||||||
private var whisperState: WhisperState
|
|
||||||
private var container: ModelContainer
|
|
||||||
private var enhancementService: AIEnhancementService
|
|
||||||
private var aiService: AIService
|
|
||||||
private var hotkeyManager: HotkeyManager
|
|
||||||
private var mainWindow: NSWindow? // Store window reference
|
|
||||||
|
|
||||||
init(updaterViewModel: UpdaterViewModel,
|
init() {
|
||||||
whisperState: WhisperState,
|
|
||||||
container: ModelContainer,
|
|
||||||
enhancementService: AIEnhancementService,
|
|
||||||
aiService: AIService,
|
|
||||||
hotkeyManager: HotkeyManager) {
|
|
||||||
self.isMenuBarOnly = UserDefaults.standard.bool(forKey: "IsMenuBarOnly")
|
self.isMenuBarOnly = UserDefaults.standard.bool(forKey: "IsMenuBarOnly")
|
||||||
self.updaterViewModel = updaterViewModel
|
|
||||||
self.whisperState = whisperState
|
|
||||||
self.container = container
|
|
||||||
self.enhancementService = enhancementService
|
|
||||||
self.aiService = aiService
|
|
||||||
self.hotkeyManager = hotkeyManager
|
|
||||||
updateAppActivationPolicy()
|
updateAppActivationPolicy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,23 +19,37 @@ class MenuBarManager: ObservableObject {
|
|||||||
isMenuBarOnly.toggle()
|
isMenuBarOnly.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyActivationPolicy() {
|
||||||
|
updateAppActivationPolicy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func focusMainWindow() {
|
||||||
|
applyActivationPolicy()
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if WindowManager.shared.showMainWindow() == nil {
|
||||||
|
print("MenuBarManager: Unable to locate main window to focus")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func updateAppActivationPolicy() {
|
private func updateAppActivationPolicy() {
|
||||||
DispatchQueue.main.async { [weak self] in
|
let applyPolicy = { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self else { return }
|
||||||
|
let application = NSApplication.shared
|
||||||
// Clean up existing window if switching to menu bar mode
|
|
||||||
if self.isMenuBarOnly && self.mainWindow != nil {
|
|
||||||
self.mainWindow?.close()
|
|
||||||
self.mainWindow = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update activation policy
|
|
||||||
if self.isMenuBarOnly {
|
if self.isMenuBarOnly {
|
||||||
NSApp.setActivationPolicy(.accessory)
|
application.setActivationPolicy(.accessory)
|
||||||
|
WindowManager.shared.hideMainWindow()
|
||||||
} else {
|
} else {
|
||||||
NSApp.setActivationPolicy(.regular)
|
application.setActivationPolicy(.regular)
|
||||||
|
WindowManager.shared.showMainWindow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if Thread.isMainThread {
|
||||||
|
applyPolicy()
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.async(execute: applyPolicy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openMainWindowAndNavigate(to destination: String) {
|
func openMainWindowAndNavigate(to destination: String) {
|
||||||
@ -64,31 +58,13 @@ class MenuBarManager: ObservableObject {
|
|||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
if self.isMenuBarOnly {
|
self.applyActivationPolicy()
|
||||||
NSApp.setActivationPolicy(.accessory)
|
|
||||||
} else {
|
guard WindowManager.shared.showMainWindow() != nil else {
|
||||||
NSApp.setActivationPolicy(.regular)
|
print("MenuBarManager: Unable to show main window for navigation")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate the app
|
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
|
||||||
|
|
||||||
// Clean up existing window if it's no longer valid
|
|
||||||
if let existingWindow = self.mainWindow, !existingWindow.isVisible {
|
|
||||||
self.mainWindow = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get or create main window
|
|
||||||
if self.mainWindow == nil {
|
|
||||||
self.mainWindow = self.createMainWindow()
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let window = self.mainWindow else { return }
|
|
||||||
|
|
||||||
// Make the window key and order front
|
|
||||||
window.makeKeyAndOrderFront(nil)
|
|
||||||
window.center() // Always center the window for consistent positioning
|
|
||||||
|
|
||||||
// Post a notification to navigate to the desired destination
|
// Post a notification to navigate to the desired destination
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
NotificationCenter.default.post(
|
NotificationCenter.default.post(
|
||||||
@ -100,47 +76,4 @@ class MenuBarManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createMainWindow() -> NSWindow {
|
|
||||||
print("MenuBarManager: Creating new main window")
|
|
||||||
|
|
||||||
// Create the content view with all required environment objects
|
|
||||||
let contentView = ContentView()
|
|
||||||
.environmentObject(whisperState)
|
|
||||||
.environmentObject(hotkeyManager)
|
|
||||||
.environmentObject(self)
|
|
||||||
.environmentObject(updaterViewModel)
|
|
||||||
.environmentObject(enhancementService)
|
|
||||||
.environmentObject(aiService)
|
|
||||||
.environment(\.modelContext, ModelContext(container))
|
|
||||||
|
|
||||||
// Create window using WindowManager
|
|
||||||
let hostingView = NSHostingView(rootView: contentView)
|
|
||||||
let window = WindowManager.shared.createMainWindow(contentView: hostingView)
|
|
||||||
|
|
||||||
// Set window delegate to handle window closing
|
|
||||||
let delegate = WindowDelegate { [weak self] in
|
|
||||||
self?.mainWindow = nil
|
|
||||||
}
|
|
||||||
window.delegate = delegate
|
|
||||||
|
|
||||||
print("MenuBarManager: Window setup complete")
|
|
||||||
|
|
||||||
return window
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window delegate to handle window closing
|
|
||||||
class WindowDelegate: NSObject, NSWindowDelegate {
|
|
||||||
let onClose: () -> Void
|
|
||||||
|
|
||||||
init(onClose: @escaping () -> Void) {
|
|
||||||
self.onClose = onClose
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func windowWillClose(_ notification: Notification) {
|
|
||||||
onClose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -180,6 +180,7 @@ struct MenuBarView: View {
|
|||||||
Button("Copy Last Transcription") {
|
Button("Copy Last Transcription") {
|
||||||
LastTranscriptionService.copyLastTranscription(from: whisperState.modelContext)
|
LastTranscriptionService.copyLastTranscription(from: whisperState.modelContext)
|
||||||
}
|
}
|
||||||
|
.keyboardShortcut("c", modifiers: [.command, .shift])
|
||||||
|
|
||||||
Button("History") {
|
Button("History") {
|
||||||
menuBarManager.openMainWindowAndNavigate(to: "History")
|
menuBarManager.openMainWindowAndNavigate(to: "History")
|
||||||
@ -194,6 +195,7 @@ struct MenuBarView: View {
|
|||||||
Button(menuBarManager.isMenuBarOnly ? "Show Dock Icon" : "Hide Dock Icon") {
|
Button(menuBarManager.isMenuBarOnly ? "Show Dock Icon" : "Hide Dock Icon") {
|
||||||
menuBarManager.toggleMenuBarOnly()
|
menuBarManager.toggleMenuBarOnly()
|
||||||
}
|
}
|
||||||
|
.keyboardShortcut("d", modifiers: [.command, .shift])
|
||||||
|
|
||||||
Toggle("Launch at Login", isOn: $launchAtLoginEnabled)
|
Toggle("Launch at Login", isOn: $launchAtLoginEnabled)
|
||||||
.onChange(of: launchAtLoginEnabled) { oldValue, newValue in
|
.onChange(of: launchAtLoginEnabled) { oldValue, newValue in
|
||||||
|
|||||||
@ -79,15 +79,9 @@ struct VoiceInkApp: App {
|
|||||||
let hotkeyManager = HotkeyManager(whisperState: whisperState)
|
let hotkeyManager = HotkeyManager(whisperState: whisperState)
|
||||||
_hotkeyManager = StateObject(wrappedValue: hotkeyManager)
|
_hotkeyManager = StateObject(wrappedValue: hotkeyManager)
|
||||||
|
|
||||||
let menuBarManager = MenuBarManager(
|
let menuBarManager = MenuBarManager()
|
||||||
updaterViewModel: updaterViewModel,
|
|
||||||
whisperState: whisperState,
|
|
||||||
container: container,
|
|
||||||
enhancementService: enhancementService,
|
|
||||||
aiService: aiService,
|
|
||||||
hotkeyManager: hotkeyManager
|
|
||||||
)
|
|
||||||
_menuBarManager = StateObject(wrappedValue: menuBarManager)
|
_menuBarManager = StateObject(wrappedValue: menuBarManager)
|
||||||
|
appDelegate.menuBarManager = menuBarManager
|
||||||
|
|
||||||
let activeWindowService = ActiveWindowService.shared
|
let activeWindowService = ActiveWindowService.shared
|
||||||
activeWindowService.configure(with: enhancementService)
|
activeWindowService.configure(with: enhancementService)
|
||||||
@ -157,8 +151,7 @@ struct VoiceInkApp: App {
|
|||||||
.environmentObject(enhancementService)
|
.environmentObject(enhancementService)
|
||||||
.frame(minWidth: 880, minHeight: 780)
|
.frame(minWidth: 880, minHeight: 780)
|
||||||
.background(WindowAccessor { window in
|
.background(WindowAccessor { window in
|
||||||
// Ensure this is called only once or is idempotent
|
if window.identifier == nil || window.identifier != NSUserInterfaceItemIdentifier("com.prakashjoshipax.voiceink.onboardingWindow") {
|
||||||
if window.title != "VoiceInk Onboarding" { // Prevent re-configuration
|
|
||||||
WindowManager.shared.configureOnboardingPanel(window)
|
WindowManager.shared.configureOnboardingPanel(window)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,12 +1,27 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import AppKit
|
import AppKit
|
||||||
|
|
||||||
class WindowManager {
|
class WindowManager: NSObject {
|
||||||
static let shared = WindowManager()
|
static let shared = WindowManager()
|
||||||
|
|
||||||
private init() {}
|
private static let mainWindowIdentifier = NSUserInterfaceItemIdentifier("com.prakashjoshipax.voiceink.mainWindow")
|
||||||
|
private static let onboardingWindowIdentifier = NSUserInterfaceItemIdentifier("com.prakashjoshipax.voiceink.onboardingWindow")
|
||||||
|
private static let mainWindowAutosaveName = NSWindow.FrameAutosaveName("VoiceInkMainWindowFrame")
|
||||||
|
|
||||||
|
private weak var mainWindow: NSWindow?
|
||||||
|
private var didApplyInitialPlacement = false
|
||||||
|
|
||||||
|
private override init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
func configureWindow(_ window: NSWindow) {
|
func configureWindow(_ window: NSWindow) {
|
||||||
|
if let existingWindow = NSApplication.shared.windows.first(where: { $0.identifier == Self.mainWindowIdentifier && $0 != window }) {
|
||||||
|
window.close()
|
||||||
|
existingWindow.makeKeyAndOrderFront(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let requiredStyleMask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
|
let requiredStyleMask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
|
||||||
window.styleMask.formUnion(requiredStyleMask)
|
window.styleMask.formUnion(requiredStyleMask)
|
||||||
window.titlebarAppearsTransparent = true
|
window.titlebarAppearsTransparent = true
|
||||||
@ -19,10 +34,17 @@ class WindowManager {
|
|||||||
window.isOpaque = true
|
window.isOpaque = true
|
||||||
window.isMovableByWindowBackground = false
|
window.isMovableByWindowBackground = false
|
||||||
window.minSize = NSSize(width: 0, height: 0)
|
window.minSize = NSSize(width: 0, height: 0)
|
||||||
|
window.setFrameAutosaveName(Self.mainWindowAutosaveName)
|
||||||
|
applyInitialPlacementIfNeeded(to: window)
|
||||||
|
registerMainWindowIfNeeded(window)
|
||||||
window.orderFrontRegardless()
|
window.orderFrontRegardless()
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureOnboardingPanel(_ window: NSWindow) {
|
func configureOnboardingPanel(_ window: NSWindow) {
|
||||||
|
if window.identifier == nil || window.identifier != Self.onboardingWindowIdentifier {
|
||||||
|
window.identifier = Self.onboardingWindowIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
let requiredStyleMask: NSWindow.StyleMask = [.titled, .fullSizeContentView, .resizable]
|
let requiredStyleMask: NSWindow.StyleMask = [.titled, .fullSizeContentView, .resizable]
|
||||||
window.styleMask.formUnion(requiredStyleMask)
|
window.styleMask.formUnion(requiredStyleMask)
|
||||||
window.titlebarAppearsTransparent = true
|
window.titlebarAppearsTransparent = true
|
||||||
@ -37,38 +59,78 @@ class WindowManager {
|
|||||||
window.minSize = NSSize(width: 900, height: 780)
|
window.minSize = NSSize(width: 900, height: 780)
|
||||||
window.makeKeyAndOrderFront(nil)
|
window.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerMainWindow(_ window: NSWindow) {
|
||||||
|
mainWindow = window
|
||||||
|
window.identifier = Self.mainWindowIdentifier
|
||||||
|
window.delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
func createMainWindow(contentView: NSView) -> NSWindow {
|
func showMainWindow() -> NSWindow? {
|
||||||
let defaultSize = NSSize(width: 940, height: 780)
|
guard let window = resolveMainWindow() else {
|
||||||
let screenFrame = NSScreen.main?.visibleFrame ?? NSRect(x: 0, y: 0, width: 1200, height: 800)
|
return nil
|
||||||
let xPosition = (screenFrame.width - defaultSize.width) / 2 + screenFrame.minX
|
}
|
||||||
let yPosition = (screenFrame.height - defaultSize.height) / 2 + screenFrame.minY
|
|
||||||
|
|
||||||
let window = NSWindow(
|
|
||||||
contentRect: NSRect(x: xPosition, y: yPosition, width: defaultSize.width, height: defaultSize.height),
|
|
||||||
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
|
|
||||||
backing: .buffered,
|
|
||||||
defer: false
|
|
||||||
)
|
|
||||||
|
|
||||||
configureWindow(window)
|
|
||||||
window.contentView = contentView
|
|
||||||
|
|
||||||
let delegate = WindowStateDelegate()
|
|
||||||
window.delegate = delegate
|
|
||||||
|
|
||||||
|
window.makeKeyAndOrderFront(nil)
|
||||||
|
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||||
return window
|
return window
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
func hideMainWindow() {
|
||||||
class WindowStateDelegate: NSObject, NSWindowDelegate {
|
guard let window = resolveMainWindow() else {
|
||||||
func windowWillClose(_ notification: Notification) {
|
return
|
||||||
guard let window = notification.object as? NSWindow else { return }
|
}
|
||||||
window.orderOut(nil)
|
window.orderOut(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func currentMainWindow() -> NSWindow? {
|
||||||
|
resolveMainWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func registerMainWindowIfNeeded(_ window: NSWindow) {
|
||||||
|
// Only register the primary content window, identified by the hidden title bar style
|
||||||
|
if window.identifier == nil || window.identifier != Self.mainWindowIdentifier {
|
||||||
|
registerMainWindow(window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func applyInitialPlacementIfNeeded(to window: NSWindow) {
|
||||||
|
guard !didApplyInitialPlacement else { return }
|
||||||
|
// Attempt to restore previous frame if one exists; otherwise fall back to a centered placement
|
||||||
|
if !window.setFrameUsingName(Self.mainWindowAutosaveName) {
|
||||||
|
window.center()
|
||||||
|
}
|
||||||
|
didApplyInitialPlacement = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private func resolveMainWindow() -> NSWindow? {
|
||||||
|
if let window = mainWindow {
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
|
||||||
|
if let window = NSApplication.shared.windows.first(where: { $0.identifier == Self.mainWindowIdentifier }) {
|
||||||
|
mainWindow = window
|
||||||
|
window.delegate = self
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension WindowManager: NSWindowDelegate {
|
||||||
|
func windowWillClose(_ notification: Notification) {
|
||||||
|
guard let window = notification.object as? NSWindow else { return }
|
||||||
|
if window.identifier == Self.mainWindowIdentifier {
|
||||||
|
window.orderOut(nil)
|
||||||
|
mainWindow = nil
|
||||||
|
didApplyInitialPlacement = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func windowDidBecomeKey(_ notification: Notification) {
|
func windowDidBecomeKey(_ notification: Notification) {
|
||||||
guard let _ = notification.object as? NSWindow else { return }
|
guard let window = notification.object as? NSWindow,
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
window.identifier == Self.mainWindowIdentifier else { return }
|
||||||
|
NSApplication.shared.activate(ignoringOtherApps: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user