Compare commits
110 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
082bad2484 | ||
|
|
af0ef1e954 | ||
|
|
67c126dc18 | ||
|
|
2ff34253dc | ||
|
|
045b22d4d6 | ||
|
|
05ee0b98b4 | ||
|
|
07c9cbcba0 | ||
|
|
1646c99cab | ||
|
|
060d33bcdd | ||
|
|
362bc3dbd4 | ||
|
|
0e85496669 | ||
|
|
ed748d94e8 | ||
|
|
fe42bba4fc | ||
|
|
ba0d907174 | ||
|
|
49cf38aa7e | ||
|
|
e21e53a974 | ||
|
|
c8038a82ef | ||
|
|
075288afad | ||
|
|
0038317cfd | ||
|
|
a7de194fac | ||
|
|
0eed16eaa6 | ||
|
|
3761490634 | ||
|
|
ded6d85556 | ||
|
|
f4d62f7183 | ||
|
|
a9b6dadcd4 | ||
|
|
6241001d9e | ||
|
|
242876ebc6 | ||
|
|
63b1fe1f85 | ||
|
|
2fa0a54714 | ||
|
|
0b0b5cbeb5 | ||
|
|
6e6a701e43 | ||
|
|
11497bfc6c | ||
|
|
b4fdf6efe1 | ||
|
|
d6857833fc | ||
|
|
6c56598daf | ||
|
|
bb9c0035d2 | ||
|
|
a6377f834c | ||
|
|
45a4e4a212 | ||
|
|
ca94b24afb | ||
|
|
6331876a3f | ||
|
|
fe4178778c | ||
|
|
b50f64242c | ||
|
|
3cb17721af | ||
|
|
15628f0e25 | ||
|
|
cd6fef471a | ||
|
|
3267aafcbb | ||
|
|
2a85af4599 | ||
|
|
44c251b0c8 | ||
|
|
941d538dc2 | ||
|
|
4c4536c70a | ||
|
|
b91edca719 | ||
|
|
c886489d1a | ||
|
|
7536e20866 | ||
|
|
8b9fc48122 | ||
|
|
788c6f4ce1 | ||
|
|
62dc027ecb | ||
|
|
6d58d80c94 | ||
|
|
906374f04f | ||
|
|
49bbb6d2e6 | ||
|
|
7440c8d5f5 | ||
|
|
9e6f9d15b8 | ||
|
|
9617d2aec3 | ||
|
|
163ea650a8 | ||
|
|
c095cdd4b6 | ||
|
|
8c8bebcc6b | ||
|
|
0916bd3f34 | ||
|
|
4d5e0869d8 | ||
|
|
469e3a8860 | ||
|
|
a44bfe9ca5 | ||
|
|
a19a7d36f9 | ||
|
|
66655b0bf6 | ||
|
|
d130b7be6c | ||
|
|
a0b5aa05f9 | ||
|
|
1149fa7db3 | ||
|
|
f7e88d6ae1 | ||
|
|
ca477f48a6 | ||
|
|
7f9c50ebd7 | ||
|
|
fed7db12b2 | ||
|
|
3e8f6395e9 | ||
|
|
e0efab4a30 | ||
|
|
b4166db60e | ||
|
|
d487a7a9a0 | ||
|
|
9911d344d7 | ||
|
|
8abd8fe461 | ||
|
|
840cea88e5 | ||
|
|
43d39197e0 | ||
|
|
3aeb3c66cf | ||
|
|
6a5e0a5ba5 | ||
|
|
6ba649eb42 | ||
|
|
d932499e6c | ||
|
|
4dccb8dee5 | ||
|
|
9b51c9bf9c | ||
|
|
363b5428f2 | ||
|
|
7d3e08b1e7 | ||
|
|
b5b7a896a3 | ||
|
|
f30f363ff0 | ||
|
|
43952a81ef | ||
|
|
f94edcc9d7 | ||
|
|
8bec765f63 | ||
|
|
84d0798348 | ||
|
|
2dae87e686 | ||
|
|
a6edf5db6b | ||
|
|
3614026fd3 | ||
|
|
9ef11a90cc | ||
|
|
752eade0a7 | ||
|
|
afa40266fd | ||
|
|
e1c0e0acc5 | ||
|
|
964d73e1e6 | ||
|
|
39c645ff6b | ||
|
|
1b784de7b0 |
15 changed files with 1453 additions and 242 deletions
27
.gitignore
vendored
27
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
766
qt6-qtbase.spec
766
qt6-qtbase.spec
File diff suppressed because it is too large
Load diff
51
qtbase-CMake-Install-objects-files-into-ARCHDATADIR.patch
Normal file
51
qtbase-CMake-Install-objects-files-into-ARCHDATADIR.patch
Normal 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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
||||
#############################################################################
|
||||
##
|
||||
|
|
@ -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
|
||||
13
qtbase-use-only-major-minor-for-private-api-tag.patch
Normal file
13
qtbase-use-only-major-minor-for-private-api-tag.patch
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
174
qtbase-wayland-compress-high-frequency-mouse-events.patch
Normal file
174
qtbase-wayland-compress-high-frequency-mouse-events.patch
Normal 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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
|
|
@ -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 ®ion, 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();
|
||||
242
qtbase-wayland-optimize-scroll-operations.patch
Normal file
242
qtbase-wayland-optimize-scroll-operations.patch
Normal 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 ®ion)
|
||||
{
|
||||
- // 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 ®ion)
|
||||
|
||||
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 ®ion, 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 ®ion, 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 ®ion, 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();
|
||||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
SHA512 (qtbase-everywhere-src-6.2.3.tar.xz) = c1adfb971723213f193223de222e10414868cf091e79c1fedbcaaa495cce57976bb65ac5d20138bc7e5668b92bf88ef054783b55c59b3a8feffc837596764698
|
||||
SHA512 (qtbase-everywhere-src-6.10.1.tar.xz) = fd5dcdc59ec3b39e48563513ae438eb4540a28e72c46961295de2ccb08609289d477ef7e91aac0b8983f2d5b05b901b4f5be10eaca4ac4c6aa8cd598f37a228e
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue