From 6f21accfaecaa7fbde585eaa88219844ae11ea24 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 10 Oct 2025 20:15:12 +0200 Subject: [PATCH] Fix focus handling when closing hidden statusbar From knezi's analysis in #8722: The problem was that in Qt, slots are called in the order of connection, so even though there's a code that tries to set up the focus correctly, it's run after the cmd widget is hidden and hence the focus is already moved and it doesn't work as expected. Follow-up for #2236/#8024. Fixes #8223. Supersedes and closes #8722. Also see #8625 and #8174 (which are not fixed by this). --- doc/changelog.asciidoc | 5 ++++- qutebrowser/mainwindow/mainwindow.py | 2 +- qutebrowser/mainwindow/statusbar/bar.py | 6 ++++++ tests/end2end/features/scroll.feature | 8 ++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 9e519900d..53515cd06 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -49,7 +49,10 @@ Fixed (#8674). - Fixed exception when closing a qutebrowser window while a download prompt is still open. -- Fixed crash with Qt 6.10 (and possibly older Qt versions) when navigating from a `qute://` page to a web page, e.g. when searching on `qute://start` +- Fixed crash with Qt 6.10 (and possibly older Qt versions) when navigating + from a `qute://` page to a web page, e.g. when searching on `qute://start` +- Hopefully proper fix for some web pages jumping to the top when the statusbar + is hidden. (#8223) [[v3.5.1]] v3.5.1 (2025-06-05) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 6e6821612..dcbaf589d 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -562,7 +562,7 @@ class MainWindow(QWidget): self._completion.on_clear_completion_selection) self.status.cmd.hide_completion.connect( self._completion.hide) - self.status.cmd.hide_cmd.connect(self.tabbed_browser.on_release_focus) + self.status.release_focus.connect(self.tabbed_browser.on_release_focus) def _set_decoration(self, hidden): """Set the visibility of the window decoration via Qt.""" diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py index b628a03cc..4b72ad59f 100644 --- a/qutebrowser/mainwindow/statusbar/bar.py +++ b/qutebrowser/mainwindow/statusbar/bar.py @@ -140,10 +140,12 @@ class StatusBar(QWidget): moved: Emitted when the statusbar has moved, so the completion widget can move to the right position. arg: The new position. + release_focus: Emitted just before the statusbar is hidden. """ resized = pyqtSignal('QRect') moved = pyqtSignal('QPoint') + release_focus = pyqtSignal() STYLESHEET = _generate_stylesheet() @@ -284,16 +286,20 @@ class StatusBar(QWidget): strategy = config.val.statusbar.show tab = self._current_tab() if tab is not None and tab.data.fullscreen: + self.release_focus.emit() self.hide() elif strategy == 'never': + self.release_focus.emit() self.hide() elif strategy == 'in-mode': try: mode_manager = modeman.instance(self._win_id) except modeman.UnavailableError: + self.release_focus.emit() self.hide() else: if mode_manager.mode == usertypes.KeyMode.normal: + self.release_focus.emit() self.hide() else: self.show() diff --git a/tests/end2end/features/scroll.feature b/tests/end2end/features/scroll.feature index 042f09735..89fb1231e 100644 --- a/tests/end2end/features/scroll.feature +++ b/tests/end2end/features/scroll.feature @@ -339,3 +339,11 @@ Feature: Scrolling And I run :tab-next And I run :jseval --world main checkAnchor() Then "[*] [PASS] Positions equal: *" should be logged + + Scenario: Showing/hiding statusbar (#2236, #8223) + When I set statusbar.show to never + And I run :scroll-to-perc 100 + And I wait until the scroll position changed + And I run :cmd-set-text / + And I run :fake-key -g + Then "Scroll position changed to Py*.QtCore.QPoint()" should not be logged