Backport upstream patches
This commit is contained in:
parent
ff1f7b4904
commit
33335644e8
@ -3,15 +3,13 @@
|
|||||||
Summary: Qt5 - Wayland platform support and QtCompositor module
|
Summary: Qt5 - Wayland platform support and QtCompositor module
|
||||||
Name: qt5-%{qt_module}
|
Name: qt5-%{qt_module}
|
||||||
Version: 5.14.2
|
Version: 5.14.2
|
||||||
Release: 3%{?dist}
|
Release: 4%{?dist}
|
||||||
|
|
||||||
License: LGPLv3
|
License: LGPLv3
|
||||||
Url: http://www.qt.io
|
Url: http://www.qt.io
|
||||||
%global majmin %(echo %{version} | cut -d. -f1-2)
|
%global majmin %(echo %{version} | cut -d. -f1-2)
|
||||||
Source0: https://download.qt.io/official_releases/qt/%{majmin}/%{version}/submodules/%{qt_module}-everywhere-src-%{version}.tar.xz
|
Source0: https://download.qt.io/official_releases/qt/%{majmin}/%{version}/submodules/%{qt_module}-everywhere-src-%{version}.tar.xz
|
||||||
|
|
||||||
# Upstream patches
|
|
||||||
|
|
||||||
# Bold fonts in qt applications appear much too heavy
|
# Bold fonts in qt applications appear much too heavy
|
||||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1823984
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1823984
|
||||||
Patch0: qtwayland-dont-force-gamma-correction-off.patch
|
Patch0: qtwayland-dont-force-gamma-correction-off.patch
|
||||||
@ -26,6 +24,14 @@ Patch1: qtwayland-remove-recursion-in-data-offer-retrieval.patch
|
|||||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1732129
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1732129
|
||||||
Patch50: qtwayland-use-gnome-platform-theme-on-gnome-based-desktops.patch
|
Patch50: qtwayland-use-gnome-platform-theme-on-gnome-based-desktops.patch
|
||||||
|
|
||||||
|
# Upstream patches
|
||||||
|
Patch100: qtwayland-fix-leaking-of-callback-timers.patch
|
||||||
|
Patch101: qtwayland-client-make-frameback-callback-timeout-configurable.patch
|
||||||
|
Patch102: qtwayland-client-fix-scroll-direction-with-touchpads.patch
|
||||||
|
Patch103: qtwayland-client-initialize-mscale-on-creation-instead-of-on-show.patch
|
||||||
|
Patch104: qtwayland-client-send-subsurface-expose-event-when-toplevel-is-configured.patch
|
||||||
|
Patch105: qtwayland-client-dont-send-fakt-surface-created-destroyed-events.patch
|
||||||
|
|
||||||
# filter qml provides
|
# filter qml provides
|
||||||
%global __provides_exclude_from ^%{_qt5_archdatadir}/qml/.*\\.so$
|
%global __provides_exclude_from ^%{_qt5_archdatadir}/qml/.*\\.so$
|
||||||
|
|
||||||
@ -131,6 +137,10 @@ popd
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Jul 27 2020 Jan Grulich <jgrulich@redhat.com> - 5.14.2-4
|
||||||
|
- Backport upstream patches
|
||||||
|
Resolves: bz#1860455
|
||||||
|
|
||||||
* Thu Apr 30 2020 Ivan Mironov <mironov.ivan@gmail.com> - 5.14.2-3
|
* Thu Apr 30 2020 Ivan Mironov <mironov.ivan@gmail.com> - 5.14.2-3
|
||||||
- Cherry-pick fix for clipboard related crash from v5.15.0
|
- Cherry-pick fix for clipboard related crash from v5.15.0
|
||||||
|
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
From cd21404f99b486ff62225699e1a4bdc0d5b3d5c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Edmundson <davidedmundson@kde.org>
|
||||||
|
Date: Sun, 23 Jun 2019 15:09:51 +0200
|
||||||
|
Subject: [PATCH] Client: Don't send fake SurfaceCreated/Destroyed events
|
||||||
|
|
||||||
|
QPlatformSurface relates to the platform window, not the wl_surface.
|
||||||
|
The events are already emitted by QPlatformWindow on create/destroy.
|
||||||
|
|
||||||
|
To preserve compatibility for a previous KDE version it was faked to
|
||||||
|
emit the events when the wl_surface is created/hidden to keep behavior.
|
||||||
|
This is no longer necessary, and it has caused multiple errors, the latest
|
||||||
|
being a crash when switching between sub-menus with the Sway compositor.
|
||||||
|
|
||||||
|
[ChangeLog][QPA plugin] QWaylandWindow no longer sends fake SurfaceCreated/Destroyed events.
|
||||||
|
Use expose events to be notified when a Wayland surface appears.
|
||||||
|
|
||||||
|
Task-number: QTBUG-76324
|
||||||
|
Fixes: QTBUG-81952
|
||||||
|
Pick-to: 5.15
|
||||||
|
Change-Id: I2f003bc9da85f032a0053677fd281152099fc9eb
|
||||||
|
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
|
||||||
|
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
|
||||||
|
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/examples/wayland/custom-extension/client-common/customextension.cpp b/examples/wayland/custom-extension/client-common/customextension.cpp
|
||||||
|
index aa0cb58..8b77c06 100644
|
||||||
|
--- a/examples/wayland/custom-extension/client-common/customextension.cpp
|
||||||
|
+++ b/examples/wayland/custom-extension/client-common/customextension.cpp
|
||||||
|
@@ -81,8 +81,11 @@ QWindow *CustomExtension::windowForSurface(struct ::wl_surface *surface)
|
||||||
|
|
||||||
|
bool CustomExtension::eventFilter(QObject *object, QEvent *event)
|
||||||
|
{
|
||||||
|
- if (event->type() == QEvent::PlatformSurface
|
||||||
|
- && static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
|
||||||
|
+ if (event->type() == QEvent::Expose) {
|
||||||
|
+ auto *exposeEvent = static_cast<QExposeEvent *>(event);
|
||||||
|
+ if (exposeEvent->region().isNull())
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
QWindow *window = qobject_cast<QWindow*>(object);
|
||||||
|
Q_ASSERT(window);
|
||||||
|
window->removeEventFilter(this);
|
||||||
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
|
index 9669cbb..d0d834b 100644
|
||||||
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
|
@@ -100,7 +100,7 @@ QWaylandWindow::~QWaylandWindow()
|
||||||
|
delete mWindowDecoration;
|
||||||
|
|
||||||
|
if (mSurface)
|
||||||
|
- reset(false);
|
||||||
|
+ reset();
|
||||||
|
|
||||||
|
const QWindow *parent = window();
|
||||||
|
const auto tlw = QGuiApplication::topLevelWindows();
|
||||||
|
@@ -127,8 +127,6 @@ void QWaylandWindow::initWindow()
|
||||||
|
|
||||||
|
if (!mSurface) {
|
||||||
|
initializeWlSurface();
|
||||||
|
- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
|
||||||
|
- QGuiApplication::sendEvent(window(), &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCreateSubSurface()) {
|
||||||
|
@@ -241,12 +239,8 @@ bool QWaylandWindow::shouldCreateSubSurface() const
|
||||||
|
return QPlatformWindow::parent() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void QWaylandWindow::reset(bool sendDestroyEvent)
|
||||||
|
+void QWaylandWindow::reset()
|
||||||
|
{
|
||||||
|
- if (mSurface && sendDestroyEvent) {
|
||||||
|
- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
|
||||||
|
- QGuiApplication::sendEvent(window(), &e);
|
||||||
|
- }
|
||||||
|
delete mShellSurface;
|
||||||
|
mShellSurface = nullptr;
|
||||||
|
delete mSubSurfaceWindow;
|
||||||
|
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||||
|
index b57f5dd..a65301c 100644
|
||||||
|
--- a/src/client/qwaylandwindow_p.h
|
||||||
|
+++ b/src/client/qwaylandwindow_p.h
|
||||||
|
@@ -261,7 +261,7 @@ private:
|
||||||
|
void initializeWlSurface();
|
||||||
|
bool shouldCreateShellSurface() const;
|
||||||
|
bool shouldCreateSubSurface() const;
|
||||||
|
- void reset(bool sendDestroyEvent = true);
|
||||||
|
+ void reset();
|
||||||
|
void sendExposeEvent(const QRect &rect);
|
||||||
|
static void closePopups(QWaylandWindow *parent);
|
||||||
|
QWaylandScreen *calculateScreenFromSurfaceEvents() const;
|
113
qtwayland-client-fix-scroll-direction-with-touchpads.patch
Normal file
113
qtwayland-client-fix-scroll-direction-with-touchpads.patch
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
From 7f065653e2f372ee5b7e2ea4dbed6681ef41be68 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Edmundson <davidedmundson@kde.org>
|
||||||
|
Date: Tue, 07 Apr 2020 17:36:19 +0100
|
||||||
|
Subject: [PATCH] Client: Fix scroll direction with touchpads
|
||||||
|
|
||||||
|
Wayland axis events and QWheelEvents are opposite way rounds. This was
|
||||||
|
handled for the case of discrete events, but not continuous events.
|
||||||
|
|
||||||
|
This leads to touchpads moving the wrong way round compared to other
|
||||||
|
clients.
|
||||||
|
|
||||||
|
Change-Id: Iee4f5c620940a491949d4039cb3ac70649d83a2b
|
||||||
|
Pick-to: 5.15
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
|
||||||
|
index e0f0c6c..ed4a0eb 100644
|
||||||
|
--- a/src/client/qwaylandinputdevice.cpp
|
||||||
|
+++ b/src/client/qwaylandinputdevice.cpp
|
||||||
|
@@ -1025,6 +1025,12 @@
|
||||||
|
*accumulatedError += delta - pixelDelta;
|
||||||
|
Q_ASSERT(qAbs(accumulatedError->x()) < 1.0);
|
||||||
|
Q_ASSERT(qAbs(accumulatedError->y()) < 1.0);
|
||||||
|
+
|
||||||
|
+ // for continuous scroll events things should be
|
||||||
|
+ // in the same direction
|
||||||
|
+ // i.e converted so downwards surface co-ordinates (positive axis_value)
|
||||||
|
+ // goes to downwards in wheel event (negative value)
|
||||||
|
+ pixelDelta *= -1;
|
||||||
|
return pixelDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/tests/auto/client/seatv5/tst_seatv5.cpp b/tests/auto/client/seatv5/tst_seatv5.cpp
|
||||||
|
index e333082..9312c2e 100644
|
||||||
|
--- a/tests/auto/client/seatv5/tst_seatv5.cpp
|
||||||
|
+++ b/tests/auto/client/seatv5/tst_seatv5.cpp
|
||||||
|
@@ -63,6 +63,7 @@
|
||||||
|
void simpleAxis();
|
||||||
|
void fingerScroll();
|
||||||
|
void fingerScrollSlow();
|
||||||
|
+ void continuousScroll();
|
||||||
|
void wheelDiscreteScroll();
|
||||||
|
|
||||||
|
// Touch tests
|
||||||
|
@@ -252,7 +253,7 @@
|
||||||
|
QCOMPARE(e.phase, Qt::ScrollUpdate);
|
||||||
|
QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll
|
||||||
|
// QCOMPARE(e.angleDelta, angleDelta); // TODO: what should this be?
|
||||||
|
- QCOMPARE(e.pixelDelta, QPoint(0, 10));
|
||||||
|
+ QCOMPARE(e.pixelDelta, QPoint(0, -10));
|
||||||
|
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -269,7 +270,7 @@
|
||||||
|
auto e = window.m_events.takeFirst();
|
||||||
|
QCOMPARE(e.phase, Qt::ScrollUpdate);
|
||||||
|
QVERIFY(qAbs(e.angleDelta.x()) > qAbs(e.angleDelta.y())); // Horizontal scroll
|
||||||
|
- QCOMPARE(e.pixelDelta, QPoint(10, 0));
|
||||||
|
+ QCOMPARE(e.pixelDelta, QPoint(-10, 0));
|
||||||
|
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -284,7 +285,7 @@
|
||||||
|
{
|
||||||
|
auto e = window.m_events.takeFirst();
|
||||||
|
QCOMPARE(e.phase, Qt::ScrollUpdate);
|
||||||
|
- QCOMPARE(e.pixelDelta, QPoint(10, 10));
|
||||||
|
+ QCOMPARE(e.pixelDelta, QPoint(-10, -10));
|
||||||
|
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -338,7 +339,7 @@
|
||||||
|
accumulated += e.pixelDelta;
|
||||||
|
QTRY_VERIFY(!window.m_events.empty());
|
||||||
|
}
|
||||||
|
- QCOMPARE(accumulated.y(), 1);
|
||||||
|
+ QCOMPARE(accumulated.y(), -1);
|
||||||
|
}
|
||||||
|
void tst_seatv5::wheelDiscreteScroll()
|
||||||
|
{
|
||||||
|
@@ -370,6 +371,32 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void tst_seatv5::continuousScroll()
|
||||||
|
+{
|
||||||
|
+ WheelWindow window;
|
||||||
|
+ QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
|
||||||
|
+
|
||||||
|
+ exec([=] {
|
||||||
|
+ auto *p = pointer();
|
||||||
|
+ auto *c = client();
|
||||||
|
+ p->sendEnter(xdgToplevel()->surface(), {32, 32});
|
||||||
|
+ p->sendFrame(c);
|
||||||
|
+ p->sendAxisSource(c, Pointer::axis_source_continuous);
|
||||||
|
+ p->sendAxis(c, Pointer::axis_vertical_scroll, 10);
|
||||||
|
+ p->sendAxis(c, Pointer::axis_horizontal_scroll, -5);
|
||||||
|
+ p->sendFrame(c);
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ QTRY_VERIFY(!window.m_events.empty());
|
||||||
|
+ {
|
||||||
|
+ auto e = window.m_events.takeFirst();
|
||||||
|
+ QCOMPARE(e.phase, Qt::NoScrollPhase);
|
||||||
|
+ QCOMPARE(e.pixelDelta, QPoint(5, -10));
|
||||||
|
+ QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // touchpads are not wheels
|
||||||
|
+ }
|
||||||
|
+ // Sending axis_stop is not mandatory when axis source != finger
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void tst_seatv5::createsTouch()
|
||||||
|
{
|
||||||
|
QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().size(), 1);
|
@ -0,0 +1,46 @@
|
|||||||
|
From 760abe1939f6afc146de2c5172b27b347043f327 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Edmundson <davidedmundson@kde.org>
|
||||||
|
Date: Fri, 24 Jul 2020 16:35:09 +0100
|
||||||
|
Subject: [PATCH] client: Initialize mScale on creation instead of on show
|
||||||
|
|
||||||
|
At the time of creating a QPlatformWindow we will have a QScreen
|
||||||
|
assigned. It may not be the right one until we get a screen_entered
|
||||||
|
event, pointing instead to the primary screen.
|
||||||
|
|
||||||
|
When we get the screen_entered event we get the correct scale and call
|
||||||
|
handleWindowScreenChanged. However if it's the same screen as before
|
||||||
|
QWindowPrivate::setTopLevelScreen will no-op because from it's POV the
|
||||||
|
screen hasn't changed at all.
|
||||||
|
|
||||||
|
This leaves the window having the scale change without any notification.
|
||||||
|
|
||||||
|
This is notable with QQuickWidget which creates an FBO very early on
|
||||||
|
before the window is shown. This would then use the devicePixelRatio of
|
||||||
|
1 as it is currently unset and then not get any change notification.
|
||||||
|
|
||||||
|
Change-Id: Ia7e4072e0bd900abc558bf8930fef4e1e7d2c553
|
||||||
|
Pick-to: 5.15
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
|
index cfcc735..f7647a4 100644
|
||||||
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
|
@@ -86,6 +86,8 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
|
||||||
|
mFrameCallbackTimeout = frameCallbackTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ mScale = waylandScreen() ? waylandScreen()->scale() : 1; // fallback to 1 if we don't have a real screen
|
||||||
|
+
|
||||||
|
static WId id = 1;
|
||||||
|
mWindowId = id++;
|
||||||
|
initializeWlSurface();
|
||||||
|
@@ -184,8 +186,6 @@ void QWaylandWindow::initWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- mScale = waylandScreen()->scale();
|
||||||
|
-
|
||||||
|
// Enable high-dpi rendering. Scale() returns the screen scale factor and will
|
||||||
|
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
|
||||||
|
// to inform the compositor that high-resolution buffers will be provided.
|
@ -0,0 +1,103 @@
|
|||||||
|
From efc94a48526baf92b8a78916e03e1fef5993fa95 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||||
|
Date: Mon, 06 Apr 2020 09:52:33 +0200
|
||||||
|
Subject: [PATCH] Client: Make frame back callback timeout configurable
|
||||||
|
|
||||||
|
To avoid rendering when windows are minimized, we try to detect
|
||||||
|
this case by checking if 100 ms passes after an update before
|
||||||
|
any frame callback arrives. Wayland expects to drive the rendering
|
||||||
|
through frame callbacks, while Qt expects to be informed when a
|
||||||
|
window is no longer visible and will run a tight, vsynced render loop
|
||||||
|
until it gets the appropriate event. This mismatch causes issues,
|
||||||
|
and the timeout is an attempt to avoid actively rendering to a hidden
|
||||||
|
surface by detecting the missing callbacks.
|
||||||
|
|
||||||
|
It causes problems on embedded, though, when a device is so
|
||||||
|
busy that the timeout happens even when the window is visible.
|
||||||
|
|
||||||
|
So we introduce a way to configure the timeout. Either increase
|
||||||
|
its duration if you can guarantee a certain minimum time between
|
||||||
|
events even with high load, or set it to 0 to disable it completely.
|
||||||
|
(at the expense of drawing to invisible windows).
|
||||||
|
|
||||||
|
Note that this is required for fixing a critical memory leak that
|
||||||
|
happens when using Wayland on embedded.
|
||||||
|
|
||||||
|
This was mistakenly pushed to 5.12 branch, so it will not be
|
||||||
|
automatically merged upstream. Therefore we have to
|
||||||
|
cherry-pick it.
|
||||||
|
|
||||||
|
[ChangeLog][Client] Added support for QT_WAYLAND_FRAME_CALLBACK_TIMEOUT
|
||||||
|
environment variable, which can be used to disable or change the
|
||||||
|
internal frame callback timeout. If you see windows that stop rendering
|
||||||
|
or minimize on heavy load, then try setting the variable to 0.
|
||||||
|
|
||||||
|
Task-number: QTBUG-82914
|
||||||
|
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||||
|
(cherry picked from commit 0a0e0eb8dca699858435dec5194b0b8b6ebd3cf8)
|
||||||
|
Change-Id: I2aeeecb0fab8f7be9b838e477c88eae22b322d75
|
||||||
|
Reviewed-by: Janne Koskinen <janne.p.koskinen@qt.io>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
|
index 884a979..0545c80 100644
|
||||||
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
|
@@ -79,6 +79,13 @@
|
||||||
|
, mFrameQueue(mDisplay->createEventQueue())
|
||||||
|
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
|
||||||
|
{
|
||||||
|
+ {
|
||||||
|
+ bool ok;
|
||||||
|
+ int frameCallbackTimeout = qEnvironmentVariableIntValue("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", &ok);
|
||||||
|
+ if (ok)
|
||||||
|
+ mFrameCallbackTimeout = frameCallbackTimeout;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
static WId id = 1;
|
||||||
|
mWindowId = id++;
|
||||||
|
initializeWlSurface();
|
||||||
|
@@ -1096,7 +1103,7 @@
|
||||||
|
if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(100);
|
||||||
|
+ bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(mFrameCallbackTimeout);
|
||||||
|
if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
|
||||||
|
killTimer(mFrameCallbackCheckIntervalTimerId);
|
||||||
|
mFrameCallbackCheckIntervalTimerId = -1;
|
||||||
|
@@ -1157,13 +1164,15 @@
|
||||||
|
mWaitingForUpdate = false;
|
||||||
|
|
||||||
|
// Start a timer for handling the case when the compositor stops sending frame callbacks.
|
||||||
|
- QMetaObject::invokeMethod(this, [this] {
|
||||||
|
- if (mWaitingForFrameCallback) {
|
||||||
|
- if (mFrameCallbackCheckIntervalTimerId < 0)
|
||||||
|
- mFrameCallbackCheckIntervalTimerId = startTimer(100);
|
||||||
|
- mFrameCallbackElapsedTimer.start();
|
||||||
|
- }
|
||||||
|
- }, Qt::QueuedConnection);
|
||||||
|
+ if (mFrameCallbackTimeout > 0) {
|
||||||
|
+ QMetaObject::invokeMethod(this, [this] {
|
||||||
|
+ if (mWaitingForFrameCallback) {
|
||||||
|
+ if (mFrameCallbackCheckIntervalTimerId < 0)
|
||||||
|
+ mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
|
||||||
|
+ mFrameCallbackElapsedTimer.start();
|
||||||
|
+ }
|
||||||
|
+ }, Qt::QueuedConnection);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandWindow::deliverUpdateRequest()
|
||||||
|
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||||
|
index ef03fd1..89d6272 100644
|
||||||
|
--- a/src/client/qwaylandwindow_p.h
|
||||||
|
+++ b/src/client/qwaylandwindow_p.h
|
||||||
|
@@ -240,6 +240,7 @@
|
||||||
|
bool mCanResize = true;
|
||||||
|
bool mResizeDirty = false;
|
||||||
|
bool mResizeAfterSwap;
|
||||||
|
+ int mFrameCallbackTimeout = 100;
|
||||||
|
QVariantMap m_properties;
|
||||||
|
|
||||||
|
bool mSentInitialResize = false;
|
@ -0,0 +1,59 @@
|
|||||||
|
From e87bc5eda5191dfec9c8bdfdcd67faf15e79d1d1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Edmundson <davidedmundson@kde.org>
|
||||||
|
Date: Sun, 26 Jul 2020 17:56:25 +0100
|
||||||
|
Subject: [PATCH] Client: Send subsurface expose event when toplevel is configured
|
||||||
|
|
||||||
|
If a subsurface is set to be visible on the cilent side before the top
|
||||||
|
level is configured it will do not create an exposeEvent and map a
|
||||||
|
buffer as we fail the check in isExposed() where we check the parent.
|
||||||
|
This is correct behavior.
|
||||||
|
|
||||||
|
However, when the toplevel receives an applyConfigure from the shell
|
||||||
|
client we need subsurfaces to update accordingly.
|
||||||
|
|
||||||
|
This fixes a race where subsurfaces are not shown with slow compositors.
|
||||||
|
|
||||||
|
Change-Id: Icd156e7655d5b25535acc4d2fe77c31e19ebfa32
|
||||||
|
Pick-to: 5.15
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
|
index f7647a4..9669cbb 100644
|
||||||
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
|
@@ -517,10 +517,22 @@ void QWaylandWindow::applyConfigure()
|
||||||
|
doApplyConfigure();
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
- sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||||
|
+ sendRecursiveExposeEvent();
|
||||||
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
+void QWaylandWindow::sendRecursiveExposeEvent()
|
||||||
|
+{
|
||||||
|
+ if (!window()->isVisible())
|
||||||
|
+ return;
|
||||||
|
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||||
|
+
|
||||||
|
+ for (QWaylandSubSurface *subsurf : qAsConst(mChildren)) {
|
||||||
|
+ auto subWindow = subsurf->window();
|
||||||
|
+ subWindow->sendRecursiveExposeEvent();
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!buffer->committed());
|
||||||
|
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||||
|
index f2055df..b57f5dd 100644
|
||||||
|
--- a/src/client/qwaylandwindow_p.h
|
||||||
|
+++ b/src/client/qwaylandwindow_p.h
|
||||||
|
@@ -268,6 +268,7 @@ private:
|
||||||
|
|
||||||
|
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
||||||
|
void handleScreensChanged();
|
||||||
|
+ void sendRecursiveExposeEvent();
|
||||||
|
|
||||||
|
bool mInResizeFromApplyConfigure = false;
|
||||||
|
QRect mLastExposeGeometry;
|
129
qtwayland-fix-leaking-of-callback-timers.patch
Normal file
129
qtwayland-fix-leaking-of-callback-timers.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
From fabaaec60a5fe477f7339c0d825d8b236a7e5330 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Janne Koskinen <janne.p.koskinen@qt.io>
|
||||||
|
Date: Tue, 24 Mar 2020 14:22:35 +0200
|
||||||
|
Subject: [PATCH] Fix leaking of callback timers
|
||||||
|
|
||||||
|
Use two timers to create timeout trigger for framecallback.
|
||||||
|
Removes multiple timers approach that is subject to race conditions.
|
||||||
|
|
||||||
|
This was mistakenly pushed to 5.12 branch which will not be
|
||||||
|
automatically merged upstream, so it has to be cherry-picked.
|
||||||
|
|
||||||
|
Fixes: QTBUG-82914
|
||||||
|
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||||
|
(cherry picked from commit d18c29931b0bc889fff66bdbde89133544ba0529)
|
||||||
|
Change-Id: I258c0c08f0ac5803192fc0024e40ba72e72c37a8
|
||||||
|
Reviewed-by: Janne Koskinen <janne.p.koskinen@qt.io>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
|
index 9fa2f15..884a979 100644
|
||||||
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
|
@@ -257,10 +257,7 @@
|
||||||
|
mFrameCallback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
- int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
|
||||||
|
- if (timerId != -1) {
|
||||||
|
- killTimer(timerId);
|
||||||
|
- }
|
||||||
|
+ mFrameCallbackElapsedTimer.invalidate();
|
||||||
|
mWaitingForFrameCallback = false;
|
||||||
|
mFrameCallbackTimedOut = false;
|
||||||
|
|
||||||
|
@@ -602,15 +599,11 @@
|
||||||
|
|
||||||
|
void QWaylandWindow::handleFrameCallback()
|
||||||
|
{
|
||||||
|
- // Stop the timer and stop waiting immediately
|
||||||
|
- int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
|
||||||
|
mWaitingForFrameCallback = false;
|
||||||
|
+ mFrameCallbackElapsedTimer.invalidate();
|
||||||
|
|
||||||
|
// The rest can wait until we can run it on the correct thread
|
||||||
|
- auto doHandleExpose = [this, timerId]() {
|
||||||
|
- if (timerId != -1)
|
||||||
|
- killTimer(timerId);
|
||||||
|
-
|
||||||
|
+ auto doHandleExpose = [this]() {
|
||||||
|
bool wasExposed = isExposed();
|
||||||
|
mFrameCallbackTimedOut = false;
|
||||||
|
if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
|
||||||
|
@@ -645,13 +638,6 @@
|
||||||
|
sendExposeEvent(QRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
|
||||||
|
- // Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
|
||||||
|
- // started by other writes
|
||||||
|
- int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
|
||||||
|
- if (fcbId != -1)
|
||||||
|
- QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
|
||||||
|
-
|
||||||
|
return !mWaitingForFrameCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1107,8 +1093,16 @@
|
||||||
|
|
||||||
|
void QWaylandWindow::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
- if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
|
||||||
|
- killTimer(event->timerId());
|
||||||
|
+ if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ bool callbackTimerExpired = mFrameCallbackElapsedTimer.hasExpired(100);
|
||||||
|
+ if (!mFrameCallbackElapsedTimer.isValid() || callbackTimerExpired ) {
|
||||||
|
+ killTimer(mFrameCallbackCheckIntervalTimerId);
|
||||||
|
+ mFrameCallbackCheckIntervalTimerId = -1;
|
||||||
|
+ }
|
||||||
|
+ if (mFrameCallbackElapsedTimer.isValid() && callbackTimerExpired) {
|
||||||
|
+ mFrameCallbackElapsedTimer.invalidate();
|
||||||
|
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||||
|
mFrameCallbackTimedOut = true;
|
||||||
|
mWaitingForUpdate = false;
|
||||||
|
@@ -1162,15 +1156,13 @@
|
||||||
|
mWaitingForFrameCallback = true;
|
||||||
|
mWaitingForUpdate = false;
|
||||||
|
|
||||||
|
- // Stop current frame timer if any, can't use killTimer directly, see comment above.
|
||||||
|
- int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
|
||||||
|
- if (fcbId != -1)
|
||||||
|
- QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
|
||||||
|
-
|
||||||
|
// Start a timer for handling the case when the compositor stops sending frame callbacks.
|
||||||
|
- QMetaObject::invokeMethod(this, [this] { // Again; can't do it directly
|
||||||
|
- if (mWaitingForFrameCallback)
|
||||||
|
- mFrameCallbackTimerId = startTimer(100);
|
||||||
|
+ QMetaObject::invokeMethod(this, [this] {
|
||||||
|
+ if (mWaitingForFrameCallback) {
|
||||||
|
+ if (mFrameCallbackCheckIntervalTimerId < 0)
|
||||||
|
+ mFrameCallbackCheckIntervalTimerId = startTimer(100);
|
||||||
|
+ mFrameCallbackElapsedTimer.start();
|
||||||
|
+ }
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||||
|
index 352df89..ef03fd1 100644
|
||||||
|
--- a/src/client/qwaylandwindow_p.h
|
||||||
|
+++ b/src/client/qwaylandwindow_p.h
|
||||||
|
@@ -58,6 +58,7 @@
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
+#include <QtCore/QElapsedTimer>
|
||||||
|
|
||||||
|
#include <qpa/qplatformwindow.h>
|
||||||
|
|
||||||
|
@@ -225,7 +226,8 @@
|
||||||
|
WId mWindowId;
|
||||||
|
bool mWaitingForFrameCallback = false;
|
||||||
|
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
|
||||||
|
- QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
|
||||||
|
+ int mFrameCallbackCheckIntervalTimerId = -1;
|
||||||
|
+ QElapsedTimer mFrameCallbackElapsedTimer;
|
||||||
|
struct ::wl_callback *mFrameCallback = nullptr;
|
||||||
|
struct ::wl_event_queue *mFrameQueue = nullptr;
|
||||||
|
QWaitCondition mFrameSyncWait;
|
Loading…
Reference in New Issue
Block a user