From 0f7ee6e29f70017dd4fdfe2dd3a6106f7204f04f Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 02 Jul 2026 02:40:40 +0800
Subject: [PATCH] Document Raycast extension backlog

---
 src/Apptag/QuickSearch.swift |   97 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/src/Apptag/QuickSearch.swift b/src/Apptag/QuickSearch.swift
index ccbf454..c7b25eb 100644
--- a/src/Apptag/QuickSearch.swift
+++ b/src/Apptag/QuickSearch.swift
@@ -7,6 +7,7 @@
     static let tagLauncherQuickSearchDismissRequested = Notification.Name("TagLauncherQuickSearchDismissRequested")
     static let tagLauncherQuickSearchVisibilityChanged = Notification.Name("TagLauncherQuickSearchVisibilityChanged")
     static let tagLauncherHotkeyRegistrationChanged = Notification.Name("TagLauncherHotkeyRegistrationChanged")
+    static let tagLauncherProEntitlementChanged = Notification.Name("TagLauncherProEntitlementChanged")
 }
 
 enum QuickSearchOpenSource {
@@ -80,6 +81,10 @@
             }
             return "Key \(keyCode)"
         }
+    }
+
+    static var printableKeyCodes: Set<Int> {
+        Set(keyCodeToPrintableScalar.keys)
     }
 
     private static let keyCodeToPrintableScalar: [Int: Character] = [
@@ -847,6 +852,7 @@
             if panel.frame != frame {
                 panel.setFrame(frame, display: true)
             }
+            NSApp.activate(ignoringOtherApps: true)
             panel.makeKeyAndOrderFront(nil)
             panel.orderFrontRegardless()
         }
@@ -871,7 +877,7 @@
 
             let panel = QuickSearchPanel(
                 contentRect: .zero,
-                styleMask: [.borderless, .fullSizeContentView, .nonactivatingPanel],
+                styleMask: [.borderless, .fullSizeContentView],
                 backing: .buffered,
                 defer: false
             )
@@ -942,8 +948,52 @@
     override var canBecomeKey: Bool { true }
     override var canBecomeMain: Bool { false }
 
+    override func sendEvent(_ event: NSEvent) {
+        if event.type == .leftMouseDown,
+           let row = quickSearchResultRow(at: event.locationInWindow) {
+            row.launchFromMouseClick()
+            return
+        }
+        super.sendEvent(event)
+    }
+
     override func constrainFrameRect(_ frameRect: NSRect, to screen: NSScreen?) -> NSRect {
         frameRect
+    }
+
+    private func quickSearchResultRow(at windowPoint: NSPoint) -> QuickSearchResultRowView? {
+        guard let contentView else { return nil }
+        if let row = contentView.quickSearchResultRowFromHitTest(atWindowPoint: windowPoint) {
+            return row
+        }
+        return contentView.quickSearchResultRowDescendant(containingWindowPoint: windowPoint)
+    }
+}
+
+private extension NSView {
+    func quickSearchResultRowFromHitTest(atWindowPoint windowPoint: NSPoint) -> QuickSearchResultRowView? {
+        let localPoint = convert(windowPoint, from: nil)
+        var hitView = hitTest(localPoint)
+        while let candidate = hitView {
+            if let row = candidate as? QuickSearchResultRowView {
+                return row
+            }
+            hitView = candidate.superview
+        }
+        return nil
+    }
+
+    func quickSearchResultRowDescendant(containingWindowPoint windowPoint: NSPoint) -> QuickSearchResultRowView? {
+        for subview in subviews.reversed() {
+            if let row = subview as? QuickSearchResultRowView,
+               row.containsWindowPointForLaunch(windowPoint) {
+                return row
+            }
+            if let row = subview.quickSearchResultRowDescendant(containingWindowPoint: windowPoint) {
+                return row
+            }
+        }
+        return nil
     }
 }
 
@@ -1432,6 +1482,15 @@
         trackingAreaRef = area
     }
 
+    override func hitTest(_ point: NSPoint) -> NSView? {
+        guard !isHidden, alphaValue > 0, bounds.contains(point) else { return nil }
+        return self
+    }
+
+    override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
+        true
+    }
+
     override func mouseEntered(with event: NSEvent) {
         super.mouseEntered(with: event)
         if let result {
@@ -1440,13 +1499,31 @@
     }
 
     override func mouseDown(with event: NSEvent) {
-        if let result {
-            DispatchQueue.main.async { [onLaunch] in
-                onLaunch(result)
-            }
-        } else {
+        if !launchFromMouseClick() {
             super.mouseDown(with: event)
         }
+    }
+
+    @discardableResult
+    func launchFromMouseClick() -> Bool {
+        guard let result else { return false }
+        DispatchQueue.main.async { [onLaunch, result] in
+            onLaunch(result)
+        }
+        return true
+    }
+
+    func containsWindowPointForLaunch(_ windowPoint: NSPoint) -> Bool {
+        guard window != nil else { return false }
+        var view: NSView? = self
+        while let candidate = view {
+            if candidate.isHidden || candidate.alphaValue <= 0 {
+                return false
+            }
+            view = candidate.superview
+        }
+        let localPoint = convert(windowPoint, from: nil)
+        return bounds.contains(localPoint) && visibleRect.contains(localPoint)
     }
 
     private func setup() {
@@ -1564,6 +1641,8 @@
         field.placeholderString = placeholder
         field.delegate = context.coordinator
         field.onCommand = onCommand
+        field.target = context.coordinator
+        field.action = #selector(Coordinator.submitAction(_:))
         context.coordinator.onCommand = onCommand
         field.setAccessibilityLabel(tr("quickSearch.inputAccessibility"))
         context.coordinator.field = field
@@ -1577,6 +1656,8 @@
         }
         field.placeholderString = placeholder
         field.onCommand = onCommand
+        field.target = context.coordinator
+        field.action = #selector(Coordinator.submitAction(_:))
         context.coordinator.onCommand = onCommand
         if context.coordinator.lastFocusToken != focusToken {
             context.coordinator.lastFocusToken = focusToken
@@ -1618,6 +1699,10 @@
             text.wrappedValue = field.stringValue
         }
 
+        @objc func submitAction(_ sender: Any?) {
+            onCommand?(.submit)
+        }
+
         func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
             switch commandSelector {
             case #selector(NSResponder.moveUp(_:)):

--
Gitblit v1.9.3