import AppKit import CoreGraphics import Foundation class WindowManager { static func getWindowsForApp(pid: pid_t, includeOffScreen: Bool = false) throws(WindowError) -> [WindowData] { Logger.shared.debug("Getting windows for PID: \(pid)") let windowList = try fetchWindowList(includeOffScreen: includeOffScreen) let windows = extractWindowsForPID(pid, from: windowList) Logger.shared.debug("Found \(windows.count) windows for PID \(pid)") return windows.sorted { $0.windowIndex < $1.windowIndex } } private static func fetchWindowList(includeOffScreen: Bool) throws(WindowError) -> [[String: Any]] { let options: CGWindowListOption = includeOffScreen ? [.excludeDesktopElements] : [.excludeDesktopElements, .optionOnScreenOnly] guard let windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: Any]] else { throw WindowError.windowListFailed } return windowList } private static func extractWindowsForPID(_ pid: pid_t, from windowList: [[String: Any]]) -> [WindowData] { var windows: [WindowData] = [] var windowIndex = 0 for windowInfo in windowList { if let window = parseWindowInfo(windowInfo, targetPID: pid, index: windowIndex) { windows.append(window) windowIndex += 1 } } return windows } private static func parseWindowInfo(_ info: [String: Any], targetPID: pid_t, index: Int) -> WindowData? { guard let windowPID = info[kCGWindowOwnerPID as String] as? Int32, windowPID == targetPID, let windowID = info[kCGWindowNumber as String] as? CGWindowID else { return nil } let title = info[kCGWindowName as String] as? String ?? "Untitled" let bounds = extractWindowBounds(from: info) let isOnScreen = info[kCGWindowIsOnscreen as String] as? Bool ?? true return WindowData( windowId: windowID, title: title, bounds: bounds, isOnScreen: isOnScreen, windowIndex: index ) } private static func extractWindowBounds(from windowInfo: [String: Any]) -> CGRect { guard let boundsDict = windowInfo[kCGWindowBounds as String] as? [String: Any] else { return .zero } let xCoordinate = boundsDict["X"] as? Double ?? 0 let yCoordinate = boundsDict["Y"] as? Double ?? 0 let width = boundsDict["Width"] as? Double ?? 0 let height = boundsDict["Height"] as? Double ?? 0 return CGRect(x: xCoordinate, y: yCoordinate, width: width, height: height) } static func getWindowsInfoForApp( pid: pid_t, includeOffScreen: Bool = false, includeBounds: Bool = false, includeIDs: Bool = false ) throws(WindowError) -> [WindowInfo] { let windowDataArray = try getWindowsForApp(pid: pid, includeOffScreen: includeOffScreen) return windowDataArray.map { windowData in WindowInfo( window_title: windowData.title, window_id: includeIDs ? windowData.windowId : nil, window_index: windowData.windowIndex, bounds: includeBounds ? WindowBounds( xCoordinate: Int(windowData.bounds.origin.x), yCoordinate: Int(windowData.bounds.origin.y), width: Int(windowData.bounds.size.width), height: Int(windowData.bounds.size.height) ) : nil, is_on_screen: includeOffScreen ? windowData.isOnScreen : nil ) } } } // Extension to add the getWindowsForApp function to ImageCommand extension ImageCommand { func getWindowsForApp(pid: pid_t) throws(WindowError) -> [WindowData] { try WindowManager.getWindowsForApp(pid: pid) } } enum WindowError: Error, LocalizedError { case windowListFailed case noWindowsFound var errorDescription: String? { switch self { case .windowListFailed: "Failed to get window list from system" case .noWindowsFound: "No windows found for the specified application" } } }