import AppKit import SwiftUI /// 悬浮窗口控制器:管理毛玻璃效果 + SwiftUI 视图嵌入 final class FloatingWindowController: NSWindowController { private var hostingView: NSHostingView? private var visualEffect: NSVisualEffectView! convenience init() { let window = FloatingWindow() window.isReleasedWhenClosed = false self.init(window: window) setupVisualEffect() } private func setupVisualEffect() { guard let window = window else { return } let ve = NSVisualEffectView() ve.wantsLayer = true ve.material = .hudWindow ve.blendingMode = .behindWindow ve.state = .active ve.translatesAutoresizingMaskIntoConstraints = false ve.layer?.cornerRadius = 16 ve.layer?.masksToBounds = true ve.layer?.borderWidth = 0 ve.layer?.borderColor = NSColor.clear.cgColor ve.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.35).cgColor self.visualEffect = ve guard let contentView = window.contentView else { return } contentView.addSubview(ve, positioned: .below, relativeTo: contentView.subviews.first) NSLayoutConstraint.activate([ ve.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), ve.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), ve.topAnchor.constraint(equalTo: contentView.topAnchor), ve.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) } func embed(rootView: ContentView) { guard let window = window, let contentView = window.contentView else { return } let hv = NSHostingView(rootView: rootView) hv.wantsLayer = true hv.layer?.cornerRadius = 16 hv.layer?.masksToBounds = true hv.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(hv) NSLayoutConstraint.activate([ hv.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), hv.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), hv.topAnchor.constraint(equalTo: contentView.topAnchor), hv.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) self.hostingView = hv } // MARK: - 显隐 func toggleVisible() { guard let window = window else { return } if window.isVisible { window.orderOut(nil) } else { positionNearMenuBar() window.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: false) } } func show() { guard let window = window else { return } if !window.isVisible { positionNearMenuBar() } window.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: false) } func hide() { window?.orderOut(nil) } var isVisible: Bool { window?.isVisible ?? false } func applyOpacity(_ value: Double) { window?.alphaValue = value } func resize(width: CGFloat, height: CGFloat) { guard let window = window else { return } var frame = window.frame frame.size.width = width frame.size.height = height window.setFrame(frame, display: true, animate: true) } private func positionNearMenuBar() { guard let window = window, let screen = NSScreen.main else { return } let screenFrame = screen.visibleFrame window.setFrameOrigin(NSPoint( x: screenFrame.maxX - window.frame.width - 24, y: screenFrame.maxY - window.frame.height - 24 )) } }