PlayingVideo + SeekRequested → SeekingVideo, stash target_ms, emit
SeekVideoTo. SeekingVideo + SeekRequested replaces the target (user
clicked again, latest seek wins). SeekingVideo + SeekCompleted →
PlayingVideo.
The slider pin behavior is the read-path query
`compute_slider_display_ms(mpv_pos_ms)` already implemented at the
skeleton stage: while in SeekingVideo, returns `seek_target_ms`;
otherwise returns `mpv_pos_ms`. The Qt-side adapter's poll timer
asks the state machine for the slider display value on every tick
and writes whatever it gets back to the slider widget.
**This replaces 96a0a9d's 500ms _seek_pending_until timestamp window
at the popout layer.** The state machine has no concept of wall-clock
time. The SeekingVideo state lasts exactly until mpv signals the seek
is done, via the playback_restart Signal added in commit 1. The
adapter distinguishes load-restart from seek-restart by checking
the state machine's current state (LoadingVideo → VideoStarted;
SeekingVideo → SeekCompleted).
The pre-commit-1 probe verified that mpv emits playback-restart
exactly once per load and exactly once per seek (3 events for 1
load + 2 seeks), so the dispatch routing is unambiguous.
VideoPlayer's internal _seek_pending_until field stays in place as
defense in depth — the state machine refactor's prompt explicitly
forbids touching media/video_player.py beyond the playback_restart
Signal addition. The popout layer no longer depends on it.
Tests passing after this commit (62 total → 46 pass, 16 fail):
- test_playing_video_seek_requested_transitions_and_pins
- test_seeking_video_completed_returns_to_playing
- test_seeking_video_seek_requested_replaces_target
- test_invariant_seek_pin_uses_compute_slider_display_ms (RACE FIX!)
Phase A (16 tests) still green.
Tests still failing (16, scheduled for commits 7-11):
- F11 round-trip (commit 7)
- Persistent viewport / drift events (commit 8)
- mute/volume/loop persistence events (commit 9)
- DisplayingImage content arrived branch (commit 10)
- Closing transitions (commit 10)
Test cases for commit 7 (Fullscreen flag + F11 round-trip):
- dispatch FullscreenToggled in any media state, assert flag flipped
- F11 enter snapshots viewport into pre_fullscreen_viewport
- F11 exit restores viewport from pre_fullscreen_viewport