From 2cdab574ca79a12ddc19b2de7b06bc1e138b6c92 Mon Sep 17 00:00:00 2001 From: pax Date: Sun, 12 Apr 2026 22:18:21 -0500 Subject: [PATCH] popout: refit window with correct aspect when leaving tiled layout behavior change: navigating to a different-aspect image/video while tiled then un-tiling now resizes the floating window to the current content's aspect and resets the image viewer zoom. Previously the window restored to the old floating geometry with the wrong aspect locked. Stash content dims on the tiled early-return in _fit_to_content, then detect the tiled-to-floating transition via a debounced resizeEvent check that re-runs the fit. --- booru_viewer/gui/popout/window.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/booru_viewer/gui/popout/window.py b/booru_viewer/gui/popout/window.py index af6551f..f75c55a 100644 --- a/booru_viewer/gui/popout/window.py +++ b/booru_viewer/gui/popout/window.py @@ -333,6 +333,15 @@ class FullscreenPreview(QMainWindow): # Qt fallback path) skip viewport updates triggered by our own # programmatic geometry changes. self._applying_dispatch: bool = False + # Stashed content dims from the tiled early-return in + # _fit_to_content. When the user un-tiles the window, resizeEvent + # fires — the debounce timer re-runs _fit_to_content with these + # dims so the floating window gets the correct aspect ratio. + self._tiled_pending_content: tuple[int, int] | None = None + self._untile_refit_timer = QTimer(self) + self._untile_refit_timer.setSingleShot(True) + self._untile_refit_timer.setInterval(50) + self._untile_refit_timer.timeout.connect(self._check_untile_refit) # Last known windowed geometry — captured on entering fullscreen so # F11 → windowed can land back on the same spot. Seeded from saved # geometry when the popout opens windowed, so even an immediate @@ -1315,7 +1324,9 @@ class FullscreenPreview(QMainWindow): floating = None if floating is False: hyprland.resize(self.windowTitle(), 0, 0) # tiled: just set keep_aspect_ratio + self._tiled_pending_content = (content_w, content_h) return + self._tiled_pending_content = None aspect = content_w / content_h screen = self.screen() if screen is None: @@ -1380,6 +1391,18 @@ class FullscreenPreview(QMainWindow): self._pending_position_restore = None self._pending_size = None + def _check_untile_refit(self) -> None: + """Debounced callback: re-run fit if we left tiled under new content.""" + if self._tiled_pending_content is not None: + cw, ch = self._tiled_pending_content + self._fit_to_content(cw, ch) + # Reset image zoom/offset so the image fits the new window + # geometry cleanly — the viewer's state is stale from the + # tiled layout. + if self._stack.currentIndex() == 0: + self._viewer._fit_to_view() + self._viewer.update() + def _show_overlay(self) -> None: """Show toolbar and video controls, restart auto-hide timer.""" if not self._ui_visible: @@ -1646,6 +1669,8 @@ class FullscreenPreview(QMainWindow): # position source on Wayland). import os if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"): + if self._tiled_pending_content is not None: + self._untile_refit_timer.start() return if self._applying_dispatch or self.isFullScreen(): return