Compare commits

...
Sign in to create a new pull request.

110 commits

Author SHA1 Message Date
Jan Grulich
082bad2484 Fix crash in QWaylandShmBackingStore::scroll() 2025-12-22 16:15:39 +01:00
Jan Grulich
af0ef1e954 Re-add wayland fixes for mouse scrolling 2025-12-08 08:17:21 +01:00
Jan Grulich
67c126dc18 6.10.1 2025-11-20 08:59:53 +01:00
Jan Grulich
2ff34253dc Backport wayland fixes for mouse scrolling 2025-11-10 11:20:53 +01:00
Jan Grulich
045b22d4d6 Backport: Wayland - convey preference for server side decorations 2025-10-29 14:29:28 +01:00
Jan Grulich
05ee0b98b4 6.10.0 2025-10-07 10:34:47 +02:00
Gwyn Ciesla
07c9cbcba0 Firebird 5 rebuild 2025-09-30 11:07:46 -05:00
Jan Grulich
1646c99cab 6.10.0 RC 2025-09-25 12:17:25 +02:00
Jan Grulich
060d33bcdd 6.9.2 2025-08-28 13:01:40 +02:00
František Zatloukal
362bc3dbd4 Rebuilt for icu 77.1 2025-08-05 23:55:00 +02:00
Adam Williamson
0e85496669 Adjust for https://fedoraproject.org/wiki/Changes/dropingOfCertPemFile removals
Backport of https://codereview.qt-project.org/c/qt/qtbase/+/664056
2025-07-28 14:25:11 -07:00
Fedora Release Engineering
ed748d94e8 Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild 2025-07-25 11:33:58 +00:00
Jan Grulich
fe42bba4fc 6.9.1 2025-06-02 13:34:16 +02:00
Jan Grulich
ba0d907174 Fix possible crash in FontConfig database 2025-04-28 08:26:13 +02:00
Jan Grulich
49cf38aa7e 6.9.0 2025-04-02 09:58:38 +02:00
Jan Grulich
e21e53a974 6.9.0 RC 2025-03-21 13:30:18 +01:00
Jan Grulich
c8038a82ef Fix rendering of combined emojis 2025-02-13 12:55:13 +01:00
Jan Grulich
075288afad Use -DFEATURE instead -DQT_FEATURE for additional compatibility checks 2025-02-10 16:17:48 +01:00
Jan Grulich
0038317cfd Backport recommended fixes for Qt 6.8.2 2025-02-06 08:09:55 +01:00
Jan Grulich
a7de194fac 6.8.2 2025-01-31 11:34:47 +01:00
Jan Grulich
0eed16eaa6 Backport additional fixes for emoji support 2025-01-16 13:22:41 +01:00
Jan Grulich
3761490634 Fix directory ownership for 3rdparty cmake plugins 2025-01-13 09:43:35 +01:00
Jan Grulich
ded6d85556 Fix directory ownership
Resolves: rhbz#2292582
2025-01-09 16:54:00 +01:00
Jan Grulich
f4d62f7183 Install CMake modules for plugins 2025-01-08 18:56:00 +01:00
Yaakov Selkowitz
a9b6dadcd4 Depend on pkgconfig(egl) rather than mesa-libEGL-devel
mesa-libEGL-devel contains only headers for Mesa-specific extensions which
are not used directly.  libglvnd-devel provides the generic EGL interface
which suffices for building qt6.
2024-12-25 21:47:21 -05:00
Jan Grulich
6241001d9e Fix QGnomePlatform obsoletes 2024-12-17 15:31:02 +01:00
Jan Grulich
242876ebc6 Backport additional fixes for emoji support 2024-12-16 11:39:01 +01:00
Jan Grulich
63b1fe1f85 Move libcupsprintersupport back to -gui as it depends on gui libs 2024-12-11 09:30:28 +01:00
Jan Grulich
2fa0a54714 Obsolete QGnomePlatform and AdwaitaQt 2024-12-10 08:27:08 +01:00
Jan Grulich
0b0b5cbeb5 Move all mkspecs to -devel 2024-12-07 20:04:58 +01:00
Jan Grulich
6e6a701e43 Re-enable Software Bill of Materials 2024-12-05 15:10:37 +01:00
Jan Grulich
11497bfc6c Move more stuff into -private-devel 2024-12-05 14:48:26 +01:00
Jan Grulich
b4fdf6efe1 Do not install ExamplesAssetDownloader 2024-12-03 09:13:43 +01:00
Jan Grulich
d6857833fc 6.8.1 2024-12-02 13:33:22 +01:00
Jan Grulich
6c56598daf Backport - a11y atspi: Watch for enabled status change 2024-10-21 13:02:32 +02:00
Jan Grulich
bb9c0035d2 QtPrintSupport: make cups optional target 2024-10-16 17:06:09 +02:00
Jan Grulich
a6377f834c Backport fix for QAbstractItemModel (kdebz#493116) 2024-10-09 17:32:11 +02:00
Jan Grulich
45a4e4a212 6.8.0 2024-10-09 13:01:27 +02:00
Jan Grulich
ca94b24afb Backport - QWidget: store initialScreen as QPointer 2024-09-04 09:33:35 +02:00
Fedora Release Engineering
6331876a3f Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild 2024-07-19 17:54:00 +00:00
Jan Grulich
fe4178778c Additional directory ownership fixes 2024-07-15 13:27:09 +02:00
Jan Grulich
b50f64242c Drop more directories that are now owned by qt6-filesystem 2024-07-15 12:09:19 +02:00
Jan Grulich
3cb17721af Use qt6-filesystem 2024-07-15 11:04:12 +02:00
Jan Grulich
15628f0e25 HTTP2: Delay any communication until encrypted() can be responded to
Resolves: CVE-2024-39936
2024-07-08 09:32:57 +02:00
Jan Grulich
cd6fef471a Revert: Consider versioned targets when checking the existens in
__qt_internal_walk_libs
2024-07-03 09:29:27 +02:00
Jan Grulich
3267aafcbb 6.7.2 2024-07-01 11:37:48 +02:00
Jan Grulich
2a85af4599 Use only major.minor version for private api tag 2024-05-21 20:34:19 +02:00
Jan Grulich
44c251b0c8 6.7.1 2024-05-21 11:34:26 +02:00
Jan Grulich
941d538dc2 QGtk3Theme: Add support for xdg-desktop-portal to get color scheme 2024-05-07 14:40:24 +02:00
Jan Grulich
4c4536c70a Use bundled double-conversion in RHEL builds 2024-04-24 13:51:51 +02:00
Jan Grulich
b91edca719 Rebuild (gcc rhbz#2272758) 2024-04-12 10:20:44 +02:00
Jan Grulich
c886489d1a Upstream backport: Use ifdef instead of if for __cpp_lib_span 2024-04-08 09:06:55 +02:00
Jan Grulich
7536e20866 6.7.0 2024-04-02 15:01:31 +02:00
Alessandro Astone
8b9fc48122 Move /usr/bin/qtpaths-qt6 to main package 2024-03-09 22:50:11 +01:00
David Abdurachmanov
788c6f4ce1 Disable SSE2 on riscv64
Signed-off-by: David Abdurachmanov <davidlt@rivosinc.com>
2024-03-01 11:41:53 +00:00
Neal Gompa
62dc027ecb Use wlheadless-run for tests instead of xvfb-run
We want to test on Wayland by default going forward, so switching
to wlheadless-run will allow that.
2024-02-23 19:18:34 -05:00
Jan Grulich
6d58d80c94 Bump build for examples change 2024-02-19 19:56:36 +01:00
Jan Grulich
906374f04f Examples: also install source files 2024-02-19 19:02:34 +01:00
Marie Loise Nolden
49bbb6d2e6 fix condition 2024-02-15 17:43:01 +00:00
Jan Grulich
7440c8d5f5 6.6.2 2024-02-15 10:20:53 +01:00
Pete Walter
9e6f9d15b8 Rebuild for ICU 74 2024-01-31 20:12:18 +00:00
Fedora Release Engineering
9617d2aec3 Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild 2024-01-26 14:16:13 +00:00
Fedora Release Engineering
163ea650a8 Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild 2024-01-22 09:57:36 +00:00
Timothée Ravier
c095cdd4b6 Minor whitespace fix 2023-12-12 16:24:27 +01:00
Timothée Ravier
8c8bebcc6b Recommend qt6-qttranslations
Required for some locales.

See: https://pagure.io/fedora-kde/SIG/issue/311
2023-12-12 16:23:32 +01:00
Jan Grulich
0916bd3f34 6.6.1 2023-11-27 14:57:46 +01:00
Alessandro Astone
4d5e0869d8 Add xkbcommon as a devel dependency
Optional dev dependency of Qt6::Gui
2023-11-10 18:29:27 +01:00
Jan Grulich
469e3a8860 Revert: Fix Qt not showing up emoji by handling emoji font family 2023-11-09 12:54:48 +01:00
Jan Grulich
a44bfe9ca5 Fix Qt not showing up emoji by handling emoji font family 2023-11-07 15:55:23 +01:00
Jan Grulich
a19a7d36f9 Upstream backports
- a11y - fix race condition on atspi startup on Wayland
2023-11-06 09:52:37 +01:00
Jan Grulich
66655b0bf6 Do not use tslib on RHEL builds 2023-10-23 08:24:07 +02:00
Neal Gompa
d130b7be6c Add qtwayland weak dep to -gui subpackage and use arched weak deps 2023-10-15 08:58:53 -04:00
Jan Grulich
a0b5aa05f9 6.6.0 2023-10-10 14:42:17 +02:00
Justin Zobel
1149fa7db3 Fix sources 2023-10-01 16:28:04 +10:30
Justin Zobel
f7e88d6ae1 Update to 6.5.3 2023-10-01 15:58:07 +10:30
LuK1337
ca477f48a6 Unbreak CMake Qt6::ExampleIconsPrivate package
This fixes build for the following CMakeLists.txt:
  cmake_minimum_required(VERSION 3.18)
  project(hello)
  find_package(Qt6 COMPONENTS ExampleIconsPrivate)
2023-09-17 11:37:37 +02:00
Yaakov Selkowitz
7f9c50ebd7 Use bundled libb2 in RHEL builds
Standalone libb2 is unwanted in RHEL.
2023-08-28 21:01:30 -04:00
Jan Grulich
fed7db12b2 Don't use QGnomePlatform by default on F39+ 2023-08-11 14:52:10 +02:00
Fedora Release Engineering
3e8f6395e9 Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2023-07-21 16:11:01 +00:00
Jan Grulich
e0efab4a30 6.5.2 2023-07-21 10:28:02 +02:00
František Zatloukal
b4166db60e Rebuilt for ICU 73.2 2023-07-12 17:00:21 +02:00
Jan Grulich
d487a7a9a0 Bump build for private API version change 2023-07-12 12:58:51 +02:00
František Zatloukal
9911d344d7 Rebuilt for ICU 73.2 2023-07-11 22:21:36 +02:00
Yaakov Selkowitz
8abd8fe461 Update PCRE build dependencies
The runtime builds show a proper dependency on libpcre2-16, so an
immediate revbump and rebuild doesn't seem necessary.
2023-07-10 13:37:04 -04:00
Jan Grulich
840cea88e5 Don't track patch version for private API version 2023-05-30 07:15:10 +02:00
Jan Grulich
43d39197e0 6.5.1 2023-05-24 12:48:13 +02:00
Jan Grulich
3aeb3c66cf Restore 'tell-truth-about-private-API' patch 2023-05-09 09:07:41 +02:00
Marie Loise Nolden
6a5e0a5ba5 fix qt6-qtbase build for xcb platform plugin, cleanup
- fix xcb plugin with new dependency xcb-cursor instead of Xcursor
  introduction with qt 6.5, add firebird sql plugin cleanly, clean up spec file
2023-04-07 21:31:35 +00:00
Jan Grulich
6ba649eb42 Cleanup commented files 2023-04-04 12:33:10 +02:00
Jan Grulich
d932499e6c 6.5.0 2023-04-03 15:38:48 +02:00
Jan Grulich
4dccb8dee5 Enable zstd support 2023-04-03 07:07:42 +02:00
Jan Grulich
9b51c9bf9c Drop already upstreamed patch 2023-03-23 09:32:50 +01:00
Jan Grulich
363b5428f2 6.4.3 2023-03-23 09:13:06 +01:00
Jan Grulich
7d3e08b1e7 Bump build 2023-03-05 10:01:23 +01:00
Jan Grulich
b5b7a896a3 Use QGnomePlatform as default platform theme on GNOME
Resolves: bz#2174905
2023-03-05 09:56:44 +01:00
Jan Grulich
f30f363ff0 Fix possible DOS involving the Qt SQL ODBC driver plugin
CVE-2023-24607
2023-02-08 13:45:43 +01:00
Jan Grulich
43952a81ef migrated to SPDX license 2023-01-31 14:59:36 +01:00
Fedora Release Engineering
f94edcc9d7 Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2023-01-20 19:09:58 +00:00
Jan Grulich
8bec765f63 Update sources 2023-01-16 13:59:58 +01:00
Jan Grulich
84d0798348 6.4.2 2023-01-16 13:26:16 +01:00
Jan Grulich
2dae87e686 Make -devel package to require database plugins 2023-01-02 11:17:22 +01:00
Pete Walter
a6edf5db6b Rebuild for ICU 72 2022-12-31 03:17:39 +00:00
Pavel Raiskup
3614026fd3 Rebuild for PostgreSQL 15, without "server" dependency
This drops the generated dependancy on "private" libpq library:

can't install qt6-qtbase-postgresql:
  - nothing provides libpq.so.private14-5()(64bit) needed by qt6-qtbase-postgresql-6.4.1-1.fc38.x86_64

Resolves: rhbz#2149924
2022-12-03 10:59:04 +01:00
Jan Grulich
9ef11a90cc 6.4.1 2022-11-23 11:10:51 +01:00
Jan Grulich
752eade0a7 6.4.0 2022-10-31 11:09:07 +01:00
František Zatloukal
afa40266fd Rebuilt for ICU 71.1 2022-08-01 15:09:37 +02:00
Jan Grulich
e1c0e0acc5 Fix moc location in pkgconfig file 2022-07-29 08:23:56 +02:00
Fedora Release Engineering
964d73e1e6 Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2022-07-23 00:11:23 +00:00
Jan Grulich
39c645ff6b 6.3.1 2022-07-13 12:29:40 +02:00
Jan Grulich
1b784de7b0 6.3.0 2022-04-13 15:13:10 +02:00
15 changed files with 1453 additions and 242 deletions

27
.gitignore vendored
View file

@ -12,3 +12,30 @@
/qtbase-everywhere-src-6.2.1.tar.xz
/qtbase-everywhere-src-6.2.2.tar.xz
/qtbase-everywhere-src-6.2.3.tar.xz
/qtbase-everywhere-src-6.3.0.tar.xz
/qtbase-everywhere-src-6.3.1.tar.xz
/qtbase-everywhere-src-6.4.0.tar.xz
/qtbase-everywhere-src-6.4.1.tar.xz
/qtbase-everywhere-src-6.4.2.tar.xz
/qtbase-everywhere-src-6.4.3.tar.xz
/qtbase-everywhere-src-6.5.0.tar.xz
/qtbase-everywhere-src-6.5.1.tar.xz
/qtbase-everywhere-src-6.5.2.tar.xz
/qt-everywhere-src-6.5.3.tar.xz
/qtbase-everywhere-src-6.5.3.tar.xz
/qtbase-everywhere-src-6.6.0.tar.xz
/qtbase-everywhere-src-6.6.1.tar.xz
/qtbase-everywhere-src-6.6.2.tar.xz
/qtbase-everywhere-src-6.7.0.tar.xz
/qtbase-everywhere-src-6.7.1.tar.xz
/qtbase-everywhere-src-6.7.2.tar.xz
/qtbase-everywhere-src-6.8.0.tar.xz
/qtbase-everywhere-src-6.8.1.tar.xz
/qtbase-everywhere-src-6.8.2.tar.xz
/qtbase-everywhere-src-6.9.0-rc.tar.xz
/qtbase-everywhere-src-6.9.0.tar.xz
/qtbase-everywhere-src-6.9.1.tar.xz
/qtbase-everywhere-src-6.9.2.tar.xz
/qtbase-everywhere-src-6.10.0-rc.tar.xz
/qtbase-everywhere-src-6.10.0.tar.xz
/qtbase-everywhere-src-6.10.1.tar.xz

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
From 4e517492a03b6c0b710a2d9a3df05922ac233992 Mon Sep 17 00:00:00 2001
From: Christophe Marin <christophe@krop.fr>
Date: Wed, 24 May 2023 11:23:39 +0200
Subject: [PATCH] CMake: Install objects files into 'ARCHDATADIR'
Change-Id: I917a9ef4d83f93eb5c3e47964bf1814d1b53fdab
---
cmake/QtResourceHelpers.cmake | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/cmake/QtResourceHelpers.cmake b/cmake/QtResourceHelpers.cmake
index 2df1fed50f..e4f34b5ff1 100644
--- a/cmake/QtResourceHelpers.cmake
+++ b/cmake/QtResourceHelpers.cmake
@@ -38,7 +38,7 @@ function(qt_internal_add_resource target resourceName)
if (out_targets)
qt_install(TARGETS ${out_targets}
EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets"
- DESTINATION "${INSTALL_LIBDIR}"
+ DESTINATION "${INSTALL_ARCHDATADIR}"
)
qt_internal_add_targets_to_additional_targets_export_file(
TARGETS ${out_targets}
@@ -47,7 +47,7 @@ function(qt_internal_add_resource target resourceName)
qt_internal_install_resource_pdb_files("${out_targets}")
qt_internal_record_rcc_object_files("${target}" "${out_targets}"
- INSTALL_DIRECTORY "${INSTALL_LIBDIR}")
+ INSTALL_DIRECTORY "${INSTALL_ARCHDATADIR}")
endif()
if (arg_OUTPUT_TARGETS)
@@ -77,7 +77,7 @@ function(qt_internal_record_rcc_object_files target resource_targets)
# It's comprised of thee following path parts:
#
# part (1) INSTALL_DIRECTORY.
- # A usual value is '${INSTALL_LIBDIR}/' for libraries
+ # A usual value is '${INSTALL_ARCHDATADIR}/' for libraries
# and '${INSTALL_QMLDIR}/foo/bar/' for qml plugin resources.
#
# part (2) the value computed by CMake's computeInstallObjectDir comprised of an
@@ -128,6 +128,6 @@ function(qt_internal_install_resource_pdb_files objlib_targets)
_qt_resource_generated_cpp_relative_path)
get_filename_component(rel_obj_file_dir "${generated_cpp_file_relative_path}" DIRECTORY)
qt_internal_install_pdb_files(${target}
- "${INSTALL_LIBDIR}/objects-$<CONFIG>/${target}/${rel_obj_file_dir}")
+ "${INSTALL_ARCHDATADIR}/objects-$<CONFIG>/${target}/${rel_obj_file_dir}")
endforeach()
endfunction()
--
2.40.1

