From d5cf4d94edbe72d53fb417bf32105c2258bce924 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 14 Jun 2026 16:02:13 +0800
Subject: [PATCH] Fix horizontal App hover linkage

---
 C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift |  131 +++++++++++++++++++------------------------
 1 files changed, 59 insertions(+), 72 deletions(-)

diff --git a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
index e03dddb..21abec8 100644
--- a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
+++ b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
@@ -129,8 +129,7 @@
             : .activationFailed
     }
 
-    func activate(window requestedWindow: AlignerWindow) throws -> WindowActivationResult {
-        let window = refreshedFinderWindowForPreciseAction(requestedWindow, operation: "windowActivation")
+    func activate(window: AlignerWindow) throws -> WindowActivationResult {
         DevelopmentDiagnostics.log("windowActivation.activate.start", [
             "windowID": window.id,
             "identifierSource": String(describing: window.identifierSource),
@@ -280,8 +279,7 @@
             : .appActivatedOnly
     }
 
-    func close(window requestedWindow: AlignerWindow) throws -> WindowCloseResult {
-        let window = refreshedFinderWindowForPreciseAction(requestedWindow, operation: "windowClose")
+    func close(window: AlignerWindow) throws -> WindowCloseResult {
         DevelopmentDiagnostics.log("windowClose.window.start", [
             "windowID": window.id,
             "identifierSource": String(describing: window.identifierSource),
@@ -358,59 +356,6 @@
             processIdentifier: matchedAXWindow.processIdentifier,
             attempt: "initial"
         )
-    }
-
-    private func refreshedFinderWindowForPreciseAction(
-        _ window: AlignerWindow,
-        operation: String
-    ) -> AlignerWindow {
-        guard isFinderCGOnlyPageCandidate(window) else { return window }
-
-        guard let refreshedWindow = try? allWindows().first(where: { refreshed in
-            refreshed.id == window.id
-                && refreshed.identifierSource == window.identifierSource
-                && refreshed.app.bundleIdentifier == window.app.bundleIdentifier
-        }) else {
-            DevelopmentDiagnostics.log("\(operation).finderRefresh.missing", [
-                "windowID": window.id,
-                "spaceIDCount": window.spaceIDs.count,
-                "hasFrame": window.frame != nil
-            ])
-            return window
-        }
-
-        let mergedWindow = AlignerWindow(
-            id: window.id,
-            app: window.app.processIdentifier == nil ? refreshedWindow.app : window.app,
-            title: window.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
-                ? refreshedWindow.title
-                : window.title,
-            identifierSource: window.identifierSource,
-            isMinimized: window.isMinimized || refreshedWindow.isMinimized,
-            isFullscreen: window.isFullscreen || refreshedWindow.isFullscreen,
-            isGhost: window.isGhost,
-            frame: window.frame ?? refreshedWindow.frame,
-            spaceIDs: window.spaceIDs.isEmpty ? refreshedWindow.spaceIDs : window.spaceIDs
-        )
-
-        if mergedWindow.spaceIDs != window.spaceIDs
-            || mergedWindow.isFullscreen != window.isFullscreen
-            || (window.frame == nil && refreshedWindow.frame != nil) {
-            DevelopmentDiagnostics.log("\(operation).finderRefresh.merged", [
-                "windowID": window.id,
-                "originalSpaceIDCount": window.spaceIDs.count,
-                "refreshedSpaceIDCount": refreshedWindow.spaceIDs.count,
-                "mergedSpaceIDCount": mergedWindow.spaceIDs.count,
-                "originalIsFullscreen": window.isFullscreen,
-                "refreshedIsFullscreen": refreshedWindow.isFullscreen,
-                "mergedIsFullscreen": mergedWindow.isFullscreen,
-                "originalHasFrame": window.frame != nil,
-                "refreshedHasFrame": refreshedWindow.frame != nil,
-                "mergedHasFrame": mergedWindow.frame != nil
-            ])
-        }
-
-        return mergedWindow
     }
 
     private func closeButton(for axWindow: AXWindowMetadata) -> AXUIElement? {
@@ -676,6 +621,28 @@
         }
 
         guard let host = finderTabHostAXWindow(for: window, in: axMetadata) else {
+            let normalizedTargetTitle = normalizedWindowTitle(window.title)
+            let applicationActivated = activateApplication(processIdentifier: processIdentifier)
+            let selectedViaWindowMenu = !normalizedTargetTitle.isEmpty
+                && selectFinderWindowMenuItem(
+                    processIdentifier: processIdentifier,
+                    window: window,
+                    normalizedTargetTitle: normalizedTargetTitle
+                )
+            DevelopmentDiagnostics.log("\(operation).finderTab.hostlessWindowMenuResult", [
+                "windowID": window.id,
+                "pid": processIdentifier,
+                "reason": reason,
+                "applicationActivated": applicationActivated,
+                "selectedViaWindowMenu": selectedViaWindowMenu,
+                "spaceIDs": window.spaceIDs,
+                "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                "targetTitleLength": window.title.count
+            ])
+            if selectedViaWindowMenu {
+                return true
+            }
+
             DevelopmentDiagnostics.log("\(operation).finderTab.hostMissing", [
                 "windowID": window.id,
                 "pid": processIdentifier,
@@ -772,21 +739,9 @@
             finderHostCanRepresentTarget(window, in: metadata)
         }
 
-        let hostCandidates: [AXWindowMetadata]
-        if targetSpaceIDs.isEmpty {
-            guard !selectableHostCandidates.isEmpty else {
-                DevelopmentDiagnostics.log("windowActivation.finderTab.noSelectableHost", [
-                    "windowID": window.id,
-                    "candidateCount": candidates.count,
-                    "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
-                    "targetTitleLength": window.title.count
-                ])
-                return nil
-            }
-            hostCandidates = selectableHostCandidates
-        } else {
-            hostCandidates = selectableHostCandidates.isEmpty ? spaceScopedCandidates : selectableHostCandidates
-        }
+        let hostCandidates = selectableHostCandidates.isEmpty
+            ? spaceScopedCandidates
+            : selectableHostCandidates
 
         let targetFrame = matchingFrame(for: window)
         let scoredHosts = hostCandidates.compactMap { metadata -> (metadata: AXWindowMetadata, score: CGFloat)? in
@@ -807,16 +762,48 @@
 
         if let best = scoredHosts.first {
             if scoredHosts.count == 1 {
+                if selectableHostCandidates.isEmpty {
+                    DevelopmentDiagnostics.log("windowActivation.finderTab.frameInferredHost", [
+                        "windowID": window.id,
+                        "hostWindowID": best.metadata.windowID,
+                        "score": Double(best.score),
+                        "spaceIDCount": targetSpaceIDs.count,
+                        "candidateCount": hostCandidates.count,
+                        "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                        "targetTitleLength": window.title.count
+                    ])
+                }
                 return best.metadata
             }
 
             let secondBest = scoredHosts[1]
             if best.score - secondBest.score >= 0.05 {
+                if selectableHostCandidates.isEmpty {
+                    DevelopmentDiagnostics.log("windowActivation.finderTab.frameInferredHost", [
+                        "windowID": window.id,
+                        "hostWindowID": best.metadata.windowID,
+                        "score": Double(best.score),
+                        "secondBestScore": Double(secondBest.score),
+                        "spaceIDCount": targetSpaceIDs.count,
+                        "candidateCount": hostCandidates.count,
+                        "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                        "targetTitleLength": window.title.count
+                    ])
+                }
                 return best.metadata
             }
         }
 
         if hostCandidates.count == 1 {
+            if selectableHostCandidates.isEmpty {
+                DevelopmentDiagnostics.log("windowActivation.finderTab.singleFrameHostFallback", [
+                    "windowID": window.id,
+                    "hostWindowID": hostCandidates[0].windowID,
+                    "spaceIDCount": targetSpaceIDs.count,
+                    "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                    "targetTitleLength": window.title.count
+                ])
+            }
             return hostCandidates[0]
         }
 

--
Gitblit v1.9.3