Der Schriftzug gehört zum Aufmacher, nicht zu sich selbst
`AsyncImage` bringt seine eigene Einblendung mit und fängt erst an zu laden, wenn es erscheint. Beim Überblenden des Aufmachers blendete sich der Schriftzug des Films deshalb getrennt und später ein, während Titelzeile, Beschreibung und Knöpfe längst mitgewandert waren — zwei Bewegungen, wo eine sein soll. Jetzt lädt er über denselben Zwischenspeicher wie alle anderen Bilder, und das Karussell holt ihn zusammen mit dem Hintergrundbild vor. Beim Erscheinen liegt er bereit und macht mit, was der Aufmacher macht. Dazu ein kleines Hilfsprogramm, das die Fensterkennung eines laufenden Programms ausgibt, damit `screencapture -l` genau dessen Fenster fotografiert und sonst nichts vom Bildschirm. Das System-Python bringt PyObjC nicht mehr mit, und ohne Kennung gibt es keinen Weg dorthin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7155f50bac
commit
e5e01838f7
@@ -0,0 +1,45 @@
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
// Sucht das größte sichtbare Fenster eines Programms und gibt seine Kennung
|
||||
// aus. Damit lässt sich `screencapture -l<kennung>` aufrufen — das fotografiert
|
||||
// genau dieses eine Fenster und sonst nichts vom Bildschirm.
|
||||
//
|
||||
// Gebaut, weil es sonst keinen Weg dorthin gibt: das System-Python bringt
|
||||
// PyObjC nicht mehr mit, und `screencapture` kennt nur Kennungen, keine Namen.
|
||||
|
||||
let name = CommandLine.arguments.dropFirst().first ?? "Flixy"
|
||||
|
||||
guard let windows = CGWindowListCopyWindowInfo(.optionOnScreenOnly, kCGNullWindowID) as? [[String: Any]] else {
|
||||
FileHandle.standardError.write(Data("Fensterliste nicht lesbar\n".utf8))
|
||||
exit(2)
|
||||
}
|
||||
|
||||
let candidates = windows.filter { window in
|
||||
guard let owner = window[kCGWindowOwnerName as String] as? String, owner == name else { return false }
|
||||
// Ebene 0 ist das normale Fenster; alles darüber sind Menüs und Schatten.
|
||||
guard (window[kCGWindowLayer as String] as? Int) == 0 else { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
let largest = candidates.max { a, b in
|
||||
func area(_ w: [String: Any]) -> Double {
|
||||
guard let bounds = w[kCGWindowBounds as String] as? [String: Any],
|
||||
let width = bounds["Width"] as? Double,
|
||||
let height = bounds["Height"] as? Double
|
||||
else { return 0 }
|
||||
return width * height
|
||||
}
|
||||
return area(a) < area(b)
|
||||
}
|
||||
|
||||
guard let window = largest, let id = window[kCGWindowNumber as String] as? Int else {
|
||||
FileHandle.standardError.write(Data("Kein sichtbares Fenster von „\(name)“\n".utf8))
|
||||
exit(1)
|
||||
}
|
||||
|
||||
if let bounds = window[kCGWindowBounds as String] as? [String: Any],
|
||||
let width = bounds["Width"] as? Double, let height = bounds["Height"] as? Double {
|
||||
FileHandle.standardError.write(Data("\(name): \(Int(width))×\(Int(height))\n".utf8))
|
||||
}
|
||||
print(id)
|
||||
Reference in New Issue
Block a user