fix: observe playback state to unhide native video surface

This commit is contained in:
2026-10-18 02:05:25 +02:00
parent 07243f0ed7
commit 3e782aff31
4 changed files with 16 additions and 1 deletions
+7
View File
@@ -285,8 +285,15 @@ def check_cli_instances(root, app, fixtures):
and state["position"] > 0 and state["hasVideo"] for state in states.values()), and state["position"] > 0 and state["hasVideo"] for state in states.values()),
"cold default CLI opens one actual player window") "cold default CLI opens one actual player window")
first_pid = next(iter(first)) first_pid = next(iter(first))
renderer = first[first_pid]["window"]
if (not renderer.get("rendererAttached") or renderer.get("rendererHidden")
or abs(renderer["rendererWidth"] - renderer["videoWidth"]) > 1
or abs(renderer["rendererHeight"] - renderer["videoHeight"]) > 1):
raise RuntimeError(f"playing renderer must fill its visible native surface: {renderer}")
opened = input_request(first_pid, 1, lambda state: state["showsQueue"] opened = input_request(first_pid, 1, lambda state: state["showsQueue"]
and state["window"].get("videoOwnsMouse") is True and state["window"].get("videoOwnsMouse") is True
and state["window"].get("rendererAttached") is True
and state["window"].get("rendererHidden") is False
and abs(state["window"]["videoWidth"] - first[first_pid]["window"]["videoWidth"]) < 1, and abs(state["window"]["videoWidth"] - first[first_pid]["window"]["videoWidth"]) < 1,
"queue preserves video size and mouse target", action="queue", visible=True) "queue preserves video size and mouse target", action="queue", visible=True)
window = opened[first_pid]["window"] window = opened[first_pid]["window"]
+6
View File
@@ -122,6 +122,12 @@ private enum CLIInstanceCheck {
result["sidebarOwnsMouse"] = hit(NSPoint(x: surface.bounds.maxX + 130, y: surface.bounds.midY)) !== surface result["sidebarOwnsMouse"] = hit(NSPoint(x: surface.bounds.maxX + 130, y: surface.bounds.midY)) !== surface
result["videoWidth"] = surface.bounds.width result["videoWidth"] = surface.bounds.width
result["videoHeight"] = surface.bounds.height result["videoHeight"] = surface.bounds.height
if let video = PlayerModel.shared.videoView {
result["rendererWidth"] = video.bounds.width
result["rendererHeight"] = video.bounds.height
result["rendererAttached"] = video.superview === surface
result["rendererHidden"] = video.isHidden
}
result["surfaceMovesOnMouseDown"] = surface.mouseDownCanMoveWindow result["surfaceMovesOnMouseDown"] = surface.mouseDownCanMoveWindow
let edges = [NSPoint(x: 1, y: content.bounds.midY), let edges = [NSPoint(x: 1, y: content.bounds.midY),
NSPoint(x: content.bounds.maxX - 1, y: content.bounds.midY), NSPoint(x: content.bounds.maxX - 1, y: content.bounds.midY),
+2
View File
@@ -155,6 +155,8 @@ make check
The full suite requires a graphical macOS session and a working audio device; it launches isolated app instances and plays short test audio. Targeted `check-*` targets are listed in the [Makefile](Makefile). Visual appearance, physical media-key routing, and receiver behavior still need manual checks. The full suite requires a graphical macOS session and a working audio device; it launches isolated app instances and plays short test audio. Targeted `check-*` targets are listed in the [Makefile](Makefile). Visual appearance, physical media-key routing, and receiver behavior still need manual checks.
The startup checks verify that playing video remains attached, unhidden and sized to its native drag surface, including with the queue open; playback-state checks alone do not establish renderer visibility.
`make benchmark-playback` measures cold source startup, cached/uncached seeks, and sustained native/Cast playback with repeatable loopback fixtures. It requires the same macOS session/audio device and fixture-generation FFmpeg; results exclude live extraction, WAN/TLS, and physical-receiver latency. `make benchmark-playback` measures cold source startup, cached/uncached seeks, and sustained native/Cast playback with repeatable loopback fixtures. It requires the same macOS session/audio device and fixture-generation FFmpeg; results exclude live extraction, WAN/TLS, and physical-receiver latency.
The [benchmark runner](Checks/playback-benchmark.py) accepts `--compare-native <baseline-binary>` for alternating native-only comparisons; add `--seek-work` to isolate cache-miss seeks when both binaries support that mode. Preserve the baseline executable before rebuilding. The [benchmark runner](Checks/playback-benchmark.py) accepts `--compare-native <baseline-binary>` for alternating native-only comparisons; add `--seek-work` to isolate cache-miss seeks when both binaries support that mode. Preserve the baseline executable before rebuilding.
+1 -1
View File
@@ -1881,7 +1881,7 @@ private struct CaptionSelector: NSViewRepresentable {
@MainActor @MainActor
struct PlaybackSurface: NSViewRepresentable { struct PlaybackSurface: NSViewRepresentable {
let model: PlayerModel @ObservedObject var model: PlayerModel
func makeNSView(context: Context) -> DragView { DragView(model: model) } func makeNSView(context: Context) -> DragView { DragView(model: model) }
func updateNSView(_ view: DragView, context: Context) { view.updateVideo() } func updateNSView(_ view: DragView, context: Context) { view.updateVideo() }