起動中のウィンドウを一覧するには、CGWindowListCopyWindowInfoを使う。
struct Window: CustomStringConvertible { let rawData: [String: AnyObject] var name: String? { get { return rawData[kCGWindowName as String] as? String } } var number: Int? { get { return rawData[kCGWindowNumber as String] as? Int } } var ownerName: String? { get { return rawData[kCGWindowOwnerName as String] as? String } } var ownerPID: Int? { get { return rawData[kCGWindowOwnerPID as String] as? Int } } var isOnScreen: Bool { get { return rawData[kCGWindowIsOnscreen as String] as? Bool ?? false } } var windowLayer: Int { get { return rawData[kCGWindowLayer as String] as? Int ?? 0 } } var description: String { get { return "Window: \"\(name ?? "nil")\" (\(number ?? -1)) Owner: \"\(ownerName ?? "nil")\" (\(ownerPID ?? -1))" } } } func enumerateWindows() -> [Window] { let options = CGWindowListOption(arrayLiteral: CGWindowListOption.optionAll) guard let results = CGWindowListCopyWindowInfo(options, CGWindowID(0)), let windowList = results as NSArray? as? [[String: AnyObject]] else { return [] } return windowList.map { Window(rawData: $0) } } let windows = enumerateWindows() for window in windows { // isOnScreen かつ windowLayer == 0 のものが、通常のアプリのウィンドウであると判断する if window.isOnScreen && window.windowLayer == 0 { print(window) } }
ただし、このままだとウィンドウのタイトルがほとんど取れない。これはプライバシーの観点で取れないようになっている。
取得するためには画面収録のパーミッションが必要で、以下のコードを実行することでパーミッションを得られる。
CGRequestScreenCaptureAccess()