import qt5-qtwayland-5.15.2-15.el9

This commit is contained in:
CentOS Sources 2022-03-01 05:06:59 -05:00 committed by Stepan Oksanichenko
parent 754e1a8e9d
commit 5d065615c2
49 changed files with 1984 additions and 65 deletions

View File

@ -1,7 +1,7 @@
From e5c272423d1bba2825086b82fd97499237a6fa4b Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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

View File

@ -1,7 +1,7 @@
From a825fb5f714fd79d16cc3ebbdd327e7961b07d0a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io>
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

View File

@ -1,7 +1,7 @@
From 2c0a03e9aea13831d05ac03996949f888afd5085 Mon Sep 17 00:00:00 2001
From: Jaehak Lee <jaehak.lee@mobis.co.kr>
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

View File

@ -1,7 +1,7 @@
From 10005185e06857ce119c50fe710f9eedde06ec5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io>
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

View File

@ -1,7 +1,7 @@
From dba4bc4f1d6dfee9fe9433c55b15653d703bed4f Mon Sep 17 00:00:00 2001
From: Andreas Cord-Landwehr <cordlandwehr@kde.org>
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

View File

@ -1,7 +1,7 @@
From a8d35b3c18bdb05a0da3ed50a554a7b7bd4ebed3 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
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

View File

@ -1,7 +1,7 @@
From 9ee2ea141adc7765f6c212e63839ef23a4494b30 Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wengxt@gmail.com>
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

View File

@ -1,7 +1,7 @@
From 9df11e79b46c77d8c83f765b2a8e85b639fd55a2 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
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

View File

@ -1,7 +1,7 @@
From 7db4f83c39d2a0c709bc0b9c0de3946d3b4ebfd5 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From a3e3ac1c86a956b25b1dc24f14518b6e6c96bcfc Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
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

View File

@ -1,7 +1,7 @@
From 2073ff99e62d4f99ed3f1f45559c5b68a61c5f66 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From 6810b0f66a34056bfe0da7299d7a768e700e58f5 Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
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

View File

@ -1,7 +1,7 @@
From cea69b8adec1e61adc1fa04cbf46b77c0d72c75e Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
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

View File

@ -1,7 +1,7 @@
From 2f84a874da064069461284db1da36dc818949ec1 Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <aacid@kde.org>
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

View File

@ -1,7 +1,7 @@
From 91c48320633e493b4cd519e5d73b836a878b2b77 Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
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

View File

@ -1,7 +1,7 @@
From d5186701e27ad6f09f3944809cec2a25c5328026 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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

View File

@ -1,7 +1,7 @@
From 62494312db0f58053d1342bfacc7984186fdf3a6 Mon Sep 17 00:00:00 2001
From: Jaeyoon Jung <jaeyoon.jung@lge.com>
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

View File

@ -1,7 +1,7 @@
From 1ccebbab3a42690a0812e2c4c76016799bf6cf1f Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <albert.astals.cid@kdab.com>
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

View File

@ -1,7 +1,7 @@
From fcc2f57cefa66339c8cb6632f45a47fbb99bb60d Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From 1b5e43a593e917610e6245f7a272ac081c508ba4 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From 36a552fa530be57091e986ebd1468d75d3061743 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From a8ddf1a7296e2d28b36231a391807226a7329ae4 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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

View File

@ -1,7 +1,7 @@
From d1c4a459faa1d514026c4834828cb33024ac2ceb Mon Sep 17 00:00:00 2001
From: Zhang Liang <zhanglianga@uniontech.com>
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

View File

@ -1,7 +1,7 @@
From a6476d1a1c78eb7f17408241b268404e27b3e161 Mon Sep 17 00:00:00 2001
From: David Redondo <qt@david-redondo.de>
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

View File

@ -1,7 +1,7 @@
From d4c41797b61a5a8da47c5821711aca72e756dcbf Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
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

View File

@ -1,7 +1,7 @@
From 3c420cd180397e3f42c8a436a7f1b11465925bdd Mon Sep 17 00:00:00 2001
From: Jan Blackquill <uhhadd@gmail.com>
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

View File

@ -1,7 +1,7 @@
From 1c53ba6dfebbf1d6e87c9ad1f2bbda94e3d45bf7 Mon Sep 17 00:00:00 2001
From: Paul Olav Tvete <paul.tvete@qt.io>
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

View File

@ -1,7 +1,7 @@
From 3be586cd8b6c8313cb6b8b7d61be17706f79590e Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <gbsneto@gnome.org>
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

View File

@ -1,7 +1,7 @@
From efe6edcaf8eba601dff99ec6ad4457c8a4442f86 Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <gbsneto@gnome.org>
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<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mFrameQueue.queue);
--
2.33.1
2.35.1

View File

@ -1,7 +1,7 @@
From 02f9585ca19c17ae0978b864195533dc527d825e Mon Sep 17 00:00:00 2001
From: Rodney Dawes <dobey.pwns@gmail.com>
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

View File

@ -1,7 +1,7 @@
From 5c180bdc1042e7cb1555e188051f09e219b00ec9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A9ven=20Car?= <meven.car@enioka.com>
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

View File

@ -1,7 +1,7 @@
From 992833ca741efe8f533c61abfaf129a1d8bfcfee Mon Sep 17 00:00:00 2001
From: Jan Grulich <jgrulich@redhat.com>
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

View File

@ -0,0 +1,29 @@
From eb422ab5e07498a7a8d086f6a942ee35ab3c9776 Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
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

View File

