From 6ddff3ae0d900eb2cb995312efa579d598ef99f6 Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Mon, 17 Nov 2025 04:26:42 +0000 Subject: [PATCH 01/30] Update dependencies --- misc/requirements/requirements-dev.txt | 4 ++-- misc/requirements/requirements-mypy.txt | 4 ++-- misc/requirements/requirements-pylint.txt | 2 +- misc/requirements/requirements-pyroma.txt | 4 ++-- misc/requirements/requirements-sphinx.txt | 2 +- misc/requirements/requirements-tests.txt | 4 ++-- misc/requirements/requirements-tox.txt | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index fe1281a68..5562a89d3 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -7,7 +7,7 @@ backports.tarfile==1.2.0 bracex==2.6 build==1.3.0 bump-my-version==1.2.4 -certifi==2025.10.5 +certifi==2025.11.12 cffi==2.0.0 charset-normalizer==3.4.4 click==8.1.8 @@ -30,7 +30,7 @@ jaraco.context==6.0.1 jaraco.functools==4.0.1 jaraco.text==3.12.1 jeepney==0.9.0 -keyring==25.6.0 +keyring==25.7.0 manhole==1.8.1 markdown-it-py==3.0.0 mdurl==0.1.2 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 656f20b7a..7fc61e6f4 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py chardet==5.2.0 -diff_cover==9.7.1 +diff_cover==9.7.2 Jinja2==3.1.6 lxml==6.0.2 MarkupSafe==3.0.3 @@ -13,7 +13,7 @@ Pygments==2.19.2 PyQt5-stubs==5.15.6.0 tomli==2.3.0 types-colorama==0.4.15.20250801 -types-docutils==0.22.2.20251006 +types-docutils==0.22.3.20251115 types-Pygments==2.19.0.20250809 types-PyYAML==6.0.12.20250915 typing_extensions==4.15.0 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index 9bdb74014..f59cc3538 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py astroid==3.3.11 -certifi==2025.10.5 +certifi==2025.11.12 cffi==2.0.0 charset-normalizer==3.4.4 cryptography==46.0.3 diff --git a/misc/requirements/requirements-pyroma.txt b/misc/requirements/requirements-pyroma.txt index 8c0b8bb5c..b844c39cd 100644 --- a/misc/requirements/requirements-pyroma.txt +++ b/misc/requirements/requirements-pyroma.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py build==1.3.0 -certifi==2025.10.5 +certifi==2025.11.12 charset-normalizer==3.4.4 check-manifest==0.51 docutils==0.22.3 @@ -13,6 +13,6 @@ pyproject_hooks==1.2.0 pyroma==5.0 requests==2.32.5 tomli==2.3.0 -trove-classifiers==2025.9.11.17 +trove-classifiers==2025.11.14.15 urllib3==2.5.0 zipp==3.23.0 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 1a430a7f9..42660ab5e 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -2,7 +2,7 @@ alabaster==0.7.16 babel==2.17.0 -certifi==2025.10.5 +certifi==2025.11.12 charset-normalizer==3.4.4 docutils==0.21.2 idna==3.11 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index 776bc5b1f..c653e1856 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -5,13 +5,13 @@ autocommand==2.2.2 backports.tarfile==1.2.0 beautifulsoup4==4.14.2 blinker==1.9.0 -certifi==2025.10.5 +certifi==2025.11.12 charset-normalizer==3.4.4 cheroot==11.1.2 click==8.1.8 coverage==7.10.7 exceptiongroup==1.3.0 -execnet==2.1.1 +execnet==2.1.2 filelock==3.19.1 Flask==3.1.2 gherkin-official==29.0.0 diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt index 0274df7fd..929fe4135 100644 --- a/misc/requirements/requirements-tox.txt +++ b/misc/requirements/requirements-tox.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -cachetools==6.2.1 +cachetools==6.2.2 chardet==5.2.0 colorama==0.4.6 distlib==0.4.0 From 0ef5053a652ca2fe4330c90dac0299d4288c3f59 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 18 Nov 2025 14:59:00 +0100 Subject: [PATCH 02/30] tests: Stabilize flaky session scrolling test Equivalent of d8079515fa2cc88b00e0ce1723e37d07b0388ebb See #5390 --- tests/end2end/data/scroll/simple.html | 4 +++- tests/end2end/features/sessions.feature | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/end2end/data/scroll/simple.html b/tests/end2end/data/scroll/simple.html index b0a36e6e4..20002a039 100644 --- a/tests/end2end/data/scroll/simple.html +++ b/tests/end2end/data/scroll/simple.html @@ -15,9 +15,11 @@ console.log("[PASS] Positions equal: " + old_position); } } + + requestAnimationFrame(() => console.log('simple loaded')) - + Just a link

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus

