Refactor and Rename to CommandNotch
This commit is contained in:
78
Downterm/CommandNotch/Components/NotchWindow.swift
Normal file
78
Downterm/CommandNotch/Components/NotchWindow.swift
Normal file
@@ -0,0 +1,78 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
/// Borderless, floating NSPanel that hosts the notch overlay.
|
||||
/// When the notch is open the window accepts key status so the
|
||||
/// terminal can receive keyboard input. On resignKey the
|
||||
/// `onResignKey` closure fires to close the notch.
|
||||
class NotchWindow: NSPanel {
|
||||
|
||||
var isNotchOpen: Bool = false
|
||||
|
||||
/// Called when the window loses key status while the notch is open.
|
||||
var onResignKey: (() -> Void)?
|
||||
|
||||
override init(
|
||||
contentRect: NSRect,
|
||||
styleMask style: NSWindow.StyleMask,
|
||||
backing backingStoreType: NSWindow.BackingStoreType,
|
||||
defer flag: Bool
|
||||
) {
|
||||
// Start as a plain borderless utility panel.
|
||||
// .nonactivatingPanel is NOT included so the window can
|
||||
// properly accept key status when the notch opens.
|
||||
super.init(
|
||||
contentRect: contentRect,
|
||||
styleMask: [.borderless, .utilityWindow, .nonactivatingPanel],
|
||||
backing: .buffered,
|
||||
defer: flag
|
||||
)
|
||||
configureWindow()
|
||||
}
|
||||
|
||||
private func configureWindow() {
|
||||
isOpaque = false
|
||||
backgroundColor = .clear
|
||||
|
||||
isFloatingPanel = true
|
||||
level = .mainMenu + 3
|
||||
|
||||
titleVisibility = .hidden
|
||||
titlebarAppearsTransparent = true
|
||||
hasShadow = false
|
||||
|
||||
isMovable = false
|
||||
isMovableByWindowBackground = false
|
||||
|
||||
collectionBehavior = [
|
||||
.canJoinAllSpaces,
|
||||
.stationary,
|
||||
.fullScreenAuxiliary,
|
||||
.ignoresCycle
|
||||
]
|
||||
|
||||
appearance = NSAppearance(named: .darkAqua)
|
||||
|
||||
// Accepts mouse events when the app is NOT active so the
|
||||
// user can click the closed notch to open it.
|
||||
acceptsMouseMovedEvents = true
|
||||
}
|
||||
|
||||
// MARK: - Key window management
|
||||
|
||||
override var canBecomeKey: Bool { isNotchOpen }
|
||||
override var canBecomeMain: Bool { false }
|
||||
|
||||
override func resignKey() {
|
||||
super.resignKey()
|
||||
if isNotchOpen {
|
||||
// Brief async dispatch so the new key window settles first —
|
||||
// avoids closing when we're just transferring focus between
|
||||
// our own windows (e.g. opening settings).
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self, self.isNotchOpen else { return }
|
||||
self.onResignKey?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user