@ -0,0 +1,29 @@
From e0646f531e1e73a90a93faaa45d933ae40769985 Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wengxt@gmail.com>
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 <liang.qi@qt.io>
(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<QInputMethodEvent::Attribute> 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

View File

@ -0,0 +1,513 @@
From 2044603ebb5ae70c785d50968ac620b842c2b14e Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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 <eskil.abrahamsen-blomfeldt@qt.io>
(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<QWaylandDrag *>(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<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response);
+ });
+ connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() {
+ static_cast<QWaylandDrag *>(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<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
+ auto drag = static_cast<QWaylandDrag *>(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<QWaylandDrag *>(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<QWaylandDrag *>(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<QWaylandDrag *>(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<QWaylandMimeData> 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<QWaylandWindow *>(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

View File

@ -0,0 +1,67 @@
From 0b15df7e9e26a4edfc2277eb3ec7b3d5c58a5dcd Mon Sep 17 00:00:00 2001
From: Arjen Hiemstra <ahiemstra@heimr.nl>
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 <davidedmundson@kde.org>
(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

View File

@ -0,0 +1,38 @@
From 867540b9d913760a847ff67c8694d817c821f2c2 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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 <qt_ci_bot@qt-project.org>
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
(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

View File

@ -0,0 +1,85 @@
From bc5a8d24f63181a36759723a4d1b39b59b3b53e6 Mon Sep 17 00:00:00 2001
From: Elvis Lee <kwangwoong.lee@lge.com>
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 <eskil.abrahamsen-blomfeldt@qt.io>
(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

View File

@ -0,0 +1,47 @@
From 98dc33fdc66f15a0e69f3024fcef046f11adc58c Mon Sep 17 00:00:00 2001
From: Elvis Lee <kwangwoong.lee@lge.com>
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 <eskil.abrahamsen-blomfeldt@qt.io>
(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

View File

@ -0,0 +1,574 @@
From 4644d51f4b52e83fc1b4d02b380d80d9d57e76fa Mon Sep 17 00:00:00 2001
From: Adrien Faveraux <af@brain-networks.fr>
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 <ratchanan@ubports.com>
Task-number: QTBUG-66075
Change-Id: Ibb33ad7f4193b866d1b8d7a0405a94d59dcad5eb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(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 <errno.h>
+#include <tuple> // 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<bool> 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<bool ()> 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<bool()> 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<EventThread> m_eventThread;
+ wl_event_queue *m_frameEventQueue = nullptr;
+ QScopedPointer<EventThread> m_frameEventQueueThread;
QtWayland::wl_compositor mCompositor;
QScopedPointer<QWaylandShm> mShm;
QList<QWaylandScreen *> mWaitingScreens;
@@ -276,11 +273,9 @@ private:
QWaylandInputDevice *mLastInputDevice = nullptr;
QPointer<QWaylandWindow> mLastInputWindow;
QPointer<QWaylandWindow> mLastKeyboardFocus;
- QVector<QWaylandWindow *> mActiveWindows;
- QVector<FrameQueue> mExternalQueues;
+ QList<QWaylandWindow *> 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<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object()));
- wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mFrameQueue.queue);
+ wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(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

View File

@ -0,0 +1,30 @@
From 460a2bb54d8377586dff6d561646f3929c71370d Mon Sep 17 00:00:00 2001
From: Roman Genkhel <roman.genhel@lge.com>
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 <davidedmundson@kde.org>
(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

View File

@ -0,0 +1,39 @@
From b6d85c2a75f5618e87267f5b5c361455be257a17 Mon Sep 17 00:00:00 2001
From: Inho Lee <inho.lee@qt.io>
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 <paul.tvete@qt.io>
(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

View File

@ -0,0 +1,131 @@
From 7200a1ad8488f157ef8ce9d5ed81a0a1c1cd1eda Mon Sep 17 00:00:00 2001
From: Paul Olav Tvete <paul.tvete@qt.io>
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 <eskil.abrahamsen-blomfeldt@qt.io>
(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

View File

@ -0,0 +1,29 @@
From ce2caf493a1343fbd9f8e4c85baf6a61c057f242 Mon Sep 17 00:00:00 2001
From: Joni Poikelin <joni.poikelin@qt.io>
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 <davidedmundson@kde.org>
(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() : "<none>");
}
QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &integrationName)
--
2.35.1

View File

@ -0,0 +1,79 @@
From 214f7ab9d3384a4123f14d9f6cd0205cf0aaa794 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
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 <davidedmundson@kde.org>
(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

View File

@ -0,0 +1,35 @@
From 157c7f55005a6ef0e65ebb02f9b5f344848670b2 Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wengxt@gmail.com>
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 <liang.qi@qt.io>
(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<QInputMethodEvent::Attribute> 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

View File

@ -0,0 +1,88 @@
From 9f66cd3784421ee5dc6538630ade0cf215f656aa Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wengxt@gmail.com>
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 <aleixpol@kde.org>
(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 <QBrush>
+#include <QGuiApplication>
#include <QInputMethod>
+#include <QPalette>
#include <QTextCharFormat>
#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

View File

@ -0,0 +1,82 @@
From d6a6b727832819d118199f7016c2c401663ee370 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
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 <vlad.zahorodnii@kde.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(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<bool *>(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

View File

@ -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 <jgrulich@redhat.com> - 5.15.2-15
- Sync with Fedora
Resolves: bz#2051384
* Mon Jan 24 2022 Jan Grulich <jgrulich@redhat.com> - 5.15.2-14
- Sync with Fedora
Resolves: bz#2044169
* Wed Dec 08 2021 Jan Grulich <jgrulich@redhat.com> - 5.15.2-13
- Sync with Fedora
Resolves: bz#2028778