From 3ef24f71a70fc47eba8bf23f6827a60a4f34a07a Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 04 Jun 2026 00:32:09 +0800
Subject: [PATCH] Fix Shottr and HBuilderX window candidates
---
C1.source/Resources/Aligner-Info.plist | 48 ++++++------
C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift | 39 +++++++++
C1.source/Sources/AlignerCore/Windows/WindowEnumerationPolicy.swift | 35 +++++++-
C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift | 70 +++++++++++++++++
4 files changed, 161 insertions(+), 31 deletions(-)
diff --git a/C1.source/Resources/Aligner-Info.plist b/C1.source/Resources/Aligner-Info.plist
index 9639d34..ffe1a14 100644
--- a/C1.source/Resources/Aligner-Info.plist
+++ b/C1.source/Resources/Aligner-Info.plist
@@ -2,29 +2,29 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>Aligner</string>
- <key>CFBundleIconFile</key>
- <string>AppIcon</string>
- <key>CFBundleIdentifier</key>
- <string>com.ar.Aligner</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>Aligner</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>0.0.20</string>
- <key>CFBundleVersion</key>
- <string>20260603.2338</string>
- <key>LSMinimumSystemVersion</key>
- <string>26.0</string>
- <key>NSHighResolutionCapable</key>
- <true/>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>Aligner</string>
+ <key>CFBundleIconFile</key>
+ <string>AppIcon</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.ar.Aligner</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Aligner</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>0.0.21</string>
+ <key>CFBundleVersion</key>
+ <string>20260604.0030</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>26.0</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
</dict>
</plist>
diff --git a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
index 773abed..49a7cf9 100644
--- a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
+++ b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
@@ -395,6 +395,7 @@
isGhost: isGhost(
rawWindow: rawWindow,
axWindow: axWindow,
+ app: app,
spaceIDs: spaceIDs,
hasAXBackedTitleDuplicate: hasAXBackedTitleDuplicate
),
@@ -583,6 +584,7 @@
private func isGhost(
rawWindow: [String: Any],
axWindow: AXWindowMetadata?,
+ app: AlignerApp,
spaceIDs: [UInt64],
hasAXBackedTitleDuplicate: Bool = false
) -> Bool {
@@ -596,10 +598,20 @@
return false
}
if axWindow != nil {
- return layer != 0 || alpha <= 0
+ if alpha <= 0 {
+ return true
+ }
+ if layer == 0 {
+ return false
+ }
+
+ return !isOnscreen
}
if hasAXBackedTitleDuplicate {
return true
+ }
+ if isKnownCGOnlyMainWindow(rawWindow: rawWindow, app: app) {
+ return false
}
if !spaceIDs.isEmpty, isLikelyFullscreenAuxiliaryCGWindow(bounds: rawBounds) {
return true
@@ -618,6 +630,31 @@
bounds.width < 500 || bounds.height < 160
}
+ private func isKnownCGOnlyMainWindow(rawWindow: [String: Any], app: AlignerApp) -> Bool {
+ let layer = intValue(rawWindow[kCGWindowLayer as String]) ?? 0
+ let alpha = doubleValue(rawWindow[kCGWindowAlpha as String]) ?? 1
+ let isOnscreen = boolValue(rawWindow[kCGWindowIsOnscreen as String])
+ let title = stringValue(rawWindow[kCGWindowName as String]) ?? ""
+ let rawBounds = bounds(rawWindow[kCGWindowBounds as String])
+ let trimmedTitle = title.trimmingCharacters(in: .whitespacesAndNewlines)
+
+ if app.bundleIdentifier == "cc.ffitch.shottr" {
+ return alpha > 0
+ && trimmedTitle == "Shottr"
+ && rawBounds.width > WindowEnumerationPolicy.minimumVisibleWidth
+ && rawBounds.height > WindowEnumerationPolicy.minimumVisibleHeight
+ }
+
+ guard app.bundleIdentifier == "io.dcloud.HBuilderX" else { return false }
+
+ return layer == 0
+ && alpha > 0
+ && !isOnscreen
+ && !trimmedTitle.isEmpty
+ && rawBounds.width > WindowEnumerationPolicy.minimumVisibleWidth
+ && rawBounds.height > WindowEnumerationPolicy.minimumVisibleHeight
+ }
+
private func isDesktopElement(rawWindow: [String: Any], app: AlignerApp) -> Bool {
guard app.bundleIdentifier == "com.apple.finder" else { return false }
let title = stringValue(rawWindow[kCGWindowName as String]) ?? ""
diff --git a/C1.source/Sources/AlignerCore/Windows/WindowEnumerationPolicy.swift b/C1.source/Sources/AlignerCore/Windows/WindowEnumerationPolicy.swift
index 75bc119..a219abb 100644
--- a/C1.source/Sources/AlignerCore/Windows/WindowEnumerationPolicy.swift
+++ b/C1.source/Sources/AlignerCore/Windows/WindowEnumerationPolicy.swift
@@ -76,7 +76,7 @@
public static func shouldInclude(_ record: WindowEnumerationRecord) -> Bool {
guard record.id != 0 else { return false }
- guard record.activationPolicy == .regular else { return false }
+ guard hasSupportedActivationPolicy(record) else { return false }
guard isSupportedSubrole(record.subrole) else { return false }
guard !record.app.isHidden || record.isFullscreen else { return false }
guard !record.isGhost else { return false }
@@ -87,6 +87,11 @@
guard !isKnownClosedDocumentPlaceholder(record) else { return false }
return record.isMinimized || record.isFullscreen || isLargeEnough(record.size)
+ }
+
+ private static func hasSupportedActivationPolicy(_ record: WindowEnumerationRecord) -> Bool {
+ record.activationPolicy == .regular
+ || (record.activationPolicy == .accessory && isKnownCGOnlyOffscreenMainWindow(record))
}
public static func window(from record: WindowEnumerationRecord) -> AlignerWindow? {
@@ -118,11 +123,29 @@
}
private static func isCGOnlyOffscreenGhost(_ record: WindowEnumerationRecord) -> Bool {
- record.identifierSource == .cgWindow
- && !record.hasAXBacking
- && !record.isOnscreen
- && !record.isMinimized
- && !record.isFullscreen
+ guard record.identifierSource == .cgWindow,
+ !record.hasAXBacking,
+ !record.isOnscreen,
+ !record.isMinimized,
+ !record.isFullscreen
+ else {
+ return false
+ }
+
+ return !isKnownCGOnlyOffscreenMainWindow(record)
+ }
+
+ private static func isKnownCGOnlyOffscreenMainWindow(_ record: WindowEnumerationRecord) -> Bool {
+ let trimmedTitle = record.title.trimmingCharacters(in: .whitespacesAndNewlines)
+
+ switch record.app.bundleIdentifier {
+ case "cc.ffitch.shottr":
+ return trimmedTitle == "Shottr" && isLargeEnough(record.size)
+ case "io.dcloud.HBuilderX":
+ return !trimmedTitle.isEmpty && isLargeEnough(record.size)
+ default:
+ return false
+ }
}
private static func isKnownClosedDocumentPlaceholder(_ record: WindowEnumerationRecord) -> Bool {
diff --git a/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift b/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
index 9eca644..66709a1 100644
--- a/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
+++ b/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
@@ -244,6 +244,76 @@
XCTAssertEqual(window?.title, "Visible Document.md")
}
+ func testWindowEnumerationPolicyKeepsKnownCGOnlyOffscreenMainWindows() {
+ let hbuilderApp = AlignerApp(
+ bundleIdentifier: "io.dcloud.HBuilderX",
+ name: "HBuilderX",
+ category: .editorIDE
+ )
+ let record = WindowEnumerationRecord(
+ id: 55_388,
+ app: hbuilderApp,
+ title: "lm-app - HBuilder X 5.07",
+ size: CGSize(width: 1048, height: 796),
+ subrole: .standard,
+ hasAXBacking: false,
+ isOnscreen: false
+ )
+ let emptyTitleRecord = WindowEnumerationRecord(
+ id: 55_389,
+ app: hbuilderApp,
+ title: "",
+ size: CGSize(width: 1048, height: 796),
+ subrole: .standard,
+ hasAXBacking: false,
+ isOnscreen: false
+ )
+ let tinyRecord = WindowEnumerationRecord(
+ id: 55_390,
+ app: hbuilderApp,
+ title: "HBuilderX Utility",
+ size: CGSize(width: 80, height: 40),
+ subrole: .standard,
+ hasAXBacking: false,
+ isOnscreen: false
+ )
+
+ XCTAssertEqual(WindowEnumerationPolicy.window(from: record)?.title, "lm-app - HBuilder X 5.07")
+ XCTAssertNil(WindowEnumerationPolicy.window(from: emptyTitleRecord))
+ XCTAssertNil(WindowEnumerationPolicy.window(from: tinyRecord))
+ }
+
+ func testWindowEnumerationPolicyKeepsShottrCGOnlyAnnotationWindow() {
+ let shottrApp = AlignerApp(
+ bundleIdentifier: "cc.ffitch.shottr",
+ name: "Shottr",
+ category: .generic
+ )
+ let annotationRecord = WindowEnumerationRecord(
+ id: 78,
+ app: shottrApp,
+ activationPolicy: .accessory,
+ title: "Shottr",
+ size: CGSize(width: 1710, height: 997),
+ subrole: .standard,
+ hasAXBacking: false,
+ isOnscreen: false
+ )
+ let utilityRecord = WindowEnumerationRecord(
+ id: 102,
+ app: shottrApp,
+ activationPolicy: .accessory,
+ title: "Colors",
+ size: CGSize(width: 250, height: 397),
+ subrole: .standard,
+ hasAXBacking: false,
+ isOnscreen: false
+ )
+
+ XCTAssertEqual(WindowEnumerationPolicy.window(from: annotationRecord)?.title, "Shottr")
+ XCTAssertNil(WindowEnumerationPolicy.window(from: utilityRecord))
+ }
+
func testWindowEnumerationPolicyKeepsMinimizedAndFullscreenCGOnlyOffscreenWindows() {
let minimized = makeWindowRecord(
title: "Minimized Document.md",
--
Gitblit v1.9.3