Backport upstream patches
This commit is contained in:
parent
ff1f7b4904
commit
33335644e8
@ -3,15 +3,13 @@
|
||||
Summary: Qt5 - Wayland platform support and QtCompositor module
|
||||
Name: qt5-%{qt_module}
|
||||
Version: 5.14.2
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
|
||||
License: LGPLv3
|
||||
Url: http://www.qt.io
|
||||
%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
|
||||
|
||||
# Upstream patches
|
||||
|
||||
# Bold fonts in qt applications appear much too heavy
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1823984
|
||||
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
|
||||
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
|
||||
%global __provides_exclude_from ^%{_qt5_archdatadir}/qml/.*\\.so$
|
||||
|
||||
@ -131,6 +137,10 @@ popd
|
||||
|
||||
|
||||
%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
|
||||
- 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