diff options
author | Florian Bruhin <me@the-compiler.org> | 2020-06-23 12:02:53 +0200 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2020-06-23 12:07:47 +0200 |
commit | c09e013e81842f123382e306ed802125882bd1c1 (patch) | |
tree | e4b16deca92852f1b005f08035f92721fc2038c7 | |
parent | fc2f18947eb534cf1fbad44c0afe0c21a3612045 (diff) | |
download | qutebrowser-c09e013e81842f123382e306ed802125882bd1c1.tar.gz qutebrowser-c09e013e81842f123382e306ed802125882bd1c1.zip |
Work around devtools window detaching bug
Recreate the inspector when it was shown inline and gets detached to work
around an issue where QtWebEngine (for some odd reason) doesn't show a window
at all.
See #5540
-rw-r--r-- | qutebrowser/browser/browsertab.py | 11 | ||||
-rw-r--r-- | qutebrowser/browser/inspector.py | 32 | ||||
-rw-r--r-- | qutebrowser/browser/webengine/webengineinspector.py | 9 | ||||
-rw-r--r-- | tests/unit/browser/test_inspector.py | 21 |
4 files changed, 62 insertions, 11 deletions
diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 4d5511df4..b847986e2 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -846,6 +846,16 @@ class AbstractTabPrivate: """ raise NotImplementedError + def _recreate_inspector(self) -> None: + """Recreate the inspector when detached to a window. + + This is needed to circumvent a QtWebEngine bug (which wasn't + investigated further) which sometimes results in the window not + appearing anymore. + """ + self._tab.data.inspector = None + self.toggle_inspector(inspector.Position.window) + def toggle_inspector(self, position: inspector.Position) -> None: """Show/hide (and if needed, create) the web inspector for this tab.""" tabdata = self._tab.data @@ -854,6 +864,7 @@ class AbstractTabPrivate: splitter=tabdata.splitter, win_id=self._tab.win_id) self._tab.shutting_down.connect(tabdata.inspector.shutdown) + tabdata.inspector.recreate.connect(self._recreate_inspector) tabdata.inspector.inspect(self._widget.page()) tabdata.inspector.set_position(position) diff --git a/qutebrowser/browser/inspector.py b/qutebrowser/browser/inspector.py index dd12f0a38..e089438be 100644 --- a/qutebrowser/browser/inspector.py +++ b/qutebrowser/browser/inspector.py @@ -25,7 +25,7 @@ import typing import enum from PyQt5.QtWidgets import QWidget -from PyQt5.QtCore import pyqtSlot, QObject, QEvent +from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent from PyQt5.QtGui import QCloseEvent from qutebrowser.browser import eventfilter @@ -110,8 +110,13 @@ class AbstractWebInspector(QWidget): Attributes: _position: position of the inspector (right/left/top/bottom/window) _splitter: InspectorSplitter where the inspector can be placed. + + Signals: + recreate: Emitted when the inspector should be recreated. """ + recreate = pyqtSignal() + def __init__(self, splitter: 'miscwidgets.InspectorSplitter', win_id: int, parent: QWidget = None) -> None: @@ -141,6 +146,16 @@ class AbstractWebInspector(QWidget): """Save the last position the inspector was in.""" configfiles.state['inspector']['position'] = position.name + def _needs_recreate(self) -> bool: + """Whether the inspector needs recreation when detaching to a window. + + This is done due to an unknown QtWebEngine bug which sometimes prevents + inspector windows from showing up. + + Needs to be overridden by subclasses. + """ + return False + def set_position(self, position: typing.Optional[Position]) -> None: """Set the position of the inspector. @@ -155,14 +170,21 @@ class AbstractWebInspector(QWidget): self.toggle() return - self._position = position - - if position == Position.window: - self.setParent(None) + if (position == Position.window and + self._position is not None and + self._needs_recreate()): + # Detaching to window + self.recreate.emit() + self.shutdown() + return + elif position == Position.window: + self.setParent(None) # type: ignore[call-overload] self._load_state_geometry() else: self._splitter.set_inspector(self, position) + self._position = position + self._widget.show() self.show() diff --git a/qutebrowser/browser/webengine/webengineinspector.py b/qutebrowser/browser/webengine/webengineinspector.py index df038abea..f84415c65 100644 --- a/qutebrowser/browser/webengine/webengineinspector.py +++ b/qutebrowser/browser/webengine/webengineinspector.py @@ -30,7 +30,7 @@ from PyQt5.QtWidgets import QWidget from qutebrowser.browser import inspector from qutebrowser.browser.webengine import webenginesettings from qutebrowser.misc import miscwidgets -from qutebrowser.utils import version +from qutebrowser.utils import version, qtutils class WebEngineInspectorView(QWebEngineView): @@ -125,3 +125,10 @@ class WebEngineInspector(inspector.AbstractWebInspector): inspector_page = self._widget.page() inspector_page.setInspectedPage(page) self._settings.update_for_url(inspector_page.requestedUrl()) + + def _needs_recreate(self) -> bool: + """Recreate the inspector when detaching to a window. + + WORKAROUND for what's likely an unknown Qt bug. + """ + return qtutils.version_check('5.12') diff --git a/tests/unit/browser/test_inspector.py b/tests/unit/browser/test_inspector.py index 1f4763608..c7e255973 100644 --- a/tests/unit/browser/test_inspector.py +++ b/tests/unit/browser/test_inspector.py @@ -35,10 +35,14 @@ class FakeInspector(inspector.AbstractWebInspector): super().__init__(splitter, win_id, parent) self._set_widget(inspector_widget) self._inspected_page = None + self.needs_recreate = False def inspect(self, page): self._inspected_page = page + def _needs_recreate(self): + return self.needs_recreate + @pytest.fixture def webview_widget(blue_widget): @@ -126,8 +130,10 @@ def test_position_loading(config_value, expected, @pytest.mark.parametrize('hidden_again', [True, False]) -def test_detach_after_toggling(hidden_again, fake_inspector, inspector_widget, - splitter, qtbot): +@pytest.mark.parametrize('needs_recreate', [True, False]) +def test_detach_after_toggling(hidden_again, needs_recreate, + fake_inspector, inspector_widget, splitter, + qtbot): """Make sure we can still detach into a window after showing inline.""" fake_inspector.set_position(inspector.Position.right) splitter.show() @@ -137,6 +143,11 @@ def test_detach_after_toggling(hidden_again, fake_inspector, inspector_widget, fake_inspector.toggle() assert not inspector_widget.isVisible() - fake_inspector.set_position(inspector.Position.window) - - assert fake_inspector.isVisible() and fake_inspector.isWindow() + if needs_recreate: + fake_inspector.needs_recreate = True + with qtbot.waitSignal(fake_inspector.recreate): + fake_inspector.set_position(inspector.Position.window) + else: + with qtbot.assertNotEmitted(fake_inspector.recreate): + fake_inspector.set_position(inspector.Position.window) + assert fake_inspector.isVisible() and fake_inspector.isWindow() |