From 1fea9bfc8a7639bb3573a7cf2a449ab55065ab9e Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sat, 20 Jun 2026 13:40:07 +0800
Subject: [PATCH] Bump version to 0.1.3

---
 C1.source/Sources/Aligner/AlignerApplicationDelegate.swift |  377 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 368 insertions(+), 9 deletions(-)

diff --git a/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift b/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
index 3b968f2..89c2a16 100644
--- a/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
+++ b/C1.source/Sources/Aligner/AlignerApplicationDelegate.swift
@@ -3,10 +3,11 @@
 import AlignerCore
 
 @MainActor
-final class AlignerApplicationDelegate: NSObject, NSApplicationDelegate {
+final class AlignerApplicationDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
     private static let quickSwitchConfirmBeforeCloseDefaultsKey = "QuickSwitchConfirmBeforeClose"
 
     private let permissionChecker = SystemPermissionChecker()
+    private let preferenceStore = UserDefaultsPreferenceStore()
     private let launchOptions = Round0DebugLaunchOptions.parse(arguments: ProcessInfo.processInfo.arguments)
     private let round1PoCOptions = Round1PerformancePoCOptions.parse(arguments: ProcessInfo.processInfo.arguments)
     private let round1TriggerProbeOptions = Round1TriggerProbeOptions.parse(arguments: ProcessInfo.processInfo.arguments)
@@ -19,8 +20,11 @@
     private var round1TriggerProbe: CGEventTapTriggerProbe?
     private var quickSwitchSessionController: QuickSwitchSessionController?
     private var quickSwitchTriggerService: CGEventTapTriggerService?
+    private var settingsWindowController: SettingsWindowController?
     private var isRunningQuickSwitchLifecycle = false
     private var statusItem: NSStatusItem?
+    private var verticalWaterfallViewModeMenuItems: [NSMenuItem] = []
+    private var horizontalWaterfallViewModeMenuItems: [NSMenuItem] = []
 
     func applicationDidFinishLaunching(_ notification: Notification) {
         let bundlePathSummary = DevelopmentDiagnostics.pathSummary(Bundle.main.bundlePath)
@@ -44,6 +48,7 @@
             return
         }
 
+        configureMainMenu()
         configureStatusItem()
         if !launchOptions.skipPermissions {
             showPermissionsIfNeeded()
@@ -91,21 +96,139 @@
         item.button?.title = "A"
 
         let menu = NSMenu()
-        menu.addItem(NSMenuItem(title: "Check Permissions...", action: #selector(showPermissions), keyEquivalent: ","))
+        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(NSMenuItem(title: "Show Quick Switch", action: #selector(showQuickSwitchFromMenu), keyEquivalent: ""))
-        menu.addItem(NSMenuItem(title: "Hide Quick Switch", action: #selector(hideQuickSwitchFromMenu), keyEquivalent: ""))
+        menu.addItem(menuItem(title: "Check Permissions...", action: #selector(showPermissions), keyEquivalent: ""))
         menu.addItem(.separator())
-        menu.addItem(NSMenuItem(title: "Show Round0 Debug Overlay", action: #selector(showRound0DebugOverlay), keyEquivalent: "d"))
-        menu.addItem(NSMenuItem(title: "Hide Round0 Debug Overlay", action: #selector(hideRound0DebugOverlay), keyEquivalent: ""))
+        menu.addItem(menuItem(title: "Show Quick Switch", action: #selector(showQuickSwitchFromMenu), keyEquivalent: ""))
+        menu.addItem(menuItem(title: "Hide Quick Switch", action: #selector(hideQuickSwitchFromMenu), keyEquivalent: ""))
+        menu.addItem(quickSwitchViewModeMenuItem())
         menu.addItem(.separator())
-        menu.addItem(NSMenuItem(title: "Quit Aligner", action: #selector(quit), keyEquivalent: "q"))
+        menu.addItem(menuItem(title: "Show Round0 Debug Overlay", action: #selector(showRound0DebugOverlay), keyEquivalent: "d"))
+        menu.addItem(menuItem(title: "Hide Round0 Debug Overlay", action: #selector(hideRound0DebugOverlay), keyEquivalent: ""))
+        menu.addItem(.separator())
+        menu.addItem(menuItem(title: "Quit Aligner", action: #selector(quit), keyEquivalent: "q"))
         item.menu = menu
 
         statusItem = item
+        updateWaterfallViewModeMenuState()
         DevelopmentDiagnostics.log("app.statusItem.configure.end", [
-            "hasButton": item.button != nil
+            "hasButton": item.button != nil,
+            "hasAboutItem": true,
+            "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
+        ])
+    }
+
+    func menuWillOpen(_ menu: NSMenu) {
+        updateWaterfallViewModeMenuState()
+    }
+
+    private func menuItem(title: String, action: Selector?, keyEquivalent: String) -> NSMenuItem {
+        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 {
+        let submenu = NSMenu(title: "Quick Switch View")
+        let verticalItem = menuItem(
+            title: "Vertical Columns",
+            action: #selector(useVerticalWaterfallViewMode),
+            keyEquivalent: ""
+        )
+        let horizontalItem = menuItem(
+            title: "Horizontal Waterfall",
+            action: #selector(useHorizontalWaterfallViewMode),
+            keyEquivalent: ""
+        )
+        submenu.addItem(verticalItem)
+        submenu.addItem(horizontalItem)
+
+        verticalWaterfallViewModeMenuItems.append(verticalItem)
+        horizontalWaterfallViewModeMenuItems.append(horizontalItem)
+
+        let rootItem = NSMenuItem(title: "Quick Switch View", action: nil, keyEquivalent: "")
+        rootItem.submenu = submenu
+        return rootItem
+    }
+
+    private func updateWaterfallViewModeMenuState() {
+        let mode = quickSwitchWaterfallViewMode()
+        for item in verticalWaterfallViewModeMenuItems {
+            item.state = mode == .verticalColumns ? .on : .off
+        }
+        for item in horizontalWaterfallViewModeMenuItems {
+            item.state = mode == .horizontalMasonry ? .on : .off
+        }
     }
 
     private func showPermissionsIfNeeded() {
@@ -354,8 +477,11 @@
             let controller = QuickSwitchSessionController(
                 snapshotLoader: quickSwitchSnapshotLoader(),
                 windowActivationService: quickSwitchWindowActivationService(),
+                spaceActivationService: quickSwitchSpaceActivationService(),
                 windowCloseService: quickSwitchWindowCloseService(),
                 disableScreenshotRefresh: round1QuickSwitchOptions.disableScreenshotRefresh,
+                waterfallViewMode: quickSwitchWaterfallViewMode(),
+                theme: quickSwitchThemePreference(),
                 closeConfirmationRequired: quickSwitchConfirmBeforeClose,
                 onCloseConfirmationDisabled: { [weak self] in
                     self?.setQuickSwitchConfirmBeforeClose(false)
@@ -368,6 +494,12 @@
             )
             controller.onSnapshotUpdated = { [weak self] in
                 self?.writeQuickSwitchReportIfNeeded()
+            }
+            controller.onToggleWaterfallViewMode = { [weak self] in
+                self?.toggleQuickSwitchWaterfallViewModeFromQuickSwitch()
+            }
+            controller.onToggleTheme = { [weak self] in
+                self?.toggleQuickSwitchThemeFromQuickSwitch()
             }
             quickSwitchSessionController = controller
         }
@@ -428,8 +560,11 @@
             let controller = QuickSwitchSessionController(
                 snapshotLoader: quickSwitchSnapshotLoader(),
                 windowActivationService: quickSwitchWindowActivationService(),
+                spaceActivationService: quickSwitchSpaceActivationService(),
                 windowCloseService: quickSwitchWindowCloseService(),
                 disableScreenshotRefresh: round1QuickSwitchOptions.disableScreenshotRefresh,
+                waterfallViewMode: quickSwitchWaterfallViewMode(),
+                theme: quickSwitchThemePreference(),
                 closeConfirmationRequired: quickSwitchConfirmBeforeClose,
                 onCloseConfirmationDisabled: { [weak self] in
                     self?.setQuickSwitchConfirmBeforeClose(false)
@@ -442,6 +577,12 @@
             )
             controller.onSnapshotUpdated = { [weak self] in
                 self?.writeQuickSwitchReportIfNeeded()
+            }
+            controller.onToggleWaterfallViewMode = { [weak self] in
+                self?.toggleQuickSwitchWaterfallViewModeFromQuickSwitch()
+            }
+            controller.onToggleTheme = { [weak self] in
+                self?.toggleQuickSwitchThemeFromQuickSwitch()
             }
             quickSwitchSessionController = controller
         }
@@ -464,13 +605,23 @@
         guard !isRunningQuickSwitchLifecycle else { return }
         let reportPathSummary = DevelopmentDiagnostics.pathSummary(reportPath)
 
-        let report = quickSwitchSessionController?.reportDictionary() ?? [
+        var report: [String: Any] = quickSwitchSessionController?.reportDictionary() ?? [
             "snapshotLoaded": false,
             "quickSwitchVisible": false,
             "permissionStatus": "\(accessibilityStatus())",
             "diagnosticLogLocationKind": DevelopmentDiagnostics.pathSummary(DevelopmentDiagnostics.logPath)["locationKind"] ?? "unknown",
             "diagnosticLogBasename": DevelopmentDiagnostics.pathSummary(DevelopmentDiagnostics.logPath)["basename"] ?? "aligner-dev.log"
         ]
+        let versionBuild = appVersionBuild()
+        report["preferenceWaterfallViewMode"] = preferenceStore.read().quickSwitchWaterfallViewMode.rawValue
+        report["resolvedWaterfallViewMode"] = quickSwitchWaterfallViewMode().rawValue
+        report["preferenceTheme"] = preferenceStore.read().theme.rawValue
+        report["resolvedQuickSwitchTheme"] = quickSwitchThemePreference().rawValue
+        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])
@@ -517,6 +668,18 @@
             return FixtureQuickSwitchSnapshotLoader(appCount: 1, mode: .candidateFiltering)
         }
 
+        if round1QuickSwitchOptions.fixtureSpaceFilter {
+            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,
@@ -542,6 +705,24 @@
         return CGWindowAXWindowService(spaceIDsByWindowIDProvider: { _ in [:] })
     }
 
+    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 {
+        if round1QuickSwitchOptions.debugWindowActivation {
+            return DebugSpaceActivationService()
+        }
+
+        return PrivateSpaceActivationService()
+    }
+
     private func quickSwitchWindowCloseService() -> any WindowCloseServiceProtocol {
         if round1QuickSwitchOptions.debugWindowClose {
             return DebugWindowCloseService()
@@ -562,6 +743,184 @@
         ])
     }
 
+    private func setQuickSwitchWaterfallViewMode(_ mode: QuickSwitchWaterfallViewMode) {
+        let preferences = preferenceStore.read()
+        let updatedPreferences = AlignerPreferences(
+            showMinimizedWindows: preferences.showMinimizedWindows,
+            showFullscreenWindows: preferences.showFullscreenWindows,
+            quickSwitchWaterfallViewMode: mode,
+            theme: preferences.theme,
+            language: preferences.language,
+            spaceDisplayStrategy: preferences.spaceDisplayStrategy
+        )
+        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) {
+        let info = Bundle.main.infoDictionary ?? [:]
+        let version = info["CFBundleShortVersionString"] as? String ?? "Unknown"
+        let build = info["CFBundleVersion"] as? String ?? "Unknown"
+        return (version, build)
+    }
+
+    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": 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
+        ]
+    }
+
+    @objc private func showAbout() {
+        let versionBuild = appVersionBuild()
+        DevelopmentDiagnostics.log("app.menu.showAbout", [
+            "version": versionBuild.version,
+            "build": versionBuild.build
+        ])
+
+        NSApp.setActivationPolicy(.regular)
+        let alert = NSAlert()
+        alert.messageText = "Aligner"
+        alert.informativeText = "Version / Build: \(versionBuild.version) / \(versionBuild.build)"
+        alert.alertStyle = .informational
+        alert.addButton(withTitle: "OK")
+        alert.icon = NSApp.applicationIconImage
+        NSApp.activate(ignoringOtherApps: true)
+        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)
+    }
+
+    @objc private func useHorizontalWaterfallViewMode() {
+        setQuickSwitchWaterfallViewMode(.horizontalMasonry)
+    }
+
     @objc private func showPermissions() {
         DevelopmentDiagnostics.log("app.permissions.show", [
             "accessibility": permissionStatusString(accessibilityStatus()),

--
Gitblit v1.9.3