View file

@ -1,36 +0,0 @@
diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.h b/examples/corelib/tools/contiguouscache/randomlistmodel.h
index 1fabb0d9..393ebaa3 100644
--- a/examples/corelib/tools/contiguouscache/randomlistmodel.h
+++ b/examples/corelib/tools/contiguouscache/randomlistmodel.h
@@ -50,6 +50,7 @@
#ifndef RANDOMLISTMODEL_H
#define RANDOMLISTMODEL_H
+#include <limits>
#include <QContiguousCache>
#include <QAbstractListModel>
diff --git a/src/corelib/text/qanystringview.h b/src/corelib/text/qanystringview.h
index a7606253..60747cf0 100644
--- a/src/corelib/text/qanystringview.h
+++ b/src/corelib/text/qanystringview.h
@@ -39,6 +39,7 @@
#ifndef QANYSTRINGVIEW_H
#define QANYSTRINGVIEW_H
+#include <limits>
#include <QtCore/qstringview.h>
#include <QtCore/qutf8stringview.h>
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 9f646aaa..a5af793c 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -41,6 +41,7 @@
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
+#include <limits>
#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qarraydata.h>

View file

@ -1,9 +0,0 @@
diff -up qtbase-everywhere-src-5.11.1/mkspecs/features/uikit/devices.py.me qtbase-everywhere-src-5.11.1/mkspecs/features/uikit/devices.py
--- qtbase-everywhere-src-5.11.1/mkspecs/features/uikit/devices.py.me 2018-06-23 11:29:21.750066271 +0200
+++ qtbase-everywhere-src-5.11.1/mkspecs/features/uikit/devices.py 2018-06-23 11:30:07.457292033 +0200
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
#############################################################################
##

