import AppKit // MARK: - 通知名 extension Notification.Name { static let showSettingsPanel = Notification.Name("FloatingMonitor.ShowSettings") static let resizeMonitorWindow = Notification.Name("FloatingMonitor.ResizeWindow") static let refreshIntervalChanged = Notification.Name("FloatingMonitor.RefreshIntervalChanged") static let backdropEnabledChanged = Notification.Name("FloatingMonitor.BackdropEnabledChanged") } // MARK: - AppDelegate final class AppDelegate: NSObject, NSApplicationDelegate { private var windowController: FloatingWindowController? private var settingsWindowController: SettingsWindowController? private var statusItem: NSStatusItem? private var statusMenu: NSMenu! let systemMonitor = SystemMonitor() func applicationDidFinishLaunching(_ notification: Notification) { NSApp.setActivationPolicy(.accessory) windowController = FloatingWindowController() let contentView = ContentView(monitor: systemMonitor, windowController: windowController) windowController?.embed(rootView: contentView) let cfg = Configuration.shared windowController?.resize(width: cfg.windowWidth, height: cfg.windowHeight) systemMonitor.interval = cfg.refreshInterval systemMonitor.topN = cfg.processCount systemMonitor.start() setupStatusItem() observeResize() } // MARK: - 菜单栏 private func setupStatusItem() { statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) guard let button = statusItem?.button else { return } if let image = NSImage(systemSymbolName: "gauge.with.dots.needle.33percent", accessibilityDescription: "Monitor") { image.isTemplate = true button.image = image } button.toolTip = "Monitor" statusMenu = NSMenu() let toggleItem = NSMenuItem(title: "显示 Monitor", action: #selector(menuToggleWindow), keyEquivalent: "") toggleItem.target = self statusMenu.addItem(toggleItem) statusMenu.addItem(.separator()) let settingsItem = NSMenuItem(title: "显示设置…", action: #selector(menuOpenSettings), keyEquivalent: ",") settingsItem.keyEquivalentModifierMask = .command settingsItem.target = self statusMenu.addItem(settingsItem) statusMenu.addItem(.separator()) let quitItem = NSMenuItem(title: "退出 Monitor", action: #selector(menuQuit), keyEquivalent: "q") quitItem.keyEquivalentModifierMask = .command quitItem.target = self statusMenu.addItem(quitItem) statusItem?.menu = statusMenu button.target = self button.action = #selector(statusItemClicked) button.sendAction(on: [.leftMouseDown, .rightMouseDown]) } @objc private func statusItemClicked() { guard let event = NSApp.currentEvent else { return } if event.type == .rightMouseDown { updateToggleMenuItemTitle() } else { toggleWindow() } } @objc private func menuToggleWindow() { toggleWindow() } @objc private func toggleWindow() { windowController?.toggleVisible() } @objc private func menuOpenSettings() { openSettingsWindow() } @objc private func menuQuit() { NSApp.terminate(nil) } private func updateToggleMenuItemTitle() { let visible = windowController?.isVisible ?? false statusMenu.item(at: 0)?.title = visible ? "隐藏 Monitor" : "显示 Monitor" } // MARK: - 设置窗口 private func openSettingsWindow() { if settingsWindowController == nil { settingsWindowController = SettingsWindowController(monitor: systemMonitor) } settingsWindowController?.show() } // MARK: - 监听 private func observeResize() { NotificationCenter.default.addObserver( forName: .resizeMonitorWindow, object: nil, queue: .main ) { [weak self] notification in guard let size = notification.object as? NSSize else { return } self?.windowController?.resize(width: size.width, height: size.height) } } func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { windowController?.show() return true } }