Created
April 10, 2025 22:54
-
-
Save hbouhadji/05a6eb6b21d23f84649f89a2090858e6 to your computer and use it in GitHub Desktop.
list windows swift (ordered)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import AppKit | |
import ApplicationServices | |
import CoreGraphics | |
import Foundation | |
// Declare the private _AXUIElementGetWindow API | |
@_silgen_name("_AXUIElementGetWindow") | |
func _AXUIElementGetWindow(_ element: AXUIElement, _ windowID: UnsafeMutablePointer<CGWindowID>) | |
-> AXError | |
func kind(of application: NSRunningApplication) -> Int { | |
switch application.activationPolicy { | |
case .accessory: return 0 | |
case .prohibited: return -1 | |
default: return 1 | |
} | |
} | |
func allWindows(of application: NSRunningApplication) -> [AXUIElement] { | |
let appRef = AXUIElementCreateApplication(application.processIdentifier) | |
let allWindows: [AXUIElement] = [] | |
var windowsPtr: CFArray? | |
let axWindowsAttribute = "AXWindows" as CFString | |
let result = AXUIElementCopyAttributeValues(appRef, axWindowsAttribute, 0, 100, &windowsPtr) | |
if result == .success, let windows = windowsPtr as? [AXUIElement] { | |
return windows | |
} | |
return allWindows | |
} | |
guard | |
let windowInfoList = CGWindowListCopyWindowInfo( | |
[.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID) as? [[String: Any]] | |
else { | |
print("Failed to retrieve window info list") | |
exit(1) | |
} | |
print("Successfully retrieved window info list with \(windowInfoList.count) windows") | |
let runningApplications = NSWorkspace.shared.runningApplications.filter { | |
!$0.isHidden && kind(of: $0) > 0 | |
} | |
var windowByID = [CGWindowID: AXUIElement]() | |
for application in runningApplications { | |
let windows = allWindows(of: application) | |
for window in windows { | |
var windowID: CGWindowID = 0 | |
let result = _AXUIElementGetWindow(window, &windowID) | |
if result == .success { | |
windowByID[windowID] = window | |
} else { | |
print("Failed to get window ID, error: \(result)") | |
} | |
} | |
} | |
for windowInfo in windowInfoList { | |
if let windowID = windowInfo["kCGWindowNumber"] as? CGWindowID { | |
if let window = windowByID[windowID] { | |
// Get window title using AXTitle attribute | |
var titleRef: CFTypeRef? | |
let titleResult = AXUIElementCopyAttributeValue( | |
window, "AXTitle" as CFString, &titleRef) | |
var title = "Unknown" | |
if titleResult == .success, let titleString = titleRef as? String { | |
title = titleString | |
} | |
print("Window ID: \(windowID), Title: \(title)") | |
} | |
} | |
} | |
print(runningApplications.map(\.localizedName)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment