From 0badb998147135c75187a0c48f926b665af734c5 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 28 Jun 2026 02:53:51 +0800
Subject: [PATCH] Release 8.1.6 build 20260628.0230

---
 src/Apptag/ApptagApp.swift |  173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 163 insertions(+), 10 deletions(-)

diff --git a/src/Apptag/ApptagApp.swift b/src/Apptag/ApptagApp.swift
index bb6b32b..53dfb40 100644
--- a/src/Apptag/ApptagApp.swift
+++ b/src/Apptag/ApptagApp.swift
@@ -39,7 +39,10 @@
     private static let downloadHelpMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherDownloadHelpMenuItem")
     private static let externalActivationNotification = Notification.Name("TagLauncherExternalActivationRequested")
     private static let externalActivationObject = AppIdentity.bundleIdentifier
+    private static let externalInvocationScheme = "taglauncher"
+    private static let externalInvocationShowHost = "show"
     private static let duplicateLaunchSuppressReopenKey = "duplicateLaunchSuppressReopenAt"
+    private static let overlaySpaceHotkeyID: UInt32 = 3
     private static let launcherOverlayLevel = NSWindow.Level(rawValue: NSWindow.Level.mainMenu.rawValue - 1)
     private static let overlayDefaultLevel = launcherOverlayLevel
     private static let overlayTextInputLevel = launcherOverlayLevel
@@ -50,8 +53,10 @@
     private var quickSearchLocalMouseMonitor: Any?
     private var quickSearchExternalMouseMonitor: Any?
     private var settingsWindow: NSWindow?    // Track Settings window to keep it above overlay
+    private var explicitPreferencesOpenRequestedAt = Date.distantPast
     private var mainHotkeyRef: EventHotKeyRef?
     private var quickSearchHotkeyRef: EventHotKeyRef?
+    private var overlaySpaceHotkeyRef: EventHotKeyRef?
     private var hotkeyEventHandlerInstalled = false
     private var isQuickSearchOpen = false
     private var quickSearchShouldHideOverlayOnClose = false
@@ -65,6 +70,8 @@
     private var statusMenuScreenForNextOverlay: NSScreen?
     private var suppressReopenUntil = Date.distantPast
     private var overlayOpenedByQuickSearchOnly = false
