summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2020-06-23 12:02:53 +0200
committerFlorian Bruhin <me@the-compiler.org>2020-06-23 12:07:47 +0200
commitc09e013e81842f123382e306ed802125882bd1c1 (patch)
treee4b16deca92852f1b005f08035f92721fc2038c7
parentfc2f18947eb534cf1fbad44c0afe0c21a3612045 (diff)
downloadqutebrowser-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.py11
-rw-r--r--qutebrowser/browser/inspector.py32
-rw-r--r--qutebrowser/browser/webengine/webengineinspector.py9
-rw-r--r--tests/unit/browser/test_inspector.py21
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()