From 14a1efc86d0295be3a0d3fe1ebe7b8080266da2d Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 13 Jul 2026 16:23:44 +0800
Subject: [PATCH] docs: clean Aligner migration metadata
---
C1.source/Sources/Aligner/AlignerApplicationDelegate.swift | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 306 insertions(+), 21 deletions(-)
diff --git a/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift b/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
index ad68641..9904f96 100644
--- a/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
+++ b/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
@@ -14,16 +14,19 @@
private let round1SnapshotDumpOptions = Round1SnapshotDumpOptions.parse(arguments: ProcessInfo.processInfo.arguments)
private let round1ScreenshotProbeOptions = Round1ScreenshotProbeOptions.parse(arguments: ProcessInfo.processInfo.arguments)
private let round1QuickSwitchOptions = Round1QuickSwitchLaunchOptions.parse(arguments: ProcessInfo.processInfo.arguments)
+ private let round015EntitlementOptions = Round015EntitlementLaunchOptions.parse(arguments: ProcessInfo.processInfo.arguments)
private var permissionWindowController: PermissionsWindowController?
private var debugOverlayController: Round0DebugOverlayController?
private var round1PerformancePoCController: Round1PerformancePoCController?
private var round1TriggerProbe: CGEventTapTriggerProbe?
private var quickSwitchSessionController: QuickSwitchSessionController?
private var quickSwitchTriggerService: CGEventTapTriggerService?
+ private var settingsWindowController: SettingsWindowController?
private var isRunningQuickSwitchLifecycle = false
+ private var lastQuickSwitchOpenRequestSource: String?
private var statusItem: NSStatusItem?
- private var verticalWaterfallViewModeMenuItem: NSMenuItem?
- private var horizontalWaterfallViewModeMenuItem: NSMenuItem?
+ private var verticalWaterfallViewModeMenuItems: [NSMenuItem] = []
+ private var horizontalWaterfallViewModeMenuItems: [NSMenuItem] = []
func applicationDidFinishLaunching(_ notification: Notification) {
let bundlePathSummary = DevelopmentDiagnostics.pathSummary(Bundle.main.bundlePath)
@@ -47,6 +50,7 @@
return
}
+ configureMainMenu()
configureStatusItem()
if !launchOptions.skipPermissions {
showPermissionsIfNeeded()
@@ -85,7 +89,8 @@
"hasVisibleWindows": flag,
"activationPolicy": sender.activationPolicy().rawValue
])
- return true
+ openQuickSwitchFromDockReopen(hasVisibleWindows: flag)
+ return false
}
private func configureStatusItem() {
@@ -96,8 +101,9 @@
let menu = NSMenu()
menu.delegate = self
menu.addItem(menuItem(title: "About Aligner...", action: #selector(showAbout), keyEquivalent: ""))
+ menu.addItem(menuItem(title: "Settings...", action: #selector(showSettingsFromMenu), keyEquivalent: ""))
menu.addItem(.separator())
- menu.addItem(menuItem(title: "Check Permissions...", action: #selector(showPermissions), keyEquivalent: ","))
+ menu.addItem(menuItem(title: "Check Permissions...", action: #selector(showPermissions), keyEquivalent: ""))
menu.addItem(.separator())
menu.addItem(menuItem(title: "Show Quick Switch", action: #selector(showQuickSwitchFromMenu), keyEquivalent: ""))
menu.addItem(menuItem(title: "Hide Quick Switch", action: #selector(hideQuickSwitchFromMenu), keyEquivalent: ""))
@@ -114,8 +120,70 @@
DevelopmentDiagnostics.log("app.statusItem.configure.end", [
"hasButton": item.button != nil,
"hasAboutItem": true,
- "hasWaterfallViewModeItems": verticalWaterfallViewModeMenuItem != nil
- && horizontalWaterfallViewModeMenuItem != nil
+ "hasSettingsItem": true,
+ "hasWaterfallViewModeItems": !verticalWaterfallViewModeMenuItems.isEmpty
+ && !horizontalWaterfallViewModeMenuItems.isEmpty
+ ])
+ }
+
+ private func configureMainMenu() {
+ DevelopmentDiagnostics.log("app.mainMenu.configure.start")
+
+ let mainMenu = NSMenu(title: "Main Menu")
+ let appMenuItem = NSMenuItem(title: "Aligner", action: nil, keyEquivalent: "")
+ let appMenu = NSMenu(title: "Aligner")
+ appMenu.delegate = self
+ appMenuItem.submenu = appMenu
+ appMenu.addItem(menuItem(title: "About Aligner...", action: #selector(showAbout), keyEquivalent: ""))
+ appMenu.addItem(.separator())
+ appMenu.addItem(menuItem(title: "Settings...", action: #selector(showSettingsFromMenu), keyEquivalent: ","))
+ appMenu.addItem(.separator())
+ appMenu.addItem(menuItem(title: "Check Permissions...", action: #selector(showPermissions), keyEquivalent: ""))
+ appMenu.addItem(menuItem(title: "Show Quick Switch", action: #selector(showQuickSwitchFromMenu), keyEquivalent: ""))
+ appMenu.addItem(menuItem(title: "Hide Quick Switch", action: #selector(hideQuickSwitchFromMenu), keyEquivalent: ""))
+ appMenu.addItem(quickSwitchViewModeMenuItem())
+ appMenu.addItem(.separator())
+ appMenu.addItem(menuItem(title: "Quit Aligner", action: #selector(quit), keyEquivalent: "q"))
+ mainMenu.addItem(appMenuItem)
+
+ let editMenuItem = NSMenuItem(title: "Edit", action: nil, keyEquivalent: "")
+ let editMenu = NSMenu(title: "Edit")
+ editMenuItem.submenu = editMenu
+ editMenu.addItem(responderMenuItem(title: "Undo", action: Selector(("undo:")), keyEquivalent: "z"))
+ editMenu.addItem(responderMenuItem(title: "Redo", action: Selector(("redo:")), keyEquivalent: "Z"))
+ editMenu.addItem(.separator())
+ editMenu.addItem(responderMenuItem(title: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x"))
+ editMenu.addItem(responderMenuItem(title: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c"))
+ editMenu.addItem(responderMenuItem(title: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v"))
+ editMenu.addItem(responderMenuItem(title: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a"))
+ mainMenu.addItem(editMenuItem)
+
+ let viewMenuItem = NSMenuItem(title: "View", action: nil, keyEquivalent: "")
+ let viewMenu = NSMenu(title: "View")
+ viewMenu.delegate = self
+ viewMenuItem.submenu = viewMenu
+ viewMenu.addItem(quickSwitchViewModeMenuItem())
+ mainMenu.addItem(viewMenuItem)
+
+ let windowMenuItem = NSMenuItem(title: "Window", action: nil, keyEquivalent: "")
+ let windowMenu = NSMenu(title: "Window")
+ windowMenuItem.submenu = windowMenu
+ windowMenu.addItem(responderMenuItem(title: "Minimize", action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent: "m"))
+ windowMenu.addItem(responderMenuItem(title: "Zoom", action: #selector(NSWindow.performZoom(_:)), keyEquivalent: ""))
+ windowMenu.addItem(.separator())
+ windowMenu.addItem(responderMenuItem(title: "Bring All to Front", action: #selector(NSApplication.arrangeInFront(_:)), keyEquivalent: ""))
+ mainMenu.addItem(windowMenuItem)
+ NSApp.windowsMenu = windowMenu
+
+ let helpMenuItem = NSMenuItem(title: "Help", action: nil, keyEquivalent: "")
+ helpMenuItem.submenu = NSMenu(title: "Help")
+ mainMenu.addItem(helpMenuItem)
+
+ NSApp.mainMenu = mainMenu
+ updateWaterfallViewModeMenuState()
+ DevelopmentDiagnostics.log("app.mainMenu.configure.end", [
+ "hasSettingsItem": appMenu.item(withTitle: "Settings...") != nil,
+ "hasQuickSwitchViewSubmenu": appMenu.item(withTitle: "Quick Switch View")?.submenu != nil
])
}
@@ -127,6 +195,10 @@
let item = NSMenuItem(title: title, action: action, keyEquivalent: keyEquivalent)
item.target = self
return item
+ }
+
+ private func responderMenuItem(title: String, action: Selector?, keyEquivalent: String) -> NSMenuItem {
+ NSMenuItem(title: title, action: action, keyEquivalent: keyEquivalent)
}
private func quickSwitchViewModeMenuItem() -> NSMenuItem {
@@ -144,8 +216,8 @@
submenu.addItem(verticalItem)
submenu.addItem(horizontalItem)
- verticalWaterfallViewModeMenuItem = verticalItem
- horizontalWaterfallViewModeMenuItem = horizontalItem
+ verticalWaterfallViewModeMenuItems.append(verticalItem)
+ horizontalWaterfallViewModeMenuItems.append(horizontalItem)
let rootItem = NSMenuItem(title: "Quick Switch View", action: nil, keyEquivalent: "")
rootItem.submenu = submenu
@@ -154,8 +226,12 @@
private func updateWaterfallViewModeMenuState() {
let mode = quickSwitchWaterfallViewMode()
- verticalWaterfallViewModeMenuItem?.state = mode == .verticalColumns ? .on : .off
- horizontalWaterfallViewModeMenuItem?.state = mode == .horizontalMasonry ? .on : .off
+ for item in verticalWaterfallViewModeMenuItems {
+ item.state = mode == .verticalColumns ? .on : .off
+ }
+ for item in horizontalWaterfallViewModeMenuItems {
+ item.state = mode == .horizontalMasonry ? .on : .off
+ }
}
private func showPermissionsIfNeeded() {
@@ -368,10 +444,13 @@
}
private func showQuickSwitchIfRequested() {
- guard round1QuickSwitchOptions.openQuickSwitch || round1QuickSwitchOptions.lifecycleCycles != nil else { return }
+ guard round1QuickSwitchOptions.openQuickSwitch
+ || round1QuickSwitchOptions.lifecycleCycles != nil
+ || round1QuickSwitchOptions.simulateDockReopenAfter != nil else { return }
DevelopmentDiagnostics.log("app.quickSwitch.launchOptionRequested", [
"openQuickSwitch": round1QuickSwitchOptions.openQuickSwitch,
- "lifecycleCycles": round1QuickSwitchOptions.lifecycleCycles
+ "lifecycleCycles": round1QuickSwitchOptions.lifecycleCycles,
+ "simulateDockReopenAfter": round1QuickSwitchOptions.simulateDockReopenAfter
])
if let lifecycleCycles = round1QuickSwitchOptions.lifecycleCycles {
@@ -379,9 +458,23 @@
return
}
- openQuickSwitchFromTrigger()
- writeQuickSwitchReportIfNeeded()
+ if let simulateDockReopenAfter = round1QuickSwitchOptions.simulateDockReopenAfter {
+ DispatchQueue.main.asyncAfter(deadline: .now() + simulateDockReopenAfter) { [weak self] in
+ guard let self else { return }
+ let hasVisibleWindows = NSApp.windows.contains { $0.isVisible }
+ self.openQuickSwitchFromDockReopen(hasVisibleWindows: hasVisibleWindows)
+ self.writeQuickSwitchReportIfNeeded()
+ self.scheduleQuickSwitchAutoHideAndQuitIfNeeded()
+ }
+ return
+ }
+ openQuickSwitchFromTrigger(source: "launchOption")
+ writeQuickSwitchReportIfNeeded()
+ scheduleQuickSwitchAutoHideAndQuitIfNeeded()
+ }
+
+ private func scheduleQuickSwitchAutoHideAndQuitIfNeeded() {
if let autoHideAfter = round1QuickSwitchOptions.autoHideAfter {
DispatchQueue.main.asyncAfter(deadline: .now() + autoHideAfter) { [weak self] in
self?.hideQuickSwitchSession(reason: .timeout)
@@ -408,6 +501,7 @@
windowCloseService: quickSwitchWindowCloseService(),
disableScreenshotRefresh: round1QuickSwitchOptions.disableScreenshotRefresh,
waterfallViewMode: quickSwitchWaterfallViewMode(),
+ theme: quickSwitchThemePreference(),
closeConfirmationRequired: quickSwitchConfirmBeforeClose,
onCloseConfirmationDisabled: { [weak self] in
self?.setQuickSwitchConfirmBeforeClose(false)
@@ -420,6 +514,12 @@
)
controller.onSnapshotUpdated = { [weak self] in
self?.writeQuickSwitchReportIfNeeded()
+ }
+ controller.onToggleWaterfallViewMode = { [weak self] in
+ self?.toggleQuickSwitchWaterfallViewModeFromQuickSwitch()
+ }
+ controller.onToggleTheme = { [weak self] in
+ self?.toggleQuickSwitchThemeFromQuickSwitch()
}
quickSwitchSessionController = controller
}
@@ -453,9 +553,19 @@
}
}
- private func openQuickSwitchFromTrigger() {
+ private func openQuickSwitchFromDockReopen(hasVisibleWindows: Bool) {
+ DevelopmentDiagnostics.log("app.quickSwitch.openFromDockReopen", [
+ "hasVisibleWindows": hasVisibleWindows,
+ "alreadyVisible": quickSwitchSessionController?.isVisible ?? false
+ ])
+ openQuickSwitchFromTrigger(source: "dockReopen")
+ }
+
+ private func openQuickSwitchFromTrigger(source: String = "trigger") {
+ lastQuickSwitchOpenRequestSource = source
let accessibility = accessibilityStatus()
DevelopmentDiagnostics.log("app.quickSwitch.openFromTrigger", [
+ "source": source,
"accessibility": permissionStatusString(accessibility),
"screenRecording": permissionStatusString(screenRecordingStatus()),
"alreadyVisible": quickSwitchSessionController?.isVisible ?? false
@@ -484,6 +594,7 @@
windowCloseService: quickSwitchWindowCloseService(),
disableScreenshotRefresh: round1QuickSwitchOptions.disableScreenshotRefresh,
waterfallViewMode: quickSwitchWaterfallViewMode(),
+ theme: quickSwitchThemePreference(),
closeConfirmationRequired: quickSwitchConfirmBeforeClose,
onCloseConfirmationDisabled: { [weak self] in
self?.setQuickSwitchConfirmBeforeClose(false)
@@ -496,6 +607,12 @@
)
controller.onSnapshotUpdated = { [weak self] in
self?.writeQuickSwitchReportIfNeeded()
+ }
+ controller.onToggleWaterfallViewMode = { [weak self] in
+ self?.toggleQuickSwitchWaterfallViewModeFromQuickSwitch()
+ }
+ controller.onToggleTheme = { [weak self] in
+ self?.toggleQuickSwitchThemeFromQuickSwitch()
}
quickSwitchSessionController = controller
}
@@ -528,9 +645,15 @@
let versionBuild = appVersionBuild()
report["preferenceWaterfallViewMode"] = preferenceStore.read().quickSwitchWaterfallViewMode.rawValue
report["resolvedWaterfallViewMode"] = quickSwitchWaterfallViewMode().rawValue
+ report["preferenceTheme"] = preferenceStore.read().theme.rawValue
+ report["resolvedQuickSwitchTheme"] = quickSwitchThemePreference().rawValue
+ report["lastQuickSwitchOpenRequestSource"] = lastQuickSwitchOpenRequestSource
+ report["authorization"] = round015EntitlementOptions.authorizationReportDictionary()
report["aboutVersion"] = versionBuild.version
report["aboutBuild"] = versionBuild.build
report["statusMenu"] = statusMenuReportDictionary()
+ report["mainMenu"] = mainMenuReportDictionary()
+ report["settingsWindow"] = settingsWindowReportDictionary()
do {
let data = try JSONSerialization.data(withJSONObject: report, options: [.prettyPrinted, .sortedKeys])
@@ -581,6 +704,14 @@
return FixtureQuickSwitchSnapshotLoader(appCount: 1, mode: .spaceFilter)
}
+ if round1QuickSwitchOptions.fixtureSplitView {
+ return FixtureQuickSwitchSnapshotLoader(appCount: 1, mode: .splitView)
+ }
+
+ if round1QuickSwitchOptions.fixtureMultiPageIdentity {
+ return FixtureQuickSwitchSnapshotLoader(appCount: 1, mode: .multiPageIdentity)
+ }
+
if let fixtureAppCount = round1QuickSwitchOptions.fixtureAppCount {
return FixtureQuickSwitchSnapshotLoader(
appCount: fixtureAppCount,
@@ -603,12 +734,21 @@
return DebugWindowActivationService()
}
- return CGWindowAXWindowService(spaceIDsByWindowIDProvider: { _ in [:] })
+ let context = quickSwitchWindowSpaceContext()
+ return CGWindowAXWindowService(
+ spaceIDsByWindowIDProvider: context.spaceIDsByWindowIDProvider,
+ fullscreenSpaceIDs: context.fullscreenSpaceIDs
+ )
}
private func quickSwitchWaterfallViewMode() -> QuickSwitchWaterfallViewMode {
round1QuickSwitchOptions.waterfallViewMode
?? preferenceStore.read().quickSwitchWaterfallViewMode
+ }
+
+ private func quickSwitchThemePreference() -> ThemePreference {
+ let theme = preferenceStore.read().theme
+ return theme == .dark ? .dark : .light
}
private func quickSwitchSpaceActivationService() -> any SpaceActivationServiceProtocol {
@@ -624,7 +764,39 @@
return DebugWindowCloseService()
}
- return CGWindowAXWindowService(spaceIDsByWindowIDProvider: { _ in [:] })
+ let context = quickSwitchWindowSpaceContext()
+ return CGWindowAXWindowService(
+ spaceIDsByWindowIDProvider: context.spaceIDsByWindowIDProvider,
+ fullscreenSpaceIDs: context.fullscreenSpaceIDs
+ )
+ }
+
+ private func quickSwitchWindowSpaceContext() -> (
+ spaceIDsByWindowIDProvider: ([UInt32]) -> [UInt32: [UInt64]],
+ fullscreenSpaceIDs: Set<UInt64>
+ ) {
+ do {
+ let spaceEnumerator = try SkyLightSpaceEnumerator()
+ let displays = try spaceEnumerator.displays()
+ let fullscreenSpaceIDs = Set(
+ displays
+ .flatMap(\.spaces)
+ .filter { $0.type == .fullscreen }
+ .map(\.id)
+ )
+ return (
+ spaceIDsByWindowIDProvider: spaceEnumerator.spaceIDsByWindowID(windowIDs:),
+ fullscreenSpaceIDs: fullscreenSpaceIDs
+ )
+ } catch {
+ DevelopmentDiagnostics.log("app.quickSwitch.windowSpaceContextUnavailable", [
+ "error": DevelopmentDiagnostics.errorSummaryString(error)
+ ])
+ return (
+ spaceIDsByWindowIDProvider: { _ in [:] },
+ fullscreenSpaceIDs: []
+ )
+ }
}
private var quickSwitchConfirmBeforeClose: Bool {
@@ -652,11 +824,56 @@
preferenceStore.write(updatedPreferences)
quickSwitchSessionController?.setWaterfallViewMode(mode)
updateWaterfallViewModeMenuState()
+ settingsWindowController?.refreshWaterfallViewMode()
writeQuickSwitchReportIfNeeded()
DevelopmentDiagnostics.log("app.quickSwitch.waterfallViewModePreferenceChanged", [
"mode": mode.rawValue,
"quickSwitchVisible": quickSwitchSessionController?.isVisible ?? false
])
+ }
+
+ private func toggleQuickSwitchWaterfallViewModeFromQuickSwitch() {
+ let currentMode = quickSwitchWaterfallViewMode()
+ let nextMode: QuickSwitchWaterfallViewMode = currentMode == .horizontalMasonry
+ ? .verticalColumns
+ : .horizontalMasonry
+ DevelopmentDiagnostics.log("app.quickSwitch.waterfallViewModeToggle", [
+ "currentMode": currentMode.rawValue,
+ "nextMode": nextMode.rawValue,
+ "quickSwitchVisible": quickSwitchSessionController?.isVisible ?? false
+ ])
+ setQuickSwitchWaterfallViewMode(nextMode)
+ }
+
+ private func setQuickSwitchThemePreference(_ theme: ThemePreference) {
+ let normalizedTheme: ThemePreference = theme == .dark ? .dark : .light
+ let preferences = preferenceStore.read()
+ let updatedPreferences = AlignerPreferences(
+ showMinimizedWindows: preferences.showMinimizedWindows,
+ showFullscreenWindows: preferences.showFullscreenWindows,
+ quickSwitchWaterfallViewMode: preferences.quickSwitchWaterfallViewMode,
+ theme: normalizedTheme,
+ language: preferences.language,
+ spaceDisplayStrategy: preferences.spaceDisplayStrategy
+ )
+ preferenceStore.write(updatedPreferences)
+ quickSwitchSessionController?.setTheme(normalizedTheme)
+ writeQuickSwitchReportIfNeeded()
+ DevelopmentDiagnostics.log("app.quickSwitch.themePreferenceChanged", [
+ "theme": normalizedTheme.rawValue,
+ "quickSwitchVisible": quickSwitchSessionController?.isVisible ?? false
+ ])
+ }
+
+ private func toggleQuickSwitchThemeFromQuickSwitch() {
+ let currentTheme = quickSwitchThemePreference()
+ let nextTheme: ThemePreference = currentTheme == .dark ? .light : .dark
+ DevelopmentDiagnostics.log("app.quickSwitch.themeToggle", [
+ "currentTheme": currentTheme.rawValue,
+ "nextTheme": nextTheme.rawValue,
+ "quickSwitchVisible": quickSwitchSessionController?.isVisible ?? false
+ ])
+ setQuickSwitchThemePreference(nextTheme)
}
private func appVersionBuild() -> (version: String, build: String) {
@@ -668,13 +885,44 @@
private func statusMenuReportDictionary() -> [String: Any] {
updateWaterfallViewModeMenuState()
+ let verticalItem = verticalWaterfallViewModeMenuItems.first
+ let horizontalItem = horizontalWaterfallViewModeMenuItems.first
return [
"hasAboutItem": statusItem?.menu?.item(withTitle: "About Aligner...") != nil,
+ "hasSettingsItem": statusItem?.menu?.item(withTitle: "Settings...") != nil,
"hasQuickSwitchViewSubmenu": statusItem?.menu?.item(withTitle: "Quick Switch View")?.submenu != nil,
- "hasVerticalColumnsItem": verticalWaterfallViewModeMenuItem != nil,
- "hasHorizontalWaterfallItem": horizontalWaterfallViewModeMenuItem != nil,
- "verticalColumnsState": verticalWaterfallViewModeMenuItem?.state == .on ? "on" : "off",
- "horizontalWaterfallState": horizontalWaterfallViewModeMenuItem?.state == .on ? "on" : "off"
+ "hasVerticalColumnsItem": verticalItem != nil,
+ "hasHorizontalWaterfallItem": horizontalItem != nil,
+ "verticalColumnsState": verticalItem?.state == .on ? "on" : "off",
+ "horizontalWaterfallState": horizontalItem?.state == .on ? "on" : "off"
+ ]
+ }
+
+ private func mainMenuReportDictionary() -> [String: Any] {
+ updateWaterfallViewModeMenuState()
+ let appMenu = NSApp.mainMenu?.items.first?.submenu
+ let viewMenu = NSApp.mainMenu?.item(withTitle: "View")?.submenu
+ return [
+ "hasMenu": NSApp.mainMenu != nil,
+ "hasAppMenu": appMenu != nil,
+ "hasAboutItem": appMenu?.item(withTitle: "About Aligner...") != nil,
+ "hasSettingsItem": appMenu?.item(withTitle: "Settings...") != nil,
+ "settingsKeyEquivalent": appMenu?.item(withTitle: "Settings...")?.keyEquivalent ?? "",
+ "hasQuickSwitchViewSubmenuInAppMenu": appMenu?.item(withTitle: "Quick Switch View")?.submenu != nil,
+ "hasQuickSwitchViewSubmenuInViewMenu": viewMenu?.item(withTitle: "Quick Switch View")?.submenu != nil
+ ]
+ }
+
+ private func settingsWindowReportDictionary() -> [String: Any] {
+ settingsWindowController?.reportDictionary() ?? [
+ "exists": false,
+ "visible": false,
+ "title": "",
+ "selectedTabLabel": "",
+ "selectedTabIdentifier": "",
+ "waterfallViewMode": quickSwitchWaterfallViewMode().rawValue,
+ "hasViewTab": false,
+ "usesSwiftUI": false
]
}
@@ -696,6 +944,43 @@
alert.runModal()
}
+ @objc private func showSettingsFromMenu() {
+ openSettingsWindow(source: "menu")
+ }
+
+ private func showSettingsFromQuickSwitch() {
+ openSettingsWindow(source: "quickSwitch")
+ }
+
+ private func openSettingsWindow(source: String) {
+ DevelopmentDiagnostics.log("app.settings.show", [
+ "source": source,
+ "quickSwitchVisible": quickSwitchSessionController?.isVisible ?? false,
+ "mode": quickSwitchWaterfallViewMode().rawValue
+ ])
+ hideQuickSwitchSession(reason: .userClosed)
+ NSApp.setActivationPolicy(.regular)
+
+ if settingsWindowController == nil {
+ settingsWindowController = SettingsWindowController(
+ modeProvider: { [weak self] in
+ self?.quickSwitchWaterfallViewMode() ?? .verticalColumns
+ },
+ onWaterfallViewModeChanged: { [weak self] mode in
+ self?.setQuickSwitchWaterfallViewMode(mode)
+ }
+ )
+ }
+
+ settingsWindowController?.showWindow(nil)
+ NSApp.activate(ignoringOtherApps: true)
+ writeQuickSwitchReportIfNeeded()
+ DevelopmentDiagnostics.log("app.settings.windowShown", [
+ "windowVisible": settingsWindowController?.window?.isVisible ?? false,
+ "activationPolicy": NSApp.activationPolicy().rawValue
+ ])
+ }
+
@objc private func useVerticalWaterfallViewMode() {
setQuickSwitchWaterfallViewMode(.verticalColumns)
}
--
Gitblit v1.9.3