diff --git a/SOURCES/0005-Scanner-Avoid-accessing-dangling-pointers-in-destroy.patch b/SOURCES/0005-Scanner-Avoid-accessing-dangling-pointers-in-destroy.patch index cde64df..4fbabfa 100644 --- a/SOURCES/0005-Scanner-Avoid-accessing-dangling-pointers-in-destroy.patch +++ b/SOURCES/0005-Scanner-Avoid-accessing-dangling-pointers-in-destroy.patch @@ -1,7 +1,7 @@ From e5c272423d1bba2825086b82fd97499237a6fa4b Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 30 Oct 2020 16:55:30 +0200 -Subject: [PATCH 05/36] Scanner: Avoid accessing dangling pointers in +Subject: [PATCH 05/52] Scanner: Avoid accessing dangling pointers in destroy_func() Usually, the object associated with the resource gets destroyed in the @@ -34,5 +34,5 @@ index 1d635f06..e2f87bbd 100644 printf(" }\n"); printf(" delete resource;\n"); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0006-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch b/SOURCES/0006-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch index acfbf99..5efd227 100644 --- a/SOURCES/0006-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch +++ b/SOURCES/0006-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch @@ -1,7 +1,7 @@ From a825fb5f714fd79d16cc3ebbdd327e7961b07d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 16 Nov 2020 19:37:33 +0100 -Subject: [PATCH 06/36] Make setting QT_SCALE_FACTOR work on Wayland +Subject: [PATCH 06/52] Make setting QT_SCALE_FACTOR work on Wayland Follow-up to 8cb1b07aea12d50b4fecc45c903705dfd368022a, fixes one additional case (Use of minimum/maximum size). @@ -34,5 +34,5 @@ index bc031ed5..eb053406 100644 if (mSubSurfaceWindow) { QMargins m = QPlatformWindow::parent()->frameMargins(); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0007-Do-not-try-to-eglMakeCurrent-for-unintended-case.patch b/SOURCES/0007-Do-not-try-to-eglMakeCurrent-for-unintended-case.patch index dd1eb8c..adaf5fa 100644 --- a/SOURCES/0007-Do-not-try-to-eglMakeCurrent-for-unintended-case.patch +++ b/SOURCES/0007-Do-not-try-to-eglMakeCurrent-for-unintended-case.patch @@ -1,7 +1,7 @@ From 2c0a03e9aea13831d05ac03996949f888afd5085 Mon Sep 17 00:00:00 2001 From: Jaehak Lee Date: Sun, 8 Nov 2020 11:40:06 +0900 -Subject: [PATCH 07/36] Do not try to eglMakeCurrent for unintended case +Subject: [PATCH 07/52] Do not try to eglMakeCurrent for unintended case The QSGThreadedRenderLoop::hide can be called at twice, when the QWindowPrivate::setVisible(false) is called. @@ -58,5 +58,5 @@ index 46c7bb76..93edaec0 100644 } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0008-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch b/SOURCES/0008-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch index 4e10015..b2a2d60 100644 --- a/SOURCES/0008-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch +++ b/SOURCES/0008-Make-setting-QT_SCALE_FACTOR-work-on-Wayland.patch @@ -1,7 +1,7 @@ From 10005185e06857ce119c50fe710f9eedde06ec5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 13 Nov 2020 11:21:50 +0100 -Subject: [PATCH 08/36] Make setting QT_SCALE_FACTOR work on Wayland +Subject: [PATCH 08/52] Make setting QT_SCALE_FACTOR work on Wayland QWindow geometry accessors return geometry in device independent pixels. Normally this coordinate system @@ -108,5 +108,5 @@ index b6d23ac1..1c762944 100644 if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)) m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0009-Ensure-that-grabbing-is-performed-in-correct-context.patch b/SOURCES/0009-Ensure-that-grabbing-is-performed-in-correct-context.patch index 1a98f8e..20b5e04 100644 --- a/SOURCES/0009-Ensure-that-grabbing-is-performed-in-correct-context.patch +++ b/SOURCES/0009-Ensure-that-grabbing-is-performed-in-correct-context.patch @@ -1,7 +1,7 @@ From dba4bc4f1d6dfee9fe9433c55b15653d703bed4f Mon Sep 17 00:00:00 2001 From: Andreas Cord-Landwehr Date: Wed, 2 Dec 2020 20:55:52 +0100 -Subject: [PATCH 09/36] Ensure that grabbing is performed in correct context +Subject: [PATCH 09/52] Ensure that grabbing is performed in correct context For multi-display rendering on EGL, it is mandatory that the grabbing of the surface happens in the same EGL context as the surface belongs to. @@ -31,5 +31,5 @@ index 49f0860e..db1cf00f 100644 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType); #endif -- -2.33.1 +2.35.1 diff --git a/SOURCES/0010-Fix-leaked-subsurface-wayland-items.patch b/SOURCES/0010-Fix-leaked-subsurface-wayland-items.patch index fbfaf41..f727f3f 100644 --- a/SOURCES/0010-Fix-leaked-subsurface-wayland-items.patch +++ b/SOURCES/0010-Fix-leaked-subsurface-wayland-items.patch @@ -1,7 +1,7 @@ From a8d35b3c18bdb05a0da3ed50a554a7b7bd4ebed3 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 30 Nov 2020 13:13:18 +0100 -Subject: [PATCH 10/36] Fix leaked subsurface wayland items +Subject: [PATCH 10/52] Fix leaked subsurface wayland items Whenever a subsurface was added we would create a QWaylandQuickItem, but this was never deleted. It is one-to-one with the surface, so it @@ -32,5 +32,5 @@ index 15f0195c..2218f43a 100644 bool success = QMetaObject::invokeMethod(d->subsurfaceHandler, "handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface)); if (!success) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0011-Use-qWarning-and-_exit-instead-of-qFatal-for-wayland.patch b/SOURCES/0011-Use-qWarning-and-_exit-instead-of-qFatal-for-wayland.patch index 5860630..2a3bd4b 100644 --- a/SOURCES/0011-Use-qWarning-and-_exit-instead-of-qFatal-for-wayland.patch +++ b/SOURCES/0011-Use-qWarning-and-_exit-instead-of-qFatal-for-wayland.patch @@ -1,7 +1,7 @@ From 9ee2ea141adc7765f6c212e63839ef23a4494b30 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Tue, 9 Mar 2021 10:43:59 -0800 -Subject: [PATCH 11/36] Use qWarning and _exit() instead of qFatal for wayland +Subject: [PATCH 11/52] Use qWarning and _exit() instead of qFatal for wayland error This type of error is likely to happen upon system logout. qFatal would @@ -34,5 +34,5 @@ index fe094f6f..f10c1f79 100644 void QWaylandDisplay::flushRequests() -- -2.33.1 +2.35.1 diff --git a/SOURCES/0012-Fix-memory-leak-in-QWaylandGLContext.patch b/SOURCES/0012-Fix-memory-leak-in-QWaylandGLContext.patch index 114570b..de5ffe3 100644 --- a/SOURCES/0012-Fix-memory-leak-in-QWaylandGLContext.patch +++ b/SOURCES/0012-Fix-memory-leak-in-QWaylandGLContext.patch @@ -1,7 +1,7 @@ From 9df11e79b46c77d8c83f765b2a8e85b639fd55a2 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 Jan 2021 09:08:50 +0100 -Subject: [PATCH 12/36] Fix memory leak in QWaylandGLContext +Subject: [PATCH 12/52] Fix memory leak in QWaylandGLContext We were leaking an EGL context with every GL context created, which lead to rapid OOM errors in stress tests. @@ -34,5 +34,5 @@ index 681f82f4..befadedc 100644 bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0013-Client-Send-set_window_geometry-only-once-configured.patch b/SOURCES/0013-Client-Send-set_window_geometry-only-once-configured.patch index 5b88f17..14e7898 100644 --- a/SOURCES/0013-Client-Send-set_window_geometry-only-once-configured.patch +++ b/SOURCES/0013-Client-Send-set_window_geometry-only-once-configured.patch @@ -1,7 +1,7 @@ From 7db4f83c39d2a0c709bc0b9c0de3946d3b4ebfd5 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 16 Nov 2020 14:57:36 +0000 -Subject: [PATCH 13/36] Client: Send set_window_geometry only once configured +Subject: [PATCH 13/52] Client: Send set_window_geometry only once configured The geometry only makes sense when a buffer exists, our currently send value is somewhat meaningless, but till now harmless. @@ -37,5 +37,5 @@ index 9b343702..e875af3a 100644 if (isOpaque() && mMask.isEmpty()) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0014-Translate-opaque-area-with-frame-margins.patch b/SOURCES/0014-Translate-opaque-area-with-frame-margins.patch index 6cc32a4..e4a2de5 100644 --- a/SOURCES/0014-Translate-opaque-area-with-frame-margins.patch +++ b/SOURCES/0014-Translate-opaque-area-with-frame-margins.patch @@ -1,7 +1,7 @@ From a3e3ac1c86a956b25b1dc24f14518b6e6c96bcfc Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Wed, 10 Feb 2021 17:11:27 +0100 -Subject: [PATCH 14/36] Translate opaque area with frame margins +Subject: [PATCH 14/52] Translate opaque area with frame margins The opaque area doesn't take window decorations into account, which may result into possible graphical artefacts. @@ -36,5 +36,5 @@ index e875af3a..2af39977 100644 wl_region_destroy(region); } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0015-Client-Send-exposeEvent-to-parent-on-subsurface-posi.patch b/SOURCES/0015-Client-Send-exposeEvent-to-parent-on-subsurface-posi.patch index d342e82..c081d91 100644 --- a/SOURCES/0015-Client-Send-exposeEvent-to-parent-on-subsurface-posi.patch +++ b/SOURCES/0015-Client-Send-exposeEvent-to-parent-on-subsurface-posi.patch @@ -1,7 +1,7 @@ From 2073ff99e62d4f99ed3f1f45559c5b68a61c5f66 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 14 Sep 2020 17:08:39 +0100 -Subject: [PATCH 15/36] Client: Send exposeEvent to parent on subsurface +Subject: [PATCH 15/52] Client: Send exposeEvent to parent on subsurface position changes When a subsurface is moved, we need the parent window to commit to apply @@ -93,5 +93,5 @@ index b8a65f15..95e4e609 100644 // Used to cause a crash in libwayland (QTBUG-79674) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0016-Get-correct-decoration-margins-region.patch b/SOURCES/0016-Get-correct-decoration-margins-region.patch index 8d827bf..844f0c9 100644 --- a/SOURCES/0016-Get-correct-decoration-margins-region.patch +++ b/SOURCES/0016-Get-correct-decoration-margins-region.patch @@ -1,7 +1,7 @@ From 6810b0f66a34056bfe0da7299d7a768e700e58f5 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Thu, 11 Feb 2021 15:12:32 +0100 -Subject: [PATCH 16/36] Get correct decoration margins region +Subject: [PATCH 16/52] Get correct decoration margins region Size we use to calculate margins region already contains size including margins. This resulted into bigger region and not properly damaging @@ -35,5 +35,5 @@ index 87dd6cea..b6ee43c9 100644 } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0017-xdgshell-Tell-the-compositor-the-screen-we-re-expect.patch b/SOURCES/0017-xdgshell-Tell-the-compositor-the-screen-we-re-expect.patch index ab9600c..336e3fb 100644 --- a/SOURCES/0017-xdgshell-Tell-the-compositor-the-screen-we-re-expect.patch +++ b/SOURCES/0017-xdgshell-Tell-the-compositor-the-screen-we-re-expect.patch @@ -1,7 +1,7 @@ From cea69b8adec1e61adc1fa04cbf46b77c0d72c75e Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Mon, 23 Nov 2020 20:07:02 +0100 -Subject: [PATCH 17/36] xdgshell: Tell the compositor the screen we're +Subject: [PATCH 17/52] xdgshell: Tell the compositor the screen we're expecting to fill The xdgshell protocol allows us to tell the output to fill. This makes @@ -37,5 +37,5 @@ index 1c762944..3a1569f7 100644 } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0018-Fix-compilation.patch b/SOURCES/0018-Fix-compilation.patch index edbb55f..742d1d6 100644 --- a/SOURCES/0018-Fix-compilation.patch +++ b/SOURCES/0018-Fix-compilation.patch @@ -1,7 +1,7 @@ From 2f84a874da064069461284db1da36dc818949ec1 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Sat, 10 Apr 2021 12:10:16 +0200 -Subject: [PATCH 18/36] Fix compilation +Subject: [PATCH 18/52] Fix compilation 9df11e79b46c77d8c83f765b2a8e85b639fd55a2 can't be backported 1:1 --- @@ -22,5 +22,5 @@ index befadedc..95d1049c 100644 bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0019-client-Allow-QWaylandInputContext-to-accept-composed.patch b/SOURCES/0019-client-Allow-QWaylandInputContext-to-accept-composed.patch index ff39a0b..e1cea9d 100644 --- a/SOURCES/0019-client-Allow-QWaylandInputContext-to-accept-composed.patch +++ b/SOURCES/0019-client-Allow-QWaylandInputContext-to-accept-composed.patch @@ -1,7 +1,7 @@ From 91c48320633e493b4cd519e5d73b836a878b2b77 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 10 Mar 2021 01:09:13 +0100 -Subject: [PATCH 19/36] client: Allow QWaylandInputContext to accept composed +Subject: [PATCH 19/52] client: Allow QWaylandInputContext to accept composed key combinations At the moment, we are forcing user to choose to either compose or use @@ -253,5 +253,5 @@ index 7ad8e05e..c53ccb78 100644 } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0020-Client-Announce-an-output-after-receiving-more-compl.patch b/SOURCES/0020-Client-Announce-an-output-after-receiving-more-compl.patch index 3249a69..e7e10d0 100644 --- a/SOURCES/0020-Client-Announce-an-output-after-receiving-more-compl.patch +++ b/SOURCES/0020-Client-Announce-an-output-after-receiving-more-compl.patch @@ -1,7 +1,7 @@ From d5186701e27ad6f09f3944809cec2a25c5328026 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 5 May 2021 20:49:26 +0300 -Subject: [PATCH 20/36] Client: Announce an output after receiving more +Subject: [PATCH 20/52] Client: Announce an output after receiving more complete state Output initialization is not atomic, meaning that the compositor may @@ -142,5 +142,5 @@ index df1c94f2..050cfdc0 100644 #if QT_CONFIG(cursor) -- -2.33.1 +2.35.1 diff --git a/SOURCES/0021-Fix-issue-with-repeated-window-size-changes.patch b/SOURCES/0021-Fix-issue-with-repeated-window-size-changes.patch index 9c7ebde..4a7469e 100644 --- a/SOURCES/0021-Fix-issue-with-repeated-window-size-changes.patch +++ b/SOURCES/0021-Fix-issue-with-repeated-window-size-changes.patch @@ -1,7 +1,7 @@ From 62494312db0f58053d1342bfacc7984186fdf3a6 Mon Sep 17 00:00:00 2001 From: Jaeyoon Jung Date: Mon, 15 Feb 2021 08:31:06 +0900 -Subject: [PATCH 21/36] Fix issue with repeated window size changes +Subject: [PATCH 21/52] Fix issue with repeated window size changes Check if the new window size is different from the size requested previously before calling wl_egl_window_resize. It addresses the issue @@ -54,5 +54,5 @@ index 5b1f4d56..0079dfef 100644 } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0022-Include-locale.h-for-setlocale-LC_CTYPE.patch b/SOURCES/0022-Include-locale.h-for-setlocale-LC_CTYPE.patch index fcb0973..67e8339 100644 --- a/SOURCES/0022-Include-locale.h-for-setlocale-LC_CTYPE.patch +++ b/SOURCES/0022-Include-locale.h-for-setlocale-LC_CTYPE.patch @@ -1,7 +1,7 @@ From 1ccebbab3a42690a0812e2c4c76016799bf6cf1f Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 10 May 2021 14:38:49 +0200 -Subject: [PATCH 22/36] Include locale.h for setlocale/LC_CTYPE +Subject: [PATCH 22/52] Include locale.h for setlocale/LC_CTYPE Pick-to: 5.15 Change-Id: Iced32a31a63cec71008549c1e0961d59ffc45a37 @@ -27,5 +27,5 @@ index ef5aa375..503fd735 100644 Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods") -- -2.33.1 +2.35.1 diff --git a/SOURCES/0023-Client-Connect-drags-being-accepted-to-updating-the-.patch b/SOURCES/0023-Client-Connect-drags-being-accepted-to-updating-the-.patch index 5780e26..8d87353 100644 --- a/SOURCES/0023-Client-Connect-drags-being-accepted-to-updating-the-.patch +++ b/SOURCES/0023-Client-Connect-drags-being-accepted-to-updating-the-.patch @@ -1,7 +1,7 @@ From fcc2f57cefa66339c8cb6632f45a47fbb99bb60d Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 9 Feb 2021 16:09:21 +0000 -Subject: [PATCH 23/36] Client: Connect drags being accepted to updating the +Subject: [PATCH 23/52] Client: Connect drags being accepted to updating the source drag icon Currently in a multi-process drag and drop when the other client accepts @@ -35,5 +35,5 @@ index 19944a34..54a69c3c 100644 start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial()); return true; -- -2.33.1 +2.35.1 diff --git a/SOURCES/0024-Client-Disconnect-registry-listener-on-destruction.patch b/SOURCES/0024-Client-Disconnect-registry-listener-on-destruction.patch index a2afc6b..e6d9550 100644 --- a/SOURCES/0024-Client-Disconnect-registry-listener-on-destruction.patch +++ b/SOURCES/0024-Client-Disconnect-registry-listener-on-destruction.patch @@ -1,7 +1,7 @@ From 1b5e43a593e917610e6245f7a272ac081c508ba4 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 14 May 2021 13:23:24 +0100 -Subject: [PATCH 24/36] Client: Disconnect registry listener on destruction +Subject: [PATCH 24/52] Client: Disconnect registry listener on destruction If a display outlives a QWaylandClientExtension and a new global is announced we end up delivering an event to a now deleted extension which @@ -45,5 +45,5 @@ index 98272e57..5bd28398 100644 QtWaylandClient::QWaylandIntegration *integration() const; int version() const; -- -2.33.1 +2.35.1 diff --git a/SOURCES/0025-Client-Set-XdgShell-size-hints-before-the-first-comm.patch b/SOURCES/0025-Client-Set-XdgShell-size-hints-before-the-first-comm.patch index 84ef091..72872aa 100644 --- a/SOURCES/0025-Client-Set-XdgShell-size-hints-before-the-first-comm.patch +++ b/SOURCES/0025-Client-Set-XdgShell-size-hints-before-the-first-comm.patch @@ -1,7 +1,7 @@ From 36a552fa530be57091e986ebd1468d75d3061743 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 3 May 2021 23:01:53 +0100 -Subject: [PATCH 25/36] Client: Set XdgShell size hints before the first commit +Subject: [PATCH 25/52] Client: Set XdgShell size hints before the first commit propagateSizeHints is only called in QWindow we have platform window and minimumSizeHint is then sent. We also need to send existing hints when @@ -54,5 +54,5 @@ index 2277bbb8..2fdd0a7c 100644 QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(100, 100)); QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(1000, 1000)); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0026-Fix-build.patch b/SOURCES/0026-Fix-build.patch index d401d84..3060032 100644 --- a/SOURCES/0026-Fix-build.patch +++ b/SOURCES/0026-Fix-build.patch @@ -1,7 +1,7 @@ From a8ddf1a7296e2d28b36231a391807226a7329ae4 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 14 Jun 2021 12:45:37 +0100 -Subject: [PATCH 26/36] Fix build +Subject: [PATCH 26/52] Fix build 1b5e43a593e917610e6245f7a272ac081c508ba4 relied on a patch that we can't backport. @@ -42,5 +42,5 @@ index 69cc46a0..9091efbe 100644 class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate -- -2.33.1 +2.35.1 diff --git a/SOURCES/0027-Fix-remove-listener.patch b/SOURCES/0027-Fix-remove-listener.patch index fbe2342..81bc6c6 100644 --- a/SOURCES/0027-Fix-remove-listener.patch +++ b/SOURCES/0027-Fix-remove-listener.patch @@ -1,7 +1,7 @@ From d1c4a459faa1d514026c4834828cb33024ac2ceb Mon Sep 17 00:00:00 2001 From: Zhang Liang Date: Mon, 1 Feb 2021 19:29:43 +0800 -Subject: [PATCH 27/36] Fix: remove listener +Subject: [PATCH 27/52] Fix: remove listener Add the operation for removing the listener form listener list @@ -29,5 +29,5 @@ index f10c1f79..e0dfe8b2 100644 uint32_t QWaylandDisplay::currentTimeMillisec() -- -2.33.1 +2.35.1 diff --git a/SOURCES/0028-Hook-up-queryKeyboardModifers.patch b/SOURCES/0028-Hook-up-queryKeyboardModifers.patch index 7e074c9..1b343d2 100644 --- a/SOURCES/0028-Hook-up-queryKeyboardModifers.patch +++ b/SOURCES/0028-Hook-up-queryKeyboardModifers.patch @@ -1,7 +1,7 @@ From a6476d1a1c78eb7f17408241b268404e27b3e161 Mon Sep 17 00:00:00 2001 From: David Redondo Date: Wed, 26 May 2021 14:49:40 +0200 -Subject: [PATCH 28/36] Hook up queryKeyboardModifers +Subject: [PATCH 28/52] Hook up queryKeyboardModifers Can be useful when upon enter a modifiers event is received but no key event so no QKeyEvent is generated. @@ -51,5 +51,5 @@ index ff70ae25..73b80658 100644 QStringList themeNames() const override; -- -2.33.1 +2.35.1 diff --git a/SOURCES/0029-Do-not-update-the-mask-if-we-do-not-have-a-surface.patch b/SOURCES/0029-Do-not-update-the-mask-if-we-do-not-have-a-surface.patch index 9764d9b..2185388 100644 --- a/SOURCES/0029-Do-not-update-the-mask-if-we-do-not-have-a-surface.patch +++ b/SOURCES/0029-Do-not-update-the-mask-if-we-do-not-have-a-surface.patch @@ -1,7 +1,7 @@ From d4c41797b61a5a8da47c5821711aca72e756dcbf Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Tue, 13 Jul 2021 13:32:15 +0200 -Subject: [PATCH 29/36] Do not update the mask if we do not have a surface +Subject: [PATCH 29/52] Do not update the mask if we do not have a surface mMask serves as a cache to remember what we've sent, the source of truth for the value is window()->mask(). @@ -40,5 +40,5 @@ index e96d8fe9..bd70f4af 100644 mSurface->set_input_region(nullptr); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0030-Correctly-detect-if-image-format-is-supported-by-QIm.patch b/SOURCES/0030-Correctly-detect-if-image-format-is-supported-by-QIm.patch index ceea624..28f0d1a 100644 --- a/SOURCES/0030-Correctly-detect-if-image-format-is-supported-by-QIm.patch +++ b/SOURCES/0030-Correctly-detect-if-image-format-is-supported-by-QIm.patch @@ -1,7 +1,7 @@ From 3c420cd180397e3f42c8a436a7f1b11465925bdd Mon Sep 17 00:00:00 2001 From: Jan Blackquill Date: Tue, 24 Aug 2021 14:36:34 -0400 -Subject: [PATCH 30/36] Correctly detect if image format is supported by +Subject: [PATCH 30/52] Correctly detect if image format is supported by QImageWriter The code queries potential image formats by stripping a mimetype of its @@ -64,5 +64,5 @@ index a5fdd34d..051a91dc 100644 fmt = imgFmt; } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0031-Wayland-client-Fix-crash-when-windows-are-shown-hidd.patch b/SOURCES/0031-Wayland-client-Fix-crash-when-windows-are-shown-hidd.patch index b5df11c..4712de9 100644 --- a/SOURCES/0031-Wayland-client-Fix-crash-when-windows-are-shown-hidd.patch +++ b/SOURCES/0031-Wayland-client-Fix-crash-when-windows-are-shown-hidd.patch @@ -1,7 +1,7 @@ From 1c53ba6dfebbf1d6e87c9ad1f2bbda94e3d45bf7 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 14 Sep 2021 11:56:23 +0200 -Subject: [PATCH 31/36] Wayland client: Fix crash when windows are shown/hidden +Subject: [PATCH 31/52] Wayland client: Fix crash when windows are shown/hidden during drag Fixes: QTBUG-87624 @@ -27,5 +27,5 @@ index 54a69c3c..bbd2d568 100644 return; // Ignore foreign surfaces -- -2.33.1 +2.35.1 diff --git a/SOURCES/0032-Client-Don-t-always-recreate-frame-callbacks.patch b/SOURCES/0032-Client-Don-t-always-recreate-frame-callbacks.patch index 4789fe8..372aae2 100644 --- a/SOURCES/0032-Client-Don-t-always-recreate-frame-callbacks.patch +++ b/SOURCES/0032-Client-Don-t-always-recreate-frame-callbacks.patch @@ -1,7 +1,7 @@ From 3be586cd8b6c8313cb6b8b7d61be17706f79590e Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 27 May 2021 19:55:04 -0300 -Subject: [PATCH 32/36] Client: Don't always recreate frame callbacks +Subject: [PATCH 32/52] Client: Don't always recreate frame callbacks The main QWaylandWindow method that is executed when handling updates is QWaylandWindow::handleUpdate(). This method always, unconditionally queues @@ -73,5 +73,5 @@ index 2fdd0a7c..e2593314 100644 void tst_xdgshell::popup() -- -2.33.1 +2.35.1 diff --git a/SOURCES/0033-Client-Always-destroy-frame-callback-in-the-actual-c.patch b/SOURCES/0033-Client-Always-destroy-frame-callback-in-the-actual-c.patch index 8446b4e..8b84cb0 100644 --- a/SOURCES/0033-Client-Always-destroy-frame-callback-in-the-actual-c.patch +++ b/SOURCES/0033-Client-Always-destroy-frame-callback-in-the-actual-c.patch @@ -1,7 +1,7 @@ From efe6edcaf8eba601dff99ec6ad4457c8a4442f86 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 27 May 2021 20:02:53 -0300 -Subject: [PATCH 33/36] Client: Always destroy frame callback in the actual +Subject: [PATCH 33/52] Client: Always destroy frame callback in the actual callback It's good hygiene to destroy all frame callbacks. Destroy the @@ -54,5 +54,5 @@ index 85307875..c020a58f 100644 struct ::wl_surface *wrappedSurface = reinterpret_cast(wl_proxy_create_wrapper(mSurface->object())); wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mFrameQueue.queue); -- -2.33.1 +2.35.1 diff --git a/SOURCES/0034-Fix-the-logic-for-decoding-modifiers-map-in-Wayland-.patch b/SOURCES/0034-Fix-the-logic-for-decoding-modifiers-map-in-Wayland-.patch index 47ac957..b97bcf7 100644 --- a/SOURCES/0034-Fix-the-logic-for-decoding-modifiers-map-in-Wayland-.patch +++ b/SOURCES/0034-Fix-the-logic-for-decoding-modifiers-map-in-Wayland-.patch @@ -1,7 +1,7 @@ From 02f9585ca19c17ae0978b864195533dc527d825e Mon Sep 17 00:00:00 2001 From: Rodney Dawes Date: Fri, 15 Oct 2021 12:55:33 -0400 -Subject: [PATCH 34/36] Fix the logic for decoding modifiers map in Wayland +Subject: [PATCH 34/52] Fix the logic for decoding modifiers map in Wayland text input protocol Correctly check for the flags in the modifiers map when we get it from @@ -36,5 +36,5 @@ index 503fd735..e290baa2 100644 return ret; } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch b/SOURCES/0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch index b8d1207..49bf2e0 100644 --- a/SOURCES/0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch +++ b/SOURCES/0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch @@ -1,7 +1,7 @@ From 5c180bdc1042e7cb1555e188051f09e219b00ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Wed, 18 Aug 2021 18:28:20 +0200 -Subject: [PATCH 35/36] Wayland client: use wl_keyboard to determine active +Subject: [PATCH 35/52] Wayland client: use wl_keyboard to determine active state Commit f497a5bb87270174b8e0106b7eca1992d44ff15d made QWaylandDisplay @@ -337,5 +337,5 @@ index e2593314..73d1eb9c 100644 const QSize screenSize(640, 480); const uint maximizedSerial = exec([=] { -- -2.33.1 +2.35.1 diff --git a/SOURCES/0036-Client-do-not-empty-clipboard-when-a-new-popup-windo.patch b/SOURCES/0036-Client-do-not-empty-clipboard-when-a-new-popup-windo.patch index c0cbefc..c241a1b 100644 --- a/SOURCES/0036-Client-do-not-empty-clipboard-when-a-new-popup-windo.patch +++ b/SOURCES/0036-Client-do-not-empty-clipboard-when-a-new-popup-windo.patch @@ -1,7 +1,7 @@ From 992833ca741efe8f533c61abfaf129a1d8bfcfee Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Fri, 16 Jul 2021 13:00:03 +0200 -Subject: [PATCH 36/36] Client: do not empty clipboard when a new popup/window +Subject: [PATCH 36/52] Client: do not empty clipboard when a new popup/window is opened If we open a new popup or a window within the same app we have to avoid @@ -64,5 +64,5 @@ index ae045f4f..514457e9 100644 mRepeatTimer.stop(); } -- -2.33.1 +2.35.1 diff --git a/SOURCES/0037-Fix-backport-context-destruction-was-omitted.patch b/SOURCES/0037-Fix-backport-context-destruction-was-omitted.patch new file mode 100644 index 0000000..1966252 --- /dev/null +++ b/SOURCES/0037-Fix-backport-context-destruction-was-omitted.patch @@ -0,0 +1,29 @@ +From eb422ab5e07498a7a8d086f6a942ee35ab3c9776 Mon Sep 17 00:00:00 2001 +From: Aleix Pol +Date: Thu, 9 Dec 2021 17:35:24 +0100 +Subject: [PATCH 37/52] Fix backport, context destruction was omitted + +When cherry-picking for 9df11e79b46c77d8c83f765b2a8e85b639fd55a2, this +line got removed when rebasing the patch, which created a leak. + +BUG: 442844 +Change-Id: Id00e8b194dcd910c5f01ce9d2cc318f96a4129a2 +--- + src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +index 95d1049c..683fe123 100644 +--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp ++++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +@@ -407,6 +407,7 @@ QWaylandGLContext::~QWaylandGLContext() + { + delete m_blitter; + m_blitter = nullptr; ++ eglDestroyContext(m_eglDisplay, m_context); + if (m_decorationsContext != EGL_NO_CONTEXT) + eglDestroyContext(m_eglDisplay, m_decorationsContext); + } +-- +2.35.1 + diff --git a/SOURCES/0038-Set-preedit-cursor-when-cursor-equals-to-0.patch b/SOURCES/0038-Set-preedit-cursor-when-cursor-equals-to-0.patch new file mode 100644 index 0000000..fe6674a --- /dev/null +++ b/SOURCES/0038-Set-preedit-cursor-when-cursor-equals-to-0.patch @@ -0,0 +1,29 @@ +From e0646f531e1e73a90a93faaa45d933ae40769985 Mon Sep 17 00:00:00 2001 +From: Weng Xuetian +Date: Sat, 18 Dec 2021 23:42:49 -0800 +Subject: [PATCH 38/52] Set preedit cursor when cursor equals to 0 + +Pick-to: 6.3 6.2 5.15 +Change-Id: I832fbb22d973b36ac4ab51570fc53bc2e4c3ed58 +Reviewed-by: Liang Qi +(cherry picked from commit 719a55be13bdadfa659a732755f280e276a894bd) +--- + src/shared/qwaylandinputmethodeventbuilder.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp +index 526d0ef4..25be2509 100644 +--- a/src/shared/qwaylandinputmethodeventbuilder.cpp ++++ b/src/shared/qwaylandinputmethodeventbuilder.cpp +@@ -151,7 +151,7 @@ QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &t + { + QList attributes; + +- if (m_preeditCursor < 0) { ++ if (m_preeditCursor <= 0) { + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant())); + } else if (m_preeditCursor > 0) { + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant())); +-- +2.35.1 + diff --git a/SOURCES/0039-Client-Implement-DataDeviceV3.patch b/SOURCES/0039-Client-Implement-DataDeviceV3.patch new file mode 100644 index 0000000..9bd9a7b --- /dev/null +++ b/SOURCES/0039-Client-Implement-DataDeviceV3.patch @@ -0,0 +1,513 @@ +From 2044603ebb5ae70c785d50968ac620b842c2b14e Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Tue, 16 Feb 2021 09:51:47 +0000 +Subject: [PATCH 39/52] Client: Implement DataDeviceV3 + +DataDeviceV2 fixes a leak of DataDevice resources. + +DataDeviceV3 brings multiple improvements: + +Action negotiation. The source announces which actions are supported, +the target then announces which subset of those action the target +supports and a preferred action. After negotiation both the source and +target are notified of which action is to be performed. + +Drag sources are now notified when contents are dropped and when a +client has finished with the drag and drop operation. + +A good test is the draggableicons example in QtBase. + +Change-Id: I55e9759ca5a2e4218d02d863144a64ade53ef764 +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 283a2d61d03315495a52d82f356e7cb5292f4bb4) +--- + src/client/qwaylanddatadevice.cpp | 84 ++++++++++++++----- + src/client/qwaylanddatadevice_p.h | 8 +- + src/client/qwaylanddatadevicemanager.cpp | 4 +- + src/client/qwaylanddatadevicemanager_p.h | 2 +- + src/client/qwaylanddataoffer.cpp | 25 ++++++ + src/client/qwaylanddataoffer_p.h | 4 + + src/client/qwaylanddatasource.cpp | 27 +++++- + src/client/qwaylanddatasource_p.h | 10 ++- + src/client/qwaylanddisplay.cpp | 2 +- + src/client/qwaylanddnd.cpp | 24 +++--- + src/client/qwaylanddnd_p.h | 7 +- + .../client/datadevicev1/tst_datadevicev1.cpp | 2 +- + 12 files changed, 153 insertions(+), 46 deletions(-) + +diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp +index bbd2d568..fbb5aa91 100644 +--- a/src/client/qwaylanddatadevice.cpp ++++ b/src/client/qwaylanddatadevice.cpp +@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl + + QWaylandDataDevice::~QWaylandDataDevice() + { ++ if (wl_data_device_get_version(object()) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION) ++ release(); + } + + QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const +@@ -110,7 +112,7 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const + return m_dragOffer.data(); + } + +-bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon) ++bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon) + { + auto *seat = m_display->currentInputDevice(); + auto *origin = seat->pointerFocus(); +@@ -123,8 +125,28 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon) + } + + m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData)); ++ ++ if (wl_data_device_get_version(object()) >= 3) ++ m_dragSource->set_actions(dropActionsToWl(supportedActions)); ++ + connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled); +- connect(m_dragSource.data(), &QWaylandDataSource::targetChanged, this, &QWaylandDataDevice::dragSourceTargetChanged); ++ connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) { ++ auto drag = static_cast(QGuiApplicationPrivate::platformIntegration()->drag()); ++ // in old versions drop action is not set, so we guess ++ if (wl_data_source_get_version(m_dragSource->object()) < 3) { ++ drag->setResponse(accepted); ++ } else { ++ QPlatformDropQtResponse response(accepted, action); ++ drag->setResponse(response); ++ } ++ }); ++ connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this, [](bool accepted, Qt::DropAction action) { ++ QPlatformDropQtResponse response(accepted, action); ++ static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response); ++ }); ++ connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() { ++ static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(); ++ }); + + start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial()); + return true; +@@ -153,7 +175,7 @@ void QWaylandDataDevice::data_device_drop() + supportedActions = drag->supportedActions(); + } else if (m_dragOffer) { + dragData = m_dragOffer->mimeData(); +- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction; ++ supportedActions = m_dragOffer->supportedActions(); + } else { + return; + } +@@ -163,7 +185,11 @@ void QWaylandDataDevice::data_device_drop() + QGuiApplication::keyboardModifiers()); + + if (drag) { +- static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response); ++ auto drag = static_cast(QGuiApplicationPrivate::platformIntegration()->drag()); ++ drag->setDropResponse(response); ++ drag->finishDrag(); ++ } else if (m_dragOffer) { ++ m_dragOffer->finish(); + } + } + +@@ -187,7 +213,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, + supportedActions = drag->supportedActions(); + } else if (m_dragOffer) { + dragData = m_dragOffer->mimeData(); +- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction; ++ supportedActions = m_dragOffer->supportedActions(); + } + + const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions, +@@ -198,11 +224,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, + static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response); + } + +- if (response.isAccepted()) { +- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData()); +- } else { +- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr); +- } ++ sendResponse(supportedActions, response); + } + + void QWaylandDataDevice::data_device_leave() +@@ -236,10 +258,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe + supportedActions = drag->supportedActions(); + } else { + dragData = m_dragOffer->mimeData(); +- supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction; ++ supportedActions = m_dragOffer->supportedActions(); + } + +- QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions, ++ const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions, + QGuiApplication::mouseButtons(), + QGuiApplication::keyboardModifiers()); + +@@ -247,11 +269,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe + static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response); + } + +- if (response.isAccepted()) { +- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData()); +- } else { +- wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr); +- } ++ sendResponse(supportedActions, response); + } + #endif // QT_CONFIG(draganddrop) + +@@ -281,11 +299,6 @@ void QWaylandDataDevice::dragSourceCancelled() + m_dragSource.reset(); + } + +-void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType) +-{ +- static_cast(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType); +-} +- + QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const + { + QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y)); +@@ -298,6 +311,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con + } + return pnt; + } ++ ++void QWaylandDataDevice::sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response) ++{ ++ if (response.isAccepted()) { ++ if (wl_data_device_get_version(object()) >= 3) ++ m_dragOffer->set_actions(dropActionsToWl(supportedActions), dropActionsToWl(response.acceptedAction())); ++ ++ m_dragOffer->accept(m_enterSerial, m_dragOffer->firstFormat()); ++ } else { ++ m_dragOffer->accept(m_enterSerial, QString()); ++ } ++} ++ ++int QWaylandDataDevice::dropActionsToWl(Qt::DropActions actions) ++{ ++ ++ int wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; ++ if (actions & Qt::CopyAction) ++ wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; ++ if (actions & (Qt::MoveAction | Qt::TargetMoveAction)) ++ wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; ++ ++ // wayland does not support LinkAction at the time of writing ++ return wlActions; ++} ++ ++ + #endif // QT_CONFIG(draganddrop) + + } +diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h +index 16c3ad28..801dcc2c 100644 +--- a/src/client/qwaylanddatadevice_p.h ++++ b/src/client/qwaylanddatadevice_p.h +@@ -64,6 +64,7 @@ QT_REQUIRE_CONFIG(wayland_datadevice); + QT_BEGIN_NAMESPACE + + class QMimeData; ++class QPlatformDragQtResponse; + class QWindow; + + namespace QtWaylandClient { +@@ -89,7 +90,7 @@ public: + + #if QT_CONFIG(draganddrop) + QWaylandDataOffer *dragOffer() const; +- bool startDrag(QMimeData *mimeData, QWaylandWindow *icon); ++ bool startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon); + void cancelDrag(); + #endif + +@@ -109,13 +110,16 @@ private Q_SLOTS: + + #if QT_CONFIG(draganddrop) + void dragSourceCancelled(); +- void dragSourceTargetChanged(const QString &mimeType); + #endif + + private: + #if QT_CONFIG(draganddrop) + QPoint calculateDragPosition(int x, int y, QWindow *wnd) const; + #endif ++ void sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response); ++ ++ static int dropActionsToWl(Qt::DropActions dropActions); ++ + + QWaylandDisplay *m_display = nullptr; + QWaylandInputDevice *m_inputDevice = nullptr; +diff --git a/src/client/qwaylanddatadevicemanager.cpp b/src/client/qwaylanddatadevicemanager.cpp +index 35d67307..6dc4f77f 100644 +--- a/src/client/qwaylanddatadevicemanager.cpp ++++ b/src/client/qwaylanddatadevicemanager.cpp +@@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE + + namespace QtWaylandClient { + +-QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id) +- : wl_data_device_manager(display->wl_registry(), id, 1) ++QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id) ++ : wl_data_device_manager(display->wl_registry(), id, qMin(version, 3)) + , m_display(display) + { + // Create transfer devices for all input devices. +diff --git a/src/client/qwaylanddatadevicemanager_p.h b/src/client/qwaylanddatadevicemanager_p.h +index bd05c0fb..510d9be4 100644 +--- a/src/client/qwaylanddatadevicemanager_p.h ++++ b/src/client/qwaylanddatadevicemanager_p.h +@@ -68,7 +68,7 @@ class QWaylandInputDevice; + class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager + { + public: +- QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id); ++ QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id); + ~QWaylandDataDeviceManager() override; + + QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice); +diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp +index 2297e8a1..c9e158cc 100644 +--- a/src/client/qwaylanddataoffer.cpp ++++ b/src/client/qwaylanddataoffer.cpp +@@ -82,6 +82,15 @@ QMimeData *QWaylandDataOffer::mimeData() + return m_mimeData.data(); + } + ++Qt::DropActions QWaylandDataOffer::supportedActions() const ++{ ++ if (wl_data_offer_get_version(const_cast<::wl_data_offer*>(object())) < 3) { ++ return Qt::MoveAction | Qt::CopyAction; ++ } ++ ++ return m_supportedActions; ++} ++ + void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd) + { + receive(mimeType, fd); +@@ -93,6 +102,22 @@ void QWaylandDataOffer::data_offer_offer(const QString &mime_type) + m_mimeData->appendFormat(mime_type); + } + ++void QWaylandDataOffer::data_offer_action(uint32_t dnd_action) ++{ ++ Q_UNUSED(dnd_action); ++ // This is the compositor telling the drag target what action it should perform ++ // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action? ++} ++ ++void QWaylandDataOffer::data_offer_source_actions(uint32_t source_actions) ++{ ++ m_supportedActions = Qt::DropActions(); ++ if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) ++ m_supportedActions |= Qt::MoveAction; ++ if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) ++ m_supportedActions |= Qt::CopyAction; ++} ++ + QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer) + : m_dataOffer(dataOffer) + { +diff --git a/src/client/qwaylanddataoffer_p.h b/src/client/qwaylanddataoffer_p.h +index 9cf1483c..6f667398 100644 +--- a/src/client/qwaylanddataoffer_p.h ++++ b/src/client/qwaylanddataoffer_p.h +@@ -82,6 +82,7 @@ public: + explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer); + ~QWaylandDataOffer() override; + QMimeData *mimeData() override; ++ Qt::DropActions supportedActions() const; + + QString firstFormat() const; + +@@ -89,10 +90,13 @@ public: + + protected: + void data_offer_offer(const QString &mime_type) override; ++ void data_offer_source_actions(uint32_t source_actions) override; ++ void data_offer_action(uint32_t dnd_action) override; + + private: + QWaylandDisplay *m_display = nullptr; + QScopedPointer m_mimeData; ++ Qt::DropActions m_supportedActions; + }; + + +diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp +index f45122fb..5599cbd4 100644 +--- a/src/client/qwaylanddatasource.cpp ++++ b/src/client/qwaylanddatasource.cpp +@@ -101,7 +101,32 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd) + + void QWaylandDataSource::data_source_target(const QString &mime_type) + { +- Q_EMIT targetChanged(mime_type); ++ m_accepted = !mime_type.isEmpty(); ++ Q_EMIT dndResponseUpdated(m_accepted, m_dropAction); ++} ++ ++void QWaylandDataSource::data_source_action(uint32_t action) ++{ ++ Qt::DropAction qtAction = Qt::IgnoreAction; ++ ++ if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) ++ qtAction = Qt::MoveAction; ++ else if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) ++ qtAction = Qt::CopyAction; ++ ++ m_dropAction = qtAction; ++ Q_EMIT dndResponseUpdated(m_accepted, m_dropAction); ++} ++ ++void QWaylandDataSource::data_source_dnd_finished() ++{ ++ Q_EMIT finished(); ++} ++ ++void QWaylandDataSource::data_source_dnd_drop_performed() ++{ ++ ++ Q_EMIT dndDropped(m_accepted, m_dropAction); + } + + } +diff --git a/src/client/qwaylanddatasource_p.h b/src/client/qwaylanddatasource_p.h +index 25afff79..96f07bc3 100644 +--- a/src/client/qwaylanddatasource_p.h ++++ b/src/client/qwaylanddatasource_p.h +@@ -77,17 +77,25 @@ public: + QMimeData *mimeData() const; + + Q_SIGNALS: +- void targetChanged(const QString &mime_type); + void cancelled(); ++ void finished(); ++ ++ void dndResponseUpdated(bool accepted, Qt::DropAction action); ++ void dndDropped(bool accepted, Qt::DropAction action); + + protected: + void data_source_cancelled() override; + void data_source_send(const QString &mime_type, int32_t fd) override; + void data_source_target(const QString &mime_type) override; ++ void data_source_dnd_drop_performed() override; ++ void data_source_dnd_finished() override; ++ void data_source_action(uint32_t action) override; + + private: + QWaylandDisplay *m_display = nullptr; + QMimeData *m_mime_data = nullptr; ++ bool m_accepted = false; ++ Qt::DropAction m_dropAction = Qt::IgnoreAction; + }; + + } +diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp +index 9f595af3..ea344c61 100644 +--- a/src/client/qwaylanddisplay.cpp ++++ b/src/client/qwaylanddisplay.cpp +@@ -354,7 +354,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin + mInputDevices.append(inputDevice); + #if QT_CONFIG(wayland_datadevice) + } else if (interface == QStringLiteral("wl_data_device_manager")) { +- mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); ++ mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id)); + #endif + } else if (interface == QStringLiteral("qt_surface_extension")) { + mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1)); +diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp +index 6535aa16..97ee5b2e 100644 +--- a/src/client/qwaylanddnd.cpp ++++ b/src/client/qwaylanddnd.cpp +@@ -66,7 +66,7 @@ void QWaylandDrag::startDrag() + { + QBasicDrag::startDrag(); + QWaylandWindow *icon = static_cast(shapedPixmapWindow()->handle()); +- if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) { ++ if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), drag()->supportedActions(), icon)) { + icon->addAttachOffset(-drag()->hotSpot()); + } else { + // Cancelling immediately does not work, since the event loop for QDrag::exec is started +@@ -103,31 +103,31 @@ void QWaylandDrag::endDrag() + m_display->currentInputDevice()->handleEndDrag(); + } + +-void QWaylandDrag::updateTarget(const QString &mimeType) ++void QWaylandDrag::setResponse(bool accepted) + { +- setCanDrop(!mimeType.isEmpty()); +- +- if (canDrop()) { +- updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers())); +- } else { +- updateCursor(Qt::IgnoreAction); +- } ++ // This method is used for old DataDevices where the drag action is not communicated ++ Qt::DropAction action = defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()); ++ setResponse(QPlatformDropQtResponse(accepted, action)); + } + +-void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response) ++void QWaylandDrag::setResponse(const QPlatformDropQtResponse &response) + { + setCanDrop(response.isAccepted()); + + if (canDrop()) { +- updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers())); ++ updateCursor(response.acceptedAction()); + } else { + updateCursor(Qt::IgnoreAction); + } + } + +-void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response) ++void QWaylandDrag::setDropResponse(const QPlatformDropQtResponse &response) + { + setExecutedDropAction(response.acceptedAction()); ++} ++ ++void QWaylandDrag::finishDrag() ++{ + QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); + eventFilter(shapedPixmapWindow(), &event); + } +diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h +index 474fe2ab..747f0190 100644 +--- a/src/client/qwaylanddnd_p.h ++++ b/src/client/qwaylanddnd_p.h +@@ -71,9 +71,10 @@ public: + QWaylandDrag(QWaylandDisplay *display); + ~QWaylandDrag() override; + +- void updateTarget(const QString &mimeType); +- void setResponse(const QPlatformDragQtResponse &response); +- void finishDrag(const QPlatformDropQtResponse &response); ++ void setResponse(bool accepted); ++ void setResponse(const QPlatformDropQtResponse &response); ++ void setDropResponse(const QPlatformDropQtResponse &response); ++ void finishDrag(); + + protected: + void startDrag() override; +diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp +index 1568b3b9..067410d0 100644 +--- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp ++++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp +@@ -35,7 +35,7 @@ + + using namespace MockCompositor; + +-constexpr int dataDeviceVersion = 1; ++constexpr int dataDeviceVersion = 3; + + class DataDeviceCompositor : public DefaultCompositor { + public: +-- +2.35.1 + diff --git a/SOURCES/0040-Client-Delay-deletion-of-QDrag-object-until-after-we.patch b/SOURCES/0040-Client-Delay-deletion-of-QDrag-object-until-after-we.patch new file mode 100644 index 0000000..b6ddb34 --- /dev/null +++ b/SOURCES/0040-Client-Delay-deletion-of-QDrag-object-until-after-we.patch @@ -0,0 +1,67 @@ +From 0b15df7e9e26a4edfc2277eb3ec7b3d5c58a5dcd Mon Sep 17 00:00:00 2001 +From: Arjen Hiemstra +Date: Thu, 18 Nov 2021 13:05:30 +0100 +Subject: [PATCH 40/52] Client: Delay deletion of QDrag object until after + we're done with it + +In certain cases, most notably when performing drag and drop operations +with touch, the QDrag object gets deleted before data_source_send is +executed. This then tries to access a deleted data_source, crashing the +client. + +To avoid this, we indicate we want the QDrag object to stay around and +then delete it in QWaylandDrag::finishDrag, which with data_device v3 is +guaranteed to be called after everyone is done with the data source. + +Change-Id: I6a2f5a219f58d1b721a9fec33c57d26d2c522ec9 +Reviewed-by: David Edmundson +(cherry picked from commit 39e3290efa2dd40722fa3322284cae3b01ccedf4) +--- + src/client/qwaylanddnd.cpp | 11 +++++++++++ + src/client/qwaylanddnd_p.h | 1 + + 2 files changed, 12 insertions(+) + +diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp +index 97ee5b2e..7c53f5fa 100644 +--- a/src/client/qwaylanddnd.cpp ++++ b/src/client/qwaylanddnd.cpp +@@ -80,6 +80,9 @@ void QWaylandDrag::cancel() + QBasicDrag::cancel(); + + m_display->currentInputDevice()->dataDevice()->cancelDrag(); ++ ++ if (drag()) ++ drag()->deleteLater(); + } + + void QWaylandDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +@@ -130,6 +133,14 @@ void QWaylandDrag::finishDrag() + { + QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); + eventFilter(shapedPixmapWindow(), &event); ++ ++ if (drag()) ++ drag()->deleteLater(); ++} ++ ++bool QWaylandDrag::ownsDragObject() const ++{ ++ return true; + } + + } +diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h +index 747f0190..46f629ac 100644 +--- a/src/client/qwaylanddnd_p.h ++++ b/src/client/qwaylanddnd_p.h +@@ -83,6 +83,7 @@ protected: + void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; + void endDrag() override; + ++ bool ownsDragObject() const override; + + private: + QWaylandDisplay *m_display = nullptr; +-- +2.35.1 + diff --git a/SOURCES/0041-Client-Avoid-processing-of-events-when-showing-windo.patch b/SOURCES/0041-Client-Avoid-processing-of-events-when-showing-windo.patch new file mode 100644 index 0000000..d57e9b6 --- /dev/null +++ b/SOURCES/0041-Client-Avoid-processing-of-events-when-showing-windo.patch @@ -0,0 +1,38 @@ +From 867540b9d913760a847ff67c8694d817c821f2c2 Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Sun, 14 Nov 2021 13:54:19 +0000 +Subject: [PATCH 41/52] Client: Avoid processing of events when showing windows + +The only time we want to dispatch events from the wayland socket is when +the application is waiting for external events. Doing so at any other +time will cause unpredictable behavior in client code. + +This caused a crash downstream where we had outputs get altered whilst +itterating through outputs, which shouldn't happen. + +There is no benefit to flushing here, it won't make anything appear +faster as we haven't attached the buffer yet. + +Change-Id: Ie13eae4012dab96a93d8810f468d1343402b8c28 +Reviewed-by: Qt CI Bot +Reviewed-by: Aleix Pol Gonzalez +(cherry picked from commit 46ed85a80b28d519cf5887bbdce55d1bf57886c3) +--- + src/client/qwaylandwindow.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index ba881cb3..1597f67e 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -436,7 +436,6 @@ void QWaylandWindow::setVisible(bool visible) + if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) + activePopups << this; + initWindow(); +- mDisplay->flushRequests(); + + setGeometry(windowGeometry()); + // Don't flush the events here, or else the newly visible window may start drawing, but since +-- +2.35.1 + diff --git a/SOURCES/0042-Handle-registry_global-out-of-constructor.patch b/SOURCES/0042-Handle-registry_global-out-of-constructor.patch new file mode 100644 index 0000000..9a4321b --- /dev/null +++ b/SOURCES/0042-Handle-registry_global-out-of-constructor.patch @@ -0,0 +1,85 @@ +From bc5a8d24f63181a36759723a4d1b39b59b3b53e6 Mon Sep 17 00:00:00 2001 +From: Elvis Lee +Date: Thu, 18 Feb 2021 15:45:49 +0900 +Subject: [PATCH 42/52] Handle registry_global out of constructor + +Factory functions in QWaylandDisplay::registry_global() can be overridden. +Later, other classes instantiated in the registry_global can support +platform specific implementation with inheritance and some factory function. + +Change-Id: I92ce574e049b8c91587687cc7c30611f3dfdbe56 +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 3793a82038682db77966ea5daf8e75964e4250fe) +--- + src/client/qwaylanddisplay.cpp | 19 ++++++++++++------- + src/client/qwaylanddisplay_p.h | 2 ++ + src/client/qwaylandintegration.cpp | 3 +++ + 3 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp +index ea344c61..0f75cb7e 100644 +--- a/src/client/qwaylanddisplay.cpp ++++ b/src/client/qwaylanddisplay.cpp +@@ -158,13 +158,6 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) + if (!mXkbContext) + qCWarning(lcQpaWayland, "failed to create xkb context"); + #endif +- +- forceRoundTrip(); +- +- if (!mWaitingScreens.isEmpty()) { +- // Give wl_output.done and zxdg_output_v1.done events a chance to arrive +- forceRoundTrip(); +- } + } + + QWaylandDisplay::~QWaylandDisplay(void) +@@ -189,6 +182,18 @@ QWaylandDisplay::~QWaylandDisplay(void) + wl_display_disconnect(mDisplay); + } + ++// Steps which is called just after constructor. This separates registry_global() out of the constructor ++// so that factory functions in integration can be overridden. ++void QWaylandDisplay::initialize() ++{ ++ forceRoundTrip(); ++ ++ if (!mWaitingScreens.isEmpty()) { ++ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive ++ forceRoundTrip(); ++ } ++} ++ + void QWaylandDisplay::ensureScreen() + { + if (!mScreens.empty() || mPlaceholderScreen) +diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h +index 09a1736a..d9c8849f 100644 +--- a/src/client/qwaylanddisplay_p.h ++++ b/src/client/qwaylanddisplay_p.h +@@ -129,6 +129,8 @@ public: + QWaylandDisplay(QWaylandIntegration *waylandIntegration); + ~QWaylandDisplay(void) override; + ++ void initialize(); ++ + #if QT_CONFIG(xkbcommon) + struct xkb_context *xkbContext() const { return mXkbContext.get(); } + #endif +diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp +index e5e7dd42..f5632982 100644 +--- a/src/client/qwaylandintegration.cpp ++++ b/src/client/qwaylandintegration.cpp +@@ -200,6 +200,9 @@ void QWaylandIntegration::initialize() + QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); + QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests())); + ++ // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip() ++ mDisplay->initialize(); ++ + // Qt does not support running with no screens + mDisplay->ensureScreen(); + } +-- +2.35.1 + diff --git a/SOURCES/0043-Connect-flushRequest-after-forceRoundTrip.patch b/SOURCES/0043-Connect-flushRequest-after-forceRoundTrip.patch new file mode 100644 index 0000000..ccfe47f --- /dev/null +++ b/SOURCES/0043-Connect-flushRequest-after-forceRoundTrip.patch @@ -0,0 +1,47 @@ +From 98dc33fdc66f15a0e69f3024fcef046f11adc58c Mon Sep 17 00:00:00 2001 +From: Elvis Lee +Date: Wed, 17 Mar 2021 16:31:10 +0900 +Subject: [PATCH 43/52] Connect flushRequest after forceRoundTrip + +If flushRequest is connected with aboutToBlock, the flushRequest +may consumes all events so that processEvents might be blocked in forceRoundTrip. + +Change-Id: I12b2c506e8442bf0e75f6ab6e418d3e1eea6d68c +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 654a54755138c520c3a41210d8078196e9a2c1bf) +--- + src/client/qwaylandintegration.cpp | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp +index f5632982..3a6fa651 100644 +--- a/src/client/qwaylandintegration.cpp ++++ b/src/client/qwaylandintegration.cpp +@@ -192,10 +192,6 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const + + void QWaylandIntegration::initialize() + { +- QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; +- QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); +- QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); +- + int fd = wl_display_get_fd(mDisplay->wl_display()); + QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); + QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests())); +@@ -203,6 +199,13 @@ void QWaylandIntegration::initialize() + // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip() + mDisplay->initialize(); + ++ // But the aboutToBlock() and awake() should be connected after initializePlatform(). ++ // Otherwise the connected flushRequests() may consumes up all events before processEvents starts to wait, ++ // so that processEvents(QEventLoop::WaitForMoreEvents) may be blocked in the forceRoundTrip(). ++ QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; ++ QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); ++ QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); ++ + // Qt does not support running with no screens + mDisplay->ensureScreen(); + } +-- +2.35.1 + diff --git a/SOURCES/0044-Move-the-wayland-socket-polling-to-a-separate-event-.patch b/SOURCES/0044-Move-the-wayland-socket-polling-to-a-separate-event-.patch new file mode 100644 index 0000000..d9d31dd --- /dev/null +++ b/SOURCES/0044-Move-the-wayland-socket-polling-to-a-separate-event-.patch @@ -0,0 +1,574 @@ +From 4644d51f4b52e83fc1b4d02b380d80d9d57e76fa Mon Sep 17 00:00:00 2001 +From: Adrien Faveraux +Date: Fri, 26 Nov 2021 09:18:58 +0100 +Subject: [PATCH 44/52] Move the wayland socket polling to a separate event + thread + +New event threads is introduced which calls poll() on the wayland fd, +instead of relying on the event dispatcher by using the QSocketNotifier. +This allows to call in the proper order the wl_display_prepare_read(), +poll() and wl_display_read_events() functions. + +One thread is responsible for the default queue; when needed, it emit +a signal so that the main thread can dispatch the queue. Another thread +is responsible for the dedicated queue for frame callbacks; this thread +will dispatch events on the thread itself. + +QWaylandWindow is updated to, instead of each window's dedicated event +queue, use this queue for frame callbacks. + +Co-authored-by: Ratchanan Srirattanamet +Task-number: QTBUG-66075 +Change-Id: Ibb33ad7f4193b866d1b8d7a0405a94d59dcad5eb +Reviewed-by: Qt CI Bot +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 92a7904d9651348b0c307e84251c8440c6f75b22) +--- + src/client/qwaylanddisplay.cpp | 302 +++++++++++++++++++++-------- + src/client/qwaylanddisplay_p.h | 21 +- + src/client/qwaylandintegration.cpp | 4 +- + src/client/qwaylandwindow.cpp | 34 +++- + src/client/qwaylandwindow_p.h | 2 +- + 5 files changed, 255 insertions(+), 108 deletions(-) + +diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp +index 0f75cb7e..a7ce280a 100644 +--- a/src/client/qwaylanddisplay.cpp ++++ b/src/client/qwaylanddisplay.cpp +@@ -85,10 +85,203 @@ + + #include + ++#include // for std::tie ++ ++static void checkWaylandError(struct wl_display *display) ++{ ++ int ecode = wl_display_get_error(display); ++ if ((ecode == EPIPE || ecode == ECONNRESET)) { ++ // special case this to provide a nicer error ++ qWarning("The Wayland connection broke. Did the Wayland compositor die?"); ++ } else { ++ qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode)); ++ } ++ _exit(1); ++} ++ + QT_BEGIN_NAMESPACE + + namespace QtWaylandClient { + ++class EventThread : public QThread ++{ ++ Q_OBJECT ++public: ++ enum OperatingMode { ++ EmitToDispatch, // Emit the signal, allow dispatching in a differnt thread. ++ SelfDispatch, // Dispatch the events inside this thread. ++ }; ++ ++ EventThread(struct wl_display * wl, struct wl_event_queue * ev_queue, ++ OperatingMode mode) ++ : m_fd(wl_display_get_fd(wl)) ++ , m_pipefd{ -1, -1 } ++ , m_wldisplay(wl) ++ , m_wlevqueue(ev_queue) ++ , m_mode(mode) ++ , m_reading(true) ++ , m_quitting(false) ++ { ++ setObjectName(QStringLiteral("WaylandEventThread")); ++ } ++ ++ void readAndDispatchEvents() ++ { ++ /* ++ * Dispatch pending events and flush the requests at least once. If the event thread ++ * is not reading, try to call _prepare_read() to allow the event thread to poll(). ++ * If that fails, re-try dispatch & flush again until _prepare_read() is successful. ++ * ++ * This allow any call to readAndDispatchEvents() to start event thread's polling, ++ * not only the one issued from event thread's waitForReading(), which means functions ++ * called from dispatch_pending() can safely spin an event loop. ++ */ ++ for (;;) { ++ if (dispatchQueuePending() < 0) { ++ checkWaylandError(m_wldisplay); ++ return; ++ } ++ ++ wl_display_flush(m_wldisplay); ++ ++ // We have to check if event thread is reading every time we dispatch ++ // something, as that may recursively call this function. ++ if (m_reading.loadAcquire()) ++ break; ++ ++ if (prepareReadQueue() == 0) { ++ QMutexLocker l(&m_mutex); ++ m_reading.storeRelease(true); ++ m_cond.wakeOne(); ++ break; ++ } ++ } ++ } ++ ++ void stop() ++ { ++ // We have to both write to the pipe and set the flag, as the thread may be ++ // either in the poll() or waiting for _prepare_read(). ++ if (m_pipefd[1] != -1 && write(m_pipefd[1], "\0", 1) == -1) ++ qWarning("Failed to write to the pipe: %s.", strerror(errno)); ++ ++ { ++ QMutexLocker l(&m_mutex); ++ m_quitting = true; ++ m_cond.wakeOne(); ++ } ++ ++ wait(); ++ } ++ ++Q_SIGNALS: ++ void needReadAndDispatch(); ++ ++protected: ++ void run() override ++ { ++ // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets ++ // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore. ++ struct Pipe ++ { ++ Pipe(int *fds) ++ : fds(fds) ++ { ++ if (qt_safe_pipe(fds) != 0) ++ qWarning("Pipe creation failed. Quitting may hang."); ++ } ++ ~Pipe() ++ { ++ if (fds[0] != -1) { ++ close(fds[0]); ++ close(fds[1]); ++ } ++ } ++ ++ int *fds; ++ } pipe(m_pipefd); ++ ++ // Make the main thread call wl_prepare_read(), dispatch the pending messages and flush the ++ // outbound ones. Wait until it's done before proceeding, unless we're told to quit. ++ while (waitForReading()) { ++ pollfd fds[2] = { { m_fd, POLLIN, 0 }, { m_pipefd[0], POLLIN, 0 } }; ++ poll(fds, 2, -1); ++ ++ if (fds[1].revents & POLLIN) { ++ // we don't really care to read the byte that was written here since we're closing down ++ wl_display_cancel_read(m_wldisplay); ++ break; ++ } ++ ++ if (fds[0].revents & POLLIN) ++ wl_display_read_events(m_wldisplay); ++ // The polll was succesfull and the event thread did the wl_display_read_events(). On the next iteration of the loop ++ // the event sent to the main thread will cause it to dispatch the messages just read, unless the loop exits in which ++ // case we don't care anymore about them. ++ else ++ wl_display_cancel_read(m_wldisplay); ++ } ++ } ++ ++private: ++ bool waitForReading() ++ { ++ Q_ASSERT(QThread::currentThread() == this); ++ ++ m_reading.storeRelease(false); ++ ++ if (m_mode == SelfDispatch) { ++ readAndDispatchEvents(); ++ } else { ++ Q_EMIT needReadAndDispatch(); ++ ++ QMutexLocker lock(&m_mutex); ++ // m_reading might be set from our emit or some other invocation of ++ // readAndDispatchEvents(). ++ while (!m_reading.loadRelaxed() && !m_quitting) ++ m_cond.wait(&m_mutex); ++ } ++ ++ return !m_quitting; ++ } ++ ++ int dispatchQueuePending() ++ { ++ if (m_wlevqueue) ++ return wl_display_dispatch_queue_pending(m_wldisplay, m_wlevqueue); ++ else ++ return wl_display_dispatch_pending(m_wldisplay); ++ } ++ ++ int prepareReadQueue() ++ { ++ if (m_wlevqueue) ++ return wl_display_prepare_read_queue(m_wldisplay, m_wlevqueue); ++ else ++ return wl_display_prepare_read(m_wldisplay); ++ } ++ ++ int m_fd; ++ int m_pipefd[2]; ++ wl_display *m_wldisplay; ++ wl_event_queue *m_wlevqueue; ++ OperatingMode m_mode; ++ ++ /* Concurrency note when operating in EmitToDispatch mode: ++ * m_reading is set to false inside event thread's waitForReading(), and is ++ * set to true inside main thread's readAndDispatchEvents(). ++ * The lock is not taken when setting m_reading to false, as the main thread ++ * is not actively waiting for it to turn false. However, the lock is taken ++ * inside readAndDispatchEvents() before setting m_reading to true, ++ * as the event thread is actively waiting for it under the wait condition. ++ */ ++ ++ QAtomicInteger m_reading; ++ bool m_quitting; ++ QMutex m_mutex; ++ QWaitCondition m_cond; ++}; ++ + Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging + + struct wl_surface *QWaylandDisplay::createSurface(void *handle) +@@ -162,6 +355,12 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) + + QWaylandDisplay::~QWaylandDisplay(void) + { ++ if (m_eventThread) ++ m_eventThread->stop(); ++ ++ if (m_frameEventQueueThread) ++ m_frameEventQueueThread->stop(); ++ + if (mSyncCallback) + wl_callback_destroy(mSyncCallback); + +@@ -208,98 +407,37 @@ void QWaylandDisplay::ensureScreen() + + void QWaylandDisplay::checkError() const + { +- int ecode = wl_display_get_error(mDisplay); +- if ((ecode == EPIPE || ecode == ECONNRESET)) { +- // special case this to provide a nicer error +- qWarning("The Wayland connection broke. Did the Wayland compositor die?"); +- } else { +- qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode)); +- } +- _exit(1); ++ checkWaylandError(mDisplay); + } + ++// Called in main thread, either from queued signal or directly. + void QWaylandDisplay::flushRequests() + { +- if (wl_display_prepare_read(mDisplay) == 0) { +- wl_display_read_events(mDisplay); +- } +- +- if (wl_display_dispatch_pending(mDisplay) < 0) +- checkError(); +- +- { +- QReadLocker locker(&m_frameQueueLock); +- for (const FrameQueue &q : mExternalQueues) { +- QMutexLocker locker(q.mutex); +- while (wl_display_prepare_read_queue(mDisplay, q.queue) != 0) +- wl_display_dispatch_queue_pending(mDisplay, q.queue); +- wl_display_read_events(mDisplay); +- wl_display_dispatch_queue_pending(mDisplay, q.queue); +- } +- } +- +- wl_display_flush(mDisplay); +-} +- +-void QWaylandDisplay::blockingReadEvents() +-{ +- if (wl_display_dispatch(mDisplay) < 0) +- checkError(); +-} +- +-void QWaylandDisplay::destroyFrameQueue(const QWaylandDisplay::FrameQueue &q) +-{ +- QWriteLocker locker(&m_frameQueueLock); +- auto it = std::find_if(mExternalQueues.begin(), +- mExternalQueues.end(), +- [&q] (const QWaylandDisplay::FrameQueue &other){ return other.queue == q.queue; }); +- Q_ASSERT(it != mExternalQueues.end()); +- mExternalQueues.erase(it); +- if (q.queue != nullptr) +- wl_event_queue_destroy(q.queue); +- delete q.mutex; ++ m_eventThread->readAndDispatchEvents(); + } + +-QWaylandDisplay::FrameQueue QWaylandDisplay::createFrameQueue() ++// We have to wait until we have an eventDispatcher before creating the eventThread, ++// otherwise forceRoundTrip() may block inside _events_read() because eventThread is ++// polling. ++void QWaylandDisplay::initEventThread() + { +- QWriteLocker locker(&m_frameQueueLock); +- FrameQueue q{createEventQueue()}; +- mExternalQueues.append(q); +- return q; +-} ++ m_eventThread.reset( ++ new EventThread(mDisplay, /* default queue */ nullptr, EventThread::EmitToDispatch)); ++ connect(m_eventThread.get(), &EventThread::needReadAndDispatch, this, ++ &QWaylandDisplay::flushRequests, Qt::QueuedConnection); ++ m_eventThread->start(); + +-wl_event_queue *QWaylandDisplay::createEventQueue() +-{ +- return wl_display_create_queue(mDisplay); ++ // wl_display_disconnect() free this. ++ m_frameEventQueue = wl_display_create_queue(mDisplay); ++ m_frameEventQueueThread.reset( ++ new EventThread(mDisplay, m_frameEventQueue, EventThread::SelfDispatch)); ++ m_frameEventQueueThread->start(); + } + +-void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function condition, int timeout) ++void QWaylandDisplay::blockingReadEvents() + { +- if (!condition()) +- return; +- +- QElapsedTimer timer; +- timer.start(); +- struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN); +- while (timeout == -1 || timer.elapsed() < timeout) { +- while (wl_display_prepare_read_queue(mDisplay, queue) != 0) +- wl_display_dispatch_queue_pending(mDisplay, queue); +- +- wl_display_flush(mDisplay); +- +- const int remaining = qMax(timeout - timer.elapsed(), 0ll); +- const int pollTimeout = timeout == -1 ? -1 : remaining; +- if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0) +- wl_display_read_events(mDisplay); +- else +- wl_display_cancel_read(mDisplay); +- +- if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) +- checkError(); +- +- if (!condition()) +- break; +- } ++ if (wl_display_dispatch(mDisplay) < 0) ++ checkWaylandError(mDisplay); + } + + QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const +@@ -674,4 +812,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p + + } // namespace QtWaylandClient + ++#include "qwaylanddisplay.moc" ++ + QT_END_NAMESPACE +diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h +index d9c8849f..42bc661d 100644 +--- a/src/client/qwaylanddisplay_p.h ++++ b/src/client/qwaylanddisplay_p.h +@@ -109,6 +109,7 @@ class QWaylandSurface; + class QWaylandShellIntegration; + class QWaylandCursor; + class QWaylandCursorTheme; ++class EventThread; + + typedef void (*RegistryListener)(void *data, + struct wl_registry *registry, +@@ -120,12 +121,6 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland + Q_OBJECT + + public: +- struct FrameQueue { +- FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {} +- wl_event_queue *queue; +- QMutex *mutex; +- }; +- + QWaylandDisplay(QWaylandIntegration *waylandIntegration); + ~QWaylandDisplay(void) override; + +@@ -212,12 +207,11 @@ public: + void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice); + void handleWindowDestroyed(QWaylandWindow *window); + +- wl_event_queue *createEventQueue(); +- FrameQueue createFrameQueue(); +- void destroyFrameQueue(const FrameQueue &q); +- void dispatchQueueWhile(wl_event_queue *queue, std::function condition, int timeout = -1); ++ wl_event_queue *frameEventQueue() { return m_frameEventQueue; }; + + bool isKeyboardAvailable() const; ++ ++ void initEventThread(); + public slots: + void blockingReadEvents(); + void flushRequests(); +@@ -240,6 +234,9 @@ private: + }; + + struct wl_display *mDisplay = nullptr; ++ QScopedPointer m_eventThread; ++ wl_event_queue *m_frameEventQueue = nullptr; ++ QScopedPointer m_frameEventQueueThread; + QtWayland::wl_compositor mCompositor; + QScopedPointer mShm; + QList mWaitingScreens; +@@ -276,11 +273,9 @@ private: + QWaylandInputDevice *mLastInputDevice = nullptr; + QPointer mLastInputWindow; + QPointer mLastKeyboardFocus; +- QVector mActiveWindows; +- QVector mExternalQueues; ++ QList mActiveWindows; + struct wl_callback *mSyncCallback = nullptr; + static const wl_callback_listener syncCallbackListener; +- QReadWriteLock m_frameQueueLock; + + bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull(); + +diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp +index 3a6fa651..3b876047 100644 +--- a/src/client/qwaylandintegration.cpp ++++ b/src/client/qwaylandintegration.cpp +@@ -192,9 +192,7 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const + + void QWaylandIntegration::initialize() + { +- int fd = wl_display_get_fd(mDisplay->wl_display()); +- QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); +- QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests())); ++ mDisplay->initEventThread(); + + // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip() + mDisplay->initialize(); +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index 1597f67e..7de19a74 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr; + QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display) + : QPlatformWindow(window) + , mDisplay(display) +- , mFrameQueue(mDisplay->createFrameQueue()) + , mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP")) + { + { +@@ -95,8 +94,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display) + + QWaylandWindow::~QWaylandWindow() + { +- mDisplay->destroyFrameQueue(mFrameQueue); +- + delete mWindowDecoration; + + if (mSurface) +@@ -635,6 +632,8 @@ const wl_callback_listener QWaylandWindow::callbackListener = { + + void QWaylandWindow::handleFrameCallback() + { ++ QMutexLocker locker(&mFrameSyncMutex); ++ + mWaitingForFrameCallback = false; + mFrameCallbackElapsedTimer.invalidate(); + +@@ -656,12 +655,16 @@ void QWaylandWindow::handleFrameCallback() + mWaitingForUpdateDelivery = true; + QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); + } ++ ++ mFrameSyncWait.notify_all(); + } + + bool QWaylandWindow::waitForFrameSync(int timeout) + { +- QMutexLocker locker(mFrameQueue.mutex); +- mDisplay->dispatchQueueWhile(mFrameQueue.queue, [&]() { return mWaitingForFrameCallback; }, timeout); ++ QMutexLocker locker(&mFrameSyncMutex); ++ ++ QDeadlineTimer deadline(timeout); ++ while (mWaitingForFrameCallback && mFrameSyncWait.wait(&mFrameSyncMutex, deadline)) { } + + if (mWaitingForFrameCallback) { + qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed"; +@@ -1157,8 +1160,11 @@ void QWaylandWindow::requestUpdate() + Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA + + // If we have a frame callback all is good and will be taken care of there +- if (mWaitingForFrameCallback) +- return; ++ { ++ QMutexLocker locker(&mFrameSyncMutex); ++ if (mWaitingForFrameCallback) ++ return; ++ } + + // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet + // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log +@@ -1171,7 +1177,12 @@ void QWaylandWindow::requestUpdate() + // so use invokeMethod to delay the delivery a bit. + QMetaObject::invokeMethod(this, [this] { + // Things might have changed in the meantime +- if (hasPendingUpdateRequest() && !mWaitingForFrameCallback) ++ { ++ QMutexLocker locker(&mFrameSyncMutex); ++ if (mWaitingForFrameCallback) ++ return; ++ } ++ if (hasPendingUpdateRequest()) + deliverUpdateRequest(); + }, Qt::QueuedConnection); + } +@@ -1191,9 +1202,10 @@ void QWaylandWindow::handleUpdate() + if (!mSurface) + return; + +- QMutexLocker locker(mFrameQueue.mutex); ++ QMutexLocker locker(&mFrameSyncMutex); ++ + struct ::wl_surface *wrappedSurface = reinterpret_cast(wl_proxy_create_wrapper(mSurface->object())); +- wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mFrameQueue.queue); ++ wl_proxy_set_queue(reinterpret_cast(wrappedSurface), mDisplay->frameEventQueue()); + mFrameCallback = wl_surface_frame(wrappedSurface); + wl_proxy_wrapper_destroy(wrappedSurface); + wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); +@@ -1203,6 +1215,8 @@ void QWaylandWindow::handleUpdate() + // Start a timer for handling the case when the compositor stops sending frame callbacks. + if (mFrameCallbackTimeout > 0) { + QMetaObject::invokeMethod(this, [this] { ++ QMutexLocker locker(&mFrameSyncMutex); ++ + if (mWaitingForFrameCallback) { + if (mFrameCallbackCheckIntervalTimerId < 0) + mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout); +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h +index e0687962..d45980a8 100644 +--- a/src/client/qwaylandwindow_p.h ++++ b/src/client/qwaylandwindow_p.h +@@ -232,7 +232,7 @@ protected: + int mFrameCallbackCheckIntervalTimerId = -1; + QElapsedTimer mFrameCallbackElapsedTimer; + struct ::wl_callback *mFrameCallback = nullptr; +- QWaylandDisplay::FrameQueue mFrameQueue; ++ QMutex mFrameSyncMutex; + QWaitCondition mFrameSyncWait; + + // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer +-- +2.35.1 + diff --git a/SOURCES/0045-Check-pointer-for-null-before-use-in-ASSERT.patch b/SOURCES/0045-Check-pointer-for-null-before-use-in-ASSERT.patch new file mode 100644 index 0000000..654b43c --- /dev/null +++ b/SOURCES/0045-Check-pointer-for-null-before-use-in-ASSERT.patch @@ -0,0 +1,30 @@ +From 460a2bb54d8377586dff6d561646f3929c71370d Mon Sep 17 00:00:00 2001 +From: Roman Genkhel +Date: Thu, 12 Nov 2020 12:21:51 +0300 +Subject: [PATCH 45/52] Check pointer for null before use in ASSERT + +Task-number: QTBUG-85195 +Change-Id: I331e54f6e58aa9d536351a55223610c60b3cb414 +Reviewed-by: David Edmundson +(cherry picked from commit e235e8ddb1fc3cc5ab3b70b1fb285770b2c8c9ca) +--- + src/client/qwaylandwindow.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index 7de19a74..ac01dc05 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -552,8 +552,8 @@ void QWaylandWindow::sendRecursiveExposeEvent() + + void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) + { +- Q_ASSERT(!buffer->committed()); + if (buffer) { ++ Q_ASSERT(!buffer->committed()); + handleUpdate(); + buffer->setBusy(); + +-- +2.35.1 + diff --git a/SOURCES/0046-Do-not-create-decorations-when-the-shellSurface-is-n.patch b/SOURCES/0046-Do-not-create-decorations-when-the-shellSurface-is-n.patch new file mode 100644 index 0000000..0d2977b --- /dev/null +++ b/SOURCES/0046-Do-not-create-decorations-when-the-shellSurface-is-n.patch @@ -0,0 +1,39 @@ +From b6d85c2a75f5618e87267f5b5c361455be257a17 Mon Sep 17 00:00:00 2001 +From: Inho Lee +Date: Mon, 1 Nov 2021 14:23:58 +0100 +Subject: [PATCH 46/52] Do not create decorations when the shellSurface is not + ready + +A cases reported that client windows try to make decorations +when their shell surfaces are null. +Since the surfaces' requests for decorations should be applied, +those case will be failed to create decorations. + +This patch was modified by Paul Tvete's advice. +(paul.tvete@qt.io) + +Pick-to: 6.2 5.15 +Task-number: QTBUG-97608 +Change-Id: I2563dbd73b730f81cc411857af07da99ceb2d063 +Reviewed-by: Paul Olav Tvete +(cherry picked from commit 246f0c0bc01dd059bf8165e81f7b49efa36e4d95) +--- + src/client/qwaylandwindow.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index ac01dc05..acfe390e 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -813,7 +813,7 @@ bool QWaylandWindow::createDecoration() + decoration = false; + if (mSubSurfaceWindow) + decoration = false; +- if (mShellSurface && !mShellSurface->wantsDecorations()) ++ if (!mShellSurface || !mShellSurface->wantsDecorations()) + decoration = false; + + bool hadDecoration = mWindowDecoration; +-- +2.35.1 + diff --git a/SOURCES/0047-Use-wl_surface.damage_buffer-on-the-client-side.patch b/SOURCES/0047-Use-wl_surface.damage_buffer-on-the-client-side.patch new file mode 100644 index 0000000..0b4c8fc --- /dev/null +++ b/SOURCES/0047-Use-wl_surface.damage_buffer-on-the-client-side.patch @@ -0,0 +1,131 @@ +From 7200a1ad8488f157ef8ce9d5ed81a0a1c1cd1eda Mon Sep 17 00:00:00 2001 +From: Paul Olav Tvete +Date: Mon, 6 Jul 2020 14:37:35 +0200 +Subject: [PATCH 47/52] Use wl_surface.damage_buffer on the client side + +Prefer the newer, recommended damage_buffer when the compositor +supports it. + +Fixes: QTBUG-74929 +Change-Id: I9107966910b616a666931404a7b41bfac14c22c0 +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 314fd6db51277224cdc799b039ef79db1101f5cd) +--- + src/client/qwaylanddisplay.cpp | 2 +- + src/client/qwaylandwindow.cpp | 16 +++++++++++++--- + tests/auto/client/shared/coreprotocol.h | 2 +- + tests/auto/client/shared_old/mockcompositor.cpp | 2 +- + tests/auto/client/shared_old/mocksurface.cpp | 10 ++++++++++ + tests/auto/client/shared_old/mocksurface.h | 2 ++ + 6 files changed, 28 insertions(+), 6 deletions(-) + +diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp +index a7ce280a..6f1bada5 100644 +--- a/src/client/qwaylanddisplay.cpp ++++ b/src/client/qwaylanddisplay.cpp +@@ -488,7 +488,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin + if (interface == QStringLiteral("wl_output")) { + mWaitingScreens << new QWaylandScreen(this, version, id); + } else if (interface == QStringLiteral("wl_compositor")) { +- mCompositorVersion = qMin((int)version, 3); ++ mCompositorVersion = qMin((int)version, 4); + mCompositor.init(registry, id, mCompositorVersion); + } else if (interface == QStringLiteral("wl_shm")) { + mShm.reset(new QWaylandShm(this, version, id)); +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index acfe390e..4c5711a0 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -571,7 +571,11 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer) + + void QWaylandWindow::damage(const QRect &rect) + { +- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height()); ++ const int s = scale(); ++ if (mDisplay->compositorVersion() >= 4) ++ mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height()); ++ else ++ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height()); + } + + void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage) +@@ -605,8 +609,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) + return; + + attachOffset(buffer); +- for (const QRect &rect: damage) +- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height()); ++ if (mDisplay->compositorVersion() >= 4) { ++ const int s = scale(); ++ for (const QRect &rect: damage) ++ mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height()); ++ } else { ++ for (const QRect &rect: damage) ++ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height()); ++ } + Q_ASSERT(!buffer->committed()); + buffer->setCommitted(); + mSurface->commit(); +diff --git a/tests/auto/client/shared/coreprotocol.h b/tests/auto/client/shared/coreprotocol.h +index a1af137a..296dbf47 100644 +--- a/tests/auto/client/shared/coreprotocol.h ++++ b/tests/auto/client/shared/coreprotocol.h +@@ -158,7 +158,7 @@ class WlCompositor : public Global, public QtWaylandServer::wl_compositor + { + Q_OBJECT + public: +- explicit WlCompositor(CoreCompositor *compositor, int version = 3) ++ explicit WlCompositor(CoreCompositor *compositor, int version = 4) + : QtWaylandServer::wl_compositor(compositor->m_display, version) + , m_compositor(compositor) + {} +diff --git a/tests/auto/client/shared_old/mockcompositor.cpp b/tests/auto/client/shared_old/mockcompositor.cpp +index a415cbf5..b1d3d07d 100644 +--- a/tests/auto/client/shared_old/mockcompositor.cpp ++++ b/tests/auto/client/shared_old/mockcompositor.cpp +@@ -342,7 +342,7 @@ Compositor::Compositor(MockCompositor *mockCompositor) + exit(EXIT_FAILURE); + } + +- wl_global_create(m_display, &wl_compositor_interface, 1, this, bindCompositor); ++ wl_global_create(m_display, &wl_compositor_interface, 4, this, bindCompositor); + + m_data_device_manager.reset(new DataDeviceManager(this, m_display)); + +diff --git a/tests/auto/client/shared_old/mocksurface.cpp b/tests/auto/client/shared_old/mocksurface.cpp +index e9df5f90..c3246e4a 100644 +--- a/tests/auto/client/shared_old/mocksurface.cpp ++++ b/tests/auto/client/shared_old/mocksurface.cpp +@@ -125,6 +125,16 @@ void Surface::surface_damage(Resource *resource, + Q_UNUSED(height); + } + ++void Surface::surface_damage_buffer(Resource *resource, ++ int32_t x, int32_t y, int32_t width, int32_t height) ++{ ++ Q_UNUSED(resource); ++ Q_UNUSED(x); ++ Q_UNUSED(y); ++ Q_UNUSED(width); ++ Q_UNUSED(height); ++} ++ + void Surface::surface_frame(Resource *resource, + uint32_t callback) + { +diff --git a/tests/auto/client/shared_old/mocksurface.h b/tests/auto/client/shared_old/mocksurface.h +index 949dc23d..d176837e 100644 +--- a/tests/auto/client/shared_old/mocksurface.h ++++ b/tests/auto/client/shared_old/mocksurface.h +@@ -65,6 +65,8 @@ protected: + struct wl_resource *buffer, int x, int y) override; + void surface_damage(Resource *resource, + int32_t x, int32_t y, int32_t width, int32_t height) override; ++ void surface_damage_buffer(Resource *resource, ++ int32_t x, int32_t y, int32_t width, int32_t height) override; + void surface_frame(Resource *resource, + uint32_t callback) override; + void surface_commit(Resource *resource) override; +-- +2.35.1 + diff --git a/SOURCES/0048-Fix-crash-if-no-input-method-module-could-be-loaded.patch b/SOURCES/0048-Fix-crash-if-no-input-method-module-could-be-loaded.patch new file mode 100644 index 0000000..b61e664 --- /dev/null +++ b/SOURCES/0048-Fix-crash-if-no-input-method-module-could-be-loaded.patch @@ -0,0 +1,29 @@ +From ce2caf493a1343fbd9f8e4c85baf6a61c057f242 Mon Sep 17 00:00:00 2001 +From: Joni Poikelin +Date: Thu, 3 Feb 2022 14:01:50 +0200 +Subject: [PATCH 48/52] Fix crash if no input method module could be loaded + +Pick-to: 6.2 6.3 5.15 +Change-Id: I8f346def616606a6c5540856bd08a84ee7ed5ca2 +Reviewed-by: David Edmundson +(cherry picked from commit 49fb7248f6ab7de046e2179c7861951ea1169e9b) +--- + src/client/qwaylandintegration.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp +index 3b876047..fbf00c6b 100644 +--- a/src/client/qwaylandintegration.cpp ++++ b/src/client/qwaylandintegration.cpp +@@ -491,7 +491,7 @@ void QWaylandIntegration::reconfigureInputContext() + } + #endif + +- qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className(); ++ qCDebug(lcQpaWayland) << "using input method:" << (inputContext() ? inputContext()->metaObject()->className() : ""); + } + + QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName) +-- +2.35.1 + diff --git a/SOURCES/0049-Client-Remove-mWaitingForUpdateDelivery.patch b/SOURCES/0049-Client-Remove-mWaitingForUpdateDelivery.patch new file mode 100644 index 0000000..abec7f5 --- /dev/null +++ b/SOURCES/0049-Client-Remove-mWaitingForUpdateDelivery.patch @@ -0,0 +1,79 @@ +From 214f7ab9d3384a4123f14d9f6cd0205cf0aaa794 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Tue, 1 Feb 2022 13:05:36 +0200 +Subject: [PATCH 49/52] Client: Remove mWaitingForUpdateDelivery + +Currently, mWaitingForUpdateDelivery is shared between the main thread +(doHandleFrameCallback()) and the frame callback event thread +(handleFrameCallback()), however the access to it is not synchronized +between both threads. On the other hand, QWaylandWindow +already ensures not to create a frame callback if there's already one +pending. + +This change removes mWaitingForUpdateDelivery flag because it should be +already covered by mWaitingForFrameCallback and to remove unsynchronized +shared state between threads. + +Change-Id: I0e5a25d18d1e66c4d7683e7e972330c4d7cbbf38 +Reviewed-by: David Edmundson +(cherry picked from commit feb1a5c207c13d0bf87c0d8ad039279dbf8cee9e) +--- + src/client/qwaylandwindow.cpp | 29 ++++++++++++----------------- + src/client/qwaylandwindow_p.h | 1 - + 2 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp +index 4c5711a0..949374b1 100644 +--- a/src/client/qwaylandwindow.cpp ++++ b/src/client/qwaylandwindow.cpp +@@ -648,23 +648,18 @@ void QWaylandWindow::handleFrameCallback() + mFrameCallbackElapsedTimer.invalidate(); + + // The rest can wait until we can run it on the correct thread +- if (!mWaitingForUpdateDelivery) { +- auto doHandleExpose = [this]() { +- bool wasExposed = isExposed(); +- mFrameCallbackTimedOut = false; +- if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed? +- sendExposeEvent(QRect(QPoint(), geometry().size())); +- if (wasExposed && hasPendingUpdateRequest()) +- deliverUpdateRequest(); +- +- mWaitingForUpdateDelivery = false; +- }; +- +- // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync() +- // in the single-threaded case. +- mWaitingForUpdateDelivery = true; +- QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); +- } ++ auto doHandleExpose = [this]() { ++ bool wasExposed = isExposed(); ++ mFrameCallbackTimedOut = false; ++ if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed? ++ sendExposeEvent(QRect(QPoint(), geometry().size())); ++ if (wasExposed && hasPendingUpdateRequest()) ++ deliverUpdateRequest(); ++ }; ++ ++ // Queued connection, to make sure we don't call handleUpdate() from inside waitForFrameSync() ++ // in the single-threaded case. ++ QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); + + mFrameSyncWait.notify_all(); + } +diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h +index d45980a8..3ff68ccb 100644 +--- a/src/client/qwaylandwindow_p.h ++++ b/src/client/qwaylandwindow_p.h +@@ -228,7 +228,6 @@ protected: + WId mWindowId; + bool mWaitingForFrameCallback = false; + bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out +- bool mWaitingForUpdateDelivery = false; + int mFrameCallbackCheckIntervalTimerId = -1; + QElapsedTimer mFrameCallbackElapsedTimer; + struct ::wl_callback *mFrameCallback = nullptr; +-- +2.35.1 + diff --git a/SOURCES/0050-Cursor-position-0-should-still-show-the-cursor.patch b/SOURCES/0050-Cursor-position-0-should-still-show-the-cursor.patch new file mode 100644 index 0000000..245a0f5 --- /dev/null +++ b/SOURCES/0050-Cursor-position-0-should-still-show-the-cursor.patch @@ -0,0 +1,35 @@ +From 157c7f55005a6ef0e65ebb02f9b5f344848670b2 Mon Sep 17 00:00:00 2001 +From: Weng Xuetian +Date: Tue, 8 Feb 2022 07:11:25 -0800 +Subject: [PATCH 50/52] Cursor position == 0 should still show the cursor + +Otherwise the cursor would be hidden even if preedit is empty. +Amends 719a55be13bdadfa659a732755f280e276a894bd + +Pick-to: 5.15 6.2 6.3 +Change-Id: I320733b917779b7b51aa4a28eaea411fdb10a318 +Reviewed-by: Liang Qi +(cherry picked from commit 31ae194e295651d9ece03408630d2358acd4f7b4) +--- + src/shared/qwaylandinputmethodeventbuilder.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp +index 25be2509..458d818e 100644 +--- a/src/shared/qwaylandinputmethodeventbuilder.cpp ++++ b/src/shared/qwaylandinputmethodeventbuilder.cpp +@@ -151,9 +151,9 @@ QInputMethodEvent QWaylandInputMethodEventBuilder::buildPreedit(const QString &t + { + QList attributes; + +- if (m_preeditCursor <= 0) { ++ if (m_preeditCursor < 0) { + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant())); +- } else if (m_preeditCursor > 0) { ++ } else { + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant())); + } + +-- +2.35.1 + diff --git a/SOURCES/0051-Update-the-preedit-styling-mapping.patch b/SOURCES/0051-Update-the-preedit-styling-mapping.patch new file mode 100644 index 0000000..beb6038 --- /dev/null +++ b/SOURCES/0051-Update-the-preedit-styling-mapping.patch @@ -0,0 +1,88 @@ +From 9f66cd3784421ee5dc6538630ade0cf215f656aa Mon Sep 17 00:00:00 2001 +From: Weng Xuetian +Date: Wed, 22 Dec 2021 10:42:38 -0800 +Subject: [PATCH 51/52] Update the preedit styling mapping + +- None mapping to no style. +- Default/Underline mapping to underline. +- Highlight/Selection mapping to background color/text color with highlight/highlight +text with underline. +- Active/Inactive mapping to bold text with underline. +- Incorrect mapping to red wave underline. + +Pick-to: 5.15 6.2 6.3 +Change-Id: Iab51d671b8f83aece8596f7f7610de19343fcceb +Reviewed-by: Aleix Pol Gonzalez +(cherry picked from commit f1fb5d9e568a24e213ee41e82a1142cef56f1098) +--- + .../qwaylandinputmethodeventbuilder.cpp | 31 ++++++++++++------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp +index 458d818e..f50ccf30 100644 +--- a/src/shared/qwaylandinputmethodeventbuilder.cpp ++++ b/src/shared/qwaylandinputmethodeventbuilder.cpp +@@ -39,7 +39,10 @@ + + #include "qwaylandinputmethodeventbuilder_p.h" + ++#include ++#include + #include ++#include + #include + + #ifdef QT_BUILD_WAYLANDCOMPOSITOR_LIB +@@ -81,32 +84,38 @@ void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t + QTextCharFormat format; + + switch (style) { +- case 0: +- case 1: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_NONE: ++ break; ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_DEFAULT: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_UNDERLINE: + format.setFontUnderline(true); + format.setUnderlineStyle(QTextCharFormat::SingleUnderline); + m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format)); + break; +- case 2: +- case 3: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_ACTIVE: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INACTIVE: + format.setFontWeight(QFont::Bold); + format.setFontUnderline(true); + format.setUnderlineStyle(QTextCharFormat::SingleUnderline); + m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format)); + break; +- case 4: +- format.setFontUnderline(true); +- format.setUnderlineStyle(QTextCharFormat::SingleUnderline); +- m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format)); ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_HIGHLIGHT: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_SELECTION: ++ { ++ format.setFontUnderline(true); ++ format.setUnderlineStyle(QTextCharFormat::SingleUnderline); ++ QPalette palette = qApp->palette(); ++ format.setBackground(QBrush(palette.color(QPalette::Active, QPalette::Highlight))); ++ format.setForeground(QBrush(palette.color(QPalette::Active, QPalette::HighlightedText))); ++ m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format)); ++ } + break; +- case 5: ++ case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INCORRECT: + format.setFontUnderline(true); + format.setUnderlineStyle(QTextCharFormat::WaveUnderline); + format.setUnderlineColor(QColor(Qt::red)); + m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format)); + break; +-// case QtWayland::wl_text_input::preedit_style_selection: +-// case QtWayland::wl_text_input::preedit_style_none: + default: + break; + } +-- +2.35.1 + diff --git a/SOURCES/0052-client-Simplify-round-trip-behavior.patch b/SOURCES/0052-client-Simplify-round-trip-behavior.patch new file mode 100644 index 0000000..4d8732a --- /dev/null +++ b/SOURCES/0052-client-Simplify-round-trip-behavior.patch @@ -0,0 +1,82 @@ +From d6a6b727832819d118199f7016c2c401663ee370 Mon Sep 17 00:00:00 2001 +From: David Edmundson +Date: Wed, 9 Feb 2022 17:20:48 +0000 +Subject: [PATCH 52/52] client: Simplify round trip behavior + +The custom event queue was removed in +302d4ffb8549214eb4028dc3e47ec4ee4e12ffbd (2015) so the comment about not +being able to use the inbuilt round trip method no longer applies. + +This fixes a real world problem. Use of a blocking round trip should not +process non wayland events. Doing so can lead to misbehaviour client +side as things happen out of order. The move to the event thread created +several regressions as we now get events before the QGuiApplication is +fully constructed. + +Change-Id: I650481f49a47ed1a9778c7e1bc3c48db6e8f0031 +Reviewed-by: Vlad Zahorodnii +Reviewed-by: Eskil Abrahamsen Blomfeldt +(cherry picked from commit 62646d9122845d7bd9104b610478cebde3e769c7) +--- + src/client/qwaylanddisplay.cpp | 43 +--------------------------------- + 1 file changed, 1 insertion(+), 42 deletions(-) + +diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp +index 6f1bada5..86045a35 100644 +--- a/src/client/qwaylanddisplay.cpp ++++ b/src/client/qwaylanddisplay.cpp +@@ -611,50 +611,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec() + return 0; + } + +-static void +-sync_callback(void *data, struct wl_callback *callback, uint32_t serial) +-{ +- Q_UNUSED(serial) +- bool *done = static_cast(data); +- +- *done = true; +- +- // If the wl_callback done event is received after the condition check in the while loop in +- // forceRoundTrip(), but before the call to processEvents, the call to processEvents may block +- // forever if no more events are posted (eventhough the callback is handled in response to the +- // aboutToBlock signal). Hence, we wake up the event dispatcher so forceRoundTrip may return. +- // (QTBUG-64696) +- if (auto *dispatcher = QThread::currentThread()->eventDispatcher()) +- dispatcher->wakeUp(); +- +- wl_callback_destroy(callback); +-} +- +-static const struct wl_callback_listener sync_listener = { +- sync_callback +-}; +- + void QWaylandDisplay::forceRoundTrip() + { +- // wl_display_roundtrip() works on the main queue only, +- // but we use a separate one, so basically reimplement it here +- int ret = 0; +- bool done = false; +- wl_callback *callback = wl_display_sync(mDisplay); +- wl_callback_add_listener(callback, &sync_listener, &done); +- flushRequests(); +- if (QThread::currentThread()->eventDispatcher()) { +- while (!done && ret >= 0) { +- QThread::currentThread()->eventDispatcher()->processEvents(QEventLoop::WaitForMoreEvents); +- ret = wl_display_dispatch_pending(mDisplay); +- } +- } else { +- while (!done && ret >= 0) +- ret = wl_display_dispatch(mDisplay); +- } +- +- if (ret == -1 && !done) +- wl_callback_destroy(callback); ++ wl_display_roundtrip(mDisplay); + } + + bool QWaylandDisplay::supportsWindowDecoration() const +-- +2.35.1 + diff --git a/SPECS/qt5-qtwayland.spec b/SPECS/qt5-qtwayland.spec index 81e818e..4f29dca 100644 --- a/SPECS/qt5-qtwayland.spec +++ b/SPECS/qt5-qtwayland.spec @@ -5,7 +5,7 @@ Summary: Qt5 - Wayland platform support and QtCompositor module Name: qt5-%{qt_module} Version: 5.15.2 -Release: 13%{?dist} +Release: 15%{?dist} License: LGPLv3 Url: http://www.qt.io @@ -53,6 +53,22 @@ Patch33: 0033-Client-Always-destroy-frame-callback-in-the-actual-c.patch Patch34: 0034-Fix-the-logic-for-decoding-modifiers-map-in-Wayland-.patch Patch35: 0035-Wayland-client-use-wl_keyboard-to-determine-active-s.patch Patch36: 0036-Client-do-not-empty-clipboard-when-a-new-popup-windo.patch +Patch37: 0037-Fix-backport-context-destruction-was-omitted.patch +Patch38: 0038-Set-preedit-cursor-when-cursor-equals-to-0.patch +Patch39: 0039-Client-Implement-DataDeviceV3.patch +Patch40: 0040-Client-Delay-deletion-of-QDrag-object-until-after-we.patch +Patch41: 0041-Client-Avoid-processing-of-events-when-showing-windo.patch +Patch42: 0042-Handle-registry_global-out-of-constructor.patch +Patch43: 0043-Connect-flushRequest-after-forceRoundTrip.patch +Patch44: 0044-Move-the-wayland-socket-polling-to-a-separate-event-.patch +Patch45: 0045-Check-pointer-for-null-before-use-in-ASSERT.patch +Patch46: 0046-Do-not-create-decorations-when-the-shellSurface-is-n.patch +Patch47: 0047-Use-wl_surface.damage_buffer-on-the-client-side.patch +Patch48: 0048-Fix-crash-if-no-input-method-module-could-be-loaded.patch +Patch49: 0049-Client-Remove-mWaitingForUpdateDelivery.patch +Patch50: 0050-Cursor-position-0-should-still-show-the-cursor.patch +Patch51: 0051-Update-the-preedit-styling-mapping.patch +Patch52: 0052-client-Simplify-round-trip-behavior.patch # Disable for now, there is a Qt bug making this broken # Patch52: qtwayland-decoration-support-backports-from-qt6.patch @@ -182,6 +198,14 @@ popd %endif %changelog +* Tue Feb 15 2022 Jan Grulich - 5.15.2-15 +- Sync with Fedora + Resolves: bz#2051384 + +* Mon Jan 24 2022 Jan Grulich - 5.15.2-14 +- Sync with Fedora + Resolves: bz#2044169 + * Wed Dec 08 2021 Jan Grulich - 5.15.2-13 - Sync with Fedora Resolves: bz#2028778