From 0f01027570934821678b6a41a768480caa63b625 Mon Sep 17 00:00:00 2001 From: toofar Date: Wed, 15 Mar 2023 16:40:54 +1300 Subject: Override QTabBar text eilding The fontMetrics().elidedText(...) call is copied from the base QTabBar implementation of initStyleOption(). But here we are calling it with a text_rect from our custom style class. In Qt6 QStyleSheetStyle no longer calls into our custom Style class for the SE_TabBarTabText SubElement so it ends up getting a text width from QCommonStyle which is wrong for vertical tabs (`QCommonStylePrivate::tabLayout()` seems to transpose the rect, maybe it thinks vertical tabs should have the text running vertically too). Also resolves the issue that when tabs.title.alignment is set to center the leftmost character or two of titles wouldn't be visible when tabs where small enough that the text got elided. Not 100% sure why but presumably it wasn't picking up the padding etc logic in our custom style class. In the test I don't test the exact elided text when we don't have much room because it might differ based on what monospace font is picked up in the tests. So the amount elided might change. Also in the not-elided one I'm only testing endswith() because the index should be at the start of the string which I don't really care about. Fixes: #7313 Fixes: #7205 --- qutebrowser/mainwindow/tabwidget.py | 26 +++++++++++++++++++++++- tests/unit/mainwindow/test_tabwidget.py | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 5e4f519fa..580da64b4 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -405,7 +405,8 @@ class TabBar(QTabBar): def __init__(self, win_id, parent=None): super().__init__(parent) self._win_id = win_id - self.setStyle(TabBarStyle()) + self._our_style = TabBarStyle() + self.setStyle(self._our_style) self.vertical = False self._auto_hide_timer = QTimer() self._auto_hide_timer.setSingleShot(True) @@ -696,6 +697,29 @@ class TabBar(QTabBar): qtutils.ensure_valid(size) return size + def initStyleOption(self, opt, idx): + """Override QTabBar.initStyleOption(). + + Used to calculate styling clues from a widget for the GUI layer. + """ + super().initStyleOption(opt, idx) + + # Re-do the text elision that the base QTabBar does, but using a text + # rectangle computed by out TabBarStyle. With Qt6 the base class ends + # up using QCommonStyle directly for that which has a different opinon + # of how vertical tabs should work. + text_rect = self._our_style.subElementRect( + QStyle.SubElement.SE_TabBarTabText, + opt, + self, + ) + opt.text = self.fontMetrics().elidedText( + self.tabText(idx), + self.elideMode(), + text_rect.width(), + Qt.TextFlag.TextShowMnemonic, + ) + def paintEvent(self, event): """Override paintEvent to draw the tabs like we want to.""" p = QStylePainter(self) diff --git a/tests/unit/mainwindow/test_tabwidget.py b/tests/unit/mainwindow/test_tabwidget.py index db300d7a6..d6289dac6 100644 --- a/tests/unit/mainwindow/test_tabwidget.py +++ b/tests/unit/mainwindow/test_tabwidget.py @@ -23,8 +23,9 @@ import functools import pytest -from qutebrowser.qt.gui import QIcon, QPixmap +from unittest.mock import Mock +from qutebrowser.qt.gui import QIcon, QPixmap from qutebrowser.mainwindow import tabwidget from qutebrowser.utils import usertypes @@ -71,6 +72,38 @@ class TestTabWidget: assert first_size == widget.tabBar().tabSizeHint(i) assert first_size_min == widget.tabBar().minimumTabSizeHint(i) + @pytest.fixture + def paint_spy(self, monkeypatch): + spy = Mock() + monkeypatch.setattr(tabwidget, "QStylePainter", spy) + return spy + + def test_tab_text_edlided_for_narrow_tabs(self, paint_spy, widget, fake_web_tab): + """Make sure text gets elided for narrow tabs.""" + widget.setMaximumWidth(100) + widget.addTab(fake_web_tab(), "one two three four") + + fake_paint_event = Mock() + fake_paint_event.region.return_value.intersects.return_value = True + widget.tabBar().paintEvent(fake_paint_event) + + style_opt = paint_spy.return_value.drawControl.call_args_list[0][0][1] + assert len(style_opt.text) < len(widget.tabBar().tabText(0)) + assert style_opt.text.endswith("…") + assert len(style_opt.text) > len("…") + + def test_tab_text_not_edlided_for_wide_tabs(self, paint_spy, widget, fake_web_tab): + """Make sure text doesn't get elided for wide tabs.""" + widget.setMaximumWidth(200) + widget.addTab(fake_web_tab(), "one two three four") + + fake_paint_event = Mock() + fake_paint_event.region.return_value.intersects.return_value = True + widget.tabBar().paintEvent(fake_paint_event) + + style_opt = paint_spy.return_value.drawControl.call_args_list[0][0][1] + assert style_opt.text.endswith(widget.tabBar().tabText(0)) + @pytest.mark.parametrize("shrink_pinned", [True, False]) @pytest.mark.parametrize("vertical", [True, False]) def test_pinned_size(self, widget, fake_web_tab, config_stub, -- cgit v1.2.3-54-g00ecf From 2d45f6f00249b0450a29b430799500abe914aab4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 15 Mar 2023 22:04:42 +0100 Subject: tests: Ignore more Qt 6.5 / debug build messages See #7624 --- pytest.ini | 3 ++ tests/end2end/fixtures/quteprocess.py | 65 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/pytest.ini b/pytest.ini index ab46bd391..3d97e9685 100644 --- a/pytest.ini +++ b/pytest.ini @@ -54,6 +54,9 @@ qt_log_ignore = # tests/unit/commands/test_userscripts.py::test_killed_command # on Windows ^QProcess: Destroyed while process .* is still running\. + # Qt 6.5 debug build + # FIXME:qt6 is this something we should/can fix properly? + ^QObject::connect: Connecting from COMPAT signal \(QSocketNotifier::activated\(int\)\)$ xfail_strict = true filterwarnings = error diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py index 5745b5356..e656b265d 100644 --- a/tests/end2end/fixtures/quteprocess.py +++ b/tests/end2end/fixtures/quteprocess.py @@ -61,6 +61,18 @@ def is_ignored_lowlevel_message(message): # Qt 6.4, from certificate error below, but on separate lines '----- Certificate i=0 (*,CN=localhost,O=qutebrowser test certificate) -----', 'ERROR: No matching issuer found', + + # Qt 6.5 debug, overflow/linebreak from a JS message... + # IGNORED: [678403:678403:0315/203342.008878:INFO:CONSOLE(65)] "Refused + # to apply inline style because it violates the following Content + # Security Policy directive: "default-src none". Either the + # 'unsafe-inline' keyword, a hash + # ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce + # ('nonce-...') is required to enable inline execution. Note also that + # 'style-src' was not explicitly set, so 'default-src' is used as a + # fallback. + # INVALID: ", source: userscript:_qute_stylesheet (65) + '", source: userscript:_qute_stylesheet (65)', ] return any(testutils.pattern_match(pattern=pattern, value=message) for pattern in ignored_messages) @@ -130,6 +142,59 @@ def is_ignored_chromium_message(line): 'CertVerifyProcBuiltin for localhost failed:', # [320667:320667:1124/135621.718232:ERROR:interface_endpoint_client.cc(687)] Message 4 rejected by interface blink.mojom.WidgetHost 'Message 4 rejected by interface blink.mojom.WidgetHost', + + + # Qt 5.15.1 debug build (Chromium 83) + # '[314297:7:0929/214605.491958:ERROR:context_provider_command_buffer.cc(145)] + # GpuChannelHost failed to create command buffer.' + # Still present on Qt 6.5 + 'GpuChannelHost failed to create command buffer.', + + # Qt 6.5 debug build + # [640812:640865:0315/200415.708148:WARNING:important_file_writer.cc(185)] + # Failed to create temporary file to update + # /tmp/qutebrowser-basedir-3kvto2eq/data/webengine/user_prefs.json: No + # such file or directory (2) + # [640812:640864:0315/200415.715398:WARNING:important_file_writer.cc(185)] + # Failed to create temporary file to update + # /tmp/qutebrowser-basedir-3kvto2eq/data/webengine/Network Persistent + # State: No such file or directory (2) + 'Failed to create temporary file to update *user_prefs.json: No such file or directory (2)', + 'Failed to create temporary file to update *Network Persistent State: No such file or directory (2)', + + # Qt 6.5 debug build + # [645145:645198:0315/200704.324733:WARNING:simple_synchronous_entry.cc(1438)] + "Could not open platform files for entry.", + + # Qt 6.5 debug build + # [664320:664320:0315/202235.943899:ERROR:node_channel.cc(861)] + # Dropping message on closed channel. + "Dropping message on closed channel.", + + # Qt 6.5 debug build + # tests/end2end/features/test_misc_bdd.py::test_webrtc_renderer_process_crash + # [679056:14:0315/203418.631075:WARNING:media_session.cc(949)] RED + # codec red is missing an associated payload type. + "RED codec red is missing an associated payload type.", + + # Qt 6.5 debug build + # tests/end2end/features/test_javascript_bdd.py::test_error_pages_without_js_enabled + # and others using internal URL schemes? + # [677785:1:0315/203308.328104:ERROR:html_media_element.cc(4874)] + # SetError: {code=4, message="MEDIA_ELEMENT_ERROR: Media load rejected + # by URL safety check"} + 'SetError: {code=4, message="MEDIA_ELEMENT_ERROR: Media load rejected by URL safety check"}', + + # Qt 6.5 debug build + # [714871:715010:0315/205751.155681:ERROR:surface_manager.cc(419)] + # Old/orphaned temporary reference to SurfaceId(FrameSinkId[](14, 3), + # LocalSurfaceId(3, 1, 5D04...)) + "Old/orphaned temporary reference to SurfaceId(FrameSinkId[](*, *), LocalSurfaceId(*, *, *...))", + + # Qt 6.5 debug build + # [758352:758352:0315/212511.747791:WARNING:render_widget_host_impl.cc(280)] + # Input request on unbound interface + "Input request on unbound interface", ] return any(testutils.pattern_match(pattern=pattern, value=message) for pattern in ignored_messages) -- cgit v1.2.3-54-g00ecf From 9b7348a880f7a4473ad8adec8b600fc8572299f2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 16:54:44 +0100 Subject: Qt 6.5: Always use new dark mode values for newer Qt's I don't quite understand why the value changed from #00000 to #121212 there with Qt 6.3, but it looks like the change is here to stay. Instead of keeping #000000 the default and adding an override for every new Qt release, let's just switch over and add an override for the old versions (5.15 and 6.2), so this won't break again for every new release. See #7624 --- tests/end2end/test_invocations.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 3730c887f..7951d52ff 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -663,20 +663,20 @@ def test_cookies_store(quteproc_new, request, short_tmpdir, store): 'blank', 'lightness-hsl', { - # FIXME:qt6 Why #121212 rather than #000000? - ('6.4', None): testutils.Color(18, 18, 18), - ('6.3', None): testutils.Color(18, 18, 18), - (None, None): testutils.Color(0, 0, 0), + ('5.15', None): testutils.Color(0, 0, 0), + ('6.2', None): testutils.Color(0, 0, 0), + # Qt 6.3+ (why #121212 rather than #000000?) + (None, None): testutils.Color(18, 18, 18), } ), ( 'blank', 'brightness-rgb', { - # FIXME:qt6 Why #121212 rather than #000000? - ('6.4', None): testutils.Color(18, 18, 18), - ('6.3', None): testutils.Color(18, 18, 18), - (None, None): testutils.Color(0, 0, 0) + ('5.15', None): testutils.Color(0, 0, 0), + ('6.2', None): testutils.Color(0, 0, 0), + # Qt 6.3+ (why #121212 rather than #000000?) + (None, None): testutils.Color(18, 18, 18), } ), -- cgit v1.2.3-54-g00ecf From e3d5367493a2b98795ebf22b450bf25dab721b00 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 17:09:06 +0100 Subject: Update settings docs --- doc/help/settings.asciidoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 29cde3b0f..0967c069b 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -2779,8 +2779,6 @@ Valid values: * +js-whatsapp-web+ * +js-discord+ * +js-string-replaceall+ - * +js-globalthis+ - * +js-object-fromentries+ * +js-array-at+ * +misc-krunker+ * +misc-mathml-darkmode+ -- cgit v1.2.3-54-g00ecf From ab7245732e04c86aabc5497b279c3a28fe945836 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 17:13:37 +0100 Subject: scripts: Patch relative links for correct doc generation In doc/help/index.asciidoc, we have links like this: * link:../quickstart{outfilesuffix}[Quick start guide] That is correct in e.g. the GitHub file structure, as those files are stored in e.g. doc/quickstart.asciidoc indeed. It's *no* longer true when we view the built files via qute://help, however: There, this turns into a flat file structure, with those pages being at qute://help/index.html and qute://help/quickstart.html, respectively. It looks like QtWebEngine < 6.5 did just ignore the and pointed from qute://help/index.html to qute://help/quickstart.html anyways, weirdly. With QtWebEngine 6.5, however, this is now interpreted as a link pointing to qute://quickstart.html instead, which is clearly wrong. Until we have a less messy doc generation (probably as part of #345), let's just patch the link to be correct. See #7624 --- scripts/asciidoc2html.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/asciidoc2html.py b/scripts/asciidoc2html.py index 6f3b170af..a7816e132 100755 --- a/scripts/asciidoc2html.py +++ b/scripts/asciidoc2html.py @@ -84,12 +84,15 @@ class AsciiDoc: dst = DOC_DIR / (src.stem + ".html") files.append((src, dst)) - # patch image links to use local copy replacements = [ + # patch image links to use local copy ("https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/cheatsheet-big.png", "qute://help/img/cheatsheet-big.png"), ("https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/cheatsheet-small.png", - "qute://help/img/cheatsheet-small.png") + "qute://help/img/cheatsheet-small.png"), + + # patch relative links to work with qute://help flat structure + ("link:../", "link:"), ] asciidoc_args = ['-a', 'source-highlighter=pygments'] -- cgit v1.2.3-54-g00ecf From 9cb54b2099a0e884df38e9de24d58b9bef195ca1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 18:07:13 +0100 Subject: Qt 6.5: Skip elf tests The ELF file structure changed in a way that it seems impossible to support reliably. Given that we have an API to get the version nowadays, let's not bother with this. We might need to figure this out for PySide6 support, but not now. See #7624, #3625 --- tests/unit/misc/test_elf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/unit/misc/test_elf.py b/tests/unit/misc/test_elf.py index 8a89d11fb..41a5e273d 100644 --- a/tests/unit/misc/test_elf.py +++ b/tests/unit/misc/test_elf.py @@ -47,7 +47,7 @@ def test_format_sizes(fmt, expected): @pytest.mark.skipif(not utils.is_linux, reason="Needs Linux") -def test_result(qapp, caplog): +def test_result(webengine_versions, qapp, caplog): """Test the real result of ELF parsing. NOTE: If you're a distribution packager (or contributor) and see this test failing, @@ -60,6 +60,10 @@ def test_result(qapp, caplog): pytest.importorskip('qutebrowser.qt.webenginecore') versions = elf.parse_webenginecore() + if webengine_versions.webengine == utils.VersionNumber(6, 5): + assert versions is None + pytest.xfail("ELF file structure not supported") + assert versions is not None # No failing mmap -- cgit v1.2.3-54-g00ecf From 8227b91d282f80d688065814dc6acc4a6922c8b1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 18:41:44 +0100 Subject: tests: Update FIXME comment PyQt insists using the deprecated signal overload, seemingly nothing we can do to change that: https://www.riverbankcomputing.com/pipermail/pyqt/2023-March/045215.html See #7624 --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 3d97e9685..82f700461 100644 --- a/pytest.ini +++ b/pytest.ini @@ -55,7 +55,7 @@ qt_log_ignore = # on Windows ^QProcess: Destroyed while process .* is still running\. # Qt 6.5 debug build - # FIXME:qt6 is this something we should/can fix properly? + # WORKAROUND for https://www.riverbankcomputing.com/pipermail/pyqt/2023-March/045215.html ^QObject::connect: Connecting from COMPAT signal \(QSocketNotifier::activated\(int\)\)$ xfail_strict = true filterwarnings = -- cgit v1.2.3-54-g00ecf From cd5624f50ad92317868514ad5b024a58dbdb233c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 17 Mar 2023 19:53:52 +0100 Subject: tests: Fix QApplication arguments With Qt 6.5, QtWebEngine complains and aborts when it gets an empty argv: https://bugreports.qt.io/browse/QTBUG-110157 https://codereview.qt-project.org/c/qt/qtwebengine/+/455347 https://codereview.qt-project.org/c/qt/qtwebengine/+/457045 https://www.riverbankcomputing.com/pipermail/pyqt/2023-March/045216.html However, our custom qapp_args override for pytest-qt *does* return [] as argv, causing all tests using QtWebEngine to fail. We might decide to add sys.argv[0] to the given qapp_args in pytest-qt: https://github.com/pytest-dev/pytest-qt/issues/483 But probably this should be fixed on the application-side, so let's do exactly that. See #7624 --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 134f967e9..3df91f4c4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -212,7 +212,7 @@ def qapp_args(): """Make QtWebEngine unit tests run on older Qt versions + newer kernels.""" if testutils.disable_seccomp_bpf_sandbox(): return [sys.argv[0], testutils.DISABLE_SECCOMP_BPF_FLAG] - return [] + return [sys.argv[0]] @pytest.fixture(scope='session') -- cgit v1.2.3-54-g00ecf