diff --git a/src/api-wrappers/AXUIElement.swift b/src/api-wrappers/AXUIElement.swift index ccc14320..1299b112 100644 --- a/src/api-wrappers/AXUIElement.swift +++ b/src/api-wrappers/AXUIElement.swift @@ -2,7 +2,7 @@ import Cocoa extension AXUIElement { static let normalLevel = CGWindowLevelForKey(.normalWindow) - + func cgWindowId() -> CGWindowID { var id = CGWindowID(0) _AXUIElementGetWindow(self, &id) @@ -15,14 +15,19 @@ extension AXUIElement { return pid } - func isActualWindow() -> Bool { - // TODO: TotalFinder and XtraFinder double-window hacks (see #84) + func isActualWindow(_ bundleIdentifier: String?) -> Bool { // Some non-windows have title: nil (e.g. some OS elements) // Some non-windows have subrole: nil (e.g. some OS elements), "AXUnknown" (e.g. Bartender), "AXSystemDialog" (e.g. Intellij tooltips) // Minimized windows or windows of a hidden app have subrole "AXDialog" // Activity Monitor main window subrole is "AXDialog" for a brief moment at launch; it then becomes "AXStandardWindow" // CGWindowLevel == .normalWindow helps filter out iStats Pro and other top-level pop-overs - return ["AXStandardWindow", "AXDialog"].contains(subrole()) && isOnNormalLevel() + let subrole_ = subrole() + return subrole_ != nil && + (["AXStandardWindow", "AXDialog"].contains(subrole_) || + // All Steam windows have subrole = AXUnknown + // some dropdown menus are not desirable; they have title == "", or sometimes role == nil when switching between menus quickly + (bundleIdentifier == "com.valvesoftware.steam" && title() != "" && role() != nil)) && + isOnNormalLevel() } func isOnNormalLevel() -> Bool { @@ -54,6 +59,10 @@ extension AXUIElement { return attribute(kAXFocusedWindowAttribute, AXUIElement.self) } + func role() -> String? { + return attribute(kAXRoleAttribute, String.self) + } + func subrole() -> String? { return attribute(kAXSubroleAttribute, String.self) } diff --git a/src/logic/Application.swift b/src/logic/Application.swift index f7a04007..04edc94c 100644 --- a/src/logic/Application.swift +++ b/src/logic/Application.swift @@ -53,7 +53,7 @@ class Application: NSObject { func observeNewWindows() { if let windows = axUiElement!.windows() { let actualWindows = windows.filter { - $0.isActualWindow() && Windows.list.firstIndexThatMatches($0) == nil + $0.isActualWindow(runningApplication.bundleIdentifier) && Windows.list.firstIndexThatMatches($0) == nil } if actualWindows.count > 0 { addWindows(actualWindows) @@ -124,7 +124,7 @@ private func eventApplicationHiddenOrShown(_ app: App, _ element: AXUIElement, _ } private func eventWindowCreated(_ app: App, _ element: AXUIElement, _ application: Application) { - guard element.isActualWindow() else { return } + guard element.isActualWindow(application.runningApplication.bundleIdentifier) else { return } // a window being un-minimized can trigger kAXWindowCreatedNotification guard Windows.list.firstIndexThatMatches(element) == nil else { return } let window = Window(element, application)