Backport upstream patches

This commit is contained in:
Jan Grulich 2020-07-27 10:55:57 +02:00
parent ff1f7b4904
commit 33335644e8
7 changed files with 555 additions and 3 deletions

View File

@ -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

View File

@ -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;

View 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);

View File

@ -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.

View File

@ -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;

View File

@ -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;

View 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;