+    private var didFinishLaunching = false
+    private var pendingShowOverlayInvocation = false
 
     private lazy var overlayController = OverlayWindowController(
         dependencies: OverlayWindowController.Dependencies(
@@ -127,14 +134,16 @@
             refreshChromeState: { [weak self] activate, avoidSpaceSwitch in
                 self?.refreshLauncherChromeState(activate: activate, avoidSpaceSwitch: avoidSpaceSwitch)
             },
-            onWillHide: {
+            onWillHide: { [weak self] in
+                self?.unregisterOverlaySpaceHotkey()
                 TagDatabase.flushPendingCategorySchemeBackupBatch()
             },
             onDidHide: { [weak self] in
                 self?.overlayOpenedByQuickSearchOnly = false
                 NotificationCenter.default.post(name: .tagLauncherOverlayDidHide, object: nil)
             },
-            onDidShow: {
+            onDidShow: { [weak self] in
+                self?.refreshOverlaySpaceHotkeyRegistration()
                 NotificationCenter.default.post(name: .tagLauncherOverlayDidShow, object: nil)
             }
         )
@@ -213,6 +222,9 @@
         observeLanguageChanges()
         setupLaunchAtLogin()
         suppressReopenUntil = Date().addingTimeInterval(1.0)
+        didFinishLaunching = true
+        closeRestoredPreferencesWindowsDuringLaunch()
+        consumePendingShowOverlayInvocationIfNeeded()
         configureApplicationMenuWhenAvailable(retries: 200)
         warmAppIndexInBackground()
         relocalizeDefaultAppNotesForCurrentLanguageAsync()
@@ -243,6 +255,54 @@
         guard isRecentUserClickNearDockArea() else { return false }
         showOrFocusOverlay()
         return false  // Suppress default "unhide all windows" behavior
+    }
+
+    func application(_ application: NSApplication, open urls: [URL]) {
+        for url in urls {
+            handleExternalInvocationURL(url)
+        }
+    }
+
+    private enum ExternalInvocationRoute {
+        case showOverlay
+    }
+
+    private func handleExternalInvocationURL(_ url: URL) {
+        guard externalInvocationRoute(for: url) == .showOverlay else {
+            Diagnostics.log("app.externalInvocation.ignored", [
+                "url": url.absoluteString
+            ])
+            return
+        }
+        requestShowOverlayFromExternalInvocation()
+    }
+
+    private func externalInvocationRoute(for url: URL) -> ExternalInvocationRoute? {
+        guard url.scheme?.lowercased() == Self.externalInvocationScheme else {
+            return nil
+        }
+        let host = url.host?.lowercased()
+        let path = url.path
+        if host == Self.externalInvocationShowHost, path.isEmpty || path == "/" {
+            return .showOverlay
+        }
+        return nil
+    }
+
+    private func requestShowOverlayFromExternalInvocation() {
+        guard didFinishLaunching else {
+            pendingShowOverlayInvocation = true
+            return
+        }
+        pendingShowOverlayInvocation = false
+        suppressReopenUntil = Date().addingTimeInterval(1.0)
+        dismissQuickSearchIfNeeded()
+        showOrFocusOverlay()
+    }
+
+    private func consumePendingShowOverlayInvocationIfNeeded() {
+        guard pendingShowOverlayInvocation else { return }
+        requestShowOverlayFromExternalInvocation()
     }
 
     private func isRecentUserClickNearDockArea() -> Bool {
@@ -293,6 +353,7 @@
         hideOverlay(force: true, discardWindow: true)
         unregisterHotkey(for: .main)
         unregisterHotkey(for: .quickSearch)
+        unregisterOverlaySpaceHotkey()
         TagDatabase.flushPendingCategorySchemeBackupBatch()
         removeOverlayKeyMonitor()
         removeQuickSearchExternalMouseMonitor()
@@ -480,14 +541,17 @@
 
         if activate && requiresForegroundOwnership
             && !shouldStayAccessoryForCurrentFullscreenSpace
-            && !shouldStayAccessoryForHiddenDockChrome
             && !shouldStayAccessoryForQuickOnlySearch {
             let keyWindow = isSettingsVisible ? settingsWindow : (isOverlayVisible ? overlayWindow : nil)
-            claimLauncherForeground(
-                keyWindow: keyWindow,
-                retries: isOverlayVisible && !isSettingsVisible ? 5 : 0,
-                overlayGeneration: isOverlayVisible ? overlayGeneration : nil
-            )
+            if shouldStayAccessoryForHiddenDockChrome {
+                beginLauncherForegroundOwnership(activate: true, keyWindow: keyWindow)
+            } else {
+                claimLauncherForeground(
+                    keyWindow: keyWindow,
+                    retries: isOverlayVisible && !isSettingsVisible ? 5 : 0,
+                    overlayGeneration: isOverlayVisible ? overlayGeneration : nil
+                )
+            }
         }
     }
 
@@ -1298,9 +1362,27 @@
         ])
         if id == LauncherHotkeyKind.quickSearch.eventID {
             showQuickSearchFromGlobalHotkey()
+        } else if id == Self.overlaySpaceHotkeyID {
+            handleOverlaySpaceHotkey()
         } else {
             performToggleOverlay(preferredScreen: nil)
         }
+    }
+
+    private func handleOverlaySpaceHotkey() {
+        guard canUseOverlaySpaceHotkey else { return }
+        unregisterOverlaySpaceHotkey()
+        requestQuickSearch(source: QuickSearchOpenSource.mainOverlay)
+    }
+
+    private var canUseOverlaySpaceHotkey: Bool {
+        overlayWindow?.isVisible == true
+            && !isSettingsVisible
+            && !isQuickSearchOpen
+            && !quickSearchOnlyOverlaySession
+            && !isInEditMode
+            && !isEditingAppNote
+            && !isModalInteractionActive
     }
 
     private func showQuickSearchFromGlobalHotkey() {
@@ -1358,6 +1440,46 @@
         }
     }
 
+    private func refreshOverlaySpaceHotkeyRegistration() {
+        if canUseOverlaySpaceHotkey {
+            registerOverlaySpaceHotkeyIfNeeded()
+        } else {
+            unregisterOverlaySpaceHotkey()
+        }
+    }
+
+    private func registerOverlaySpaceHotkeyIfNeeded() {
+        guard overlaySpaceHotkeyRef == nil else { return }
+
+        var hotkeyID = EventHotKeyID()
+        hotkeyID.signature = OSType(0x41505447) // 'APTG'
+        hotkeyID.id = Self.overlaySpaceHotkeyID
+
+        var newRef: EventHotKeyRef?
+        let status = RegisterEventHotKey(
+            UInt32(kVK_Space),
+            0,
+            hotkeyID,
+            GetApplicationEventTarget(),
+            0,
+            &newRef
+        )
+
+        if status == noErr, let newRef {
+            overlaySpaceHotkeyRef = newRef
+        } else {
+            overlaySpaceHotkeyRef = nil
+            Diagnostics.log("app.overlay.spaceHotkey.failed", ["status": status])
+        }
+    }
+
+    private func unregisterOverlaySpaceHotkey() {
+        if let overlaySpaceHotkeyRef {
+            UnregisterEventHotKey(overlaySpaceHotkeyRef)
+            self.overlaySpaceHotkeyRef = nil
+        }
+    }
+
     // MARK: - Preferences
 
     /// Hide overlay when any other window becomes key (catches Cmd+, via SwiftUI Settings).
