summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/changelog.asciidoc2
-rw-r--r--qutebrowser/mainwindow/mainwindow.py3
-rw-r--r--qutebrowser/mainwindow/prompt.py17
-rw-r--r--qutebrowser/mainwindow/statusbar/bar.py12
-rw-r--r--qutebrowser/mainwindow/tabbedbrowser.py34
5 files changed, 50 insertions, 18 deletions
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 98a10ad48..cbf4dc0de 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -49,6 +49,8 @@ Changed
Fixed
~~~~~
+- Some web pages jumping to the top when the statusbar is hidden or (with
+ v3.0.x) when a prompt is hidden.
- Compatibility with PDF.js v4
- Added an elaborate workaround for a bug in QtWebEngine 6.6.0 causing crashes
on Google Mail/Meet/Chat, and a bug in QtWebEngine 6.5.0/.1/.2 causing crashes
diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py
index da951da1b..e39ac4f9a 100644
--- a/qutebrowser/mainwindow/mainwindow.py
+++ b/qutebrowser/mainwindow/mainwindow.py
@@ -483,6 +483,8 @@ class MainWindow(QWidget):
mode_manager = modeman.instance(self.win_id)
# misc
+ self._prompt_container.release_focus.connect(
+ self.tabbed_browser.on_release_focus)
self.tabbed_browser.close_window.connect(self.close)
mode_manager.entered.connect(hints.on_mode_entered)
@@ -559,6 +561,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)
def _set_decoration(self, hidden):
"""Set the visibility of the window decoration via Qt."""
diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py
index 84b6cd18f..92d3cc2ea 100644
--- a/qutebrowser/mainwindow/prompt.py
+++ b/qutebrowser/mainwindow/prompt.py
@@ -202,6 +202,7 @@ class PromptQueue(QObject):
log.prompt.debug("Left mode {}, hiding {}".format(
mode, self._question))
self.show_prompts.emit(None)
+
if self._question.answer is None and not self._question.is_aborted:
log.prompt.debug("Cancelling {} because {} was left".format(
self._question, mode))
@@ -261,6 +262,7 @@ class PromptContainer(QWidget):
}
"""
update_geometry = pyqtSignal()
+ release_focus = pyqtSignal()
def __init__(self, win_id, parent=None):
super().__init__(parent)
@@ -287,19 +289,26 @@ class PromptContainer(QWidget):
Args:
question: A Question object or None.
"""
- item = self._layout.takeAt(0)
- if item is not None:
+ item = qtutils.add_optional(self._layout.takeAt(0))
+ if item is None:
+ widget = None
+ else:
widget = item.widget()
assert widget is not None
- log.prompt.debug("Deleting old prompt {}".format(widget))
- widget.hide()
+ log.prompt.debug(f"Deleting old prompt {widget!r}")
widget.deleteLater()
if question is None:
log.prompt.debug("No prompts left, hiding prompt container.")
self._prompt = None
+ self.release_focus.emit()
self.hide()
return
+ elif widget is not None:
+ # We have more prompts to show, just hide the old one.
+ # This needs to happen *after* we possibly hid the entire prompt container,
+ # so that keyboard focus can be reassigned properly via release_focus.
+ widget.hide()
classes = {
usertypes.PromptMode.yesno: YesNoPrompt,
diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py
index a2652a69a..b628a03cc 100644
--- a/qutebrowser/mainwindow/statusbar/bar.py
+++ b/qutebrowser/mainwindow/statusbar/bar.py
@@ -377,9 +377,11 @@ class StatusBar(QWidget):
@pyqtSlot(usertypes.KeyMode)
def on_mode_entered(self, mode):
"""Mark certain modes in the commandline."""
- mode_manager = modeman.instance(self._win_id)
- if config.val.statusbar.show == 'in-mode':
+ if config.val.statusbar.show == 'in-mode' and mode != usertypes.KeyMode.command:
+ # Showing in command mode is handled via _show_cmd_widget()
self.show()
+
+ mode_manager = modeman.instance(self._win_id)
if mode_manager.parsers[mode].passthrough:
self._set_mode_text(mode.name)
if mode in [usertypes.KeyMode.insert,
@@ -393,9 +395,11 @@ class StatusBar(QWidget):
@pyqtSlot(usertypes.KeyMode, usertypes.KeyMode)
def on_mode_left(self, old_mode, new_mode):
"""Clear marked mode."""
- mode_manager = modeman.instance(self._win_id)
- if config.val.statusbar.show == 'in-mode':
+ if config.val.statusbar.show == 'in-mode' and old_mode != usertypes.KeyMode.command:
+ # Hiding in command mode is handled via _hide_cmd_widget()
self.hide()
+
+ mode_manager = modeman.instance(self._win_id)
if mode_manager.parsers[old_mode].passthrough:
if mode_manager.parsers[new_mode].passthrough:
self._set_mode_text(new_mode.name)
diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py
index 98cb67cb2..28f32c4fd 100644
--- a/qutebrowser/mainwindow/tabbedbrowser.py
+++ b/qutebrowser/mainwindow/tabbedbrowser.py
@@ -858,20 +858,34 @@ class TabbedBrowser(QWidget):
assert isinstance(tab, browsertab.AbstractTab), tab
tab.data.input_mode = mode
- @pyqtSlot(usertypes.KeyMode)
- def on_mode_left(self, mode):
- """Give focus to current tab if command mode was left."""
+ @pyqtSlot()
+ def on_release_focus(self):
+ """Give keyboard focus to the current tab when requested by statusbar/prompt.
+
+ This gets emitted by the statusbar and prompt container before they call .hide()
+ on themselves, with the idea that we can explicitly reassign the focus,
+ instead of Qt implicitly calling its QWidget::focusNextPrevChild() method,
+ finding a new widget to give keyboard focus to.
+ """
+ widget = qtutils.add_optional(self.widget.currentWidget())
+ if widget is None:
+ return
+
+ log.modes.debug(f"Focus released, focusing {widget!r}")
+ widget.setFocus()
+
+ @pyqtSlot()
+ def on_mode_left(self):
+ """Save input mode for restoring if needed."""
+ if config.val.tabs.mode_on_change != 'restore':
+ return
+
widget = qtutils.add_optional(self.widget.currentWidget())
if widget is None:
return
- if mode in [usertypes.KeyMode.command] + modeman.PROMPT_MODES:
- log.modes.debug("Left status-input mode, focusing {!r}".format(
- widget))
- widget.setFocus()
- if config.val.tabs.mode_on_change == 'restore':
- assert isinstance(widget, browsertab.AbstractTab), widget
- widget.data.input_mode = usertypes.KeyMode.normal
+ assert isinstance(widget, browsertab.AbstractTab), widget
+ widget.data.input_mode = usertypes.KeyMode.normal
@pyqtSlot(int)
def _on_current_changed(self, idx):