Gentoo Archives: gentoo-commits

From: Andreas Sturmlechner <asturm@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: dev-qt/qtwayland/files/, dev-qt/qtwayland/
Date: Sat, 20 Jul 2019 08:52:08
Message-Id: 1563612602.1a7c2d8589db7205b8fe7f907e2cb15b277953d5.asturm@gentoo
1 commit: 1a7c2d8589db7205b8fe7f907e2cb15b277953d5
2 Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
3 AuthorDate: Fri Jul 19 16:15:38 2019 +0000
4 Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
5 CommitDate: Sat Jul 20 08:50:02 2019 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=1a7c2d85
7
8 dev-qt/qtwayland: Various upstream regression fixes
9
10 See also: https://mail.kde.org/pipermail/kde-distro-packagers/2019-July/000379
11
12 Signed-off-by: Andreas Sturmlechner <asturm <AT> gentoo.org>
13 Package-Manager: Portage-2.3.66, Repoman-2.3.11
14
15 ...ke-handleupdate-aware-of-exposure-changes.patch | 82 +++++++++++++
16 ...t-no-fake-surfacecreated-destroyed-events.patch | 92 ++++++++++++++
17 ...t-frame-callback-timer-when-window-hiding.patch | 39 ++++++
18 ....12.4-fix-stuttering-when-gui-thread-busy.patch | 133 +++++++++++++++++++++
19 dev-qt/qtwayland/qtwayland-5.12.4-r1.ebuild | 50 ++++++++
20 5 files changed, 396 insertions(+)
21
22 diff --git a/dev-qt/qtwayland/files/qtwayland-5.12.4-client-make-handleupdate-aware-of-exposure-changes.patch b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-make-handleupdate-aware-of-exposure-changes.patch
23 new file mode 100644
24 index 00000000000..6aacad2a942
25 --- /dev/null
26 +++ b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-make-handleupdate-aware-of-exposure-changes.patch
27 @@ -0,0 +1,82 @@
28 +From b13b595dc4f4fe6bdca7b69a21fd934ee233e149 Mon Sep 17 00:00:00 2001
29 +From: David Edmundson <davidedmundson@×××.org>
30 +Date: Sun, 23 Jun 2019 14:48:30 +0200
31 +Subject: [PATCH] Client: Make handleUpdate aware of exposure changes
32 +
33 +The wl_surface can be destroyed whilst a render is happening. Calling
34 +wl_surface::frame after the window is reset can crash as wl_surface is
35 +null.
36 +
37 +Change-Id: I139a9b234cb6acba81d6c1d5fa58629904a25053
38 +---
39 + src/client/qwaylandwindow.cpp | 10 +++++++++-
40 + src/client/qwaylandwindow_p.h | 4 ++++
41 + 2 files changed, 13 insertions(+), 1 deletion(-)
42 +
43 +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
44 +index 5ea0dce1e..7e7a4929c 100644
45 +--- a/src/client/qwaylandwindow.cpp
46 ++++ b/src/client/qwaylandwindow.cpp
47 +@@ -79,6 +79,8 @@ Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
48 +
49 + QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
50 +
51 ++QReadWriteLock mSurfaceLock;
52 ++
53 + QWaylandWindow::QWaylandWindow(QWindow *window)
54 + : QPlatformWindow(window)
55 + , mDisplay(waylandScreen()->display())
56 +@@ -210,6 +212,7 @@ void QWaylandWindow::initWindow()
57 +
58 + void QWaylandWindow::initializeWlSurface()
59 + {
60 ++ QWriteLocker lock(&mSurfaceLock);
61 + init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
62 + }
63 +
64 +@@ -245,8 +248,10 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
65 + mShellSurface = nullptr;
66 + delete mSubSurfaceWindow;
67 + mSubSurfaceWindow = nullptr;
68 +- if (isInitialized())
69 ++ if (isInitialized()) {
70 ++ QWriteLocker lock(&mSurfaceLock);
71 + destroy();
72 ++ }
73 + mScreens.clear();
74 +
75 + if (mFrameCallback) {
76 +@@ -1145,6 +1150,9 @@ void QWaylandWindow::requestUpdate()
77 + void QWaylandWindow::handleUpdate()
78 + {
79 + // TODO: Should sync subsurfaces avoid requesting frame callbacks?
80 ++ QReadLocker lock(&mSurfaceLock);
81 ++ if (!isInitialized())
82 ++ return;
83 +
84 + if (mFrameCallback) {
85 + wl_callback_destroy(mFrameCallback);
86 +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
87 +index e8c9d5684..d3706442f 100644
88 +--- a/src/client/qwaylandwindow_p.h
89 ++++ b/src/client/qwaylandwindow_p.h
90 +@@ -53,6 +53,8 @@
91 +
92 + #include <QtCore/QWaitCondition>
93 + #include <QtCore/QMutex>
94 ++#include <QtCore/QReadWriteLock>
95 ++
96 + #include <QtGui/QIcon>
97 + #include <QtCore/QVariant>
98 + #include <QtCore/QLoggingCategory>
99 +@@ -271,6 +273,8 @@ private:
100 + static QMutex mFrameSyncMutex;
101 + static QWaylandWindow *mMouseGrab;
102 +
103 ++ QReadWriteLock mSurfaceLock;
104 ++
105 + friend class QWaylandSubSurface;
106 + };
107 +
108 +--
109 +2.16.3
110
111 diff --git a/dev-qt/qtwayland/files/qtwayland-5.12.4-client-no-fake-surfacecreated-destroyed-events.patch b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-no-fake-surfacecreated-destroyed-events.patch
112 new file mode 100644
113 index 00000000000..c358e0f72de
114 --- /dev/null
115 +++ b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-no-fake-surfacecreated-destroyed-events.patch
116 @@ -0,0 +1,92 @@
117 +From e6edc73942a76e57e7ac745217092333480f2c64 Mon Sep 17 00:00:00 2001
118 +From: David Edmundson <davidedmundson@×××.org>
119 +Date: Sun, 23 Jun 2019 15:09:51 +0200
120 +Subject: [PATCH] Client: Don't send fake SurfaceCreated/Destroyed events
121 +
122 +QPlatformSurface relates to the backing store. Not the wl_surface.
123 +They are emitted by QPlatformWindow.
124 +
125 +Due to a previously incorrect usage by KDE developers it was faked to
126 +emit the events when the wl_surface is created/hidden to keep behavior.
127 +
128 +With QtBase a9246c7132a2c8864d3ae6cebd260bb9ee711fcb this now causes an
129 +issue as now QWidgets react to this event in a breaking way.
130 +
131 +Change-Id: I2f003bc9da85f032a0053677fd281152099fc9eb
132 +---
133 + .../wayland/custom-extension/client-common/customextension.cpp | 9 +++++++--
134 + src/client/qwaylandwindow.cpp | 10 ++--------
135 + src/client/qwaylandwindow_p.h | 2 +-
136 + 3 files changed, 10 insertions(+), 11 deletions(-)
137 +
138 +diff --git a/examples/wayland/custom-extension/client-common/customextension.cpp b/examples/wayland/custom-extension/client-common/customextension.cpp
139 +index aa0cb58a4..16f18fd7a 100644
140 +--- a/examples/wayland/custom-extension/client-common/customextension.cpp
141 ++++ b/examples/wayland/custom-extension/client-common/customextension.cpp
142 +@@ -81,8 +81,13 @@ QWindow *CustomExtension::windowForSurface(struct ::wl_surface *surface)
143 +
144 + bool CustomExtension::eventFilter(QObject *object, QEvent *event)
145 + {
146 +- if (event->type() == QEvent::PlatformSurface
147 +- && static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
148 ++ if (event->type() == QEvent::Expose) {
149 ++ auto ee = static_cast<QExposeEvent*>(event);
150 ++
151 ++ if ((ee->region().isNull())) {
152 ++ return false;
153 ++ }
154 ++
155 + QWindow *window = qobject_cast<QWindow*>(object);
156 + Q_ASSERT(window);
157 + window->removeEventFilter(this);
158 +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
159 +index ca7c8495c..a6331621d 100644
160 +--- a/src/client/qwaylandwindow.cpp
161 ++++ b/src/client/qwaylandwindow.cpp
162 +@@ -93,7 +93,7 @@ QWaylandWindow::~QWaylandWindow()
163 + delete mWindowDecoration;
164 +
165 + if (isInitialized())
166 +- reset(false);
167 ++ reset();
168 +
169 + const QWindow *parent = window();
170 + foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
171 +@@ -119,8 +119,6 @@ void QWaylandWindow::initWindow()
172 +
173 + if (!isInitialized()) {
174 + initializeWlSurface();
175 +- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
176 +- QGuiApplication::sendEvent(window(), &e);
177 + }
178 +
179 + if (shouldCreateSubSurface()) {
180 +@@ -227,12 +225,8 @@ bool QWaylandWindow::shouldCreateSubSurface() const
181 + return QPlatformWindow::parent() != nullptr;
182 + }
183 +
184 +-void QWaylandWindow::reset(bool sendDestroyEvent)
185 ++void QWaylandWindow::reset()
186 + {
187 +- if (isInitialized() && sendDestroyEvent) {
188 +- QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
189 +- QGuiApplication::sendEvent(window(), &e);
190 +- }
191 + delete mShellSurface;
192 + mShellSurface = nullptr;
193 + delete mSubSurfaceWindow;
194 +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
195 +index 121ad8219..ba69fd9dc 100644
196 +--- a/src/client/qwaylandwindow_p.h
197 ++++ b/src/client/qwaylandwindow_p.h
198 +@@ -263,7 +263,7 @@ private:
199 + void initializeWlSurface();
200 + bool shouldCreateShellSurface() const;
201 + bool shouldCreateSubSurface() const;
202 +- void reset(bool sendDestroyEvent = true);
203 ++ void reset();
204 + void sendExposeEvent(const QRect &rect);
205 + static void closePopups(QWaylandWindow *parent);
206 + QWaylandScreen *calculateScreenFromSurfaceEvents() const;
207 +--
208 +2.16.3
209
210 diff --git a/dev-qt/qtwayland/files/qtwayland-5.12.4-client-reset-frame-callback-timer-when-window-hiding.patch b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-reset-frame-callback-timer-when-window-hiding.patch
211 new file mode 100644
212 index 00000000000..8d437824341
213 --- /dev/null
214 +++ b/dev-qt/qtwayland/files/qtwayland-5.12.4-client-reset-frame-callback-timer-when-window-hiding.patch
215 @@ -0,0 +1,39 @@
216 +From a4e6f88f50d1a1dd56df77ce8b07b98aceb20ddc Mon Sep 17 00:00:00 2001
217 +From: David Edmundson <davidedmundson@×××.org>
218 +Date: Sun, 23 Jun 2019 13:25:16 +0200
219 +Subject: [PATCH] Client: Reset frame callback timer when hiding a window
220 +
221 +If we hide a window whilst a compositor has a pending frame to show,
222 +it's possible the compositor will not render the frame and not return
223 +the callback.
224 +
225 +If this happens on the next window expose we can be left with
226 +mFrameCallbackTimedOut still true causing isExposed() to remain false
227 +and us to not send the next buffer when we later show the window again.
228 +
229 +Change-Id: I507410415d1a930fd5fa736412055e68fdf6c1d3
230 +Reviewed-by: Johan Helsing <johan.helsing@××.io>
231 +---
232 + src/client/qwaylandwindow.cpp | 7 +++++++
233 + 1 file changed, 7 insertions(+)
234 +
235 +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
236 +index 7c8ecadaa..2b243bc44 100644
237 +--- a/src/client/qwaylandwindow.cpp
238 ++++ b/src/client/qwaylandwindow.cpp
239 +@@ -254,6 +254,13 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
240 + mFrameCallback = nullptr;
241 + }
242 +
243 ++ int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
244 ++ if (timerId != -1) {
245 ++ killTimer(timerId);
246 ++ }
247 ++ mWaitingForFrameCallback = false;
248 ++ mFrameCallbackTimedOut = false;
249 ++
250 + mMask = QRegion();
251 + mQueuedBuffer = nullptr;
252 + }
253 +--
254 +2.16.3
255
256 diff --git a/dev-qt/qtwayland/files/qtwayland-5.12.4-fix-stuttering-when-gui-thread-busy.patch b/dev-qt/qtwayland/files/qtwayland-5.12.4-fix-stuttering-when-gui-thread-busy.patch
257 new file mode 100644
258 index 00000000000..794fb127529
259 --- /dev/null
260 +++ b/dev-qt/qtwayland/files/qtwayland-5.12.4-fix-stuttering-when-gui-thread-busy.patch
261 @@ -0,0 +1,133 @@
262 +From ec9057081f1094fbfeb11449bc533997731e4079 Mon Sep 17 00:00:00 2001
263 +From: Johan Klokkhammer Helsing <johan.helsing@××.io>
264 +Date: Wed, 19 Jun 2019 14:05:22 +0200
265 +Subject: [PATCH] Client: Fix stuttering when the GUI thread is busy
266 +
267 +When we did invokeMethod for handling the frame callbacks, we had to wait for
268 +the GUI thread to finish whatever it's doing before we would stop blocking.
269 +
270 +Fix it by clearing the frame callback timer and stop blocking immediately,
271 +while delaying the rest of the work until it can be run on the other thread.
272 +
273 +Fixes: QTBUG-76397
274 +Change-Id: I343e4feac4838926b4fa2ccac2948988bc6c3bb7
275 +Reviewed-by: Paul Olav Tvete <paul.tvete@××.io>
276 +---
277 + src/client/qwaylandwindow.cpp | 59 +++++++++++++++++++++++--------------------
278 + src/client/qwaylandwindow_p.h | 2 +-
279 + 2 files changed, 32 insertions(+), 29 deletions(-)
280 +
281 +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
282 +index cecdbda92..7c8ecadaa 100644
283 +--- a/src/client/qwaylandwindow.cpp
284 ++++ b/src/client/qwaylandwindow.cpp
285 +@@ -610,29 +610,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = {
286 + Q_UNUSED(callback);
287 + Q_UNUSED(time);
288 + auto *window = static_cast<QWaylandWindow*>(data);
289 +- if (window->thread() != QThread::currentThread())
290 +- QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection);
291 +- else
292 +- window->handleFrameCallback();
293 ++ window->handleFrameCallback();
294 + }
295 + };
296 +
297 + void QWaylandWindow::handleFrameCallback()
298 + {
299 +- bool wasExposed = isExposed();
300 ++ // Stop the timer and stop waiting immediately
301 ++ int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
302 ++ mWaitingForFrameCallback = false;
303 +
304 +- if (mFrameCallbackTimerId != -1) {
305 +- killTimer(mFrameCallbackTimerId);
306 +- mFrameCallbackTimerId = -1;
307 +- }
308 ++ // The rest can wait until we can run it on the correct thread
309 ++ auto doHandleExpose = [this, timerId]() {
310 ++ if (timerId != -1)
311 ++ killTimer(timerId);
312 +
313 +- mWaitingForFrameCallback = false;
314 +- mFrameCallbackTimedOut = false;
315 ++ bool wasExposed = isExposed();
316 ++ mFrameCallbackTimedOut = false;
317 ++ if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
318 ++ sendExposeEvent(QRect(QPoint(), geometry().size()));
319 ++ if (wasExposed && hasPendingUpdateRequest())
320 ++ deliverUpdateRequest();
321 ++ };
322 +
323 +- if (!wasExposed && isExposed())
324 +- sendExposeEvent(QRect(QPoint(), geometry().size()));
325 +- if (wasExposed && hasPendingUpdateRequest())
326 +- deliverUpdateRequest();
327 ++ if (thread() != QThread::currentThread()) {
328 ++ QMetaObject::invokeMethod(this, doHandleExpose);
329 ++ } else {
330 ++ doHandleExpose();
331 ++ }
332 + }
333 +
334 + QMutex QWaylandWindow::mFrameSyncMutex;
335 +@@ -654,11 +659,11 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
336 + }
337 +
338 + // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
339 +- if (mFrameCallbackTimerId != -1) {
340 +- int id = mFrameCallbackTimerId;
341 +- mFrameCallbackTimerId = -1;
342 +- QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
343 +- }
344 ++ // Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
345 ++ // started by other writes
346 ++ int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
347 ++ if (fcbId != -1)
348 ++ QMetaObject::invokeMethod(this, [=] { killTimer(fcbId); }, Qt::QueuedConnection);
349 +
350 + return !mWaitingForFrameCallback;
351 + }
352 +@@ -1090,9 +1095,9 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
353 + }
354 + }
355 +
356 +- if (event->timerId() == mFrameCallbackTimerId) {
357 +- killTimer(mFrameCallbackTimerId);
358 +- mFrameCallbackTimerId = -1;
359 ++
360 ++ if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
361 ++ killTimer(event->timerId());
362 + qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
363 + mFrameCallbackTimedOut = true;
364 + mWaitingForUpdate = false;
365 +@@ -1154,11 +1159,9 @@ void QWaylandWindow::handleUpdate()
366 + mWaitingForUpdate = false;
367 +
368 + // Stop current frame timer if any, can't use killTimer directly, see comment above.
369 +- if (mFrameCallbackTimerId != -1) {
370 +- int id = mFrameCallbackTimerId;
371 +- mFrameCallbackTimerId = -1;
372 +- QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
373 +- }
374 ++ int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
375 ++ if (fcbId != -1)
376 ++ QMetaObject::invokeMethod(this, [=] { killTimer(fcbId); }, Qt::QueuedConnection);
377 +
378 + // Start a timer for handling the case when the compositor stops sending frame callbacks.
379 + QMetaObject::invokeMethod(this, [=] { // Again; can't do it directly
380 +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
381 +index c47123dc9..e8c9d5684 100644
382 +--- a/src/client/qwaylandwindow_p.h
383 ++++ b/src/client/qwaylandwindow_p.h
384 +@@ -216,7 +216,7 @@ protected:
385 + WId mWindowId;
386 + bool mWaitingForFrameCallback = false;
387 + bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
388 +- int mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
389 ++ QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
390 + struct ::wl_callback *mFrameCallback = nullptr;
391 + struct ::wl_event_queue *mFrameQueue = nullptr;
392 + QWaitCondition mFrameSyncWait;
393 +--
394 +2.16.3
395
396 diff --git a/dev-qt/qtwayland/qtwayland-5.12.4-r1.ebuild b/dev-qt/qtwayland/qtwayland-5.12.4-r1.ebuild
397 new file mode 100644
398 index 00000000000..6bc4d61f211
399 --- /dev/null
400 +++ b/dev-qt/qtwayland/qtwayland-5.12.4-r1.ebuild
401 @@ -0,0 +1,50 @@
402 +# Copyright 1999-2019 Gentoo Authors
403 +# Distributed under the terms of the GNU General Public License v2
404 +
405 +EAPI=7
406 +inherit qt5-build
407 +
408 +DESCRIPTION="Wayland platform plugin for Qt"
409 +
410 +if [[ ${QT5_BUILD_TYPE} == release ]]; then
411 + KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~ppc ~ppc64 ~x86"
412 +fi
413 +
414 +IUSE="+libinput xcomposite"
415 +
416 +DEPEND="
417 + >=dev-libs/wayland-1.6.0
418 + ~dev-qt/qtcore-${PV}
419 + ~dev-qt/qtdeclarative-${PV}
420 + ~dev-qt/qtgui-${PV}[egl,libinput=]
421 + media-libs/mesa[egl]
422 + >=x11-libs/libxkbcommon-0.2.0
423 + xcomposite? (
424 + x11-libs/libX11
425 + x11-libs/libXcomposite
426 + )
427 +"
428 +RDEPEND="${DEPEND}"
429 +
430 +PATCHES=(
431 + "${FILESDIR}"/${P}-client-no-fake-surfacecreated-destroyed-events.patch
432 + "${FILESDIR}"/${P}-fix-stuttering-when-gui-thread-busy.patch
433 + "${FILESDIR}"/${P}-client-reset-frame-callback-timer-when-window-hiding.patch
434 + "${FILESDIR}"/${P}-client-make-handleupdate-aware-of-exposure-changes.patch
435 +)
436 +
437 +src_prepare() {
438 + qt_use_disable_config libinput xkbcommon-evdev \
439 + src/client/client.pro \
440 + src/compositor/wayland_wrapper/wayland_wrapper.pri \
441 + src/plugins/shellintegration/ivi-shell/ivi-shell.pro \
442 + src/plugins/shellintegration/wl-shell/wl-shell.pro \
443 + src/plugins/shellintegration/xdg-shell/xdg-shell.pro \
444 + src/plugins/shellintegration/xdg-shell-v5/xdg-shell-v5.pro \
445 + src/plugins/shellintegration/xdg-shell-v6/xdg-shell-v6.pro \
446 + tests/auto/compositor/compositor/compositor.pro
447 +
448 + use xcomposite || rm -r config.tests/xcomposite || die
449 +
450 + qt5-build_src_prepare
451 +}