diff --git a/tests/end2end/features/sessions.feature b/tests/end2end/features/sessions.feature index 1d352fbf8..3e83d8568 100644 --- a/tests/end2end/features/sessions.feature +++ b/tests/end2end/features/sessions.feature @@ -75,6 +75,7 @@ Feature: Saving and loading sessions @qtwebkit_skip Scenario: Scrolling (qtwebengine) When I open data/scroll/simple.html + And I wait for "* simple loaded" in the log And I run :scroll-px 10 20 And I wait until the scroll position changed to 10/20 Then the session should look like: From 66cbe0d9c962073d8983bfbac4810c9365a54a3c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 21 Nov 2025 18:31:43 +0100 Subject: [PATCH 03/30] Add QtWebEngine 6.10.1 security patch version --- qutebrowser/utils/version.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index fc9c6edc7..698843058 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -657,6 +657,7 @@ class WebEngineVersions: ## Qt 6.10 utils.VersionNumber(6, 10): (_BASES[134], '140.0.7339.207'), # 2025-09-22 + utils.VersionNumber(6, 10, 1): (_BASES[134], '142.0.7444.162'), # 2025-11-11 } def __post_init__(self) -> None: From 59a64af67f9451ebc84de4f58cd042e7543d8a6b Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 21 Nov 2025 18:35:03 +0100 Subject: [PATCH 04/30] tests: Adjust permissions storage workaround for Qt 6.10.1 --- tests/end2end/features/test_prompts_bdd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/end2end/features/test_prompts_bdd.py b/tests/end2end/features/test_prompts_bdd.py index c08405d3e..5c6130c8e 100644 --- a/tests/end2end/features/test_prompts_bdd.py +++ b/tests/end2end/features/test_prompts_bdd.py @@ -50,13 +50,13 @@ def fresh_instance(quteproc): # on PyQt6.8 we disable that with the new API, otherwise restart the # browser to make it forget previous prompts. # - # Qt 6.10 Beta 4 accidentally persists some permissions; - # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-140194 + # Starting with Qt 6.10, QtWebEngine unconditionally persists some permissions; + # see https://bugreports.qt.io/browse/QTBUG-140194 if ( qtutils.version_check("6.8", compiled=False) and PYQT_WEBENGINE_VERSION and PYQT_WEBENGINE_VERSION < 0x60800 - ) or qtutils.version_check("6.10", compiled=False, exact=True): + ) or qtutils.version_check("6.10", compiled=False): quteproc.terminate() quteproc.start() From 4f40a8b46b2ea2b256a1728c2dbbd935bc5f6152 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 21 Nov 2025 18:39:24 +0100 Subject: [PATCH 05/30] tests: Improve test_version output --- tests/end2end/test_invocations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 8d9f86ab9..5f5e70faf 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -251,6 +251,7 @@ def test_optimize(request, quteproc_new, capfd, level): def test_version(request): """Test invocation with --version argument.""" args = ['-m', 'qutebrowser', '--version'] + _base_args(request.config) + args.remove("--json-logging") # can't use quteproc_new here because it's confused by # early process termination proc = QProcess() From 8ae5e3d83b0733cfeefe149eae6cec6cd782936a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 21 Nov 2025 22:50:52 +0100 Subject: [PATCH 06/30] version: Use correct profile for extension list See #8785 --- doc/changelog.asciidoc | 2 + .../browser/webengine/webenginesettings.py | 14 ++++--- qutebrowser/utils/version.py | 15 ++++--- tests/unit/utils/test_version.py | 39 ++++++++++++------- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index b6035614c..bc93293a6 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -28,6 +28,8 @@ Fixed - The version info now includes the Wayland compositor name if wayland-client is available under a different name than `libwayland-client.so` (#8771). +- The list of Chromium extensions in `--version` / `:version` now uses the + correct Chromium data profile, also fixing a crash with Qt 6.10.1 (#8785). [[v3.6.1]] v3.6.1 (2025-11-03) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 08d52b16c..599111196 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -458,14 +458,18 @@ def _clear_webengine_permissions_json(): ) +def default_qt_profile() -> QWebEngineProfile: + """Get the default profile from Qt.""" + if machinery.IS_QT6: + return QWebEngineProfile("Default") + else: + return QWebEngineProfile.defaultProfile() + + def _init_default_profile(): """Init the default QWebEngineProfile.""" global default_profile - - if machinery.IS_QT6: - default_profile = QWebEngineProfile("Default") - else: - default_profile = QWebEngineProfile.defaultProfile() + default_profile = default_qt_profile() assert not default_profile.isOffTheRecord() assert parsed_user_agent is None # avoid earlier profile initialization diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 698843058..0d0598ca5 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -931,12 +931,18 @@ def _webengine_extensions() -> Sequence[str]: lines: list[str] = [] if ( objects.backend == usertypes.Backend.QtWebEngine - and "avoid-chromium-init" not in objects.debug_flags and machinery.IS_QT6 # mypy; TODO early return once Qt 5 is dropped ): - from qutebrowser.qt.webenginecore import QWebEngineProfile - profile = QWebEngineProfile.defaultProfile() - assert profile is not None # mypy + from qutebrowser.browser.webengine import webenginesettings + lines.append("WebExtensions:") + + if webenginesettings.default_profile: + profile = webenginesettings.default_profile + elif "avoid-chromium-init" in objects.debug_flags: + lines[0] += " unknown (avoiding init)" + return lines + else: + profile = webenginesettings.default_qt_profile() try: ext_manager = profile.extensionManager() @@ -945,7 +951,6 @@ def _webengine_extensions() -> Sequence[str]: return [] assert ext_manager is not None # mypy - lines.append("WebExtensions:") if not ext_manager.extensions(): lines[0] += " none" diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 5c7b94523..5988ce732 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -1449,11 +1449,9 @@ def test_version_info(params, stubs, monkeypatch, config_stub): monkeypatch.delattr(version, 'qtutils.qWebKitVersion', raising=False) if machinery.IS_QT6: monkeypatch.setattr( - QWebEngineProfile, - "defaultProfile", - lambda: FakeExtensionProfile( - FakeExtensionManager([FakeExtensionInfo("ext1")]) - ), + webenginesettings, + "default_profile", + FakeExtensionProfile(FakeExtensionManager([FakeExtensionInfo("ext1")])), ) substitutions['webextensions'] = ( "\n" @@ -1592,20 +1590,35 @@ class TestOpenGLInfo: class TestWebEngineExtensions: def test_qtwebkit(self, monkeypatch: pytest.MonkeyPatch) -> None: + assert webenginesettings.default_profile is None # -> default_qt_profile() used monkeypatch.setattr(version.objects, "backend", usertypes.Backend.QtWebKit) - monkeypatch.setattr(QWebEngineProfile, "defaultProfile", lambda: 1/0) + monkeypatch.setattr(webenginesettings, "default_qt_profile", lambda: 1 / 0) assert not version._webengine_extensions() def test_avoid_chromium_init(self, monkeypatch: pytest.MonkeyPatch) -> None: + assert webenginesettings.default_profile is None # -> default_qt_profile() used monkeypatch.setattr(version.objects, "backend", usertypes.Backend.QtWebEngine) monkeypatch.setattr(objects, "debug_flags", {"avoid-chromium-init"}) - monkeypatch.setattr(QWebEngineProfile, "defaultProfile", lambda: 1/0) - assert not version._webengine_extensions() + monkeypatch.setattr(webenginesettings, "default_qt_profile", lambda: 1 / 0) + assert version._webengine_extensions() == [ + "WebExtensions: unknown (avoiding init)" + ] def test_no_extension_manager(self, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setattr(QWebEngineProfile, "defaultProfile", object) + assert webenginesettings.default_profile is None # -> default_qt_profile() used + monkeypatch.setattr(webenginesettings, "default_qt_profile", object) assert not version._webengine_extensions() + @pytest.mark.parametrize("avoid_init", [True, False]) + def test_preexisting_profile(self, monkeypatch: pytest.MonkeyPatch, avoid_init: bool) -> None: + """Test that we use the pre-existing profile if available.""" + monkeypatch.setattr(webenginesettings, "default_profile", FakeExtensionProfile(FakeExtensionManager([]))) + if avoid_init: + monkeypatch.setattr(objects, "debug_flags", {"avoid-chromium-init"}) + + result = version._webengine_extensions() + assert result == ["WebExtensions: none"] + @pytest.mark.parametrize( "extensions, expected", [ @@ -1666,11 +1679,9 @@ class TestWebEngineExtensions: expected: list[str], ) -> None: monkeypatch.setattr( - QWebEngineProfile, - "defaultProfile", - lambda: FakeExtensionProfile( - FakeExtensionManager(extensions) - ), + webenginesettings, + "default_profile", + FakeExtensionProfile(FakeExtensionManager(extensions)), ) assert version._webengine_extensions() == expected From 31a5737c61c4ed09cec4ad82a3fb964aca9de3ca Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 22 Nov 2025 10:38:46 +0100 Subject: [PATCH 07/30] Avoid disabling off-the-record profile Hangouts extension with Qt 6.10.1 Otherwise this results in a crash, see #8785 --- .../browser/webengine/webenginesettings.py | 11 ++++++++++ tests/end2end/test_invocations.py | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 599111196..b272eab19 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -431,6 +431,17 @@ def _maybe_disable_hangouts_extension(profile: QWebEngineProfile) -> None: except AttributeError: return # added in QtWebEngine 6.10 + qtwe_versions = version.qtwebengine_versions(avoid_init=True) + if ( + qtwe_versions.webengine == utils.VersionNumber(6, 10, 1) + and profile.isOffTheRecord() + ): + # WORKAROUND for https://github.com/qutebrowser/qutebrowser/issues/8785 + log.misc.warning( + "Not disabling Hangouts extension on private profile to avoid " + "QtWebEngine crash with Qt 6.10.1") + return + assert ext_manager is not None # mypy for info in ext_manager.extensions(): if info.id() == pakjoy.HANGOUTS_EXT_ID: diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 5f5e70faf..b5e1f08bf 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -21,6 +21,7 @@ import pytest from qutebrowser.qt.core import QProcess, QPoint from helpers import testutils +from end2end.fixtures import quteprocess from qutebrowser.utils import qtutils, utils, version @@ -612,6 +613,25 @@ def test_service_worker_workaround( assert not service_worker_dir.exists() +def test_disable_hangouts_extension_crash( + quteproc_new: quteprocess.QuteProc, + request: pytest.FixtureRequest, + webengine_versions: version.WebEngineVersions, +): + """Make sure disabling the Hangouts extension doesn't crash.""" + args = _base_args(request.config) + [ + '--temp-basedir', + '-s', 'qt.workarounds.disable_hangouts_extension', 'true', + ] + quteproc_new.start(args) + if webengine_versions.webengine == utils.VersionNumber(6, 10, 1): + line = quteproc_new.wait_for(message="Not disabling Hangouts extension *") + line.expected = True + + quteproc_new.send_cmd(':quit') + quteproc_new.wait_for_quit() + + @pytest.mark.parametrize('store', [True, False]) def test_cookies_store(quteproc_new, request, short_tmpdir, store): # Start test process From 8e42727d310e9fe6e90b5e6455186f1148de94bb Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 22 Nov 2025 10:40:30 +0100 Subject: [PATCH 08/30] Update changelog --- doc/changelog.asciidoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index bc93293a6..7a74e3486 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -30,6 +30,8 @@ Fixed available under a different name than `libwayland-client.so` (#8771). - The list of Chromium extensions in `--version` / `:version` now uses the correct Chromium data profile, also fixing a crash with Qt 6.10.1 (#8785). +- With Qt 6.10.1, `qt.workarounds.disable_hangouts_extension` now doesn't apply + on private profiles, avoiding a Qt bug leading to a crash (#8785). [[v3.6.1]] v3.6.1 (2025-11-03) From 69f3882ce3654929896e91cf5925d8b03ee8f915 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 23 Nov 2025 11:42:49 +0100 Subject: [PATCH 09/30] tests: Skip hangouts extension test on Qt 5 --- tests/end2end/test_invocations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index b5e1f08bf..dc6bb61c3 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -613,6 +613,7 @@ def test_service_worker_workaround( assert not service_worker_dir.exists() +@pytest.mark.qt6_only def test_disable_hangouts_extension_crash( quteproc_new: quteprocess.QuteProc, request: pytest.FixtureRequest, From f5e26608904834f354366330e1ba2fc43b2f69dd Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Mon, 24 Nov 2025 04:28:20 +0000 Subject: [PATCH 10/30] Update dependencies --- misc/requirements/requirements-dev.txt | 2 +- misc/requirements/requirements-mypy.txt | 2 +- misc/requirements/requirements-pyinstaller.txt | 4 ++-- misc/requirements/requirements-tests.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 5562a89d3..4b9fbe600 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -13,7 +13,7 @@ charset-normalizer==3.4.4 click==8.1.8 cryptography==46.0.3 docutils==0.22.3 -exceptiongroup==1.3.0 +exceptiongroup==1.3.1 github3.py==4.0.1 h11==0.16.0 httpcore==1.0.9 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 7fc61e6f4..3b75558bd 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -14,6 +14,6 @@ PyQt5-stubs==5.15.6.0 tomli==2.3.0 types-colorama==0.4.15.20250801 types-docutils==0.22.3.20251115 -types-Pygments==2.19.0.20250809 +types-Pygments==2.19.0.20251121 types-PyYAML==6.0.12.20250915 typing_extensions==4.15.0 diff --git a/misc/requirements/requirements-pyinstaller.txt b/misc/requirements/requirements-pyinstaller.txt index 5972efabf..594de37e5 100644 --- a/misc/requirements/requirements-pyinstaller.txt +++ b/misc/requirements/requirements-pyinstaller.txt @@ -1,8 +1,8 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -altgraph==0.17.4 +altgraph==0.17.5 importlib_metadata==8.7.0 packaging==25.0 pyinstaller==6.16.0 -pyinstaller-hooks-contrib==2025.9 +pyinstaller-hooks-contrib==2025.10 zipp==3.23.0 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index c653e1856..0b69c7e36 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -10,7 +10,7 @@ charset-normalizer==3.4.4 cheroot==11.1.2 click==8.1.8 coverage==7.10.7 -exceptiongroup==1.3.0 +exceptiongroup==1.3.1 execnet==2.1.2 filelock==3.19.1 Flask==3.1.2 From 41642056636db038d2db5c983da8e038847f6eb2 Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Thu, 27 Nov 2025 15:55:11 +0000 Subject: [PATCH 11/30] Update dependencies --- misc/requirements/requirements-dev.txt | 2 +- misc/requirements/requirements-pyinstaller.txt | 2 +- misc/requirements/requirements-pyqt-6.10.txt | 4 ++-- misc/requirements/requirements-pyqt-6.txt | 4 ++-- misc/requirements/requirements-pyqt.txt | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 4b9fbe600..cd9ea4668 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -40,7 +40,7 @@ packaging==25.0 platformdirs==4.4.0 prompt_toolkit==3.0.52 pycparser==2.23 -pydantic==2.12.4 +pydantic==2.12.5 pydantic-settings==2.11.0 pydantic_core==2.41.5 Pygments==2.19.2 diff --git a/misc/requirements/requirements-pyinstaller.txt b/misc/requirements/requirements-pyinstaller.txt index 594de37e5..076cb5c67 100644 --- a/misc/requirements/requirements-pyinstaller.txt +++ b/misc/requirements/requirements-pyinstaller.txt @@ -3,6 +3,6 @@ altgraph==0.17.5 importlib_metadata==8.7.0 packaging==25.0 -pyinstaller==6.16.0 +pyinstaller==6.17.0 pyinstaller-hooks-contrib==2025.10 zipp==3.23.0 diff --git a/misc/requirements/requirements-pyqt-6.10.txt b/misc/requirements/requirements-pyqt-6.10.txt index cf32f5046..802128a67 100644 --- a/misc/requirements/requirements-pyqt-6.10.txt +++ b/misc/requirements/requirements-pyqt-6.10.txt @@ -1,8 +1,8 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py PyQt6==6.10.0 -PyQt6-Qt6==6.10.0 +PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 -PyQt6-WebEngine-Qt6==6.10.0 +PyQt6-WebEngine-Qt6==6.10.1 PyQt6_sip==13.10.2 --extra-index-url https://www.riverbankcomputing.com/pypi/simple/ diff --git a/misc/requirements/requirements-pyqt-6.txt b/misc/requirements/requirements-pyqt-6.txt index cf32f5046..802128a67 100644 --- a/misc/requirements/requirements-pyqt-6.txt +++ b/misc/requirements/requirements-pyqt-6.txt @@ -1,8 +1,8 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py PyQt6==6.10.0 -PyQt6-Qt6==6.10.0 +PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 -PyQt6-WebEngine-Qt6==6.10.0 +PyQt6-WebEngine-Qt6==6.10.1 PyQt6_sip==13.10.2 --extra-index-url https://www.riverbankcomputing.com/pypi/simple/ diff --git a/misc/requirements/requirements-pyqt.txt b/misc/requirements/requirements-pyqt.txt index cf32f5046..802128a67 100644 --- a/misc/requirements/requirements-pyqt.txt +++ b/misc/requirements/requirements-pyqt.txt @@ -1,8 +1,8 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py PyQt6==6.10.0 -PyQt6-Qt6==6.10.0 +PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 -PyQt6-WebEngine-Qt6==6.10.0 +PyQt6-WebEngine-Qt6==6.10.1 PyQt6_sip==13.10.2 --extra-index-url https://www.riverbankcomputing.com/pypi/simple/ From b3e4dba731b581fd9a746c32a4a42d0e992e2853 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 27 Nov 2025 21:28:34 +0100 Subject: [PATCH 12/30] qtargs: Remove old workaround with Qt 6.10.1 --- qutebrowser/config/qtargs.py | 3 +-- tests/unit/config/test_qtargs.py | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qutebrowser/config/qtargs.py b/qutebrowser/config/qtargs.py index 78ea3b782..f89f62733 100644 --- a/qutebrowser/config/qtargs.py +++ b/qutebrowser/config/qtargs.py @@ -159,10 +159,9 @@ def _qtwebengine_features( # noqa: C901 # TODO adjust if fixed in Qt 6.9.2+ disabled_features.append('DocumentPictureInPictureAPI') - if versions.webengine >= utils.VersionNumber(6, 9): + if utils.VersionNumber(6, 9) <= versions.webengine < utils.VersionNumber(6, 10, 1): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-135787 # and https://bugreports.qt.io/browse/QTBUG-141096 - # TODO adjust if fixed in Qt 6.9.2+ disabled_features.append('PermissionElement') if not config.val.input.media_keys: diff --git a/tests/unit/config/test_qtargs.py b/tests/unit/config/test_qtargs.py index 5048222a3..49d02e107 100644 --- a/tests/unit/config/test_qtargs.py +++ b/tests/unit/config/test_qtargs.py @@ -471,6 +471,9 @@ class TestWebEngineArgs: # Qt 6.9 ('6.9.0', "DocumentPictureInPictureAPI,PermissionElement"), ('6.9.1', "DocumentPictureInPictureAPI,PermissionElement"), + # Qt 6.10 + ('6.10.0', "DocumentPictureInPictureAPI,PermissionElement"), + ('6.10.1', "DocumentPictureInPictureAPI"), ]) def test_disable_feature_workaround( self, parser, version_patcher, qt_version, disabled From 13d9904b90533ba0d9cb7f3ed2ca21165f5fe78d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 27 Nov 2025 21:29:21 +0100 Subject: [PATCH 13/30] Update changelog for v3.6.2 --- doc/changelog.asciidoc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 7a74e3486..c222f47e6 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -15,14 +15,16 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Fixed` for any bug fixes. // `Security` to invite users to upgrade in case of vulnerabilities. -[[v3.7.0]] -v3.7.0 (unreleased) -------------------- - [[v3.6.2]] v3.6.2 (unreleased) ------------------- +Changed +~~~~~~~ + +* Windows and macOS releases now ship with Qt 6.10.1, which include + security patches up to Chromium 142.0.7444.162. + Fixed ~~~~~ From 500a8df2095a6df5bd1a39b494aed6eea5ba5bca Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 27 Nov 2025 21:55:44 +0100 Subject: [PATCH 14/30] Update user agents --- qutebrowser/browser/webengine/webenginesettings.py | 2 +- qutebrowser/config/configdata.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index b272eab19..9c82643e4 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -541,7 +541,7 @@ def _init_site_specific_quirks(): # "{qt_key}/{qt_version} " # "{upstream_browser_key}/{upstream_browser_version_short} " # "Safari/{webkit_version}") - firefox_ua = "Mozilla/5.0 ({os_info}; rv:144.0) Gecko/20100101 Firefox/144.0" + firefox_ua = "Mozilla/5.0 ({os_info}; rv:145.0) Gecko/20100101 Firefox/145.0" # Needed for gitlab.gnome.org which blocks old Chromium versions outright, # except when QtWebEngine/... is in the UA. diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 1ba855a77..68c36ccd0 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -773,14 +773,14 @@ content.headers.user_agent: # Vim-protip: Place your cursor below this comment and run # :r!python scripts/dev/ua_fetch.py - - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 - (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36" - - Chrome 141 macOS + (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" + - Chrome 142 macOS - - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, - like Gecko) Chrome/141.0.0.0 Safari/537.36" - - Chrome 141 Win10 + like Gecko) Chrome/142.0.0.0 Safari/537.36" + - Chrome 142 Win10 - - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like - Gecko) Chrome/141.0.0.0 Safari/537.36" - - Chrome 141 Linux + Gecko) Chrome/142.0.0.0 Safari/537.36" + - Chrome 142 Linux supports_pattern: true desc: | User agent to send. From f408f20ad9026695c61d25c8d852c04eed9109f7 Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Thu, 27 Nov 2025 20:57:11 +0000 Subject: [PATCH 15/30] Release v3.6.2 (cherry picked from commit b2c5d5fa0d3a30f137e1026e1a418d66e3bdbf87) --- .bumpversion.toml | 2 +- doc/changelog.asciidoc | 2 +- misc/org.qutebrowser.qutebrowser.appdata.xml | 1 + qutebrowser/__init__.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.bumpversion.toml b/.bumpversion.toml index 926d73ce6..4c78f7935 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "3.6.1" +current_version = "3.6.2" commit = true message = "Release v{new_version}" tag = true diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index c222f47e6..8fc476f93 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -16,7 +16,7 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Security` to invite users to upgrade in case of vulnerabilities. [[v3.6.2]] -v3.6.2 (unreleased) +v3.6.2 (2025-11-27) ------------------- Changed diff --git a/misc/org.qutebrowser.qutebrowser.appdata.xml b/misc/org.qutebrowser.qutebrowser.appdata.xml index 18728c7c6..457bcd393 100644 --- a/misc/org.qutebrowser.qutebrowser.appdata.xml +++ b/misc/org.qutebrowser.qutebrowser.appdata.xml @@ -44,6 +44,7 @@ + diff --git a/qutebrowser/__init__.py b/qutebrowser/__init__.py index f86a929f1..34af13dd1 100644 --- a/qutebrowser/__init__.py +++ b/qutebrowser/__init__.py @@ -14,7 +14,7 @@ __copyright__ = "Copyright 2013-{} Florian Bruhin (The Compiler)".format(_year) __license__ = "GPL-3.0-or-later" __maintainer__ = __author__ __email__ = "mail@qutebrowser.org" -__version__ = "3.6.1" +__version__ = "3.6.2" __version_info__ = tuple(int(part) for part in __version__.split('.')) __description__ = "A keyboard-driven, vim-like browser based on Python and Qt." From 0570545342b1ea0a6d1fa387b187d1528a01935e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 18:21:33 +0000 Subject: [PATCH 16/30] build(deps): bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/bleeding.yml | 2 +- .github/workflows/ci.yml | 8 ++++---- .github/workflows/docker.yml | 2 +- .github/workflows/nightly.yml | 2 +- .github/workflows/recompile-requirements.yml | 2 +- .github/workflows/release.yml | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/bleeding.yml b/.github/workflows/bleeding.yml index 97fce58da..227ee16cd 100644 --- a/.github/workflows/bleeding.yml +++ b/.github/workflows/bleeding.yml @@ -31,7 +31,7 @@ jobs: - /home/runner/work/_temp/:/home/runner/work/_temp/ options: --privileged --tty steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Set up problem matchers diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff984ce8e..f100d9a4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - testenv: actionlint - testenv: package steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - uses: actions/cache@v4 @@ -106,7 +106,7 @@ jobs: - /home/runner/work/_temp/:/home/runner/work/_temp/ options: --privileged --tty steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Set up problem matchers @@ -217,7 +217,7 @@ jobs: python: "3.14" runs-on: "${{ matrix.os }}" steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - uses: actions/cache@v4 @@ -285,7 +285,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: persist-credentials: false - name: Initialize CodeQL diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 57c3379e5..b66df3aba 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -16,7 +16,7 @@ jobs: - archlinux-webengine - archlinux-webengine-unstable steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: '3.x' diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index abb5fbd42..8f42d42ee 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -37,7 +37,7 @@ jobs: runs-on: "${{ matrix.os }}" timeout-minutes: 45 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Set up Python diff --git a/.github/workflows/recompile-requirements.yml b/.github/workflows/recompile-requirements.yml index 4debcaa66..07f11428e 100644 --- a/.github/workflows/recompile-requirements.yml +++ b/.github/workflows/recompile-requirements.yml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 20 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: persist-credentials: false - name: Set up Python 3.9 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1cedfbc42..5c6b2e58f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: console.log(`sorted: ${sorted}`); return sorted.at(-1); result-encoding: string - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 with: @@ -78,7 +78,7 @@ jobs: git config --global user.name "qutebrowser bot" git config --global user.email "bot@qutebrowser.org" - name: Switch to release branch - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ steps.find-branch.outputs.result }} - name: Import GPG Key @@ -163,7 +163,7 @@ jobs: permissions: contents: write # To upload release artifacts steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: ref: v${{ inputs.release_type == 'reupload' && needs.prepare.outputs.version_x || needs.prepare.outputs.version }} - name: Set up Python From 88aa47c377b21b0d6489fdb527e825ca708d8973 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 30 Nov 2025 17:54:33 +0100 Subject: [PATCH 17/30] Add qt.workarounds.disable_accessibility setting This disables accessibility with Qt 6.10.1, which causes frequent segfaults. Closes #8797 --- doc/changelog.asciidoc | 12 +++++++++ doc/help/settings.asciidoc | 19 +++++++++++++ qutebrowser/config/configdata.yml | 13 +++++++++ qutebrowser/config/qtargs.py | 10 +++++++ tests/unit/config/test_qtargs.py | 45 ++++++++++++++++++++++++++++++- 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 8fc476f93..f9e2766cd 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -15,6 +15,18 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Fixed` for any bug fixes. // `Security` to invite users to upgrade in case of vulnerabilities. +[[v3.6.3]] +v3.6.3 (unreleased) +------------------- + +Fixed +~~~~~ + +- New `qt.workarounds.disable_accessibility` setting, which disables Chromium + accessibility support. By default, is it set to `auto`, which only disables + accessibility on Qt versions with known issues. This works around a bug in Qt + 6.10.1 causing frequent segfaults (#8797). + [[v3.6.2]] v3.6.2 (2025-11-27) ------------------- diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 2160a15f9..434260b20 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -302,6 +302,7 @@ |<>|Force software rendering for QtWebEngine. |<>|Turn on Qt HighDPI scaling. |<>|Disable accelerated 2d canvas to avoid graphical glitches. +|<>|Disable accessibility to avoid crashes on Qt 6.10.1. |<>|Disable the Hangouts extension. |<>|Work around locale parsing issues in QtWebEngine 5.15.3. |<>|Delete the QtWebEngine Service Worker directory on every start. @@ -3996,6 +3997,24 @@ Valid values: Default: +pass:[auto]+ +[[qt.workarounds.disable_accessibility]] +=== qt.workarounds.disable_accessibility +Disable accessibility to avoid crashes on Qt 6.10.1. + +This setting requires a restart. + +This setting is only available with the QtWebEngine backend. + +Type: <> + +Valid values: + + * +always+: Disable renderer accessibility + * +auto+: Disable on Qt versions with known issues, enable otherwise + * +never+: Enable renderer accessibility + +Default: +pass:[auto]+ + [[qt.workarounds.disable_hangouts_extension]] === qt.workarounds.disable_hangouts_extension Disable the Hangouts extension. diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 68c36ccd0..b221a70dc 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -422,6 +422,19 @@ qt.workarounds.disable_hangouts_extension: disabled to avoid crashes on Qt 6.5.0 to 6.5.3 if dark mode is enabled, as well as on Qt 6.6.0. +qt.workarounds.disable_accessibility: + type: + name: String + valid_values: + - always: Disable renderer accessibility + - auto: Disable on Qt versions with known issues, enable otherwise + - never: Enable renderer accessibility + default: auto + backend: QtWebEngine + restart: true + desc: >- + Disable accessibility to avoid crashes on Qt 6.10.1. + ## auto_save auto_save.interval: diff --git a/qutebrowser/config/qtargs.py b/qutebrowser/config/qtargs.py index f89f62733..c96cd61b1 100644 --- a/qutebrowser/config/qtargs.py +++ b/qutebrowser/config/qtargs.py @@ -362,6 +362,16 @@ _WEBENGINE_SETTINGS: dict[str, dict[Any, Optional[_SettingValueType]]] = { and versions.webengine < utils.VersionNumber(6, 8, 2) else None, }, + 'qt.workarounds.disable_accessibility': { + 'always': '--disable-renderer-accessibility', + 'never': None, + # WORKAROUND for https://qt-project.atlassian.net/browse/QTBUG-142320 + 'auto': lambda versions: '--disable-renderer-accessibility' + if machinery.IS_QT6 + and versions.webengine + and versions.webengine == utils.VersionNumber(6, 10, 1) + else None, + }, } diff --git a/tests/unit/config/test_qtargs.py b/tests/unit/config/test_qtargs.py index 49d02e107..b29949628 100644 --- a/tests/unit/config/test_qtargs.py +++ b/tests/unit/config/test_qtargs.py @@ -12,7 +12,7 @@ import pytest from qutebrowser.qt import machinery from qutebrowser import qutebrowser from qutebrowser.config import qtargs, configdata -from qutebrowser.utils import usertypes, version +from qutebrowser.utils import usertypes, version, utils @pytest.fixture @@ -52,6 +52,7 @@ def reduce_args(config_stub, version_patcher, monkeypatch): config_stub.val.scrolling.bar = 'never' config_stub.val.qt.chromium.experimental_web_platform_features = 'never' config_stub.val.qt.workarounds.disable_accelerated_2d_canvas = 'never' + config_stub.val.qt.workarounds.disable_accessibility = 'never' monkeypatch.setattr(qtargs.utils, 'is_mac', False) # Avoid WebRTC pipewire feature monkeypatch.setattr(qtargs.utils, 'is_linux', False) @@ -117,6 +118,14 @@ def test_no_webengine_available(monkeypatch, config_stub, parser, stubs): assert args == [sys.argv[0]] +_XFAIL_FUTURE_QT = ( + pytest.mark.xfail( + utils.VersionNumber(6, 11) not in version.WebEngineVersions._CHROMIUM_VERSIONS, + reason="Unknown security patch version for Qt 6.11 so far", + ), +) + + @pytest.mark.usefixtures('reduce_args') class TestWebEngineArgs: @@ -190,6 +199,40 @@ class TestWebEngineArgs: args = qtargs.qt_args(parsed) assert ('--disable-accelerated-2d-canvas' in args) == has_arg + @pytest.mark.parametrize( + "qt_version, qt6, value, has_arg", + [ + ("5.15.2", False, "auto", False), + # 6.8.5 is broken too, but commercial-only + ("6.10.0", True, "always", True), + ("6.10.0", True, "auto", False), + ("6.10.1", True, "auto", True), + ("6.10.1", True, "never", False), + ("6.10.2", True, "always", True), + ("6.10.2", True, "auto", False), + pytest.param("6.11.0", True, "always", True, marks=_XFAIL_FUTURE_QT), + pytest.param("6.11.0", True, "auto", False, marks=_XFAIL_FUTURE_QT), + ], + ) + def test_disable_accessibility( + self, + parser, + version_patcher, + config_stub, + monkeypatch, + qt_version, + qt6, + value, + has_arg, + ): + version_patcher(qt_version) + config_stub.val.qt.workarounds.disable_accessibility = value + monkeypatch.setattr(machinery, 'IS_QT6', qt6) + + parsed = parser.parse_args([]) + args = qtargs.qt_args(parsed) + assert ('--disable-renderer-accessibility' in args) == has_arg + @pytest.mark.parametrize('flags, args', [ ([], []), (['--debug-flag', 'chromium'], ['--enable-logging', '--v=1']), From 17c19a09b7f209cd470e6b1eca1dafc4ea4768fe Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 30 Nov 2025 18:11:25 +0100 Subject: [PATCH 18/30] build_release: Try to get more information on crashes Currently CI crashes on macOS, but without any useful logs. --- scripts/dev/build_release.py | 102 ++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index cdef25279..ab8844e6a 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -134,7 +134,7 @@ def _smoke_test_run( return subprocess.run(argv, check=True, capture_output=True) -def smoke_test(executable: pathlib.Path, debug: bool) -> None: +def smoke_test(executable: pathlib.Path, debug_build: bool) -> None: """Try starting the given qutebrowser executable.""" stdout_whitelist = [] stderr_whitelist = [ @@ -204,8 +204,15 @@ def smoke_test(executable: pathlib.Path, debug: bool) -> None: r'\(0x80004002\)'), ]) - proc = _smoke_test_run(executable) - if debug: + try: + proc = _smoke_test_run(executable) + except subprocess.CalledProcessError as e: + print(f"Smoke test failed: {e}, running with --debug") + smoke_test_debug(executable, original_stdout=e.stdout.decode('utf-8'), + original_stderr=e.stderr.decode('utf-8')) + return + + if debug_build: print("Skipping output check for debug build") return @@ -214,48 +221,55 @@ def smoke_test(executable: pathlib.Path, debug: bool) -> None: if stdout or stderr: print("Unexpected output, running with --debug") - proc = _smoke_test_run(executable, '--debug') - debug_stdout = proc.stdout.decode('utf-8') - debug_stderr = proc.stderr.decode('utf-8') + smoke_test_debug(executable, original_stdout=stdout, original_stderr=stderr) - lines = [ - "Unexpected output!", + +def smoke_test_debug( + executable: pathlib.Path, *, original_stdout: str, original_stderr: str +) -> None: + """Run smoke test in debug mode to get more output.""" + proc = _smoke_test_run(executable, '--debug') + debug_stdout = proc.stdout.decode('utf-8') + debug_stderr = proc.stderr.decode('utf-8') + + lines = [ + "Unexpected output!", + "", + ] + if original_stdout: + lines += [ + "stdout", + "------", + "", + original_stdout, + "", + ] + if original_stderr: + lines += [ + "stderr", + "------", + "", + original_stderr, + "", + ] + if debug_stdout: + lines += [ + "debug rerun stdout", + "------------------", + "", + debug_stdout, + "", + ] + if debug_stderr: + lines += [ + "debug rerun stderr", + "------------------", + "", + debug_stderr, "", ] - if stdout: - lines += [ - "stdout", - "------", - "", - stdout, - "", - ] - if stderr: - lines += [ - "stderr", - "------", - "", - stderr, - "", - ] - if debug_stdout: - lines += [ - "debug rerun stdout", - "------------------", - "", - debug_stdout, - "", - ] - if debug_stderr: - lines += [ - "debug rerun stderr", - "------------------", - "", - debug_stderr, - "", - ] - raise Exception("\n".join(lines)) # pylint: disable=broad-exception-raised + raise Exception("\n".join(lines)) # pylint: disable=broad-exception-raised def verify_windows_exe(exe_path: pathlib.Path) -> None: @@ -311,7 +325,7 @@ def build_mac( dist_path = pathlib.Path("dist") utils.print_title("Running pre-dmg smoke test") - smoke_test(_mac_bin_path(dist_path), debug=debug) + smoke_test(_mac_bin_path(dist_path), debug_build=debug) if skip_packaging: return [] @@ -334,7 +348,7 @@ def build_mac( subprocess.run(['hdiutil', 'attach', dmg_path, '-mountpoint', tmp_path], check=True) try: - smoke_test(_mac_bin_path(tmp_path), debug=debug) + smoke_test(_mac_bin_path(tmp_path), debug_build=debug) finally: print("Waiting 10s for dmg to be detachable...") time.sleep(10) @@ -393,7 +407,7 @@ def _build_windows_single( verify_windows_exe(exe_path) utils.print_title("Running smoke test") - smoke_test(exe_path, debug=debug) + smoke_test(exe_path, debug_build=debug) if skip_packaging: return [] From 184a2429371439ebddc280e3764a113a5be79ac2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 30 Nov 2025 18:35:05 +0100 Subject: [PATCH 19/30] ci: Make sure git knows the main branch Something seems to have changed about how sparse checkouts are done on GHA, so the main branch isn't found. --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c6b2e58f..6ac2736e2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,6 +110,7 @@ jobs: - name: Cherry-pick release commit if: ${{ inputs.release_type == 'patch' }} run: | + git fetch origin main git checkout main git cherry-pick -x v${{ steps.bump.outputs.version }} git push origin main From edd5114492b6b364f5f326db1ed04bc1acbc272e Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Sun, 30 Nov 2025 17:37:44 +0000 Subject: [PATCH 20/30] Release v3.6.3 (cherry picked from commit ee13dac7382dd4ff90aa4a3750a28ae06ce602b4) --- .bumpversion.toml | 2 +- doc/changelog.asciidoc | 2 +- misc/org.qutebrowser.qutebrowser.appdata.xml | 1 + qutebrowser/__init__.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.bumpversion.toml b/.bumpversion.toml index 4c78f7935..d0ee3d599 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "3.6.2" +current_version = "3.6.3" commit = true message = "Release v{new_version}" tag = true diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index f9e2766cd..faa04b7ba 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -16,7 +16,7 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Security` to invite users to upgrade in case of vulnerabilities. [[v3.6.3]] -v3.6.3 (unreleased) +v3.6.3 (2025-11-30) ------------------- Fixed diff --git a/misc/org.qutebrowser.qutebrowser.appdata.xml b/misc/org.qutebrowser.qutebrowser.appdata.xml index 457bcd393..dc677ccce 100644 --- a/misc/org.qutebrowser.qutebrowser.appdata.xml +++ b/misc/org.qutebrowser.qutebrowser.appdata.xml @@ -44,6 +44,7 @@ + diff --git a/qutebrowser/__init__.py b/qutebrowser/__init__.py index 34af13dd1..997172aef 100644 --- a/qutebrowser/__init__.py +++ b/qutebrowser/__init__.py @@ -14,7 +14,7 @@ __copyright__ = "Copyright 2013-{} Florian Bruhin (The Compiler)".format(_year) __license__ = "GPL-3.0-or-later" __maintainer__ = __author__ __email__ = "mail@qutebrowser.org" -__version__ = "3.6.2" +__version__ = "3.6.3" __version_info__ = tuple(int(part) for part in __version__.split('.')) __description__ = "A keyboard-driven, vim-like browser based on Python and Qt." From f2547f8a09d2b858f2e63bbd112576c4774ebea7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 30 Nov 2025 18:45:48 +0100 Subject: [PATCH 21/30] scripts: Make smoke test fail output less confusing --- scripts/dev/build_release.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index ab8844e6a..8dd3aa5c3 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -208,8 +208,12 @@ def smoke_test(executable: pathlib.Path, debug_build: bool) -> None: proc = _smoke_test_run(executable) except subprocess.CalledProcessError as e: print(f"Smoke test failed: {e}, running with --debug") - smoke_test_debug(executable, original_stdout=e.stdout.decode('utf-8'), - original_stderr=e.stderr.decode('utf-8')) + smoke_test_debug( + executable, + original_stdout=e.stdout.decode("utf-8"), + original_stderr=e.stderr.decode("utf-8"), + issue_description=str(e), + ) return if debug_build: @@ -221,11 +225,20 @@ def smoke_test(executable: pathlib.Path, debug_build: bool) -> None: if stdout or stderr: print("Unexpected output, running with --debug") - smoke_test_debug(executable, original_stdout=stdout, original_stderr=stderr) + smoke_test_debug( + executable, + original_stdout=stdout, + original_stderr=stderr, + issue_description="Unexpected output", + ) def smoke_test_debug( - executable: pathlib.Path, *, original_stdout: str, original_stderr: str + executable: pathlib.Path, + *, + original_stdout: str, + original_stderr: str, + issue_description: str, ) -> None: """Run smoke test in debug mode to get more output.""" proc = _smoke_test_run(executable, '--debug') @@ -233,7 +246,7 @@ def smoke_test_debug( debug_stderr = proc.stderr.decode('utf-8') lines = [ - "Unexpected output!", + issue_description, "", ] if original_stdout: From 3f9ef123e772d546aff7475bc3a76c3bb9ca489d Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Mon, 8 Dec 2025 04:29:09 +0000 Subject: [PATCH 22/30] Update dependencies --- misc/requirements/requirements-dev.txt | 7 +++---- misc/requirements/requirements-mypy.txt | 3 ++- misc/requirements/requirements-pylint.txt | 2 +- misc/requirements/requirements-pyqt-6.10.txt | 2 +- misc/requirements/requirements-pyqt-6.txt | 2 +- misc/requirements/requirements-pyqt.txt | 2 +- misc/requirements/requirements-pyroma.txt | 4 ++-- misc/requirements/requirements-sphinx.txt | 2 +- misc/requirements/requirements-tests.txt | 6 +++--- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index cd9ea4668..321d9d8e0 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py annotated-types==0.7.0 -anyio==4.11.0 +anyio==4.12.0 autocommand==2.2.2 backports.tarfile==1.2.0 bracex==2.6 @@ -47,7 +47,7 @@ Pygments==2.19.2 PyJWT==2.10.1 Pympler==1.1 pyproject_hooks==1.2.0 -PyQt-builder==1.19.0 +PyQt-builder==1.19.1 python-dateutil==2.9.0.post0 python-dotenv==1.2.1 questionary==2.1.1 @@ -60,7 +60,6 @@ rich-click==1.9.4 SecretStorage==3.3.3 sip==6.14.0 six==1.17.0 -sniffio==1.3.1 tomli==2.3.0 tomlkit==0.13.3 twine==6.2.0 @@ -68,7 +67,7 @@ typeguard==4.3.0 typing-inspection==0.4.2 typing_extensions==4.15.0 uritemplate==4.2.0 -# urllib3==2.5.0 +# urllib3==2.6.0 wcmatch==10.1 wcwidth==0.2.14 zipp==3.23.0 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 3b75558bd..4f89dadb3 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -3,9 +3,10 @@ chardet==5.2.0 diff_cover==9.7.2 Jinja2==3.1.6 +librt==0.7.3 lxml==6.0.2 MarkupSafe==3.0.3 -mypy==1.18.2 +mypy==1.19.0 mypy_extensions==1.1.0 pathspec==0.12.1 pluggy==1.6.0 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index f59cc3538..b2fed373a 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -24,5 +24,5 @@ tomli==2.3.0 tomlkit==0.13.3 typing_extensions==4.15.0 uritemplate==4.2.0 -# urllib3==2.5.0 +# urllib3==2.6.0 zipp==3.23.0 diff --git a/misc/requirements/requirements-pyqt-6.10.txt b/misc/requirements/requirements-pyqt-6.10.txt index 802128a67..a37b3b68a 100644 --- a/misc/requirements/requirements-pyqt-6.10.txt +++ b/misc/requirements/requirements-pyqt-6.10.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -PyQt6==6.10.0 +PyQt6==6.10.1 PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 PyQt6-WebEngine-Qt6==6.10.1 diff --git a/misc/requirements/requirements-pyqt-6.txt b/misc/requirements/requirements-pyqt-6.txt index 802128a67..a37b3b68a 100644 --- a/misc/requirements/requirements-pyqt-6.txt +++ b/misc/requirements/requirements-pyqt-6.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -PyQt6==6.10.0 +PyQt6==6.10.1 PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 PyQt6-WebEngine-Qt6==6.10.1 diff --git a/misc/requirements/requirements-pyqt.txt b/misc/requirements/requirements-pyqt.txt index 802128a67..a37b3b68a 100644 --- a/misc/requirements/requirements-pyqt.txt +++ b/misc/requirements/requirements-pyqt.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -PyQt6==6.10.0 +PyQt6==6.10.1 PyQt6-Qt6==6.10.1 PyQt6-WebEngine==6.10.0 PyQt6-WebEngine-Qt6==6.10.1 diff --git a/misc/requirements/requirements-pyroma.txt b/misc/requirements/requirements-pyroma.txt index b844c39cd..769261252 100644 --- a/misc/requirements/requirements-pyroma.txt +++ b/misc/requirements/requirements-pyroma.txt @@ -13,6 +13,6 @@ pyproject_hooks==1.2.0 pyroma==5.0 requests==2.32.5 tomli==2.3.0 -trove-classifiers==2025.11.14.15 -urllib3==2.5.0 +trove-classifiers==2025.12.1.14 +urllib3==2.6.0 zipp==3.23.0 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 42660ab5e..f03cd8132 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -22,5 +22,5 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==2.0.0 tomli==2.3.0 -urllib3==2.5.0 +urllib3==2.6.0 zipp==3.23.0 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index 0b69c7e36..a7adc8421 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -3,7 +3,7 @@ attrs==25.4.0 autocommand==2.2.2 backports.tarfile==1.2.0 -beautifulsoup4==4.14.2 +beautifulsoup4==4.14.3 blinker==1.9.0 certifi==2025.11.12 charset-normalizer==3.4.4 @@ -61,7 +61,7 @@ tldextract==5.3.0 tomli==2.3.0 typeguard==4.3.0 typing_extensions==4.15.0 -urllib3==2.5.0 +urllib3==2.6.0 vulture==2.14 -Werkzeug==3.1.3 +Werkzeug==3.1.4 zipp==3.23.0 From c32b7d4b60c91e02d48528c4fdc5ce1cbb6c1270 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 8 Dec 2025 10:53:13 +0100 Subject: [PATCH 23/30] Fix dependency update issues --- qutebrowser/misc/earlyinit.py | 1 + scripts/dev/changelog_urls.json | 1 + 2 files changed, 2 insertions(+) diff --git a/qutebrowser/misc/earlyinit.py b/qutebrowser/misc/earlyinit.py index 60d2c7c09..d1f1669a8 100644 --- a/qutebrowser/misc/earlyinit.py +++ b/qutebrowser/misc/earlyinit.py @@ -23,6 +23,7 @@ import datetime from typing import NoReturn try: import tkinter + import tkinter.messagebox except ImportError: tkinter = None # type: ignore[assignment] diff --git a/scripts/dev/changelog_urls.json b/scripts/dev/changelog_urls.json index 7c1ba32d9..9a9fe7269 100644 --- a/scripts/dev/changelog_urls.json +++ b/scripts/dev/changelog_urls.json @@ -23,6 +23,7 @@ "Mako": "https://docs.makotemplates.org/en/latest/changelog.html", "hypothesis": "https://hypothesis.readthedocs.io/en/latest/changes.html", "mypy": "https://github.com/python/mypy/blob/master/CHANGELOG.md", + "librt": "https://github.com/mypyc/librt/commits/master/", "types-PyYAML": "https://github.com/python/typeshed/commits/main/stubs/PyYAML", "types-colorama": "https://github.com/python/typeshed/commits/main/stubs/colorama", "types-docutils": "https://github.com/python/typeshed/commits/main/stubs/docutils", From bc72687d7dcdf57822021d626e983c20d4a9bc90 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 8 Dec 2025 16:55:52 +0100 Subject: [PATCH 24/30] Update changelog URLs --- scripts/dev/changelog_urls.json | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/dev/changelog_urls.json b/scripts/dev/changelog_urls.json index 9a9fe7269..0b49ada48 100644 --- a/scripts/dev/changelog_urls.json +++ b/scripts/dev/changelog_urls.json @@ -102,7 +102,6 @@ "h11": "https://h11.readthedocs.io/en/latest/changes.html", "httpcore": "https://github.com/encode/httpcore/blob/master/CHANGELOG.md", "httpx": "https://github.com/encode/httpx/blob/master/CHANGELOG.md", - "sniffio": "https://sniffio.readthedocs.io/en/latest/history.html", "six": "https://github.com/benjaminp/six/blob/master/CHANGES", "altgraph": "https://github.com/ronaldoussoren/altgraph/blob/master/doc/changelog.rst", "urllib3": "https://github.com/urllib3/urllib3/blob/main/CHANGES.rst", From 12bed611c5f187112f99b228ff7e07f4c098ef19 Mon Sep 17 00:00:00 2001 From: qutebrowser bot Date: Mon, 15 Dec 2025 04:35:46 +0000 Subject: [PATCH 25/30] Update dependencies --- misc/requirements/requirements-dev.txt | 4 ++-- misc/requirements/requirements-mypy.txt | 2 +- misc/requirements/requirements-pylint.txt | 2 +- misc/requirements/requirements-pyroma.txt | 4 ++-- misc/requirements/requirements-sphinx.txt | 2 +- misc/requirements/requirements-tests.txt | 2 +- misc/requirements/requirements-tox.txt | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 321d9d8e0..33b28204c 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -6,7 +6,7 @@ autocommand==2.2.2 backports.tarfile==1.2.0 bracex==2.6 build==1.3.0 -bump-my-version==1.2.4 +bump-my-version==1.2.5 certifi==2025.11.12 cffi==2.0.0 charset-normalizer==3.4.4 @@ -67,7 +67,7 @@ typeguard==4.3.0 typing-inspection==0.4.2 typing_extensions==4.15.0 uritemplate==4.2.0 -# urllib3==2.6.0 +# urllib3==2.6.2 wcmatch==10.1 wcwidth==0.2.14 zipp==3.23.0 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 4f89dadb3..32e42a231 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py chardet==5.2.0 -diff_cover==9.7.2 +diff_cover==10.0.0 Jinja2==3.1.6 librt==0.7.3 lxml==6.0.2 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index b2fed373a..432386f55 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -24,5 +24,5 @@ tomli==2.3.0 tomlkit==0.13.3 typing_extensions==4.15.0 uritemplate==4.2.0 -# urllib3==2.6.0 +# urllib3==2.6.2 zipp==3.23.0 diff --git a/misc/requirements/requirements-pyroma.txt b/misc/requirements/requirements-pyroma.txt index 769261252..3558f0a69 100644 --- a/misc/requirements/requirements-pyroma.txt +++ b/misc/requirements/requirements-pyroma.txt @@ -10,9 +10,9 @@ importlib_metadata==8.7.0 packaging==25.0 Pygments==2.19.2 pyproject_hooks==1.2.0 -pyroma==5.0 +pyroma==5.0.1 requests==2.32.5 tomli==2.3.0 trove-classifiers==2025.12.1.14 -urllib3==2.6.0 +urllib3==2.6.2 zipp==3.23.0 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index f03cd8132..e5ff746d1 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -22,5 +22,5 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==2.0.0 tomli==2.3.0 -urllib3==2.6.0 +urllib3==2.6.2 zipp==3.23.0 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index a7adc8421..30bd927fa 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -61,7 +61,7 @@ tldextract==5.3.0 tomli==2.3.0 typeguard==4.3.0 typing_extensions==4.15.0 -urllib3==2.6.0 +urllib3==2.6.2 vulture==2.14 Werkzeug==3.1.4 zipp==3.23.0 diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt index 929fe4135..3256e0af4 100644 --- a/misc/requirements/requirements-tox.txt +++ b/misc/requirements/requirements-tox.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -cachetools==6.2.2 +cachetools==6.2.3 chardet==5.2.0 colorama==0.4.6 distlib==0.4.0 From 65c1ca96912811194820a444264ff8bf78d13bf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 18:04:22 +0000 Subject: [PATCH 26/30] build(deps): bump actions/cache from 4 to 5 Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f100d9a4b..79d091b91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: | .mypy_cache @@ -220,7 +220,7 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: | .mypy_cache From 615cee7309224dc54e6b07da1ed98ed52749201e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 18:04:15 +0000 Subject: [PATCH 27/30] build(deps): bump actions/upload-artifact from 5 to 6 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/bleeding.yml | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/nightly.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bleeding.yml b/.github/workflows/bleeding.yml index 227ee16cd..29441f3a7 100644 --- a/.github/workflows/bleeding.yml +++ b/.github/workflows/bleeding.yml @@ -48,7 +48,7 @@ jobs: shell: bash if: failure() - name: Upload screenshots - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.image }}" path: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79d091b91..9d65407b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,7 +121,7 @@ jobs: shell: bash if: failure() - name: Upload screenshots - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.image }}" path: | @@ -269,7 +269,7 @@ jobs: shell: bash if: failure() - name: Upload screenshots - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.testenv }}-${{ matrix.os }}" path: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8f42d42ee..9981a1e6d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -72,7 +72,7 @@ jobs: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" shell: bash - name: Upload artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: "qutebrowser-nightly-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.name }}" path: | From b417f2a23ba05fe1f0e840c25e1dbaeecb1e63b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 18:04:09 +0000 Subject: [PATCH 28/30] build(deps): bump peter-evans/create-pull-request from 7 to 8 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7 to 8. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v7...v8) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/recompile-requirements.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/recompile-requirements.yml b/.github/workflows/recompile-requirements.yml index 07f11428e..9e3e44cb6 100644 --- a/.github/workflows/recompile-requirements.yml +++ b/.github/workflows/recompile-requirements.yml @@ -41,7 +41,7 @@ jobs: - name: Run qutebrowser smoke test run: "xvfb-run .venv/bin/python3 -m qutebrowser --no-err-windows --nowindow --temp-basedir about:blank ':later 500 quit'" - name: Create pull request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: committer: qutebrowser bot author: qutebrowser bot From 9ae082b29b2c20288b3107be9e517dd2ff54d005 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 26 Dec 2025 14:25:36 +0100 Subject: [PATCH 29/30] version: Add QtWebEngine 6.9.3 --- qutebrowser/utils/version.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 0d0598ca5..2eb67838a 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -654,6 +654,7 @@ class WebEngineVersions: utils.VersionNumber(6, 9): (_BASES[130], '133.0.6943.141'), # 2025-02-25 utils.VersionNumber(6, 9, 1): (_BASES[130], '136.0.7103.114'), # 2025-05-13 utils.VersionNumber(6, 9, 2): (_BASES[130], '139.0.7258.67'), # 2025-07-29 + utils.VersionNumber(6, 9, 3): (_BASES[130], '140.0.7339.207'), # 2025-09-22 ## Qt 6.10 utils.VersionNumber(6, 10): (_BASES[134], '140.0.7339.207'), # 2025-09-22 From 7e3df43463d16815e8d29fee1b11489de688dee9 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 4 Jan 2026 22:24:28 +0100 Subject: [PATCH 30/30] Disable child focus workaround on unaffected Qt versions The workaround added for #7820 seems to cause datalist dropdowns to lose focus on Wayland. Let's just disable the old workaround on Qt versions that are not affected by the original issue, which seems to be Qt 6.6.3+. Fixes #8831. --- doc/changelog.asciidoc | 11 +++++++++++ qutebrowser/browser/eventfilter.py | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index faa04b7ba..bdc7529a3 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -15,6 +15,17 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Fixed` for any bug fixes. // `Security` to invite users to upgrade in case of vulnerabilities. +[[v3.6.4]] +v3.6.4 (unreleased) +------------------- + +Fixed +~~~~~ + +- datalist dropdowns not opening correctly on Wayland/Sway (#8831). + This was caused by an old workaround for a different QtWebEngine issue, + which is now disabled for QtWebEngine 6.6.3 and newer. + [[v3.6.3]] v3.6.3 (2025-11-30) ------------------- diff --git a/qutebrowser/browser/eventfilter.py b/qutebrowser/browser/eventfilter.py index 2e6cc3a2c..db01e8613 100644 --- a/qutebrowser/browser/eventfilter.py +++ b/qutebrowser/browser/eventfilter.py @@ -10,7 +10,7 @@ from qutebrowser.qt.gui import QKeyEvent from qutebrowser.qt.widgets import QWidget from qutebrowser.config import config -from qutebrowser.utils import log, message, usertypes, qtutils +from qutebrowser.utils import log, message, usertypes, qtutils, version, utils from qutebrowser.keyinput import modeman, keyutils @@ -55,16 +55,16 @@ class ChildEventFilter(QObject): # - This is a child event filter on a tab (self._widget is not None) # - We find an old existing child which is a QQuickWidget and is # currently focused. - # - We're using QtWebEngine >= 6.4 (older versions are not affected) + # - We're using an affected QtWebEngine version children = [ c for c in self._widget.findChildren( QWidget, "", Qt.FindChildOption.FindDirectChildrenOnly) if c is not child and c.hasFocus() and c.metaObject() is not None and - c.metaObject().className() == "QQuickWidget" + c.metaObject().className() == "QQuickWidget" # Qt 6.4+ ] - if children: + if children and version.qtwebengine_versions().webengine < utils.VersionNumber(6, 6, 3): log.misc.debug("Focusing new child") child.setFocus()