1 parent
80a883c7d4
commit
f150b7e3dc
2 files changed
+16
-9
No files matched your search
@@ -1,6 +1,8 @@
|
||||
import Cocoa
|
||||
import Foundation
|
||||
|
||||
let minimumWindowSize: CGFloat = 200
|
||||
|
||||
class OpenWindow {
|
||||
var target: AXUIElement?
|
||||
var ownerPid: pid_t?
|
||||
@@ -46,10 +48,10 @@ func computeDownscaledSize(_ image: NSImage) -> (Int, Int) {
|
||||
func axWindows(_ cgOwnerPid: pid_t) -> [AXUIElement] {
|
||||
if let windows = AXUIElementCopyAttributeValue(AXUIElementCreateApplication(cgOwnerPid), kAXWindowsAttribute, [AXUIElement].self) {
|
||||
return windows.filter {
|
||||
let hasTitle = !(AXUIElementCopyAttributeValue($0, kAXTitleAttribute, String.self) ?? "").isEmpty
|
||||
// workaround: some apps like chrome use a window to implement the search popover
|
||||
let isReasonablyTall = AXValueGetValue($0, kAXSizeAttribute, NSSize(), AXValueType.cgSize)!.height > 200
|
||||
return hasTitle && isReasonablyTall
|
||||
let windowBounds = AXValueGetValue($0, kAXSizeAttribute, NSSize(), AXValueType.cgSize)!
|
||||
let isReasonablyBig = windowBounds.width > minimumWindowSize && windowBounds.height > minimumWindowSize
|
||||
return isReasonablyBig
|
||||
}
|
||||
}
|
||||
return []
|
||||
@@ -58,9 +60,12 @@ func axWindows(_ cgOwnerPid: pid_t) -> [AXUIElement] {
|
||||
func cgWindows() -> [NSDictionary] {
|
||||
let windows = CGWindowListCopyWindowInfo([.excludeDesktopElements, .optionOnScreenOnly], kCGNullWindowID) as! [NSDictionary]
|
||||
return windows.filter {
|
||||
// workaround: filtering this criteria seems to remove non-windows UI elements
|
||||
let isWindowNotMenubarOrOthers = $0[kCGWindowLayer] as? Int == 0
|
||||
let hasTitle = !(($0[kCGWindowName] as? String ?? "").isEmpty)
|
||||
return isWindowNotMenubarOrOthers && hasTitle
|
||||
let windowBounds = CGRect(dictionaryRepresentation: $0[kCGWindowBounds] as! NSDictionary)!
|
||||
// workaround: some apps like chrome use a window to implement the search popover
|
||||
let isReasonablyBig = windowBounds.width > minimumWindowSize && windowBounds.height > minimumWindowSize
|
||||
return isWindowNotMenubarOrOthers && isReasonablyBig
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,14 +117,16 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
|
||||
var pidAndCurrentIndex: [pid_t: Int] = [:]
|
||||
for cgWindow in cgWindows() {
|
||||
let cgId = cgWindow[kCGWindowNumber] as! CGWindowID
|
||||
let cgTitle = String(cgWindow[kCGWindowName] as! NSString)
|
||||
let cgTitle = cgWindow[kCGWindowName] as? String ?? ""
|
||||
let cgOwnerName = cgWindow[kCGWindowOwnerName] as? String ?? ""
|
||||
let cellTitle = cgTitle.isEmpty ? cgOwnerName : cgTitle
|
||||
let cgOwnerPid = cgWindow[kCGWindowOwnerPID] as! pid_t
|
||||
let i = pidAndCurrentIndex.index(forKey: cgOwnerPid)
|
||||
pidAndCurrentIndex[cgOwnerPid] = (i == nil ? 0 : pidAndCurrentIndex[i!].value + 1)
|
||||
let axWindow = axWindows(cgOwnerPid)
|
||||
let axWindows_ = axWindows(cgOwnerPid)
|
||||
// windows may have changed between the CG and the AX calls
|
||||
if axWindow.count > pidAndCurrentIndex[cgOwnerPid]! {
|
||||
openWindows.append(OpenWindow(target: axWindow[pidAndCurrentIndex[cgOwnerPid]!], ownerPid: cgOwnerPid, cgId: cgId, cgTitle: cgTitle))
|
||||
if axWindows_.count > pidAndCurrentIndex[cgOwnerPid]! {
|
||||
openWindows.append(OpenWindow(target: axWindows_[pidAndCurrentIndex[cgOwnerPid]!], ownerPid: cgOwnerPid, cgId: cgId, cgTitle: cellTitle))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user