diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-07-16 03:00:13 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-07-16 03:00:19 +0200 |
commit | 4cf9a701bd3f4017afcd69285eeba9ee85d9da52 (patch) | |
tree | dcfaf517d1c2657f814df49b6fdb44b67b22a90c | |
parent | 905cdffeaa1813123a27a2151b345d106923ca24 (diff) | |
parent | 146530db10e72c353c0455affb246a8a39efc41c (diff) |
Merge "Merge remote-tracking branch 'origin/5.13' into dev"
-rw-r--r-- | dist/changes-5.12.4 | 40 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 70 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 2 | ||||
-rw-r--r-- | src/compositor/doc/qtwaylandcompositor.qdocconf | 1 |
4 files changed, 82 insertions, 31 deletions
diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4 new file mode 100644 index 000000000..672b9a7c1 --- /dev/null +++ b/dist/changes-5.12.4 @@ -0,0 +1,40 @@ +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. + - Fixed a crash when closing multiple popups at once. diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 9a58ec39a..8c462c113 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -249,6 +249,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; } @@ -573,29 +580,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = { Q_UNUSED(callback); Q_UNUSED(time); auto *window = static_cast<QWaylandWindow*>(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; @@ -617,11 +629,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, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection); return !mWaitingForFrameCallback; } @@ -1077,9 +1089,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; @@ -1132,7 +1144,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 = mSurface->frame(); @@ -1141,14 +1153,12 @@ 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, [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); diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 5eadc02c8..eca883a74 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -219,7 +219,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; diff --git a/src/compositor/doc/qtwaylandcompositor.qdocconf b/src/compositor/doc/qtwaylandcompositor.qdocconf index 4fa9f394d..45928b640 100644 --- a/src/compositor/doc/qtwaylandcompositor.qdocconf +++ b/src/compositor/doc/qtwaylandcompositor.qdocconf @@ -1,4 +1,5 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtwayland.qdocconf) project = QtWaylandCompositor description = Qt Wayland Compositor Reference Documentation |