mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-03-19 05:19:47 +08:00
110 lines
5.0 KiB
Swift
110 lines
5.0 KiB
Swift
import Cocoa
|
|
import FlutterMacOS
|
|
|
|
class MainFlutterWindow: NSWindow {
|
|
// Offsets from the top-left corner of the title bar container (in points)
|
|
// Tweak these to your preferred locations.
|
|
private let closeButtonTopLeftOffset = NSPoint(x: 10, y: 13)
|
|
private let miniaturizeButtonTopLeftOffset = NSPoint(x: 32, y: 13)
|
|
private let zoomButtonTopLeftOffset = NSPoint(x: 52, y: 13)
|
|
|
|
// Whether to auto-apply on window events
|
|
private let shouldAutoApplyTrafficLightPositions = true
|
|
private var trafficLightObserversRegistered = false
|
|
|
|
override func awakeFromNib() {
|
|
let flutterViewController = FlutterViewController()
|
|
let windowFrame = self.frame
|
|
self.contentViewController = flutterViewController
|
|
self.setFrame(windowFrame, display: true)
|
|
|
|
AppLifecycleChannel.registerChannel(flutterViewController: flutterViewController)
|
|
|
|
RegisterGeneratedPlugins(registry: flutterViewController)
|
|
|
|
super.awakeFromNib()
|
|
|
|
// Apply custom positions for traffic-light buttons and observe changes
|
|
if shouldAutoApplyTrafficLightPositions {
|
|
applyTrafficLightButtonPositions()
|
|
registerWindowObservers()
|
|
}
|
|
}
|
|
|
|
deinit {
|
|
unregisterWindowObservers()
|
|
}
|
|
|
|
// MARK: - Traffic-light buttons positioning
|
|
|
|
private func applyTrafficLightButtonPositions() {
|
|
// Skip in full screen; macOS manages buttons differently there
|
|
if self.styleMask.contains(.fullScreen) { return }
|
|
|
|
setStandardWindowButton(.closeButton, topLeftOffset: closeButtonTopLeftOffset)
|
|
setStandardWindowButton(.miniaturizeButton, topLeftOffset: miniaturizeButtonTopLeftOffset)
|
|
setStandardWindowButton(.zoomButton, topLeftOffset: zoomButtonTopLeftOffset)
|
|
}
|
|
|
|
private func setStandardWindowButton(_ type: NSWindow.ButtonType, topLeftOffset: NSPoint) {
|
|
guard let button = self.standardWindowButton(type), let container = button.superview else { return }
|
|
|
|
// Ensure autoresizing mask changes are respected when moving via frames
|
|
button.translatesAutoresizingMaskIntoConstraints = true
|
|
|
|
// Convert a top-left based offset to the container's default bottom-left coordinate system
|
|
let containerHeight = container.bounds.height
|
|
let targetY = containerHeight - topLeftOffset.y - button.frame.height
|
|
let targetX = topLeftOffset.x
|
|
let newOrigin = NSPoint(x: max(0, targetX), y: max(0, targetY))
|
|
|
|
// Avoid redundant layout churn
|
|
if button.frame.origin.equalTo(newOrigin) { return }
|
|
button.setFrameOrigin(newOrigin)
|
|
}
|
|
|
|
private func registerWindowObservers() {
|
|
guard !trafficLightObserversRegistered else { return }
|
|
trafficLightObserversRegistered = true
|
|
NotificationCenter.default.addObserver(self, selector: #selector(onWindowDidResize(_:)), name: NSWindow.didResizeNotification, object: self)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(onWindowDidEndLiveResize(_:)), name: NSWindow.didEndLiveResizeNotification, object: self)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(onWindowDidBecomeKey(_:)), name: NSWindow.didBecomeKeyNotification, object: self)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(onWindowDidExitFullScreen(_:)), name: NSWindow.didExitFullScreenNotification, object: self)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(onWindowDidEnterFullScreen(_:)), name: NSWindow.didEnterFullScreenNotification, object: self)
|
|
}
|
|
|
|
private func unregisterWindowObservers() {
|
|
if trafficLightObserversRegistered {
|
|
NotificationCenter.default.removeObserver(self, name: NSWindow.didResizeNotification, object: self)
|
|
NotificationCenter.default.removeObserver(self, name: NSWindow.didEndLiveResizeNotification, object: self)
|
|
NotificationCenter.default.removeObserver(self, name: NSWindow.didBecomeKeyNotification, object: self)
|
|
NotificationCenter.default.removeObserver(self, name: NSWindow.didExitFullScreenNotification, object: self)
|
|
NotificationCenter.default.removeObserver(self, name: NSWindow.didEnterFullScreenNotification, object: self)
|
|
trafficLightObserversRegistered = false
|
|
}
|
|
}
|
|
|
|
@objc private func onWindowDidResize(_ notification: Notification) {
|
|
applyTrafficLightButtonPositions()
|
|
}
|
|
|
|
@objc private func onWindowDidEndLiveResize(_ notification: Notification) {
|
|
applyTrafficLightButtonPositions()
|
|
}
|
|
|
|
@objc private func onWindowDidBecomeKey(_ notification: Notification) {
|
|
applyTrafficLightButtonPositions()
|
|
}
|
|
|
|
@objc private func onWindowDidExitFullScreen(_ notification: Notification) {
|
|
// Re-apply after leaving full screen
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
|
|
self?.applyTrafficLightButtonPositions()
|
|
}
|
|
}
|
|
|
|
@objc private func onWindowDidEnterFullScreen(_ notification: Notification) {
|
|
// No-op; let system manage buttons
|
|
}
|
|
}
|