summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-07-09 03:06:39 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2019-07-11 13:51:39 +0200
commit11a726d88672b43bef6d360bebfbe79257e97b09 (patch)
tree531a5aadaf8a462dd3b927711a85ecedf66ee732
parentc12c6712305883eff72d8da3f5cab837c5997f70 (diff)
parent1b529c7a5069965bcc404fb90c795deed4199c23 (diff)
Merge "Merge remote-tracking branch 'origin/5.12' into 5.13"
-rw-r--r--dist/changes-5.12.440
-rw-r--r--src/client/qwaylandwindow.cpp70
-rw-r--r--src/client/qwaylandwindow_p.h2
3 files changed, 81 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 8b2c12277..f61c141c8 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -245,6 +245,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;
}
@@ -614,29 +621,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;
@@ -658,11 +670,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;
}
@@ -1100,9 +1112,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;
@@ -1155,7 +1167,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();
@@ -1164,14 +1176,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 8c1ebe167..861392430 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -222,7 +222,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;