@@ -1409,6 +1531,9 @@
             forContentRect: NSRect(origin: .zero, size: settingsSize)
         ).size
         window.identifier = NSUserInterfaceItemIdentifier("TagLauncherPreferencesWindow")
+        window.isRestorable = false
+        window.restorationClass = nil
+        _ = window.setFrameAutosaveName("")
         window.contentMinSize = settingsSize
         window.contentMaxSize = settingsSize
         window.minSize = settingsFrameSize
@@ -1441,6 +1566,7 @@
         window.makeKeyAndOrderFront(nil)
         window.orderFrontRegardless()
         settingsWindow = window
+        refreshOverlaySpaceHotkeyRegistration()
         refreshLauncherChromeState(
             activate: !overlayAvoidsSpaceSwitch,
             avoidSpaceSwitch: overlayAvoidsSpaceSwitch
@@ -1545,6 +1671,7 @@
                 activate: shouldRefocusOverlay && !self.overlayAvoidsSpaceSwitch,
                 avoidSpaceSwitch: self.overlayAvoidsSpaceSwitch
             )
+            self.refreshOverlaySpaceHotkeyRegistration()
             guard shouldRefocusOverlay else { return }
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.12) { [weak self] in
                 self?.showOrFocusOverlay(preferredScreen: preferredScreen)
@@ -1559,7 +1686,9 @@
             object: nil,
             queue: .main
         ) { [weak self] notification in
-            self?.isInEditMode = (notification.userInfo?["active"] as? Bool) ?? false
+            guard let self else { return }
+            self.isInEditMode = (notification.userInfo?["active"] as? Bool) ?? false
+            self.refreshOverlaySpaceHotkeyRegistration()
         }
     }
 
@@ -1576,6 +1705,7 @@
                 self.promoteOverlayToForegroundInput()
             }
             self.updateOverlayLevelForTextInput()
+            self.refreshOverlaySpaceHotkeyRegistration()
         }
     }
 
@@ -1642,6 +1772,7 @@
                     self.hideOverlay(force: true, discardWindow: wasQuickSearchOnlyOverlay)
                 }
             }
+            self.refreshOverlaySpaceHotkeyRegistration()
         }
 
         NotificationCenter.default.addObserver(
@@ -1649,7 +1780,9 @@
             object: nil,
             queue: .main
         ) { [weak self] notification in
-            self?.isModalInteractionActive = (notification.userInfo?["active"] as? Bool) ?? false
+            guard let self else { return }
+            self.isModalInteractionActive = (notification.userInfo?["active"] as? Bool) ?? false
+            self.refreshOverlaySpaceHotkeyRegistration()
         }
 
         NotificationCenter.default.addObserver(
@@ -1757,6 +1890,7 @@
     }
 
     private func openPreferences(targetTab: String?) {
+        explicitPreferencesOpenRequestedAt = Date()
         dismissQuickSearchIfNeeded()
         TagDatabase.flushPendingCategorySchemeBackupBatch()
         if overlayAvoidsSpaceSwitch {
@@ -1789,6 +1923,25 @@
         prepareSettingsWindow(window)
     }
 
+    private func closeRestoredPreferencesWindowsDuringLaunch() {
+        for delay in [0.25, 0.8, 1.6, 2.6] {
+            DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
+                self?.closeRestoredPreferencesWindowIfNeeded()
+            }
+        }
+    }
+
+    private func closeRestoredPreferencesWindowIfNeeded() {
+        guard Date().timeIntervalSince(explicitPreferencesOpenRequestedAt) > 3.0 else { return }
+        for window in NSApp.windows where isSettingsWindowCandidate(window) {
+            detachSettingsWindow(window)
+            window.close()
+            if settingsWindow == window {
+                settingsWindow = nil
+            }
+        }
+    }
+
     private func requestPreferencesTabSelection(_ targetTab: String?) {
         guard let targetTab else { return }
         NotificationCenter.default.post(

--
Gitblit v1.9.3