View file

@ -1,16 +0,0 @@
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 3cacc8df..469e6f50 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -218,9 +218,9 @@ android: CONFIG += qt_android_deps no_linker_version_script
QMAKE_LFLAGS += $${QMAKE_LFLAGS_VERSION_SCRIPT}$$verscript
internal_module {
- verscript_content = "Qt_$${QT_MAJOR_VERSION}_PRIVATE_API { *; };"
+ verscript_content = "Qt_$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}_PRIVATE_API { *; };"
} else {
- verscript_content = "Qt_$${QT_MAJOR_VERSION}_PRIVATE_API {" \
+ verscript_content = "Qt_$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}_PRIVATE_API {" \
" qt_private_api_tag*;"
private_api_headers = $$SYNCQT.PRIVATE_HEADER_FILES $$SYNCQT.QPA_HEADER_FILES

View file

@ -0,0 +1,13 @@
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index 6a62b85c..1fc1f88d 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -71,7 +71,7 @@ function(qt_internal_add_linker_version_script target)
string(APPEND contents "\n};\nQt_${PROJECT_VERSION_MAJOR}")
if(QT_FEATURE_elf_private_full_version)
- string(APPEND contents ".${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+ string(APPEND contents ".${PROJECT_VERSION_MINOR}")
endif()
string(APPEND contents "_PRIVATE_API { qt_private_api_tag*;\n")
if(arg_PRIVATE_HEADERS)

View file

@ -0,0 +1,12 @@
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp
index 1efd759b..d0129f73 100644
--- a/src/gui/platform/unix/qgenericunixthemes.cpp
+++ b/src/gui/platform/unix/qgenericunixthemes.cpp
@@ -977,6 +977,7 @@ QStringList QGenericUnixTheme::themeNames()
result.push_back(QLatin1StringView(QKdeTheme::name));
#endif
} else if (gtkBasedEnvironments.contains(desktopName)) {
+ result.push_back(QStringLiteral("qgnomeplatform"));
// prefer the GTK3 theme implementation with native dialogs etc.
result.push_back(QStringLiteral("gtk3"));
// fallback to the generic Gnome theme if loading the GTK3 theme fails

View file

@ -1,13 +1,13 @@
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index c6b5c5a9..bb0076b3 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -58,7 +58,7 @@
diff --git a/src/corelib/global/qtversionchecks.h b/src/corelib/global/qtversionchecks.h
index d3b7a7b0..a8b9c6f3 100644
--- a/src/corelib/global/qtversionchecks.h
+++ b/src/corelib/global/qtversionchecks.h
@@ -26,7 +26,7 @@
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
*/
-#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+#define QT_VERSION_CHECK(qt_version_check_major, qt_version_check_minor, qt_version_check_patch) ((qt_version_check_major<<16)|(qt_version_check_minor<<8)|(qt_version_check_patch))
#ifdef QT_BOOTSTRAPPED
#include <QtCore/qconfig-bootstrapped.h>
/*
Helper macros to make some simple code active in Qt 6 or Qt 7 only,

View file

@ -0,0 +1,174 @@
From 095759818854e5a011aa8f859e566bbc6368ab76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
Date: Sun, 27 Jul 2025 00:50:00 +0200
Subject: [PATCH] wayland: Compress high frequency mouse events
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add support for Qt::AA_CompressHighFrequencyEvents on Wayland.
The highest USB HID polling rate is 8 kHz (125 μs). Most mice use lower
polling rate [125 Hz - 1000 Hz]. Reject all events faster than 100 μs,
because it definitely means the application main thread is freezed by
the long operation and events are delivered one after another from the
queue. Since now we rely on the 0 ms timer to deliver the last pending
event when application main thread is no longer freezed.
Pick-to: 6.10
Task-number: QTBUG-138706
Change-Id: Ie9d539e233c5551b1756d599b65495571e195f9d
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
src/corelib/global/qnamespace.qdoc | 1 +
.../platforms/wayland/qwaylandinputdevice.cpp | 38 +++++++++++++++++++
.../platforms/wayland/qwaylandinputdevice_p.h | 12 ++++++
.../platforms/wayland/qwaylandintegration.cpp | 2 +
tests/auto/wayland/client/tst_client.cpp | 2 +
5 files changed, 55 insertions(+)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index c845cfa7..f463d736 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -227,6 +227,7 @@
application later.
On Windows 8 and above the default value is also true, but it only applies
to touch events. Mouse and window events remain unaffected by this flag.
+ On Wayland the default value is also true, but it only applies to mouse events.
On other platforms, the default is false.
(In the future, the compression feature may be implemented across platforms.)
You can test the attribute to see whether compression is enabled.
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index 170e80f8..45c78765 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -63,6 +63,34 @@ Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input");
// reasonable number of them. As of 2021 most touchscreen panels support 10 concurrent touchpoints.
static const int MaxTouchPoints = 10;
+QWaylandEventCompressionPrivate::QWaylandEventCompressionPrivate()
+{
+ timeElapsed.start();
+ delayTimer.setSingleShot(true);
+}
+
+bool QWaylandEventCompressionPrivate::compressEvent()
+{
+ using namespace std::chrono_literals;
+
+ if (!QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents))
+ return false;
+
+ const auto elapsed = timeElapsed.durationElapsed();
+ timeElapsed.start();
+ if (elapsed < 100us || delayTimer.isActive())
+ {
+ // The highest USB HID polling rate is 8 kHz (125 μs). Most mice use lowe polling rate [125 Hz - 1000 Hz].
+ // Reject all events faster than 100 μs, because it definitely means the application main thread is
+ // freezed by long operation and events are delivered one after another from the queue. Since now we rely
+ // on the 0 ms timer to deliver the last pending event when application main thread is no longer freezed.
+ delayTimer.start(0);
+ return true;
+ }
+
+ return false;
+}
+
QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
: mParent(p)
{
@@ -140,6 +168,8 @@ QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
cursorTimerCallback();
});
#endif
+
+ mEventCompression.delayTimer.callOnTimeout(this, &QWaylandInputDevice::Pointer::flushFrameEvent);
}
QWaylandInputDevice::Pointer::~Pointer()
@@ -922,6 +952,11 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
void QWaylandInputDevice::Pointer::pointer_frame()
{
+ if (mEventCompression.compressEvent()) {
+ qCDebug(lcQpaWaylandInput) << "compressed pointer_frame event";
+ return;
+ }
+
flushFrameEvent();
}
@@ -1051,6 +1086,7 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
flushFrameEvent();
}
+ delete mFrameData.event;
mFrameData.event = event;
if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
@@ -1170,6 +1206,8 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
void QWaylandInputDevice::Pointer::flushFrameEvent()
{
+ mEventCompression.delayTimer.stop();
+
if (auto *event = mFrameData.event) {
if (auto window = event->surface) {
window->handleMouse(mParent, *event);
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
index bcaf0258..0b24999e 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
@@ -75,6 +75,16 @@ class CursorSurface;
Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput);
+struct QWaylandEventCompressionPrivate
+{
+ QWaylandEventCompressionPrivate();
+
+ bool compressEvent();
+
+ QElapsedTimer timeElapsed;
+ QTimer delayTimer;
+};
+
class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice
: public QObject
, public QtWayland::wl_seat
@@ -381,6 +391,8 @@ public:
bool mScrollBeginSent = false;
QPointF mScrollDeltaRemainder;
+ QWaylandEventCompressionPrivate mEventCompression;
+
void setFrameEvent(QWaylandPointerEvent *event);
void flushScrollEvent();
void flushFrameEvent();
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
index 669d47ee..fc869de6 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
@@ -87,6 +87,8 @@ QWaylandIntegration::QWaylandIntegration(const QString &platformName)
: mPlatformName(platformName), mFontDb(new QGenericUnixFontDatabase())
#endif
{
+ QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
+
mDisplay.reset(new QWaylandDisplay(this));
mPlatformServices.reset(new QWaylandPlatformServices(mDisplay.data()));
diff --git a/tests/auto/wayland/client/tst_client.cpp b/tests/auto/wayland/client/tst_client.cpp
index 04400e3f..09ac4f7f 100644
--- a/tests/auto/wayland/client/tst_client.cpp
+++ b/tests/auto/wayland/client/tst_client.cpp
@@ -276,6 +276,8 @@ void tst_WaylandClient::events()
exec([&] {
pointer()->sendEnter(s, window.frameOffset() + mousePressPos);
pointer()->sendFrame(client());
+ pointer()->sendMotion(client(), window.frameOffset() + mousePressPos / 2);
+ pointer()->sendFrame(client());
pointer()->sendMotion(client(), window.frameOffset() + mousePressPos);
pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);

View file

@ -0,0 +1,55 @@
From 18550cd9ad04913d50abfc88a6048b7cfaf80687 Mon Sep 17 00:00:00 2001
From: Igor Khanin <igor@khanin.biz>
Date: Mon, 13 Oct 2025 14:26:39 +0300
Subject: [PATCH] wayland: Convey preference for server side decorations
As discussed in the mailing list, Qt applications generally expect top
level windows to be decorated by the windowing system - unless
explicitly requested by the developer by marking a window as frameless.
Furthermore, Qt's client side decorations for Wayland were only really
intended as a fallback.
However until now the Wayland xdg-shell integration conveyed to the
compositor (if it supports decorations negotiations) that it didn't
care whose responsibility it was to draw window decorations. This did
not matter under KWin, which resolves such cases in favor of SSDs - but
does matter under other SSD-capable compositors like cosmic-comp (which
considers SSDs to be the fallback option).
This changes the xdg-shell integration code to be explicit about
requesting SSDs.
[ChangeLog][QtWaylandClient][Important Behavior Changes] The Wayland
XDG shell integration now requests server side decorations with
compositors supporting the zxdg_decoration_manager_v1 protocol.
Change-Id: Ia025b1f6ff17248a5710f981a0cecd90c47b6cd8
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index a1a173f..8386b65 100644
--- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -201,7 +201,7 @@
delete m_decoration;
m_decoration = nullptr;
} else {
- m_decoration->unsetMode();
+ m_decoration->requestMode(QWaylandXdgToplevelDecorationV1::mode_server_side);
}
}
}
diff --git a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
index 5ee8569..65ac08f 100644
--- a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
+++ b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
@@ -149,7 +149,7 @@
QVERIFY(window.frameMargins().isNull());
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
- QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_unsetModeRequested);
+ QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_requestedMode == XdgToplevelDecorationV1::mode_server_side);
QVERIFY(window.frameMargins().isNull()); // We're still waiting for a configure
exec([&] {
toplevelDecoration()->sendConfigure(XdgToplevelDecorationV1::mode_client_side);

View file

@ -0,0 +1,235 @@
From 9dd0d936d6691904a4bb212dcf48999a5228b84f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
Date: Thu, 7 Aug 2025 15:42:55 +0200
Subject: [PATCH] wayland: Enable event compression and fix scroll end event
We have to deliver the scroll end event in order with other scroll
events, so move scroll end event logic into flushScrollEvent().
Track the target scroll window on scroll begin and check whether we
have a target window to prevent a crash.
Also we can't clear the scroll delta when scroll end event arrives,
because the event compression relies on this value.
Use scoped pointer for frame event to simplify code and make sure it's
deleted in destructor.
Amends 095759818854e5a011aa8f859e566bbc6368ab76
Updates 789681872fb62450fc78d1a06472a40d970a8d57
Change-Id: Ifb149c8fde1286b60439be0dab16b1df65279ea8
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
.../platforms/wayland/qwaylandinputdevice.cpp | 98 ++++++++++---------
.../platforms/wayland/qwaylandinputdevice_p.h | 6 +-
.../platforms/wayland/qwaylandintegration.cpp | 2 +
3 files changed, 61 insertions(+), 45 deletions(-)
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index 7fcda34c57ca..6ce43714a35f 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -935,10 +935,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
mParent->mTime = time;
- if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
- qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
- flushFrameEvent();
- }
+ maybePointerFrame();
}
void QWaylandInputDevice::Pointer::pointer_frame()
@@ -978,11 +975,9 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi
switch (axis) {
case axis_vertical_scroll:
qCDebug(lcQpaWaylandInput) << "Received vertical wl_pointer.axis_stop";
- mFrameData.delta.setY(0); //TODO: what's the point of doing this?
break;
case axis_horizontal_scroll:
qCDebug(lcQpaWaylandInput) << "Received horizontal wl_pointer.axis_stop";
- mFrameData.delta.setX(0);
break;
default:
qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_stop: Unknown axis: " << axis
@@ -990,25 +985,7 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi
return;
}
- // May receive axis_stop for events we haven't sent a ScrollBegin for because
- // most axis_sources do not mandate an axis_stop event to be sent.
- if (!mScrollBeginSent) {
- // TODO: For now, we just ignore these events, but we could perhaps take this as an
- // indication that this compositor will in fact send axis_stop events for these sources
- // and send a ScrollBegin the next time an axis_source event with this type is encountered.
- return;
- }
-
- QWaylandWindow *target = QWaylandWindow::mouseGrab();
- if (!target)
- target = focusWindow();
- Qt::KeyboardModifiers mods = mParent->modifiers();
- const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
- WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
- QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods, inverted);
- target->handleMouse(mParent, wheelEvent);
- mScrollBeginSent = false;
- mScrollDeltaRemainder = QPointF();
+ mScrollEnd = true;
}
void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t value)
@@ -1069,6 +1046,14 @@ void QWaylandInputDevice::Pointer::pointer_axis_relative_direction(uint32_t axis
}
}
+inline void QWaylandInputDevice::Pointer::maybePointerFrame()
+{
+ if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
+ qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
+ pointer_frame();
+ }
+}
+
void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
{
qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type;
@@ -1077,13 +1062,9 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
flushFrameEvent();
}
- delete mFrameData.event;
- mFrameData.event = event;
+ mFrameData.event.reset(event);
- if (version() < WL_POINTER_FRAME_SINCE_VERSION) {
- qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
- flushFrameEvent();
- }
+ maybePointerFrame();
}
void QWaylandInputDevice::Pointer::FrameData::resetScrollData()
@@ -1163,11 +1144,24 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
{
QPoint angleDelta = mFrameData.angleDelta();
+ // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
+ // Pragmatically it should't come up
+ const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
+
// Angle delta is required for Qt wheel events, so don't try to send events if it's zero
if (!angleDelta.isNull()) {
- QWaylandWindow *target = QWaylandWindow::mouseGrab();
- if (!target)
- target = focusWindow();
+ QWaylandWindow *target = mScrollTarget;
+ if (!mScrollBeginSent) {
+ if (!target)
+ target = QWaylandWindow::mouseGrab();
+ if (!target)
+ target = focusWindow();
+ }
+ if (!target) {
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll event aborted - no scroll target";
+ mFrameData.resetScrollData();
+ return;
+ }
if (isDefinitelyTerminated(mFrameData.axisSource) && !mScrollBeginSent) {
qCDebug(lcQpaWaylandInput) << "Flushing scroll event sending ScrollBegin";
@@ -1177,21 +1171,38 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
mParent->modifiers(), false));
mScrollBeginSent = true;
mScrollDeltaRemainder = QPointF();
+ mScrollTarget = target;
}
Qt::ScrollPhase phase = mScrollBeginSent ? Qt::ScrollUpdate : Qt::NoScrollPhase;
QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder);
- Qt::MouseEventSource source = mFrameData.wheelEventSource();
-
-
- // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
- // Pragmatically it should't come up
- const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted;
qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta;
target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos,
- pixelDelta, angleDelta, source, mParent->modifiers(), inverted));
+ pixelDelta, angleDelta, mFrameData.wheelEventSource(), mParent->modifiers(), inverted));
+ }
+
+ if (mScrollEnd) {
+ if (mScrollBeginSent) {
+ if (auto target = mScrollTarget.get()) {
+ qCDebug(lcQpaWaylandInput) << "Flushing scroll end event";
+ target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
+ QPoint(), QPoint(), mFrameData.wheelEventSource(), mParent->modifiers(), inverted));
+ }
+ mScrollBeginSent = false;
+ mScrollDeltaRemainder = QPointF();
+ } else {
+ // May receive axis_stop for events we haven't sent a ScrollBegin for because
+ // most axis_sources do not mandate an axis_stop event to be sent.
+
+ // TODO: For now, we just ignore these events, but we could perhaps take this as an
+ // indication that this compositor will in fact send axis_stop events for these sources
+ // and send a ScrollBegin the next time an axis_source event with this type is encountered.
+ }
+ mScrollEnd = false;
+ mScrollTarget.clear();
}
+
mFrameData.resetScrollData();
}
@@ -1199,7 +1210,7 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
{
mEventCompression.delayTimer.stop();
- if (auto *event = mFrameData.event) {
+ if (auto *event = mFrameData.event.get()) {
if (auto window = event->surface) {
window->handleMouse(mParent, *event);
} else if (mFrameData.event->type == QEvent::MouseButtonRelease) {
@@ -1212,8 +1223,7 @@ void QWaylandInputDevice::Pointer::flushFrameEvent()
event->modifiers); // , Qt::MouseEventSource source =
// Qt::MouseEventNotSynthesized);
}
- delete mFrameData.event;
- mFrameData.event = nullptr;
+ mFrameData.event.reset();
}
//TODO: do modifiers get passed correctly here?
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
index 533a10991e5e..aa2ccddbcdb8 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h
@@ -370,7 +370,7 @@ private Q_SLOTS:
Qt::MouseButton mLastButton = Qt::NoButton;
struct FrameData {
- QWaylandPointerEvent *event = nullptr;
+ QScopedPointer<QWaylandPointerEvent> event;
QPointF delta;
QPoint delta120;
@@ -387,10 +387,14 @@ private Q_SLOTS:
} mFrameData;
bool mScrollBeginSent = false;
+ bool mScrollEnd = false;
QPointF mScrollDeltaRemainder;
+ QPointer<QWaylandWindow> mScrollTarget;
QWaylandEventCompressionPrivate mEventCompression;
+ void maybePointerFrame();
+
void setFrameEvent(QWaylandPointerEvent *event);
void flushScrollEvent();
void flushFrameEvent();

View file

@ -0,0 +1,39 @@
From c93008e4d06abb0072e0e5e57d84a4ae182ecfc0 Mon Sep 17 00:00:00 2001
From: Błażej Szczygieł <mumei6102@gmail.com>
Date: Tue, 21 Oct 2025 19:49:17 +0200
Subject: [PATCH] wayland: Fix crash in QWaylandShmBackingStore::scroll()
Fixes a crash when monitor is unplugged while scrolling.
recreateBackBufferIfNeeded() calls getBuffer() which may set
mFrontBuffer to nullptr.
Amends: 6f25f703fd37a900c139e14a33a4639502bfeae7
Task-number: QTBUG-139231
Change-Id: Ia5bedce2a3f6580c722f73446de81a26d40ea2f4
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
index b853db2..fa70b53 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
@@ -229,7 +229,7 @@
// Inspired by QCALayerBackingStore.
bool QWaylandShmBackingStore::scroll(const QRegion &region, int dx, int dy)
{
- if (Q_UNLIKELY(!mBackBuffer || !mFrontBuffer))
+ if (Q_UNLIKELY(!mBackBuffer))
return false;
const qreal devicePixelRatio = waylandWindow()->scale();
@@ -241,6 +241,8 @@
return false;
recreateBackBufferIfNeeded();
+ if (!mFrontBuffer)
+ return false;
const QPoint scrollDelta(dx, dy);
const QMargins margins = windowDecorationMargins();

View file

@ -0,0 +1,242 @@
From 6f25f703fd37a900c139e14a33a4639502bfeae7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <mumei6102@gmail.com>
Date: Wed, 13 Aug 2025 00:48:08 +0200
Subject: [PATCH] wayland: Optimize scroll operation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Don't copy the dirty region in "recreateBackBufferIfNeeded()" in
"beginPaint()". Mark this region as non-dirty in the back buffer
and paint. Finalize the back buffer (copy remaining dirty region)
before flushing. This allows to optimize scrolling, we no longer
have to do a redundant dirty area copy.
This matches the "QCALayerBackingStore" logic.
Task-number: QTBUG-139231
Change-Id: I6c19491fa8f093de9c9ce7624d8f9b65b0b722c5
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: David Edmundson <davidedmundson@kde.org>
---
.../wayland/qwaylandshmbackingstore.cpp | 111 ++++++++++++------
.../wayland/qwaylandshmbackingstore_p.h | 3 +-
2 files changed, 74 insertions(+), 40 deletions(-)
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
index d8fc7b18ca34..591e5064ebd6 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
@@ -159,6 +159,8 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window, QWaylandDispla
// recreateBackBufferIfNeeded always resets mBackBuffer
if (mRequestedSize.isValid() && waylandWindow())
recreateBackBufferIfNeeded();
+ else
+ mBackBuffer = nullptr;
qDeleteAll(copy);
wl_event_queue_destroy(oldEventQueue);
});
@@ -183,11 +185,15 @@ QPaintDevice *QWaylandShmBackingStore::paintDevice()
void QWaylandShmBackingStore::updateDirtyStates(const QRegion &region)
{
- // Update dirty state of buffers based on what was painted. The back buffer will
- // not be dirty since we already painted on it, while other buffers will become dirty.
+ // Update dirty state of buffers based on what was painted. The back buffer will be
+ // less dirty, since we painted to it, while other buffers will become more dirty.
+ // This allows us to minimize copies between front and back buffers on swap in the
+ // cases where the painted region overlaps with the previous frame (front buffer).
for (QWaylandShmBuffer *b : std::as_const(mBuffers)) {
if (b != mBackBuffer)
b->dirtyRegion() += region;
+ else
+ b->dirtyRegion() -= region;
}
}
@@ -198,7 +204,7 @@ void QWaylandShmBackingStore::beginPaint(const QRegion &region)
const QMargins margins = windowDecorationMargins();
const QRegion regionTranslated = region.translated(margins.left(), margins.top());
- const bool bufferWasRecreated = recreateBackBufferIfNeeded(regionTranslated);
+ const bool bufferWasRecreated = recreateBackBufferIfNeeded();
updateDirtyStates(regionTranslated);
// Although undocumented, QBackingStore::beginPaint expects the painted region
@@ -223,7 +229,7 @@ void QWaylandShmBackingStore::endPaint()
// Inspired by QCALayerBackingStore.
bool QWaylandShmBackingStore::scroll(const QRegion &region, int dx, int dy)
{
- if (!mBackBuffer)
+ if (Q_UNLIKELY(!mBackBuffer || !mFrontBuffer))
return false;
const qreal devicePixelRatio = waylandWindow()->scale();
@@ -236,19 +242,35 @@ bool QWaylandShmBackingStore::scroll(const QRegion &region, int dx, int dy)
recreateBackBufferIfNeeded();
- QImage *backBufferImage = mBackBuffer->image();
-
const QPoint scrollDelta(dx, dy);
const QMargins margins = windowDecorationMargins();
const QRegion adjustedRegion = region.translated(margins.left(), margins.top());
- const QRect boundingRect = adjustedRegion.boundingRect();
- const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
+ const QRegion inPlaceRegion = adjustedRegion - mBackBuffer->dirtyRegion();
+ const QRegion frontBufferRegion = adjustedRegion - inPlaceRegion;
+
+ if (!inPlaceRegion.isEmpty()) {
+ const QRect inPlaceBoundingRect = inPlaceRegion.boundingRect();
+ const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
+
+ qt_scrollRectInImage(*mBackBuffer->image(),
+ QRect(inPlaceBoundingRect.topLeft() * devicePixelRatio,
+ inPlaceBoundingRect.size() * devicePixelRatio),
+ devicePixelDelta);
+ }
- qt_scrollRectInImage(*backBufferImage,
- QRect(boundingRect.topLeft() * devicePixelRatio,
- boundingRect.size() * devicePixelRatio),
- devicePixelDelta);
+ if (!frontBufferRegion.isEmpty()) {
+ QPainter painter(mBackBuffer->image());
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.scale(qreal(1) / devicePixelRatio, qreal(1) / devicePixelRatio);
+ for (const QRect &rect : frontBufferRegion) {
+ QRect sourceRect(rect.topLeft() * devicePixelRatio,
+ rect.size() * devicePixelRatio);
+ QRect destinationRect((rect.topLeft() + scrollDelta) * devicePixelRatio,
+ rect.size() * devicePixelRatio);
+ painter.drawImage(destinationRect, *mFrontBuffer->image(), sourceRect);
+ }
+ }
// We do not mark the source region as dirty, even though it technically has "moved".
// This matches the behavior of other backingstore implementations using qt_scrollRectInImage.
@@ -289,6 +311,8 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, cons
if (windowDecoration() && windowDecoration()->isDirty())
updateDecorations();
+ finalizeBackBuffer();
+
mFrontBuffer = mBackBuffer;
QMargins margins = windowDecorationMargins();
@@ -313,6 +337,8 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &b
mBuffers.removeAt(i);
if (mBackBuffer == buffer)
mBackBuffer = nullptr;
+ if (mFrontBuffer == buffer)
+ mFrontBuffer = nullptr;
delete buffer;
}
}
@@ -341,7 +367,7 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &b
return nullptr;
}
-bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirtyRegion)
+bool QWaylandShmBackingStore::recreateBackBufferIfNeeded()
{
wl_display_dispatch_queue_pending(mDisplay->wl_display(), mEventQueue);
@@ -375,30 +401,6 @@ bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirty
qsizetype oldSizeInBytes = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0;
qsizetype newSizeInBytes = buffer->image()->sizeInBytes();
- // mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway
- if (mBackBuffer != buffer && oldSizeInBytes == newSizeInBytes) {
- const QRegion clipRegion = buffer->dirtyRegion() - nonDirtyRegion;
- const auto clipRects = clipRegion.rects();
- if (!clipRects.empty()) {
- Q_ASSERT(mBackBuffer);
- const QImage *sourceImage = mBackBuffer->image();
- QImage *targetImage = buffer->image();
-
- QPainter painter(targetImage);
- painter.setCompositionMode(QPainter::CompositionMode_Source);
- const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
- for (const QRect &clipRect : clipRects) { // Iterate clip rects, because complicated clip region causes higher CPU usage
- if (clipRects.size() > 1)
- painter.save();
- painter.setClipRect(clipRect);
- painter.scale(qreal(1) / targetDevicePixelRatio, qreal(1) / targetDevicePixelRatio);
- painter.drawImage(QRectF(QPointF(), targetImage->size()), *sourceImage, sourceImage->rect());
- if (clipRects.size() > 1)
- painter.restore();
- }
- }
- }
-
mBackBuffer = buffer;
for (QWaylandShmBuffer *buffer : std::as_const(mBuffers)) {
@@ -412,11 +414,40 @@ bool QWaylandShmBackingStore::recreateBackBufferIfNeeded(const QRegion &nonDirty
if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
windowDecoration()->update();
- buffer->dirtyRegion() = QRegion();
-
return bufferWasRecreated;
}
+void QWaylandShmBackingStore::finalizeBackBuffer()
+{
+ Q_ASSERT(mBackBuffer);
+
+ const QRegion clipRegion = mBackBuffer->dirtyRegion();
+ if (clipRegion.isEmpty())
+ return;
+
+ if (Q_UNLIKELY(!mFrontBuffer || mFrontBuffer == mBackBuffer))
+ return;
+
+ const QImage *sourceImage = mFrontBuffer->image();
+ QImage *targetImage = mBackBuffer->image();
+
+ QPainter painter(targetImage);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
+ const auto clipRects = clipRegion.rects();
+ for (const QRect &clipRect : clipRects) { // Iterate clip rects, because complicated clip region causes higher CPU usage
+ if (clipRects.size() > 1)
+ painter.save();
+ painter.setClipRect(clipRect);
+ painter.scale(qreal(1) / targetDevicePixelRatio, qreal(1) / targetDevicePixelRatio);
+ painter.drawImage(QRectF(QPointF(), targetImage->size()), *sourceImage, sourceImage->rect());
+ if (clipRects.size() > 1)
+ painter.restore();
+ }
+
+ mBackBuffer->dirtyRegion() = QRegion();
+}
+
QImage *QWaylandShmBackingStore::entireSurface() const
{
return mBackBuffer->image();
@@ -496,6 +527,8 @@ QImage QWaylandShmBackingStore::toImage() const
// instead of flush() for widgets that have renderToTexture children
// (QOpenGLWidget, QQuickWidget).
+ const_cast<QWaylandShmBackingStore *>(this)->finalizeBackBuffer();
+
return *contentSurface();
}
#endif // opengl
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
index efd80159e859..cfcafb283265 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h
@@ -73,7 +73,8 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingSt
QMargins windowDecorationMargins() const;
QImage *entireSurface() const;
QImage *contentSurface() const;
- bool recreateBackBufferIfNeeded(const QRegion &nonDirtyRegion = QRegion());
+ bool recreateBackBufferIfNeeded();
+ void finalizeBackBuffer();
QWaylandWindow *waylandWindow() const;
void iterateBuffer();

View file

@ -1 +1 @@
SHA512 (qtbase-everywhere-src-6.2.3.tar.xz) = c1adfb971723213f193223de222e10414868cf091e79c1fedbcaaa495cce57976bb65ac5d20138bc7e5668b92bf88ef054783b55c59b3a8feffc837596764698
SHA512 (qtbase-everywhere-src-6.10.1.tar.xz) = fd5dcdc59ec3b39e48563513ae438eb4540a28e72c46961295de2ccb08609289d477ef7e91aac0b8983f2d5b05b901b4f5be10eaca4ac4c6aa8cd598f37a228e