Ariver
2026-06-13 bedb145ee1413482763707fe73787b622cb52cbf
C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
@@ -162,9 +162,10 @@
        let privateActivationOutcome = activateViaPrivateWindowServerAPI(window)
        let didPrivatelyActivate = privateActivationOutcome?.succeeded == true
        let currentAXMetadata = AXWindowMetadataReader.metadata(appCategorizer: appCategorizer)
        let axWindow = axWindow(
            for: window,
            in: AXWindowMetadataReader.metadata(appCategorizer: appCategorizer),
            in: currentAXMetadata,
            operation: "windowActivation",
            matchAttempt: "initial"
        )
@@ -188,6 +189,20 @@
            "spaceFocusError": spaceFocusOutcome?.error
        ])
        guard let axWindow else {
            if let finderTabActivated = activateFinderTabPageIfNeeded(
                window: window,
                axMetadata: currentAXMetadata,
                operation: "windowActivation",
                reason: "axMissing"
            ) {
                DevelopmentDiagnostics.log("windowActivation.activate.finderTabResult", [
                    "windowID": window.id,
                    "pid": window.app.processIdentifier,
                    "activated": finderTabActivated
                ])
                return finderTabActivated ? .activated : .activationFailed
            }
            let activated = activateApplication(for: window)
            DevelopmentDiagnostics.log("windowActivation.activate.axMissing", [
                "windowID": window.id,
@@ -393,15 +408,31 @@
            return nil
        }
        guard let activationOutcome = activateViaPrivateWindowServerAPI(window),
              activationOutcome.succeeded
        else {
            DevelopmentDiagnostics.log("windowClose.commandW.activationFailed", [
                "windowID": window.id,
                "pid": processIdentifier,
                "reason": reason
            ])
            return nil
        if let finderTabActivated = activateFinderTabPageIfNeeded(
            window: window,
            axMetadata: AXWindowMetadataReader.metadata(appCategorizer: appCategorizer),
            operation: "windowClose",
            reason: reason
        ) {
            guard finderTabActivated else {
                DevelopmentDiagnostics.log("windowClose.commandW.finderTabActivationFailed", [
                    "windowID": window.id,
                    "pid": processIdentifier,
                    "reason": reason
                ])
                return .failed("finderTabActivationFailed")
            }
        } else {
            guard let activationOutcome = activateViaPrivateWindowServerAPI(window),
                  activationOutcome.succeeded
            else {
                DevelopmentDiagnostics.log("windowClose.commandW.activationFailed", [
                    "windowID": window.id,
                    "pid": processIdentifier,
                    "reason": reason
                ])
                return nil
            }
        }
        Thread.sleep(forTimeInterval: 0.08)
@@ -564,6 +595,271 @@
                && metadata.subrole == .standard
        }
        return finderCandidates.count == 1 ? finderCandidates[0] : nil
    }
    private func activateFinderTabPageIfNeeded(
        window: AlignerWindow,
        axMetadata: [AXWindowMetadata],
        operation: String,
        reason: String
    ) -> Bool? {
        guard isFinderCGOnlyPageCandidate(window),
              let processIdentifier = window.app.processIdentifier
        else {
            return nil
        }
        guard let host = finderTabHostAXWindow(for: window, in: axMetadata) else {
            DevelopmentDiagnostics.log("\(operation).finderTab.hostMissing", [
                "windowID": window.id,
                "pid": processIdentifier,
                "reason": reason,
                "spaceIDs": window.spaceIDs
            ])
            return false
        }
        let hostPrivateActivationSucceeded: Bool
        if let hostWindowID = host.windowID,
           let privateActivationBridge {
            hostPrivateActivationSucceeded = privateActivationBridge.activate(
                processIdentifier: processIdentifier,
                windowID: hostWindowID
            ).succeeded
        } else {
            hostPrivateActivationSucceeded = false
        }
        let applicationActivated = activateApplication(processIdentifier: processIdentifier)
        let focusBeforeResult = focusWindowResult(host.element, processIdentifier: processIdentifier)
        let raiseBeforeResult = raiseWindowResult(host.element)
        let selectedTab = selectFinderTab(window, in: host)
        Thread.sleep(forTimeInterval: 0.05)
        let focusAfterResult = focusWindowResult(host.element, processIdentifier: processIdentifier)
        let raiseAfterResult = raiseWindowResult(host.element)
        let didFocusOrRaise = focusBeforeResult.success
            || raiseBeforeResult.success
            || focusAfterResult.success
            || raiseAfterResult.success
        let activated = selectedTab
            && (hostPrivateActivationSucceeded || applicationActivated || didFocusOrRaise)
        DevelopmentDiagnostics.log("\(operation).finderTab.result", [
            "windowID": window.id,
            "pid": processIdentifier,
            "reason": reason,
            "hostWindowID": host.windowID,
            "hostTitleHash": DevelopmentDiagnostics.stableFingerprint(host.title),
            "hostTitleLength": host.title?.count,
            "hostPrivateActivated": hostPrivateActivationSucceeded,
            "applicationActivated": applicationActivated,
            "selectedTab": selectedTab,
            "focusBeforeAXError": String(describing: focusBeforeResult.error),
            "raiseBeforeAXError": String(describing: raiseBeforeResult.error),
            "focusAfterAXError": String(describing: focusAfterResult.error),
            "raiseAfterAXError": String(describing: raiseAfterResult.error),
            "activated": activated
        ])
        return activated
    }
    private func isFinderCGOnlyPageCandidate(_ window: AlignerWindow) -> Bool {
        window.identifierSource == .cgWindow
            && window.app.bundleIdentifier == "com.apple.finder"
            && !window.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }
    private func finderTabHostAXWindow(
        for window: AlignerWindow,
        in axMetadata: [AXWindowMetadata]
    ) -> AXWindowMetadata? {
        guard let processIdentifier = window.app.processIdentifier else { return nil }
        let candidates = axMetadata.filter { metadata in
            metadata.processIdentifier == processIdentifier
                && metadata.subrole == .standard
                && metadata.frame?.isEmpty == false
        }
        guard !candidates.isEmpty else { return nil }
        let targetSpaceIDs = Set(window.spaceIDs)
        let candidateIDs = candidates.compactMap(\.windowID)
        let candidateSpacesByID = targetSpaceIDs.isEmpty ? [:] : spaceIDsByWindowIDProvider(candidateIDs)
        let spaceCompatibleCandidates = targetSpaceIDs.isEmpty
            ? candidates
            : candidates.filter { metadata in
                guard let windowID = metadata.windowID else { return false }
                return !Set(candidateSpacesByID[windowID] ?? []).isDisjoint(with: targetSpaceIDs)
            }
        let hostCandidates = spaceCompatibleCandidates.isEmpty ? candidates : spaceCompatibleCandidates
        let targetFrame = cgWindowFrame(for: window) ?? window.frame
        let scoredHosts = hostCandidates.compactMap { metadata -> (metadata: AXWindowMetadata, score: CGFloat)? in
            guard let score = frameOverlapScore(targetFrame, metadata.frame),
                  score >= 0.85
            else {
                return nil
            }
            return (metadata, score)
        }
        .sorted { lhs, rhs in
            if lhs.score != rhs.score {
                return lhs.score > rhs.score
            }
            return (lhs.metadata.windowID ?? UInt32.max) < (rhs.metadata.windowID ?? UInt32.max)
        }
        if let best = scoredHosts.first {
            if scoredHosts.count == 1 {
                return best.metadata
            }
            let secondBest = scoredHosts[1]
            if best.score - secondBest.score >= 0.05 {
                return best.metadata
            }
        }
        return hostCandidates.count == 1 ? hostCandidates[0] : nil
    }
    private func selectFinderTab(
        _ window: AlignerWindow,
        in host: AXWindowMetadata
    ) -> Bool {
        let normalizedTargetTitle = normalizedWindowTitle(window.title)
        guard !normalizedTargetTitle.isEmpty else { return false }
        if normalizedWindowTitle(host.title ?? "") == normalizedTargetTitle {
            return true
        }
        guard let tabButton = finderTabButton(
            matchingNormalizedTitle: normalizedTargetTitle,
            in: host.element
        ) else {
            DevelopmentDiagnostics.log("windowActivation.finderTab.tabButtonMissing", [
                "windowID": window.id,
                "hostWindowID": host.windowID,
                "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
                "targetTitleLength": window.title.count
            ])
            return false
        }
        let tabButtonRole = axStringAttribute(kAXRoleAttribute as String, for: tabButton)
        let tabButtonSubrole = axStringAttribute(kAXSubroleAttribute as String, for: tabButton)
        let pressResult = AXUIElementPerformAction(tabButton, kAXPressAction as CFString)
        DevelopmentDiagnostics.log("windowActivation.finderTab.pressTab", [
            "windowID": window.id,
            "hostWindowID": host.windowID,
            "tabButtonRole": tabButtonRole,
            "tabButtonSubrole": tabButtonSubrole,
            "axError": String(describing: pressResult)
        ])
        guard pressResult == .success else { return false }
        for _ in 0..<10 {
            Thread.sleep(forTimeInterval: 0.04)
            let selectedTitle = normalizedWindowTitle(
                axStringAttribute(kAXTitleAttribute as String, for: host.element) ?? ""
            )
            if selectedTitle == normalizedTargetTitle {
                return true
            }
        }
        let currentHostTitle = axStringAttribute(kAXTitleAttribute as String, for: host.element) ?? ""
        DevelopmentDiagnostics.log("windowActivation.finderTab.selectionVerificationFailed", [
            "windowID": window.id,
            "hostWindowID": host.windowID,
            "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
            "targetTitleLength": window.title.count,
            "currentHostTitleHash": DevelopmentDiagnostics.stableFingerprint(currentHostTitle),
            "currentHostTitleLength": currentHostTitle.count
        ])
        return false
    }
    private func finderTabButton(
        matchingNormalizedTitle targetTitle: String,
        in root: AXUIElement
    ) -> AXUIElement? {
        var visitedCount = 0
        func search(_ element: AXUIElement, depth: Int, insideTabGroup: Bool) -> AXUIElement? {
            visitedCount += 1
            guard visitedCount <= 240, depth <= 9 else { return nil }
            let role = axStringAttribute(kAXRoleAttribute as String, for: element)
            let subrole = axStringAttribute(kAXSubroleAttribute as String, for: element)
            let title = axStringAttribute(kAXTitleAttribute as String, for: element)
                ?? axStringAttribute(kAXDescriptionAttribute as String, for: element)
                ?? axStringAttribute(kAXValueAttribute as String, for: element)
            let isTabGroup = role == "AXTabGroup"
            let isTabControl = subrole == "AXTabButton"
                || (insideTabGroup && (role == kAXRadioButtonRole as String || role == kAXButtonRole as String))
            if normalizedWindowTitle(title ?? "") == targetTitle,
               isTabControl {
                return element
            }
            guard isTabGroup || insideTabGroup || depth < 7 else { return nil }
            for child in axChildren(of: element) {
                if let match = search(child, depth: depth + 1, insideTabGroup: insideTabGroup || isTabGroup) {
                    return match
                }
            }
            return nil
        }
        return search(root, depth: 0, insideTabGroup: false)
    }
    private func axChildren(of element: AXUIElement) -> [AXUIElement] {
        var value: CFTypeRef?
        guard AXUIElementCopyAttributeValue(element, kAXChildrenAttribute as CFString, &value) == .success,
              let children = value as? [AXUIElement]
        else {
            return []
        }
        return children
    }
    private func axStringAttribute(_ attribute: String, for element: AXUIElement) -> String? {
        var value: CFTypeRef?
        guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success,
              let value
        else {
            return nil
        }
        return value as? String
    }
    private func frameOverlapScore(_ lhs: CGRect?, _ rhs: CGRect?) -> CGFloat? {
        guard let lhs,
              let rhs,
              !lhs.isEmpty,
              !rhs.isEmpty
        else {
            return nil
        }
        let intersection = lhs.intersection(rhs)
        guard !intersection.isNull,
              !intersection.isEmpty
        else {
            return nil
        }
        let denominator = min(lhs.width * lhs.height, rhs.width * rhs.height)
        guard denominator > 0 else { return nil }
        return (intersection.width * intersection.height) / denominator
    }
    private func cgWindowFingerprint(for window: AlignerWindow) -> AXWindowFingerprint? {
@@ -895,7 +1191,31 @@
        }
        restorableAXWindowsByID = nextRestorableAXWindowsByID
        return cgRecords + axOnlyRecords
        let records = cgRecords + axOnlyRecords
        let attributedRecords = FinderTabSpaceAttributionPolicy.attributedRecords(records)
        DevelopmentDiagnostics.log("windowEnumeration.finderTabSpaceAttribution", [
            "finderNoSpaceCandidateCount": records.filter { record in
                record.app.bundleIdentifier == "com.apple.finder"
                    && record.identifierSource == .cgWindow
                    && record.spaceIDs.isEmpty
                    && !record.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
                    && record.frame?.isEmpty == false
            }.count,
            "finderFullscreenHostCount": records.filter { record in
                record.app.bundleIdentifier == "com.apple.finder"
                    && record.isFullscreen
                    && !record.spaceIDs.isEmpty
                    && record.subrole == .standard
                    && record.frame?.isEmpty == false
            }.count,
            "attributedCount": zip(records, attributedRecords).filter { before, after in
                before.spaceIDs.isEmpty && !after.spaceIDs.isEmpty
            }.count,
            "attributedWindowIDs": zip(records, attributedRecords).compactMap { before, after in
                before.spaceIDs.isEmpty && !after.spaceIDs.isEmpty ? after.id : nil
            }
        ])
        return attributedRecords
    }
    private func app(