From 07ec3a37bd6bf28a96b8ff228eea86a09550db51 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 23 May 2019 11:17:37 +0200 Subject: Bump version Change-Id: I76df7709ee1e21440c647a4419900800edfacac2 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 1bf9543a..f1a6177b 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.12.3 +MODULE_VERSION = 5.12.4 -- cgit v1.2.1 From 06cccc30c09830fe75f5757d9eae74f326af03e9 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 23 May 2019 15:20:42 +0300 Subject: Add changes file for Qt 5.12.4 Change-Id: I3402a5297448aa4f4e0703ffbae897f00f0f6577 Reviewed-by: Paul Olav Tvete --- dist/changes-5.12.4 | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 dist/changes-5.12.4 diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4 new file mode 100644 index 00000000..0fb38030 --- /dev/null +++ b/dist/changes-5.12.4 @@ -0,0 +1,39 @@ +Qt 5.12.4 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.12.0 through 5.12.3. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.12 series is binary compatible with the 5.11.x series. +Applications compiled for 5.11 will continue to run with 5.12. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Compositor * +**************************************************************************** + + - Fixed a crash that could happen when accessing the d_func of + QWaylandShell. + +**************************************************************************** +* QPA plugin * +**************************************************************************** + + - The non-blocking version of eglSwapBuffers is now used, if supported. + This fixed a bug where minimized windows would block the event loop. + - Windows that don't get frame callbacks from the compositor within 100 ms + are now set as not exposed. This should stop most clients from rendering + unnecessary frames to minimized or hidden windows. + - Fixed a crash on xdg-shell v5 when creating a popup without a valid + parent. + - Fixed a protocol error when an application tried to render to a window + before a shell or sub-surface was created. -- cgit v1.2.1 From 2e4246ee71dd6689d3731e380f393185a1e3bd8e Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 5 Jun 2019 13:10:38 +0200 Subject: Client: Don't add all windows to activePopups Neither Qt::ToolTip nor Qt::Popup are single bits in Qt::WindowFlags, and do in fact include Qt::Window. This meant that when we or'ed them and did a bitwise and with QWindow::type(), we would match more types than just Qt::Popup and Qt::ToolTip. We would for instance get any Qt::Window as well, which meant the main window would be added to activePopups, leading to strange things happening, such as crashes and the main window closing unexpectedly. [ChangeLog][QPA plugin] Fixed a crash when closing multiple popups at once. Fixes: QTBUG-76124 Change-Id: I1a6a59e161a436604a7ac8ab824396481dc99a20 Reviewed-by: Paul Olav Tvete (cherry picked from commit af9ec8a76d7e62444fadb518256fc58723fe5186) --- dist/changes-5.12.4 | 1 + src/client/qwaylandwindow.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4 index 0fb38030..672b9a7c 100644 --- a/dist/changes-5.12.4 +++ b/dist/changes-5.12.4 @@ -37,3 +37,4 @@ information about a particular change. parent. - Fixed a protocol error when an application tried to render to a window before a shell or sub-surface was created. + - Fixed a crash when closing multiple popups at once. diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 58e0fc58..cecdbda9 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -393,7 +393,7 @@ QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const void QWaylandWindow::setVisible(bool visible) { if (visible) { - if (window()->type() & (Qt::Popup | Qt::ToolTip)) + if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) activePopups << this; initWindow(); mDisplay->flushRequests(); -- cgit v1.2.1 From ec9057081f1094fbfeb11449bc533997731e4079 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 19 Jun 2019 14:05:22 +0200 Subject: Client: Fix stuttering when the GUI thread is busy When we did invokeMethod for handling the frame callbacks, we had to wait for the GUI thread to finish whatever it's doing before we would stop blocking. Fix it by clearing the frame callback timer and stop blocking immediately, while delaying the rest of the work until it can be run on the other thread. Fixes: QTBUG-76397 Change-Id: I343e4feac4838926b4fa2ccac2948988bc6c3bb7 Reviewed-by: Paul Olav Tvete --- src/client/qwaylandwindow.cpp | 59 +++++++++++++++++++++++-------------------- src/client/qwaylandwindow_p.h | 2 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index cecdbda9..7c8ecada 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -610,29 +610,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = { Q_UNUSED(callback); Q_UNUSED(time); auto *window = static_cast(data); - if (window->thread() != QThread::currentThread()) - QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection); - else - window->handleFrameCallback(); + window->handleFrameCallback(); } }; void QWaylandWindow::handleFrameCallback() { - bool wasExposed = isExposed(); + // Stop the timer and stop waiting immediately + int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1); + mWaitingForFrameCallback = false; - if (mFrameCallbackTimerId != -1) { - killTimer(mFrameCallbackTimerId); - mFrameCallbackTimerId = -1; - } + // The rest can wait until we can run it on the correct thread + auto doHandleExpose = [this, timerId]() { + if (timerId != -1) + killTimer(timerId); - mWaitingForFrameCallback = false; - mFrameCallbackTimedOut = false; + bool wasExposed = isExposed(); + mFrameCallbackTimedOut = false; + if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed? + sendExposeEvent(QRect(QPoint(), geometry().size())); + if (wasExposed && hasPendingUpdateRequest()) + deliverUpdateRequest(); + }; - if (!wasExposed && isExposed()) - sendExposeEvent(QRect(QPoint(), geometry().size())); - if (wasExposed && hasPendingUpdateRequest()) - deliverUpdateRequest(); + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, doHandleExpose); + } else { + doHandleExpose(); + } } QMutex QWaylandWindow::mFrameSyncMutex; @@ -654,11 +659,11 @@ bool QWaylandWindow::waitForFrameSync(int timeout) } // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread - if (mFrameCallbackTimerId != -1) { - int id = mFrameCallbackTimerId; - mFrameCallbackTimerId = -1; - QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); - } + // 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, [=] { killTimer(fcbId); }, Qt::QueuedConnection); return !mWaitingForFrameCallback; } @@ -1090,9 +1095,9 @@ void QWaylandWindow::timerEvent(QTimerEvent *event) } } - if (event->timerId() == mFrameCallbackTimerId) { - killTimer(mFrameCallbackTimerId); - mFrameCallbackTimerId = -1; + + if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) { + killTimer(event->timerId()); qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed"; mFrameCallbackTimedOut = true; mWaitingForUpdate = false; @@ -1154,11 +1159,9 @@ void QWaylandWindow::handleUpdate() mWaitingForUpdate = false; // Stop current frame timer if any, can't use killTimer directly, see comment above. - if (mFrameCallbackTimerId != -1) { - int id = mFrameCallbackTimerId; - mFrameCallbackTimerId = -1; - QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); - } + int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1); + if (fcbId != -1) + QMetaObject::invokeMethod(this, [=] { killTimer(fcbId); }, Qt::QueuedConnection); // Start a timer for handling the case when the compositor stops sending frame callbacks. QMetaObject::invokeMethod(this, [=] { // Again; can't do it directly diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index c47123dc..e8c9d568 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -216,7 +216,7 @@ protected: WId mWindowId; bool mWaitingForFrameCallback = false; bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out - int mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback + QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback struct ::wl_callback *mFrameCallback = nullptr; struct ::wl_event_queue *mFrameQueue = nullptr; QWaitCondition mFrameSyncWait; -- cgit v1.2.1 From a4e6f88f50d1a1dd56df77ce8b07b98aceb20ddc Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sun, 23 Jun 2019 13:25:16 +0200 Subject: Client: Reset frame callback timer when hiding a window If we hide a window whilst a compositor has a pending frame to show, it's possible the compositor will not render the frame and not return the callback. If this happens on the next window expose we can be left with mFrameCallbackTimedOut still true causing isExposed() to remain false and us to not send the next buffer when we later show the window again. Change-Id: I507410415d1a930fd5fa736412055e68fdf6c1d3 Reviewed-by: Johan Helsing --- src/client/qwaylandwindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 7c8ecada..2b243bc4 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -254,6 +254,13 @@ void QWaylandWindow::reset(bool sendDestroyEvent) mFrameCallback = nullptr; } + int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1); + if (timerId != -1) { + killTimer(timerId); + } + mWaitingForFrameCallback = false; + mFrameCallbackTimedOut = false; + mMask = QRegion(); mQueuedBuffer = nullptr; } -- cgit v1.2.1 From acba020f1b6725e2d431636b1a2cfb075672ddcb Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 1 Jul 2019 16:02:08 +0200 Subject: Bump version Change-Id: If69992b414824405267ea0d8c20b9f1bd996944b --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index f1a6177b..b5454e50 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.12.4 +MODULE_VERSION = 5.12.5 -- cgit v1.2.1 From 5ca9f28f4b272d3265b97c16029071a0070195a6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 6 Jul 2019 21:05:32 +0200 Subject: Fix compilation with C++20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implicit capture of 'this' in [=] is deprecated in C++20. Fix by using explicit captures. Change-Id: Ie3a94ec60d7c56b2856d201fa3d68d0670bdd7b9 Reviewed-by: MÃ¥rten Nordheim --- src/client/qwaylandwindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 2b243bc4..5ea0dce1 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -670,7 +670,7 @@ bool QWaylandWindow::waitForFrameSync(int timeout) // started by other writes int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1); if (fcbId != -1) - QMetaObject::invokeMethod(this, [=] { killTimer(fcbId); }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection); return !mWaitingForFrameCallback; } @@ -1157,7 +1157,7 @@ void QWaylandWindow::handleUpdate() // ignore it if it times out before it's cleaned up by the invokeMethod call. int id = mFallbackUpdateTimerId; mFallbackUpdateTimerId = -1; - QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection); } mFrameCallback = frame(); @@ -1168,10 +1168,10 @@ void QWaylandWindow::handleUpdate() // 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, [=] { killTimer(fcbId); }, Qt::QueuedConnection); + 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, [=] { // Again; can't do it directly + QMetaObject::invokeMethod(this, [this] { // Again; can't do it directly if (mWaitingForFrameCallback) mFrameCallbackTimerId = startTimer(100); }, Qt::QueuedConnection); -- cgit v1.2.1