import CoreGraphics
|
import Foundation
|
|
func usage() -> Never {
|
FileHandle.standardError.write(
|
Data("usage: round1-visible-owner-window-sampler.swift <owner-name> <duration-seconds> <interval-seconds> <output-path>\n".utf8)
|
)
|
exit(2)
|
}
|
|
let args = CommandLine.arguments
|
guard args.count == 5,
|
let duration = Double(args[2]),
|
let interval = Double(args[3]),
|
duration > 0,
|
interval > 0 else {
|
usage()
|
}
|
|
let ownerName = args[1]
|
let outputPath = args[4]
|
let deadline = Date().addingTimeInterval(duration)
|
var sampleCount = 0
|
|
func describe(_ item: [String: Any]) -> String {
|
let title = item[kCGWindowName as String] as? String ?? ""
|
let layer = item[kCGWindowLayer as String] as? Int ?? 0
|
let number = item[kCGWindowNumber as String] as? Int ?? 0
|
let bounds = item[kCGWindowBounds as String] as? [String: Any] ?? [:]
|
return "windowNumber=\(number) title=\"\(title)\" layer=\(layer) bounds=\(bounds)"
|
}
|
|
func writeReport(_ text: String) {
|
do {
|
try text.write(toFile: outputPath, atomically: true, encoding: .utf8)
|
} catch {
|
FileHandle.standardError.write(Data("failed to write sampler report: \(error)\n".utf8))
|
}
|
}
|
|
repeat {
|
sampleCount += 1
|
let windows = CGWindowListCopyWindowInfo([.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID) as? [[String: Any]] ?? []
|
let matches = windows
|
.filter { item in
|
(item[kCGWindowOwnerName as String] as? String) == ownerName
|
}
|
.map(describe)
|
|
if !matches.isEmpty {
|
let report = """
|
owner=\(ownerName)
|
samples=\(sampleCount)
|
visibleWindows=\(matches.count)
|
\(matches.joined(separator: "\n"))
|
"""
|
writeReport(report + "\n")
|
print(report)
|
exit(1)
|
}
|
|
if Date() < deadline {
|
Thread.sleep(forTimeInterval: interval)
|
}
|
} while Date() < deadline
|
|
let report = "owner=\(ownerName) samples=\(sampleCount) visibleWindows=0 duration=\(duration) interval=\(interval)"
|
writeReport(report + "\n")
|
print(report)
|