popout/window: reorder stack switch, drop stop, fix close position

behavior change: _apply_load_video now switches the stack to the video
surface BEFORE calling play_file so mpv's first frame lands on a visible
widget instead of a cleared image viewer. Removes the redundant stop()
call — loadfile("replace") atomically replaces the current file.

Also fixes video position not surviving popout close: StopMedia (part of
CloseRequested effects) destroyed mpv's time_pos before get_video_state
could read it. Now closeEvent snapshots position_ms before dispatching
CloseRequested, and get_video_state returns the snapshot.
This commit is contained in:
pax 2026-04-09 20:51:59 -05:00
parent 510b423327
commit 8c5c2e37d3

View File

@ -592,15 +592,15 @@ class FullscreenPreview(QMainWindow):
def _apply_load_video(self, e: LoadVideo) -> None: def _apply_load_video(self, e: LoadVideo) -> None:
"""Apply LoadVideo effect — hand the path or URL to mpv. """Apply LoadVideo effect — hand the path or URL to mpv.
Mirrors the legacy `set_media` body's video branch. play_file Stack switch happens FIRST so the video surface is visible
already handles the http(s) referer detection internally the moment mpv produces its first frame. clear() releases the
(see media/video_player.py:343-347), so the adapter doesn't previous image (now hidden behind the video surface). No
need to thread the referer through. explicit stop() loadfile("replace") atomically replaces the
current file without the eof side-effect of command('stop').
""" """
self._viewer.clear()
self._video.stop()
self._video.play_file(e.path, e.info)
self._stack.setCurrentIndex(1) self._stack.setCurrentIndex(1)
self._viewer.clear()
self._video.play_file(e.path, e.info)
def _apply_stop_media(self) -> None: def _apply_stop_media(self) -> None:
"""Apply StopMedia effect — clear both surfaces. """Apply StopMedia effect — clear both surfaces.
@ -719,7 +719,7 @@ class FullscreenPreview(QMainWindow):
"mute": self._video.is_muted, "mute": self._video.is_muted,
"autoplay": self._video.autoplay, "autoplay": self._video.autoplay,
"loop_state": self._video.loop_state, "loop_state": self._video.loop_state,
"position_ms": ( "position_ms": getattr(self, "_close_position_ms", None) or (
self._video.get_position_ms() self._video.get_position_ms()
if self.is_video_active() if self.is_video_active()
else 0 else 0
@ -1558,6 +1558,14 @@ class FullscreenPreview(QMainWindow):
else: else:
FullscreenPreview._saved_geometry = self.frameGeometry() FullscreenPreview._saved_geometry = self.frameGeometry()
QApplication.instance().removeEventFilter(self) QApplication.instance().removeEventFilter(self)
# Snapshot video position BEFORE StopMedia destroys it.
# _on_fullscreen_closed reads this via get_video_state() to
# seek the embedded preview to the same position.
self._close_position_ms = (
self._video.get_position_ms()
if self.is_video_active()
else 0
)
# NOW dispatch + apply CloseRequested. Effects are # NOW dispatch + apply CloseRequested. Effects are
# [StopMedia, EmitClosed]. StopMedia clears the media stack; # [StopMedia, EmitClosed]. StopMedia clears the media stack;
# EmitClosed emits self.closed which triggers main_window's # EmitClosed emits self.closed which triggers main_window's