From b2a06ec5ebc86c0241e635782ae5a032ab5aad0a Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 02 Jul 2026 02:43:51 +0800
Subject: [PATCH] Prepare TagLauncher 8.3.2 App Store candidate
---
src/Apptag/QuickSearch.swift | 67 +++++++++++++++++++++++++++++----
1 files changed, 58 insertions(+), 9 deletions(-)
diff --git a/src/Apptag/QuickSearch.swift b/src/Apptag/QuickSearch.swift
index c7b25eb..f4365c4 100644
--- a/src/Apptag/QuickSearch.swift
+++ b/src/Apptag/QuickSearch.swift
@@ -6,6 +6,7 @@
static let tagLauncherQuickSearchRequested = Notification.Name("TagLauncherQuickSearchRequested")
static let tagLauncherQuickSearchDismissRequested = Notification.Name("TagLauncherQuickSearchDismissRequested")
static let tagLauncherQuickSearchVisibilityChanged = Notification.Name("TagLauncherQuickSearchVisibilityChanged")
+ static let tagLauncherQuickSearchCompositionChanged = Notification.Name("TagLauncherQuickSearchCompositionChanged")
static let tagLauncherHotkeyRegistrationChanged = Notification.Name("TagLauncherHotkeyRegistrationChanged")
static let tagLauncherProEntitlementChanged = Notification.Name("TagLauncherProEntitlementChanged")
}
@@ -849,12 +850,15 @@
self.parentWindow = parentWindow
}
+ let shouldOrderForInput = shouldOrderPanelForInput(panel)
if panel.frame != frame {
panel.setFrame(frame, display: true)
}
- NSApp.activate(ignoringOtherApps: true)
- panel.makeKeyAndOrderFront(nil)
- panel.orderFrontRegardless()
+ if shouldOrderForInput {
+ NSApp.activate(ignoringOtherApps: true)
+ panel.makeKeyAndOrderFront(nil)
+ panel.orderFrontRegardless()
+ }
}
func closePanel() {
@@ -899,6 +903,10 @@
self.panel = panel
self.hostingView = hostingView
return panel
+ }
+
+ private func shouldOrderPanelForInput(_ panel: QuickSearchPanel) -> Bool {
+ !panel.isVisible || !panel.isKeyWindow || NSApp.keyWindow !== panel
}
private func scheduleDeferredApply(
@@ -1651,9 +1659,10 @@
}
func updateNSView(_ field: QuickSearchNativeTextField, context: Context) {
- if field.stringValue != text {
+ if !field.isComposingText, field.stringValue != text {
field.stringValue = text
}
+ field.publishCompositionStateIfNeeded()
field.placeholderString = placeholder
field.onCommand = onCommand
field.target = context.coordinator
@@ -1671,10 +1680,13 @@
guard let field,
let window = field.window,
window.isVisible,
- window.firstResponder !== field
+ field.currentEditor() == nil
else { return }
- window.makeKeyAndOrderFront(nil)
- window.orderFrontRegardless()
+ if !window.isKeyWindow || NSApp.keyWindow !== window {
+ NSApp.activate(ignoringOtherApps: true)
+ window.makeKeyAndOrderFront(nil)
+ window.orderFrontRegardless()
+ }
window.makeFirstResponder(field)
}
}
@@ -1688,22 +1700,36 @@
var text: Binding<String>
var lastFocusToken = 0
var onCommand: ((QuickSearchCommand) -> Void)?
- weak var field: NSTextField?
+ weak var field: QuickSearchNativeTextField?
init(text: Binding<String>) {
self.text = text
}
func controlTextDidChange(_ obj: Notification) {
- guard let field = obj.object as? NSTextField else { return }
+ guard let field = obj.object as? QuickSearchNativeTextField else { return }
+ field.publishCompositionStateIfNeeded()
+ if !field.isComposingText {
+ text.wrappedValue = field.stringValue
+ }
+ }
+
+ func controlTextDidEndEditing(_ obj: Notification) {
+ guard let field = obj.object as? QuickSearchNativeTextField else { return }
+ field.publishCompositionState(active: false, force: true)
text.wrappedValue = field.stringValue
}
@objc func submitAction(_ sender: Any?) {
+ guard field?.isComposingText != true else { return }
onCommand?(.submit)
}
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
+ if textView.hasMarkedText() {
+ (control as? QuickSearchNativeTextField)?.publishCompositionState(active: true)
+ return false
+ }
switch commandSelector {
case #selector(NSResponder.moveUp(_:)):
onCommand?(.moveUp)
@@ -1729,10 +1755,33 @@
private final class QuickSearchNativeTextField: NSTextField {
var onCommand: ((QuickSearchCommand) -> Void)?
+ private var lastPublishedCompositionActive = false
override var acceptsFirstResponder: Bool { true }
+ var isComposingText: Bool {
+ (currentEditor() as? NSTextView)?.hasMarkedText() == true
+ }
+
+ func publishCompositionStateIfNeeded() {
+ publishCompositionState(active: isComposingText)
+ }
+
+ func publishCompositionState(active: Bool, force: Bool = false) {
+ guard force || active != lastPublishedCompositionActive else { return }
+ lastPublishedCompositionActive = active
+ NotificationCenter.default.post(
+ name: .tagLauncherQuickSearchCompositionChanged,
+ object: self,
+ userInfo: ["active": active]
+ )
+ }
+
override func keyDown(with event: NSEvent) {
+ guard !isComposingText else {
+ super.keyDown(with: event)
+ return
+ }
switch Int(event.keyCode) {
case kVK_UpArrow:
onCommand?(.moveUp)
--
Gitblit v1.9.3