mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-06-05 15:08:38 +03:00
81 lines
2.4 KiB
Swift
81 lines
2.4 KiB
Swift
import SwiftUI
|
|
|
|
/// This modifier tracks whether the window is the key window in the isKeyWindow environment value.
|
|
struct WindowObservationModifier: ViewModifier {
|
|
@StateObject var windowObserver: WindowObserver = WindowObserver()
|
|
|
|
func body(content: Content) -> some View {
|
|
content.background(
|
|
HostingWindowFinder { [weak windowObserver] window in
|
|
windowObserver?.window = window
|
|
}
|
|
).environment(\.isKeyWindow, windowObserver.isKeyWindow)
|
|
}
|
|
}
|
|
|
|
extension EnvironmentValues {
|
|
struct IsKeyWindowKey: EnvironmentKey {
|
|
static var defaultValue: Bool = false
|
|
typealias Value = Bool
|
|
}
|
|
|
|
fileprivate(set) var isKeyWindow: Bool {
|
|
get {
|
|
self[IsKeyWindowKey.self]
|
|
}
|
|
set {
|
|
self[IsKeyWindowKey.self] = newValue
|
|
}
|
|
}
|
|
}
|
|
|
|
class WindowObserver: ObservableObject {
|
|
@Published public private(set) var isKeyWindow: Bool = false
|
|
|
|
private var becomeKeyobserver: NSObjectProtocol?
|
|
private var resignKeyobserver: NSObjectProtocol?
|
|
|
|
weak var window: NSWindow? {
|
|
didSet {
|
|
self.isKeyWindow = window?.isKeyWindow ?? false
|
|
guard let window = window else {
|
|
self.becomeKeyobserver = nil
|
|
self.resignKeyobserver = nil
|
|
return
|
|
}
|
|
|
|
self.becomeKeyobserver = NotificationCenter.default.addObserver(
|
|
forName: NSWindow.didBecomeKeyNotification,
|
|
object: window,
|
|
queue: .main
|
|
) { (n) in
|
|
self.isKeyWindow = true
|
|
}
|
|
|
|
self.resignKeyobserver = NotificationCenter.default.addObserver(
|
|
forName: NSWindow.didResignKeyNotification,
|
|
object: window,
|
|
queue: .main
|
|
) { (n) in
|
|
self.isKeyWindow = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// This view calls the callback with the window value that hosts the view.
|
|
struct HostingWindowFinder: NSViewRepresentable {
|
|
var callback: (NSWindow?) -> ()
|
|
|
|
func makeNSView(context: Self.Context) -> NSView {
|
|
let view = NSView()
|
|
view.translatesAutoresizingMaskIntoConstraints = false
|
|
DispatchQueue.main.async { [weak view] in
|
|
self.callback(view?.window)
|
|
}
|
|
return view
|
|
}
|
|
|
|
func updateNSView(_ nsView: NSView, context: Context) {}
|
|
}
|