Include patches
This commit is contained in:
parent
243f1d5b6b
commit
d8d5f4827b
@ -0,0 +1,38 @@
|
||||
From 610af8f0ba9de42cb22228e4e4b3fd77275e3e17 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Xuetian <wengxt@gmail.com>
|
||||
Date: Tue, 9 Mar 2021 10:43:59 -0800
|
||||
Subject: [PATCH 01/40] Use qWarning and _exit() instead of qFatal for wayland
|
||||
error
|
||||
|
||||
This type of error is likely to happen upon system logout. qFatal would
|
||||
trigger sigabrt and leave unnecessary coredump on the system. Using
|
||||
qWarning here would make it consistent with xcb's io error.
|
||||
|
||||
Pick-to: 5.15 6.0 6.1
|
||||
Change-Id: I571ba007bf2453486b81837cccdbefa5f181b63d
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
src/client/qwaylanddisplay.cpp | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
||||
index fe094f6f..f10c1f79 100644
|
||||
--- a/src/client/qwaylanddisplay.cpp
|
||||
+++ b/src/client/qwaylanddisplay.cpp
|
||||
@@ -206,10 +206,11 @@ void QWaylandDisplay::checkError() const
|
||||
int ecode = wl_display_get_error(mDisplay);
|
||||
if ((ecode == EPIPE || ecode == ECONNRESET)) {
|
||||
// special case this to provide a nicer error
|
||||
- qFatal("The Wayland connection broke. Did the Wayland compositor die?");
|
||||
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
|
||||
} else {
|
||||
- qFatal("The Wayland connection experienced a fatal error: %s", strerror(ecode));
|
||||
+ qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode));
|
||||
}
|
||||
+ _exit(1);
|
||||
}
|
||||
|
||||
void QWaylandDisplay::flushRequests()
|
||||
--
|
||||
2.35.1
|
||||
|
40
0002-Translate-opaque-area-with-frame-margins.patch
Normal file
40
0002-Translate-opaque-area-with-frame-margins.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From d353938c1a07a803656489cada8683e31f8f1c62 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 17:11:27 +0100
|
||||
Subject: [PATCH 02/40] Translate opaque area with frame margins
|
||||
|
||||
The opaque area doesn't take window decorations into account, which may
|
||||
result into possible graphical artefacts.
|
||||
|
||||
Pick-to: 5.15 6.0 6.1
|
||||
Change-Id: I1606e8256e7e204dad927931eb1221b576e227fd
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
src/client/qwaylandwindow.cpp | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index e875af3a..2af39977 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -1234,12 +1234,14 @@ bool QWaylandWindow::isOpaque() const
|
||||
|
||||
void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
|
||||
{
|
||||
- if (opaqueArea == mOpaqueArea || !mSurface)
|
||||
+ const QRegion translatedOpaqueArea = opaqueArea.translated(frameMargins().left(), frameMargins().top());
|
||||
+
|
||||
+ if (translatedOpaqueArea == mOpaqueArea || !mSurface)
|
||||
return;
|
||||
|
||||
- mOpaqueArea = opaqueArea;
|
||||
+ mOpaqueArea = translatedOpaqueArea;
|
||||
|
||||
- struct ::wl_region *region = mDisplay->createRegion(opaqueArea);
|
||||
+ struct ::wl_region *region = mDisplay->createRegion(translatedOpaqueArea);
|
||||
mSurface->set_opaque_region(region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,97 @@
|
||||
From 11e9bd41951ec9f229e20566f821aa39ca011352 Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Mon, 14 Sep 2020 17:08:39 +0100
|
||||
Subject: [PATCH 03/40] Client: Send exposeEvent to parent on subsurface
|
||||
position changes
|
||||
|
||||
When a subsurface is moved, we need the parent window to commit to apply
|
||||
that move. Ideally we want this in sync with any potential rendering on
|
||||
the parent window.
|
||||
|
||||
Currently the code calls requestUpdate() which acts more like a frame
|
||||
callback; it will only do something if the main QWindow considers itself
|
||||
dirty.
|
||||
|
||||
We want to force a repaint, which is semantically more similar to an
|
||||
ExposeEvent.
|
||||
|
||||
Fixes: QTBUG-86177
|
||||
Pick-to: 5.15
|
||||
Change-Id: I30bdfa357beee860ce2b00a256eaea6d040dd55c
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
---
|
||||
src/client/qwaylandwindow.cpp | 7 ++++-
|
||||
tests/auto/client/surface/tst_surface.cpp | 33 +++++++++++++++++++----
|
||||
2 files changed, 34 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index 2af39977..e96d8fe9 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -342,7 +342,12 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
|
||||
if (mSubSurfaceWindow) {
|
||||
QMargins m = QPlatformWindow::parent()->frameMargins();
|
||||
mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top());
|
||||
- mSubSurfaceWindow->parent()->window()->requestUpdate();
|
||||
+
|
||||
+ QWaylandWindow *parentWindow = mSubSurfaceWindow->parent();
|
||||
+ if (parentWindow && parentWindow->isExposed()) {
|
||||
+ QRect parentExposeGeometry(QPoint(), parentWindow->geometry().size());
|
||||
+ parentWindow->sendExposeEvent(parentExposeGeometry);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tests/auto/client/surface/tst_surface.cpp b/tests/auto/client/surface/tst_surface.cpp
|
||||
index b8a65f15..95e4e609 100644
|
||||
--- a/tests/auto/client/surface/tst_surface.cpp
|
||||
+++ b/tests/auto/client/surface/tst_surface.cpp
|
||||
@@ -167,17 +167,40 @@ void tst_surface::negotiateShmFormat()
|
||||
void tst_surface::createSubsurface()
|
||||
{
|
||||
QRasterWindow window;
|
||||
- window.resize(64, 64);
|
||||
- window.show();
|
||||
- QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||
- exec([=] { xdgToplevel()->sendCompleteConfigure(); });
|
||||
- QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial);
|
||||
+ window.setObjectName("main");
|
||||
+ window.resize(200, 200);
|
||||
|
||||
QRasterWindow subWindow;
|
||||
+ subWindow.setObjectName("subwindow");
|
||||
subWindow.setParent(&window);
|
||||
subWindow.resize(64, 64);
|
||||
+
|
||||
+ window.show();
|
||||
subWindow.show();
|
||||
+
|
||||
QCOMPOSITOR_TRY_VERIFY(subSurface());
|
||||
+ QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||
+ exec([=] { xdgToplevel()->sendCompleteConfigure(); });
|
||||
+ QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial);
|
||||
+
|
||||
+ const Surface *mainSurface = exec([=] {return surface(0);});
|
||||
+ const Surface *childSurface = exec([=] {return surface(1);});
|
||||
+ QSignalSpy mainSurfaceCommitSpy(mainSurface, &Surface::commit);
|
||||
+ QSignalSpy childSurfaceCommitSpy(childSurface, &Surface::commit);
|
||||
+
|
||||
+ // Move subsurface. The parent should redraw and commit
|
||||
+ subWindow.setGeometry(100, 100, 64, 64);
|
||||
+ // the toplevel should commit to indicate the subsurface moved
|
||||
+ QCOMPOSITOR_TRY_COMPARE(mainSurfaceCommitSpy.count(), 1);
|
||||
+ mainSurfaceCommitSpy.clear();
|
||||
+ childSurfaceCommitSpy.clear();
|
||||
+
|
||||
+ // Move and resize the subSurface. The parent should redraw and commit
|
||||
+ // The child should also redraw
|
||||
+ subWindow.setGeometry(50, 50, 80, 80);
|
||||
+ QCOMPOSITOR_TRY_COMPARE(mainSurfaceCommitSpy.count(), 1);
|
||||
+ QCOMPOSITOR_TRY_COMPARE(childSurfaceCommitSpy.count(), 1);
|
||||
+
|
||||
}
|
||||
|
||||
// Used to cause a crash in libwayland (QTBUG-79674)
|
||||
--
|
||||
2.35.1
|
||||
|
39
0004-Get-correct-decoration-margins-region.patch
Normal file
39
0004-Get-correct-decoration-margins-region.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 50a9256db8cd43665cf74cf94a293d1c05375d33 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 11 Feb 2021 15:12:32 +0100
|
||||
Subject: [PATCH 04/40] 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
|
||||
region we need to update.
|
||||
|
||||
Pick-to: 5.15 6.0 6.1
|
||||
Change-Id: Id1b7f4cd2a7b894b82db09c5af2b2d1f1f43fa2a
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
src/client/qwaylandabstractdecoration.cpp | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp
|
||||
index 87dd6cea..b6ee43c9 100644
|
||||
--- a/src/client/qwaylandabstractdecoration.cpp
|
||||
+++ b/src/client/qwaylandabstractdecoration.cpp
|
||||
@@ -108,11 +108,11 @@ void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window)
|
||||
static QRegion marginsRegion(const QSize &size, const QMargins &margins)
|
||||
{
|
||||
QRegion r;
|
||||
- const int widthWithMargins = margins.left() + size.width() + margins.right();
|
||||
- r += QRect(0, 0, widthWithMargins, margins.top()); // top
|
||||
- r += QRect(0, size.height()+margins.top(), widthWithMargins, margins.bottom()); //bottom
|
||||
+
|
||||
+ r += QRect(0, 0, size.width(), margins.top()); // top
|
||||
+ r += QRect(0, size.height()-margins.bottom(), size.width(), margins.bottom()); //bottom
|
||||
r += QRect(0, margins.top(), margins.left(), size.height()); //left
|
||||
- r += QRect(size.width()+margins.left(), margins.top(), margins.right(), size.height()); // right
|
||||
+ r += QRect(size.width()-margins.left(), margins.top(), margins.right(), size.height()-margins.top()); // right
|
||||
return r;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From f408482e4364293e5ab9889854a759796436971d Mon Sep 17 00:00:00 2001
|
||||
From: Aleix Pol <aleixpol@kde.org>
|
||||
Date: Mon, 23 Nov 2020 20:07:02 +0100
|
||||
Subject: [PATCH 05/40] xdgshell: Tell the compositor the screen we're
|
||||
expecting to fill
|
||||
|
||||
The xdgshell protocol allows us to tell the output to fill. This makes
|
||||
it possible to use fullscreen confidently on systems with multiple
|
||||
screens knowing that our windows won't be overlapping one another by
|
||||
calling setScreen accordingly before QWindow::showFullScreen.
|
||||
|
||||
Pick-to: 6.1 6.0 5.15
|
||||
Change-Id: I757854c3698639472f3a25ef298ddcca031e1ed5
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
.../shellintegration/xdg-shell/qwaylandxdgshell.cpp | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
index 1c762944..3a1569f7 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
@@ -178,9 +178,12 @@ void QWaylandXdgSurface::Toplevel::requestWindowStates(Qt::WindowStates states)
|
||||
}
|
||||
|
||||
if (changedStates & Qt::WindowFullScreen) {
|
||||
- if (states & Qt::WindowFullScreen)
|
||||
- set_fullscreen(nullptr);
|
||||
- else
|
||||
+ if (states & Qt::WindowFullScreen) {
|
||||
+ auto screen = m_xdgSurface->window()->waylandScreen();
|
||||
+ if (screen) {
|
||||
+ set_fullscreen(screen->output());
|
||||
+ }
|
||||
+ } else
|
||||
unset_fullscreen();
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
257
0006-client-Allow-QWaylandInputContext-to-accept-composed.patch
Normal file
257
0006-client-Allow-QWaylandInputContext-to-accept-composed.patch
Normal file
@ -0,0 +1,257 @@
|
||||
From d6dd815014564f235fb972eb72d28ccca6cf3549 Mon Sep 17 00:00:00 2001
|
||||
From: Aleix Pol <aleixpol@kde.org>
|
||||
Date: Wed, 10 Mar 2021 01:09:13 +0100
|
||||
Subject: [PATCH 06/40] client: Allow QWaylandInputContext to accept composed
|
||||
key combinations
|
||||
|
||||
At the moment, we are forcing user to choose to either compose or use
|
||||
the text-input channel. This patch brings some of the QComposeInputContext
|
||||
functionality in order to let applications understand dead key
|
||||
combinations like they are supposed to.
|
||||
|
||||
Having it in QWaylandInputContext rather than in QWaylandInputDevice
|
||||
should solve the problems 3aedd01271dc4f4a13103d632df224971ab2b6df had
|
||||
with 57c4af2b18c0fb1d266b245a107fa6cb876b9d9e, because we are doing it
|
||||
in the input context rather than before. This way, if the user is
|
||||
overriding the input method (e.g. by setting QT_IM_MODULE), all the key
|
||||
strokes will still be properly forwarded to the module to use.
|
||||
|
||||
This in turn allows us to solve https://bugs.kde.org/show_bug.cgi?id=411729
|
||||
and https://bugs.kde.org/show_bug.cgi?id=405388 since we don't need to
|
||||
choose anymore between physical and virual keyboards anymore.
|
||||
|
||||
Pick-to: 5.15
|
||||
Change-Id: I8601f5d7ae21edf4b3a1191fa75877286e505588
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
---
|
||||
src/client/qwaylanddisplay_p.h | 3 -
|
||||
src/client/qwaylandinputcontext.cpp | 95 ++++++++++++++++++++++++++++-
|
||||
src/client/qwaylandinputcontext_p.h | 21 +++++++
|
||||
src/client/qwaylandinputdevice.cpp | 2 +-
|
||||
src/client/qwaylandintegration.cpp | 8 +--
|
||||
5 files changed, 119 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
|
||||
index 188e9131..3b092bc8 100644
|
||||
--- a/src/client/qwaylanddisplay_p.h
|
||||
+++ b/src/client/qwaylanddisplay_p.h
|
||||
@@ -175,8 +175,6 @@ public:
|
||||
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
|
||||
QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
|
||||
|
||||
- bool usingInputContextFromCompositor() const { return mUsingInputContextFromCompositor; }
|
||||
-
|
||||
struct RegistryGlobal {
|
||||
uint32_t id;
|
||||
QString interface;
|
||||
@@ -282,7 +280,6 @@ private:
|
||||
QReadWriteLock m_frameQueueLock;
|
||||
|
||||
bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
|
||||
- bool mUsingInputContextFromCompositor = false;
|
||||
|
||||
void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
|
||||
void registry_global_remove(uint32_t id) override;
|
||||
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
|
||||
index e9afe05e..ef5aa375 100644
|
||||
--- a/src/client/qwaylandinputcontext.cpp
|
||||
+++ b/src/client/qwaylandinputcontext.cpp
|
||||
@@ -406,6 +406,8 @@ bool QWaylandInputContext::isValid() const
|
||||
void QWaylandInputContext::reset()
|
||||
{
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
+ if (m_composeState)
|
||||
+ xkb_compose_state_reset(m_composeState);
|
||||
|
||||
QPlatformInputContext::reset();
|
||||
|
||||
@@ -526,9 +528,14 @@ Qt::LayoutDirection QWaylandInputContext::inputDirection() const
|
||||
return textInput()->inputDirection();
|
||||
}
|
||||
|
||||
-void QWaylandInputContext::setFocusObject(QObject *)
|
||||
+void QWaylandInputContext::setFocusObject(QObject *object)
|
||||
{
|
||||
qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+ m_focusObject = object;
|
||||
+#else
|
||||
+ Q_UNUSED(object);
|
||||
+#endif
|
||||
|
||||
if (!textInput())
|
||||
return;
|
||||
@@ -561,6 +568,92 @@ QWaylandTextInput *QWaylandInputContext::textInput() const
|
||||
return mDisplay->defaultInputDevice()->textInput();
|
||||
}
|
||||
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+
|
||||
+void QWaylandInputContext::ensureInitialized()
|
||||
+{
|
||||
+ if (m_initialized)
|
||||
+ return;
|
||||
+
|
||||
+ if (!m_XkbContext) {
|
||||
+ qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ m_initialized = true;
|
||||
+ const char *locale = setlocale(LC_CTYPE, "");
|
||||
+ if (!locale)
|
||||
+ locale = setlocale(LC_CTYPE, nullptr);
|
||||
+ qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
|
||||
+
|
||||
+ m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
+ if (m_composeTable)
|
||||
+ m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
+
|
||||
+ if (!m_composeTable) {
|
||||
+ qCWarning(qLcQpaInputMethods, "failed to create compose table");
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!m_composeState) {
|
||||
+ qCWarning(qLcQpaInputMethods, "failed to create compose state");
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool QWaylandInputContext::filterEvent(const QEvent *event)
|
||||
+{
|
||||
+ auto keyEvent = static_cast<const QKeyEvent *>(event);
|
||||
+ if (keyEvent->type() != QEvent::KeyPress)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!inputMethodAccepted())
|
||||
+ return false;
|
||||
+
|
||||
+ // lazy initialization - we don't want to do this on an app startup
|
||||
+ ensureInitialized();
|
||||
+
|
||||
+ if (!m_composeTable || !m_composeState)
|
||||
+ return false;
|
||||
+
|
||||
+ xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
|
||||
+
|
||||
+ switch (xkb_compose_state_get_status(m_composeState)) {
|
||||
+ case XKB_COMPOSE_COMPOSING:
|
||||
+ return true;
|
||||
+ case XKB_COMPOSE_CANCELLED:
|
||||
+ reset();
|
||||
+ return false;
|
||||
+ case XKB_COMPOSE_COMPOSED:
|
||||
+ {
|
||||
+ const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
|
||||
+ QVarLengthArray<char, 32> buffer(size + 1);
|
||||
+ xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
|
||||
+ QString composedText = QString::fromUtf8(buffer.constData());
|
||||
+
|
||||
+ QInputMethodEvent event;
|
||||
+ event.setCommitString(composedText);
|
||||
+
|
||||
+ if (!m_focusObject && qApp)
|
||||
+ m_focusObject = qApp->focusObject();
|
||||
+
|
||||
+ if (m_focusObject)
|
||||
+ QCoreApplication::sendEvent(m_focusObject, &event);
|
||||
+ else
|
||||
+ qCWarning(qLcQpaInputMethods, "no focus object");
|
||||
+
|
||||
+ reset();
|
||||
+ return true;
|
||||
+ }
|
||||
+ case XKB_COMPOSE_NOTHING:
|
||||
+ return false;
|
||||
+ default:
|
||||
+ Q_UNREACHABLE();
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
diff --git a/src/client/qwaylandinputcontext_p.h b/src/client/qwaylandinputcontext_p.h
|
||||
index 10132dfe..50db6344 100644
|
||||
--- a/src/client/qwaylandinputcontext_p.h
|
||||
+++ b/src/client/qwaylandinputcontext_p.h
|
||||
@@ -61,6 +61,10 @@
|
||||
|
||||
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
|
||||
#include <qwaylandinputmethodeventbuilder_p.h>
|
||||
+#include <qtwaylandclientglobal_p.h>
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+#include <xkbcommon/xkbcommon-compose.h>
|
||||
+#endif
|
||||
|
||||
struct wl_callback;
|
||||
struct wl_callback_listener;
|
||||
@@ -155,11 +159,28 @@ public:
|
||||
|
||||
void setFocusObject(QObject *object) override;
|
||||
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+ bool filterEvent(const QEvent *event) override;
|
||||
+
|
||||
+ // This invokable is called from QXkbCommon::setXkbContext().
|
||||
+ Q_INVOKABLE void setXkbContext(struct xkb_context *context) { m_XkbContext = context; }
|
||||
+#endif
|
||||
+
|
||||
private:
|
||||
QWaylandTextInput *textInput() const;
|
||||
|
||||
QWaylandDisplay *mDisplay = nullptr;
|
||||
QPointer<QWindow> mCurrentWindow;
|
||||
+
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+ void ensureInitialized();
|
||||
+
|
||||
+ bool m_initialized = false;
|
||||
+ QObject *m_focusObject = nullptr;
|
||||
+ xkb_compose_table *m_composeTable = nullptr;
|
||||
+ xkb_compose_state *m_composeState = nullptr;
|
||||
+ struct xkb_context *m_XkbContext = nullptr;
|
||||
+#endif
|
||||
};
|
||||
|
||||
}
|
||||
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
|
||||
index ed4a0eb4..ae045f4f 100644
|
||||
--- a/src/client/qwaylandinputdevice.cpp
|
||||
+++ b/src/client/qwaylandinputdevice.cpp
|
||||
@@ -1201,7 +1201,7 @@ void QWaylandInputDevice::Keyboard::handleKey(ulong timestamp, QEvent::Type type
|
||||
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
|
||||
bool filtered = false;
|
||||
|
||||
- if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) {
|
||||
+ if (inputContext) {
|
||||
QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey,
|
||||
nativeModifiers, text, autorepeat, count);
|
||||
event.setTimestamp(timestamp);
|
||||
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
|
||||
index 7ad8e05e..c53ccb78 100644
|
||||
--- a/src/client/qwaylandintegration.cpp
|
||||
+++ b/src/client/qwaylandintegration.cpp
|
||||
@@ -474,13 +474,11 @@ void QWaylandIntegration::reconfigureInputContext()
|
||||
|
||||
#if QT_CONFIG(xkbcommon)
|
||||
QXkbCommon::setXkbContext(mInputContext.data(), mDisplay->xkbContext());
|
||||
+ if (QWaylandInputContext* waylandInput = qobject_cast<QWaylandInputContext*>(mInputContext.get())) {
|
||||
+ waylandInput->setXkbContext(mDisplay->xkbContext());
|
||||
+ }
|
||||
#endif
|
||||
|
||||
- // Even if compositor-side input context handling has been requested, we fallback to
|
||||
- // client-side handling if compositor does not provide the text-input extension. This
|
||||
- // is why we need to check here which input context actually is being used.
|
||||
- mDisplay->mUsingInputContextFromCompositor = qobject_cast<QWaylandInputContext *>(mInputContext.data());
|
||||
-
|
||||
qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className();
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
146
0007-Client-Announce-an-output-after-receiving-more-compl.patch
Normal file
146
0007-Client-Announce-an-output-after-receiving-more-compl.patch
Normal file
@ -0,0 +1,146 @@
|
||||
From a6fb2a976ecd778e450afe89c180c8c748beb568 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 07/40] Client: Announce an output after receiving more
|
||||
complete state
|
||||
|
||||
Output initialization is not atomic, meaning that the compositor may
|
||||
process a wl_output bind request in one event loop cycle, and the
|
||||
xdg_output_manager.get_xdg_output in another event loop cycle.
|
||||
|
||||
This means that xdg_output properties may arrive in another wl_output
|
||||
done frame. Prior to xdg-output v3, that wasn't an issue because the
|
||||
compositor is required to send an xdg_output.done event after sending
|
||||
xdg_output properties.
|
||||
|
||||
Starting with v3, the compositor may choose not to send an
|
||||
xdg_output.done event after sending xdg_output properties. Therefore,
|
||||
as is, QtWayland may announce an output with bad logical geometry or
|
||||
even worse without name assigned by the compositor.
|
||||
|
||||
Unfortunately, that breaks applications such as plasmashell. Plasma uses
|
||||
output names as a criterion to determine what kind of contents should be
|
||||
displayed on a particular output.
|
||||
|
||||
In order to fix the initialization sequence, this change makes every
|
||||
QWaylandScreen track processed events. After all required events have
|
||||
been received, the screen can be announced to the rest of Qt.
|
||||
|
||||
Change-Id: If5da747edd7af277ec1364cbea105c6994f47402
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
(cherry picked from commit 69ea480f2e53ad4a5bbca78cde044eb8d4c48896)
|
||||
|
||||
Original Ticket: https://codereview.qt-project.org/c/qt/qtwayland/+/347774
|
||||
CCBUG: 435124
|
||||
---
|
||||
src/client/qwaylandscreen.cpp | 32 +++++++++++++++++++++++---------
|
||||
src/client/qwaylandscreen_p.h | 10 ++++++++--
|
||||
2 files changed, 31 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
|
||||
index 6cb337de..7c2d9be3 100644
|
||||
--- a/src/client/qwaylandscreen.cpp
|
||||
+++ b/src/client/qwaylandscreen.cpp
|
||||
@@ -72,7 +72,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin
|
||||
qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor,"
|
||||
<< "QScreen may not work correctly";
|
||||
mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc.
|
||||
- mOutputDone = true; // Fake the done event
|
||||
+ mProcessedEvents |= OutputDoneEvent; // Fake the done event
|
||||
maybeInitialize();
|
||||
}
|
||||
}
|
||||
@@ -83,14 +83,25 @@ QWaylandScreen::~QWaylandScreen()
|
||||
zxdg_output_v1::destroy();
|
||||
}
|
||||
|
||||
+uint QWaylandScreen::requiredEvents() const
|
||||
+{
|
||||
+ uint ret = OutputDoneEvent;
|
||||
+
|
||||
+ if (mWaylandDisplay->xdgOutputManager()) {
|
||||
+ ret |= XdgOutputNameEvent;
|
||||
+
|
||||
+ if (mWaylandDisplay->xdgOutputManager()->version() < 3)
|
||||
+ ret |= XdgOutputDoneEvent;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void QWaylandScreen::maybeInitialize()
|
||||
{
|
||||
Q_ASSERT(!mInitialized);
|
||||
|
||||
- if (!mOutputDone)
|
||||
- return;
|
||||
-
|
||||
- if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone)
|
||||
+ const uint requiredEvents = this->requiredEvents();
|
||||
+ if ((mProcessedEvents & requiredEvents) != requiredEvents)
|
||||
return;
|
||||
|
||||
mInitialized = true;
|
||||
@@ -276,9 +287,8 @@ void QWaylandScreen::output_scale(int32_t factor)
|
||||
|
||||
void QWaylandScreen::output_done()
|
||||
{
|
||||
- mOutputDone = true;
|
||||
- if (zxdg_output_v1::isInitialized() && mWaylandDisplay->xdgOutputManager()->version() >= 3)
|
||||
- mXdgOutputDone = true;
|
||||
+ mProcessedEvents |= OutputDoneEvent;
|
||||
+
|
||||
if (mInitialized) {
|
||||
updateOutputProperties();
|
||||
if (zxdg_output_v1::isInitialized())
|
||||
@@ -339,7 +349,7 @@ void QWaylandScreen::zxdg_output_v1_done()
|
||||
if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3))
|
||||
qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor";
|
||||
|
||||
- mXdgOutputDone = true;
|
||||
+ mProcessedEvents |= XdgOutputDoneEvent;
|
||||
if (mInitialized)
|
||||
updateXdgOutputProperties();
|
||||
else
|
||||
@@ -348,7 +358,11 @@ void QWaylandScreen::zxdg_output_v1_done()
|
||||
|
||||
void QWaylandScreen::zxdg_output_v1_name(const QString &name)
|
||||
{
|
||||
+ if (Q_UNLIKELY(mInitialized))
|
||||
+ qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor";
|
||||
+
|
||||
mOutputName = name;
|
||||
+ mProcessedEvents |= XdgOutputNameEvent;
|
||||
}
|
||||
|
||||
void QWaylandScreen::updateXdgOutputProperties()
|
||||
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
|
||||
index df1c94f2..050cfdc0 100644
|
||||
--- a/src/client/qwaylandscreen_p.h
|
||||
+++ b/src/client/qwaylandscreen_p.h
|
||||
@@ -116,6 +116,13 @@ public:
|
||||
static QWaylandScreen *fromWlOutput(::wl_output *output);
|
||||
|
||||
private:
|
||||
+ enum Event : uint {
|
||||
+ XdgOutputDoneEvent = 0x1,
|
||||
+ OutputDoneEvent = 0x2,
|
||||
+ XdgOutputNameEvent = 0x4,
|
||||
+ };
|
||||
+ uint requiredEvents() const;
|
||||
+
|
||||
void output_mode(uint32_t flags, int width, int height, int refresh) override;
|
||||
void output_geometry(int32_t x, int32_t y,
|
||||
int32_t width, int32_t height,
|
||||
@@ -148,8 +155,7 @@ private:
|
||||
QSize mPhysicalSize;
|
||||
QString mOutputName;
|
||||
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
|
||||
- bool mOutputDone = false;
|
||||
- bool mXdgOutputDone = false;
|
||||
+ uint mProcessedEvents = 0;
|
||||
bool mInitialized = false;
|
||||
|
||||
#if QT_CONFIG(cursor)
|
||||
--
|
||||
2.35.1
|
||||
|
58
0008-Fix-issue-with-repeated-window-size-changes.patch
Normal file
58
0008-Fix-issue-with-repeated-window-size-changes.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From bb9288c913dc49aefc3fad03ec243809b6b21a88 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 08/40] 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
|
||||
where repeated setGeometry calls between two sizes might not work as
|
||||
expected. The problem occurs when wl_egl_window_get_attached_size does
|
||||
not get the same size that was requested by the previous setGeometry
|
||||
call. If the returned size happened to match the new size instead,
|
||||
we would mistakenly skip the resize.
|
||||
|
||||
Change-Id: Iafe4a91cc707f854b9099b6109b6be1423d7bd29
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
(cherry picked from commit 14d066c61025e548227ccd8d655e80ffa31fa15e)
|
||||
---
|
||||
.../client/wayland-egl/qwaylandeglwindow.cpp | 4 +++-
|
||||
.../client/wayland-egl/qwaylandeglwindow.h | 1 +
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
|
||||
index 7889f575..201b583b 100644
|
||||
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
|
||||
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp
|
||||
@@ -131,14 +131,16 @@ void QWaylandEglWindow::updateSurface(bool create)
|
||||
if (!disableResizeCheck) {
|
||||
wl_egl_window_get_attached_size(m_waylandEglWindow, ¤t_width, ¤t_height);
|
||||
}
|
||||
- if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height())) {
|
||||
+ if (disableResizeCheck || (current_width != sizeWithMargins.width() || current_height != sizeWithMargins.height()) || m_requestedSize != sizeWithMargins) {
|
||||
wl_egl_window_resize(m_waylandEglWindow, sizeWithMargins.width(), sizeWithMargins.height(), mOffset.x(), mOffset.y());
|
||||
+ m_requestedSize = sizeWithMargins;
|
||||
mOffset = QPoint();
|
||||
|
||||
m_resize = true;
|
||||
}
|
||||
} else if (create && wlSurface()) {
|
||||
m_waylandEglWindow = wl_egl_window_create(wlSurface(), sizeWithMargins.width(), sizeWithMargins.height());
|
||||
+ m_requestedSize = sizeWithMargins;
|
||||
}
|
||||
|
||||
if (!m_eglSurface && m_waylandEglWindow && create) {
|
||||
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
|
||||
index 5b1f4d56..0079dfef 100644
|
||||
--- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
|
||||
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h
|
||||
@@ -88,6 +88,7 @@ private:
|
||||
mutable QOpenGLFramebufferObject *m_contentFBO = nullptr;
|
||||
|
||||
QSurfaceFormat m_format;
|
||||
+ QSize m_requestedSize;
|
||||
};
|
||||
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
31
0009-Include-locale.h-for-setlocale-LC_CTYPE.patch
Normal file
31
0009-Include-locale.h-for-setlocale-LC_CTYPE.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 82720c9d7e0a706793f9716144347171820ddf4d 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 09/40] Include locale.h for setlocale/LC_CTYPE
|
||||
|
||||
Pick-to: 5.15
|
||||
Change-Id: Iced32a31a63cec71008549c1e0961d59ffc45a37
|
||||
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
(cherry picked from commit e9522eda46028f351d87311d898ab985856970b0)
|
||||
---
|
||||
src/client/qwaylandinputcontext.cpp | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
|
||||
index ef5aa375..503fd735 100644
|
||||
--- a/src/client/qwaylandinputcontext.cpp
|
||||
+++ b/src/client/qwaylandinputcontext.cpp
|
||||
@@ -51,6 +51,10 @@
|
||||
#include "qwaylandinputmethodeventbuilder_p.h"
|
||||
#include "qwaylandwindow_p.h"
|
||||
|
||||
+#if QT_CONFIG(xkbcommon)
|
||||
+#include <locale.h>
|
||||
+#endif
|
||||
+
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods")
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,39 @@
|
||||
From 6b2084a4c9f87d3575fc6aec3f7454304bcc6188 Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Tue, 9 Feb 2021 16:09:21 +0000
|
||||
Subject: [PATCH 10/40] Client: Connect drags being accepted to updating the
|
||||
source drag icon
|
||||
|
||||
Currently in a multi-process drag and drop when the other client accepts
|
||||
a given mimetype for dropping it calls accept, which is received by the
|
||||
client, but the drag cursor is never updated.
|
||||
|
||||
Instead the drag cursor was updated in the data_device_enter events
|
||||
which only works if we are operating within one process.
|
||||
|
||||
The code existed to handle this existed but both the targetChanged
|
||||
signal and the dragSourceTargetChanged were unused.
|
||||
|
||||
Change-Id: I443f31f1b2ef72d4b5eadaf7115f97544dac883a
|
||||
Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
(cherry picked from commit 08e478448a97a440d5a968a5d797f0d7302140c2)
|
||||
---
|
||||
src/client/qwaylanddatadevice.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
|
||||
index 19944a34..54a69c3c 100644
|
||||
--- a/src/client/qwaylanddatadevice.cpp
|
||||
+++ b/src/client/qwaylanddatadevice.cpp
|
||||
@@ -124,6 +124,7 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
||||
|
||||
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
||||
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
||||
+ connect(m_dragSource.data(), &QWaylandDataSource::targetChanged, this, &QWaylandDataDevice::dragSourceTargetChanged);
|
||||
|
||||
start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
|
||||
return true;
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,49 @@
|
||||
From a1d6aa2078b8a840469f13ae720669cb4f99291d Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Fri, 14 May 2021 13:23:24 +0100
|
||||
Subject: [PATCH 11/40] 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
|
||||
will crash.
|
||||
|
||||
Change-Id: Idc0de40be61a2f7627ab4963e1fe29b22fbf3f04
|
||||
(cherry picked from commit c4ba37cd2f8cb81b9438b56ac604fc2f3e45083c)
|
||||
---
|
||||
src/client/global/qwaylandclientextension.cpp | 7 +++++++
|
||||
src/client/global/qwaylandclientextension.h | 1 +
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/client/global/qwaylandclientextension.cpp b/src/client/global/qwaylandclientextension.cpp
|
||||
index 125b1e19..797b06fe 100644
|
||||
--- a/src/client/global/qwaylandclientextension.cpp
|
||||
+++ b/src/client/global/qwaylandclientextension.cpp
|
||||
@@ -88,6 +88,13 @@ QWaylandClientExtension::QWaylandClientExtension(const int ver)
|
||||
QMetaObject::invokeMethod(this, "addRegistryListener", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
+QWaylandClientExtension::~QWaylandClientExtension()
|
||||
+{
|
||||
+ Q_D(QWaylandClientExtension);
|
||||
+ if (d->registered && !QCoreApplication::closingDown())
|
||||
+ d->waylandIntegration->display()->removeListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
|
||||
+}
|
||||
+
|
||||
QtWaylandClient::QWaylandIntegration *QWaylandClientExtension::integration() const
|
||||
{
|
||||
Q_D(const QWaylandClientExtension);
|
||||
diff --git a/src/client/global/qwaylandclientextension.h b/src/client/global/qwaylandclientextension.h
|
||||
index 98272e57..5bd28398 100644
|
||||
--- a/src/client/global/qwaylandclientextension.h
|
||||
+++ b/src/client/global/qwaylandclientextension.h
|
||||
@@ -63,6 +63,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtension : public QObject
|
||||
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
|
||||
public:
|
||||
QWaylandClientExtension(const int version);
|
||||
+ ~QWaylandClientExtension();
|
||||
|
||||
QtWaylandClient::QWaylandIntegration *integration() const;
|
||||
int version() const;
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,58 @@
|
||||
From d9d7c73f908db351921cf016c5e079f3d13e84aa Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Mon, 3 May 2021 23:01:53 +0100
|
||||
Subject: [PATCH 12/40] 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
|
||||
we create the shell window.
|
||||
|
||||
Sending them when we apply configure is too late, we need these hints
|
||||
available for the compositor to correctly configure the window.
|
||||
|
||||
Change-Id: I6cbb294b11db06ecd87535fa4816bb8ad34a29c6
|
||||
Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
(cherry picked from commit d6e074d0d35221b0fac14c94fc79c98363f2f6c3)
|
||||
---
|
||||
src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp | 3 +--
|
||||
tests/auto/client/xdgshell/tst_xdgshell.cpp | 2 +-
|
||||
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
index 3a1569f7..7d33dabd 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
@@ -105,8 +105,6 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
|
||||
m_xdgSurface->m_window->resizeFromApplyConfigure(m_pending.size);
|
||||
}
|
||||
|
||||
- m_xdgSurface->setSizeHints();
|
||||
-
|
||||
m_applied = m_pending;
|
||||
qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
|
||||
}
|
||||
@@ -257,6 +255,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
|
||||
m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
|
||||
}
|
||||
}
|
||||
+ setSizeHints();
|
||||
}
|
||||
|
||||
QWaylandXdgSurface::~QWaylandXdgSurface()
|
||||
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
index 2277bbb8..2fdd0a7c 100644
|
||||
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
@@ -505,7 +505,7 @@ void tst_xdgshell::minMaxSize()
|
||||
window.show();
|
||||
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||
|
||||
- exec([=] { xdgToplevel()->sendCompleteConfigure(); });
|
||||
+ // we don't roundtrip with our configuration the initial commit should be correct
|
||||
|
||||
QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(100, 100));
|
||||
QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(1000, 1000));
|
||||
--
|
||||
2.35.1
|
||||
|
46
0013-Fix-build.patch
Normal file
46
0013-Fix-build.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 2e8e8b87d800f1ef2e0fb0a6f0818de0a8fa0951 Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Mon, 14 Jun 2021 12:45:37 +0100
|
||||
Subject: [PATCH 13/40] Fix build
|
||||
|
||||
1b5e43a593e917610e6245f7a272ac081c508ba4 relied on a patch that we can't
|
||||
backport.
|
||||
|
||||
This adds that extra internal boolean backporting just the tiny part of
|
||||
d6ac8cf6.
|
||||
---
|
||||
src/client/global/qwaylandclientextension.cpp | 5 ++++-
|
||||
src/client/global/qwaylandclientextension_p.h | 1 +
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/global/qwaylandclientextension.cpp b/src/client/global/qwaylandclientextension.cpp
|
||||
index 797b06fe..edccfe63 100644
|
||||
--- a/src/client/global/qwaylandclientextension.cpp
|
||||
+++ b/src/client/global/qwaylandclientextension.cpp
|
||||
@@ -74,7 +74,10 @@ void QWaylandClientExtensionPrivate::handleRegistryGlobal(void *data, ::wl_regis
|
||||
void QWaylandClientExtension::addRegistryListener()
|
||||
{
|
||||
Q_D(QWaylandClientExtension);
|
||||
- d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
|
||||
+ if (!d->registered) {
|
||||
+ d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this);
|
||||
+ d->registered = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
QWaylandClientExtension::QWaylandClientExtension(const int ver)
|
||||
diff --git a/src/client/global/qwaylandclientextension_p.h b/src/client/global/qwaylandclientextension_p.h
|
||||
index 69cc46a0..9091efbe 100644
|
||||
--- a/src/client/global/qwaylandclientextension_p.h
|
||||
+++ b/src/client/global/qwaylandclientextension_p.h
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
QtWaylandClient::QWaylandIntegration *waylandIntegration = nullptr;
|
||||
int version = -1;
|
||||
bool active = false;
|
||||
+ bool registered = false;
|
||||
};
|
||||
|
||||
class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
|
||||
--
|
||||
2.35.1
|
||||
|
33
0014-Fix-remove-listener.patch
Normal file
33
0014-Fix-remove-listener.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 88b2e6c9728d01a9aa334026629fbb1ce85fe197 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Liang <zhanglianga@uniontech.com>
|
||||
Date: Mon, 1 Feb 2021 19:29:43 +0800
|
||||
Subject: [PATCH 14/40] Fix: remove listener
|
||||
|
||||
Add the operation for removing the listener form listener list
|
||||
|
||||
Change-Id: Ief2ff1303b607eee499543303fe80e51f8f10cc5
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
(cherry picked from commit 16760280fd04cf70255bab16d9acecad254fdd8f)
|
||||
---
|
||||
src/client/qwaylanddisplay.cpp | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
||||
index f10c1f79..e0dfe8b2 100644
|
||||
--- a/src/client/qwaylanddisplay.cpp
|
||||
+++ b/src/client/qwaylanddisplay.cpp
|
||||
@@ -452,9 +452,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
|
||||
|
||||
void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
|
||||
{
|
||||
- std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
|
||||
+ auto iter = std::remove_if(mRegistryListeners.begin(), mRegistryListeners.end(), [=](Listener l){
|
||||
return (l.listener == listener && l.data == data);
|
||||
});
|
||||
+ mRegistryListeners.erase(iter, mRegistryListeners.end());
|
||||
}
|
||||
|
||||
uint32_t QWaylandDisplay::currentTimeMillisec()
|
||||
--
|
||||
2.35.1
|
||||
|
55
0015-Hook-up-queryKeyboardModifers.patch
Normal file
55
0015-Hook-up-queryKeyboardModifers.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 75693b47dcac101f74f98e5902c4c6b39d407e4f 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 15/40] Hook up queryKeyboardModifers
|
||||
|
||||
Can be useful when upon enter a modifiers event is received but no key
|
||||
event so no QKeyEvent is generated.
|
||||
|
||||
Fixes: QTBUG-62786
|
||||
Change-Id: I30b57fc78ce6d54d8f644ca95ba40e7e26eb24ed
|
||||
Reviewed-by: Marco Martin <mart@kde.org>
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
|
||||
(cherry picked from commit 4fa2baba8181ade4958a94e9531ec4f6919438a9)
|
||||
---
|
||||
src/client/qwaylandintegration.cpp | 8 ++++++++
|
||||
src/client/qwaylandintegration_p.h | 2 ++
|
||||
2 files changed, 10 insertions(+)
|
||||
|
||||
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
|
||||
index c53ccb78..e5e7dd42 100644
|
||||
--- a/src/client/qwaylandintegration.cpp
|
||||
+++ b/src/client/qwaylandintegration.cpp
|
||||
@@ -262,6 +262,14 @@ QWaylandDisplay *QWaylandIntegration::display() const
|
||||
return mDisplay.data();
|
||||
}
|
||||
|
||||
+Qt::KeyboardModifiers QWaylandIntegration::queryKeyboardModifiers() const
|
||||
+{
|
||||
+ if (auto *seat = mDisplay->currentInputDevice()) {
|
||||
+ return seat->modifiers();
|
||||
+ }
|
||||
+ return Qt::NoModifier;
|
||||
+}
|
||||
+
|
||||
QList<int> QWaylandIntegration::possibleKeys(const QKeyEvent *event) const
|
||||
{
|
||||
if (auto *seat = mDisplay->currentInputDevice())
|
||||
diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h
|
||||
index ff70ae25..73b80658 100644
|
||||
--- a/src/client/qwaylandintegration_p.h
|
||||
+++ b/src/client/qwaylandintegration_p.h
|
||||
@@ -107,6 +107,8 @@ public:
|
||||
|
||||
QWaylandDisplay *display() const;
|
||||
|
||||
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
|
||||
+
|
||||
QList<int> possibleKeys(const QKeyEvent *event) const override;
|
||||
|
||||
QStringList themeNames() const override;
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 537c5d43941d26d89ebf00f6abf7f12f9bac1caf Mon Sep 17 00:00:00 2001
|
||||
From: Aleix Pol <aleixpol@kde.org>
|
||||
Date: Tue, 13 Jul 2021 13:32:15 +0200
|
||||
Subject: [PATCH 16/40] 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().
|
||||
No need to store values that we are going to discard, because it will
|
||||
confuse the state of newly created windows.
|
||||
|
||||
Change-Id: I6aa3da82c7f09c7ef90d0f7060f292fb042730f0
|
||||
Pick-to: 5.15 6.2
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
(cherry picked from commit 962f87190c682562b369c5ebd93dc9ce0915ed7a)
|
||||
---
|
||||
src/client/qwaylandwindow.cpp | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index e96d8fe9..bd70f4af 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -464,14 +464,15 @@ void QWaylandWindow::lower()
|
||||
|
||||
void QWaylandWindow::setMask(const QRegion &mask)
|
||||
{
|
||||
+ QReadLocker locker(&mSurfaceLock);
|
||||
+ if (!mSurface)
|
||||
+ return;
|
||||
+
|
||||
if (mMask == mask)
|
||||
return;
|
||||
|
||||
mMask = mask;
|
||||
|
||||
- if (!mSurface)
|
||||
- return;
|
||||
-
|
||||
if (mMask.isEmpty()) {
|
||||
mSurface->set_input_region(nullptr);
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,68 @@
|
||||
From ae3ea8875b9475532e5779154e3992affe2b9a32 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Blackquill <uhhadd@gmail.com>
|
||||
Date: Tue, 24 Aug 2021 14:36:34 -0400
|
||||
Subject: [PATCH 17/40] Correctly detect if image format is supported by
|
||||
QImageWriter
|
||||
|
||||
The code queries potential image formats by stripping a mimetype of its
|
||||
'image/' prefix and making the rest of the mimetype capitalised, such as
|
||||
'image/png' -> 'PNG'. The problem is that this is then searched for in
|
||||
QImageWriter::supportedImageFormats() by simple equality. The method
|
||||
returns a list of lowercase byte arrays, not uppercase. As the codepath
|
||||
can never match due to checking for an uppercase word in an array of
|
||||
lowercase words, this means that images are effectively always sent as
|
||||
BMP format, even if they should be sent in other formats, such as PNG
|
||||
or JPEG.
|
||||
|
||||
A simple inspection with GDB (or a qDebug) reveals this:
|
||||
|
||||
```
|
||||
(gdb) p QImageWriter::supportedImageFormats()
|
||||
$31 = {"bmp" = {...}, "bw" = {...}, "cur" = {...}, "eps" = {...},
|
||||
"epsf" = {...}, "epsi" = {...}, "icns" = {...},
|
||||
"ico" = {...}, "jp2" = {...}, "jpeg" = {...}, "jpg" = {...},
|
||||
"pbm" = {...}, "pcx" = {...}, "pgm" = {...},
|
||||
"pic" = {...}, "png" = {...}, "ppm" = {...},
|
||||
"rgb" = {...}, "rgba" = {...}, "sgi" = {...},
|
||||
"tga" = {...}, "tif" = {...}, "tiff" = {...},
|
||||
"wbmp" = {...}, "webp" = {...}, "xbm" = {...}, "xpm" = {...}}
|
||||
```
|
||||
|
||||
```
|
||||
(gdb) p QImageWriter::supportedImageFormats().contains("PNG")
|
||||
$32 = false
|
||||
```
|
||||
|
||||
```
|
||||
(gdb) p QImageWriter::supportedImageFormats().contains("png")
|
||||
$33 = true
|
||||
```
|
||||
|
||||
The fix for this is simple: lowercase the remainder of the mimetype,
|
||||
instead of uppercasing it, and we can start hitting the codepath that's
|
||||
supposed to write non-BMP formats.
|
||||
|
||||
Change-Id: Id3e9b730b7edcabcb2f1b04d8ef0a4c1fb9c9159
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
||||
(cherry picked from commit 6072c1dc87e185f30c014f764737ac97b906640f)
|
||||
---
|
||||
src/shared/qwaylandmimehelper.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/shared/qwaylandmimehelper.cpp b/src/shared/qwaylandmimehelper.cpp
|
||||
index a5fdd34d..051a91dc 100644
|
||||
--- a/src/shared/qwaylandmimehelper.cpp
|
||||
+++ b/src/shared/qwaylandmimehelper.cpp
|
||||
@@ -60,7 +60,7 @@ QByteArray QWaylandMimeHelper::getByteArray(QMimeData *mimeData, const QString &
|
||||
buf.open(QIODevice::ReadWrite);
|
||||
QByteArray fmt = "BMP";
|
||||
if (mimeType.startsWith(QLatin1String("image/"))) {
|
||||
- QByteArray imgFmt = mimeType.mid(6).toUpper().toLatin1();
|
||||
+ QByteArray imgFmt = mimeType.mid(6).toLower().toLatin1();
|
||||
if (QImageWriter::supportedImageFormats().contains(imgFmt))
|
||||
fmt = imgFmt;
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 8d673fe2edebe2c5bf338a779ef22ae212dc244a 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 18/40] Wayland client: Fix crash when windows are shown/hidden
|
||||
during drag
|
||||
|
||||
Fixes: QTBUG-87624
|
||||
Pick-to: 6.2 5.15
|
||||
Change-Id: I1b9443df091878abcd4fbe9c55927cb819aebd59
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
(cherry picked from commit c64c5d3849b40617e1de0295f8690f354cab2b3a)
|
||||
---
|
||||
src/client/qwaylanddatadevice.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
|
||||
index 54a69c3c..bbd2d568 100644
|
||||
--- a/src/client/qwaylanddatadevice.cpp
|
||||
+++ b/src/client/qwaylanddatadevice.cpp
|
||||
@@ -169,7 +169,7 @@ void QWaylandDataDevice::data_device_drop()
|
||||
|
||||
void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
|
||||
{
|
||||
- auto *dragWaylandWindow = QWaylandWindow::fromWlSurface(surface);
|
||||
+ auto *dragWaylandWindow = surface ? QWaylandWindow::fromWlSurface(surface) : nullptr;
|
||||
if (!dragWaylandWindow)
|
||||
return; // Ignore foreign surfaces
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
77
0019-Client-Don-t-always-recreate-frame-callbacks.patch
Normal file
77
0019-Client-Don-t-always-recreate-frame-callbacks.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From bdd2dacf2d8668b3a1f59db3c6cc859f95868eb2 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 19/40] 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
|
||||
a frame callback, regardless of whether any other one is already queued.
|
||||
|
||||
On some circumstances, e.g. when a window is hidden or completely obscured
|
||||
by other windows, it stops receiving frame callbacks from the compositor.
|
||||
However, QWaylandWindow would continue to request for them, which eventually
|
||||
fills up the Wayland socket, and causes the application to crash.
|
||||
|
||||
This can be avoided by checking if the platform window is already waiting
|
||||
for a frame callback, before queueing another one.
|
||||
|
||||
In QWaylandWindow::handleUpdate(), check if mWaitingForFrameCallback is true
|
||||
before queueing frame callbacks, and early return if that's the case.
|
||||
|
||||
The XDG-shell test needed to be updated for this: The mock compositor is
|
||||
not responding to any frame callbacks, so the window will be unexposed,
|
||||
no longer get paint events and therefore not trigger any commit. This
|
||||
worked by accident before because we were issuing updates quickly enough
|
||||
to reset the timer before it had a chance to unexpose the window. The
|
||||
easiest fix is just to disable the dependency on frame callbacks in
|
||||
this test, since that is clearly not what it's testing.
|
||||
|
||||
Task-number: QTBUG-81504
|
||||
Change-Id: Ieacb05c7d5a5fcf662243d9177ebcc308cb9ca84
|
||||
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
||||
Reviewed-by: Georges Basile Stavracas Neto <gbsneto@gnome.org>
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
(cherry picked from commit cbc74ba6d7186457d8d07183272e952dee5f34f9)
|
||||
---
|
||||
src/client/qwaylandwindow.cpp | 4 ++++
|
||||
tests/auto/client/xdgshell/tst_xdgshell.cpp | 2 ++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index bd70f4af..85307875 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -1170,6 +1170,10 @@ void QWaylandWindow::requestUpdate()
|
||||
void QWaylandWindow::handleUpdate()
|
||||
{
|
||||
qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
|
||||
+
|
||||
+ if (mWaitingForFrameCallback)
|
||||
+ return;
|
||||
+
|
||||
// TODO: Should sync subsurfaces avoid requesting frame callbacks?
|
||||
QReadLocker lock(&mSurfaceLock);
|
||||
if (!mSurface)
|
||||
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
index 2fdd0a7c..e2593314 100644
|
||||
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
@@ -138,6 +138,7 @@ void tst_xdgshell::configureSize()
|
||||
|
||||
void tst_xdgshell::configureStates()
|
||||
{
|
||||
+ QVERIFY(qputenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", "0"));
|
||||
QRasterWindow window;
|
||||
window.resize(64, 48);
|
||||
window.show();
|
||||
@@ -186,6 +187,7 @@ void tst_xdgshell::configureStates()
|
||||
QCOMPARE(window.windowStates(), Qt::WindowNoState);
|
||||
QCOMPARE(window.frameGeometry().size(), windowedSize);
|
||||
// QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
|
||||
+ QVERIFY(qunsetenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT"));
|
||||
}
|
||||
|
||||
void tst_xdgshell::popup()
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,58 @@
|
||||
From fb0a5265ec9d83b56563769cc1b756aeca42ce65 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 20/40] Client: Always destroy frame callback in the actual
|
||||
callback
|
||||
|
||||
It's good hygiene to destroy all frame callbacks. Destroy the
|
||||
frame callback and cleanup the mFrameCallback class member in
|
||||
the callback itself. The callback destruction happens before
|
||||
calling handleFrameCallback() to avoid the theoretical case
|
||||
where another frame callback is queued by handleFrameCallback(),
|
||||
and then immediately destroyed in the callback handler.
|
||||
|
||||
* asturmlechner 2021-09-27:
|
||||
Conflict resolved from non-backported commit in dev branch:
|
||||
93058de8d7e7c2f320c22b3bd898aa06cf5babcd
|
||||
|
||||
Change-Id: Ide6dc95e3402932c58bfc088a9d471fda821e9a1
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
(cherry picked from commit 42cdc61a93cf2acb09936aebb5e431fdbc0a26c6)
|
||||
---
|
||||
src/client/qwaylandwindow.cpp | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index 85307875..c020a58f 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -622,9 +622,13 @@ void QWaylandWindow::commit()
|
||||
|
||||
const wl_callback_listener QWaylandWindow::callbackListener = {
|
||||
[](void *data, wl_callback *callback, uint32_t time) {
|
||||
- Q_UNUSED(callback);
|
||||
Q_UNUSED(time);
|
||||
auto *window = static_cast<QWaylandWindow*>(data);
|
||||
+
|
||||
+ Q_ASSERT(callback == window->mFrameCallback);
|
||||
+ wl_callback_destroy(callback);
|
||||
+ window->mFrameCallback = nullptr;
|
||||
+
|
||||
window->handleFrameCallback();
|
||||
}
|
||||
};
|
||||
@@ -1179,11 +1183,6 @@ void QWaylandWindow::handleUpdate()
|
||||
if (!mSurface)
|
||||
return;
|
||||
|
||||
- if (mFrameCallback) {
|
||||
- wl_callback_destroy(mFrameCallback);
|
||||
- mFrameCallback = nullptr;
|
||||
- }
|
||||
-
|
||||
QMutexLocker locker(mFrameQueue.mutex);
|
||||
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.35.1
|
||||
|
@ -0,0 +1,40 @@
|
||||
From 1e0519c6465335dd380ad8d8209969c71eb78d48 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 21/40] 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
|
||||
the compositor, instead of modifying the map in the for loop conditional.
|
||||
|
||||
[ChangeLog][QWaylandInputContext] Fix modifiers map decoding
|
||||
logic when receiving the map from the compositor.
|
||||
|
||||
Fixes: QTBUG-97094
|
||||
Pick-to: 6.2 5.15 5.12
|
||||
Change-Id: Idad19f7b1f4560d40abbb5b31032360cfe915261
|
||||
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
|
||||
---
|
||||
src/client/qwaylandinputcontext.cpp | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
|
||||
index 503fd735..e290baa2 100644
|
||||
--- a/src/client/qwaylandinputcontext.cpp
|
||||
+++ b/src/client/qwaylandinputcontext.cpp
|
||||
@@ -387,8 +387,10 @@ void QWaylandTextInput::zwp_text_input_v2_input_method_changed(uint32_t serial,
|
||||
Qt::KeyboardModifiers QWaylandTextInput::modifiersToQtModifiers(uint32_t modifiers)
|
||||
{
|
||||
Qt::KeyboardModifiers ret = Qt::NoModifier;
|
||||
- for (int i = 0; modifiers >>= 1; ++i) {
|
||||
- ret |= m_modifiersMap[i];
|
||||
+ for (int i = 0; i < m_modifiersMap.size(); ++i) {
|
||||
+ if (modifiers & (1 << i)) {
|
||||
+ ret |= m_modifiersMap[i];
|
||||
+ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
341
0022-Wayland-client-use-wl_keyboard-to-determine-active-s.patch
Normal file
341
0022-Wayland-client-use-wl_keyboard-to-determine-active-s.patch
Normal file
@ -0,0 +1,341 @@
|
||||
From 64e133f830ce48b6732397325b768ed9193c2cb4 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 22/40] Wayland client: use wl_keyboard to determine active
|
||||
state
|
||||
|
||||
Commit f497a5bb87270174b8e0106b7eca1992d44ff15d made QWaylandDisplay
|
||||
use the xdgshell's active state for QWindow::isActive(), instead of
|
||||
using wl_keyboard activate/deactivate events.
|
||||
|
||||
That seems to have been a misunderstanding, since xdgshell activation
|
||||
is only supposed to be used to determine visual appearance, and there
|
||||
is an explicit warning not to assume it means focus.
|
||||
|
||||
This commit reverts this logic back to listening to wl_keyboard.
|
||||
It adds a fallback when there is no wl_keyboard available to handle
|
||||
activated/deactivated events through xdg-shell, in order to fix
|
||||
QTBUG-53702.
|
||||
|
||||
windowStates is handled so that we're not using the Xdg hint for
|
||||
anything with QWindowSystemInterface::handleWindowStateChanged or
|
||||
anything where we need to track only having one active.
|
||||
|
||||
We are still exposing it for decorations, which is the only reason to
|
||||
use the Xdghint over keyboard focus - so you can keep the toplevel
|
||||
active whilst you show a popup.
|
||||
|
||||
cherry-pick 40036a1b80e5234e6db7d5cbeff122aa7ee13e20
|
||||
|
||||
Change-Id: I4343d2ed9fb5b066cde95628ed0b4ccc84a424db
|
||||
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
---
|
||||
src/client/qwaylanddisplay.cpp | 19 +++++++++++--------
|
||||
src/client/qwaylanddisplay_p.h | 1 +
|
||||
src/client/qwaylandwindow.cpp | 13 +++++++++++--
|
||||
src/client/qwaylandwindow_p.h | 1 +
|
||||
.../qwaylandshellintegration_p.h | 7 +++----
|
||||
.../qwaylandxdgshellv5integration.cpp | 7 -------
|
||||
.../qwaylandxdgshellv5integration_p.h | 1 -
|
||||
.../qwaylandxdgshellv6integration.cpp | 14 --------------
|
||||
.../qwaylandxdgshellv6integration_p.h | 1 -
|
||||
.../xdg-shell/qwaylandxdgshell.cpp | 16 +++++-----------
|
||||
.../xdg-shell/qwaylandxdgshellintegration.cpp | 14 --------------
|
||||
.../xdg-shell/qwaylandxdgshellintegration_p.h | 1 -
|
||||
tests/auto/client/xdgshell/tst_xdgshell.cpp | 10 +++++++---
|
||||
13 files changed, 39 insertions(+), 66 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
||||
index e0dfe8b2..27303110 100644
|
||||
--- a/src/client/qwaylanddisplay.cpp
|
||||
+++ b/src/client/qwaylanddisplay.cpp
|
||||
@@ -575,14 +575,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
|
||||
if (mLastKeyboardFocus == keyboardFocus)
|
||||
return;
|
||||
|
||||
- if (mWaylandIntegration->mShellIntegration) {
|
||||
- mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus);
|
||||
- } else {
|
||||
- if (keyboardFocus)
|
||||
- handleWindowActivated(keyboardFocus);
|
||||
- if (mLastKeyboardFocus)
|
||||
- handleWindowDeactivated(mLastKeyboardFocus);
|
||||
- }
|
||||
+ if (keyboardFocus)
|
||||
+ handleWindowActivated(keyboardFocus);
|
||||
+ if (mLastKeyboardFocus)
|
||||
+ handleWindowDeactivated(mLastKeyboardFocus);
|
||||
|
||||
mLastKeyboardFocus = keyboardFocus;
|
||||
}
|
||||
@@ -627,6 +623,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
|
||||
return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
|
||||
}
|
||||
|
||||
+bool QWaylandDisplay::isKeyboardAvailable() const
|
||||
+{
|
||||
+ return std::any_of(
|
||||
+ mInputDevices.constBegin(), mInputDevices.constEnd(),
|
||||
+ [this](const QWaylandInputDevice *device) { return device->keyboard() != nullptr; });
|
||||
+}
|
||||
+
|
||||
#if QT_CONFIG(cursor)
|
||||
|
||||
QWaylandCursor *QWaylandDisplay::waylandCursor()
|
||||
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
|
||||
index 3b092bc8..09a1736a 100644
|
||||
--- a/src/client/qwaylanddisplay_p.h
|
||||
+++ b/src/client/qwaylanddisplay_p.h
|
||||
@@ -215,6 +215,7 @@ public:
|
||||
void destroyFrameQueue(const FrameQueue &q);
|
||||
void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
|
||||
|
||||
+ bool isKeyboardAvailable() const;
|
||||
public slots:
|
||||
void blockingReadEvents();
|
||||
void flushRequests();
|
||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||
index c020a58f..ba881cb3 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -96,7 +96,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
|
||||
QWaylandWindow::~QWaylandWindow()
|
||||
{
|
||||
mDisplay->destroyFrameQueue(mFrameQueue);
|
||||
- mDisplay->handleWindowDestroyed(this);
|
||||
|
||||
delete mWindowDecoration;
|
||||
|
||||
@@ -266,6 +265,8 @@ void QWaylandWindow::reset()
|
||||
|
||||
mMask = QRegion();
|
||||
mQueuedBuffer = nullptr;
|
||||
+
|
||||
+ mDisplay->handleWindowDestroyed(this);
|
||||
}
|
||||
|
||||
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
|
||||
@@ -1083,10 +1084,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
||||
return true;
|
||||
}
|
||||
|
||||
+Qt::WindowStates QWaylandWindow::windowStates() const
|
||||
+{
|
||||
+ return mLastReportedWindowStates;
|
||||
+}
|
||||
+
|
||||
void QWaylandWindow::handleWindowStatesChanged(Qt::WindowStates states)
|
||||
{
|
||||
createDecoration();
|
||||
- QWindowSystemInterface::handleWindowStateChanged(window(), states, mLastReportedWindowStates);
|
||||
+ Qt::WindowStates statesWithoutActive = states & ~Qt::WindowActive;
|
||||
+ Qt::WindowStates lastStatesWithoutActive = mLastReportedWindowStates & ~Qt::WindowActive;
|
||||
+ QWindowSystemInterface::handleWindowStateChanged(window(), statesWithoutActive,
|
||||
+ lastStatesWithoutActive);
|
||||
mLastReportedWindowStates = states;
|
||||
}
|
||||
|
||||
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||
index 6cc1664b..e0687962 100644
|
||||
--- a/src/client/qwaylandwindow_p.h
|
||||
+++ b/src/client/qwaylandwindow_p.h
|
||||
@@ -148,6 +148,7 @@ public:
|
||||
void setWindowState(Qt::WindowStates states) override;
|
||||
void setWindowFlags(Qt::WindowFlags flags) override;
|
||||
void handleWindowStatesChanged(Qt::WindowStates states);
|
||||
+ Qt::WindowStates windowStates() const;
|
||||
|
||||
void raise() override;
|
||||
void lower() override;
|
||||
diff --git a/src/client/shellintegration/qwaylandshellintegration_p.h b/src/client/shellintegration/qwaylandshellintegration_p.h
|
||||
index ccad0048..4cc9b3b8 100644
|
||||
--- a/src/client/shellintegration/qwaylandshellintegration_p.h
|
||||
+++ b/src/client/shellintegration/qwaylandshellintegration_p.h
|
||||
@@ -73,11 +73,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0;
|
||||
+ // kept for binary compat with layer-shell-qt
|
||||
virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
|
||||
- if (newFocus)
|
||||
- m_display->handleWindowActivated(newFocus);
|
||||
- if (oldFocus)
|
||||
- m_display->handleWindowDeactivated(oldFocus);
|
||||
+ Q_UNUSED(newFocus);
|
||||
+ Q_UNUSED(oldFocus);
|
||||
}
|
||||
virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) {
|
||||
Q_UNUSED(resource);
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
|
||||
index 4e25949f..cfc60939 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
|
||||
@@ -85,13 +85,6 @@ QWaylandShellSurface *QWaylandXdgShellV5Integration::createShellSurface(QWayland
|
||||
return m_xdgShell->createXdgSurface(window);
|
||||
}
|
||||
|
||||
-void QWaylandXdgShellV5Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {
|
||||
- if (newFocus && qobject_cast<QWaylandXdgPopupV5 *>(newFocus->shellSurface()))
|
||||
- m_display->handleWindowActivated(newFocus);
|
||||
- if (oldFocus && qobject_cast<QWaylandXdgPopupV5 *>(oldFocus->shellSurface()))
|
||||
- m_display->handleWindowDeactivated(oldFocus);
|
||||
-}
|
||||
-
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
|
||||
index ce6bdb9e..aed88670 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
|
||||
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration_p.h
|
||||
@@ -67,7 +67,6 @@ public:
|
||||
QWaylandXdgShellV5Integration() {}
|
||||
bool initialize(QWaylandDisplay *display) override;
|
||||
QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
|
||||
- void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
|
||||
|
||||
private:
|
||||
QScopedPointer<QWaylandXdgShellV5> m_xdgShell;
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
|
||||
index 03164316..e8da8ba1 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
|
||||
@@ -68,20 +68,6 @@ QWaylandShellSurface *QWaylandXdgShellV6Integration::createShellSurface(QWayland
|
||||
return m_xdgShell->getXdgSurface(window);
|
||||
}
|
||||
|
||||
-void QWaylandXdgShellV6Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
|
||||
-{
|
||||
- if (newFocus) {
|
||||
- auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(newFocus->shellSurface());
|
||||
- if (xdgSurface && !xdgSurface->handlesActiveState())
|
||||
- m_display->handleWindowActivated(newFocus);
|
||||
- }
|
||||
- if (oldFocus && qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface())) {
|
||||
- auto *xdgSurface = qobject_cast<QWaylandXdgSurfaceV6 *>(oldFocus->shellSurface());
|
||||
- if (xdgSurface && !xdgSurface->handlesActiveState())
|
||||
- m_display->handleWindowDeactivated(oldFocus);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
|
||||
index 261f8cbb..c1bcd5c6 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
|
||||
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration_p.h
|
||||
@@ -65,7 +65,6 @@ public:
|
||||
QWaylandXdgShellV6Integration() {}
|
||||
bool initialize(QWaylandDisplay *display) override;
|
||||
QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
|
||||
- void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
|
||||
|
||||
private:
|
||||
QScopedPointer<QWaylandXdgShellV6> m_xdgShell;
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
index 7d33dabd..d7d0ddf7 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
|
||||
@@ -67,11 +67,6 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
|
||||
|
||||
QWaylandXdgSurface::Toplevel::~Toplevel()
|
||||
{
|
||||
- if (m_applied.states & Qt::WindowActive) {
|
||||
- QWaylandWindow *window = m_xdgSurface->window();
|
||||
- window->display()->handleWindowDeactivated(window);
|
||||
- }
|
||||
-
|
||||
// The protocol spec requires that the decoration object is deleted before xdg_toplevel.
|
||||
delete m_decoration;
|
||||
m_decoration = nullptr;
|
||||
@@ -85,16 +80,15 @@ void QWaylandXdgSurface::Toplevel::applyConfigure()
|
||||
if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen)))
|
||||
m_normalSize = m_xdgSurface->m_window->windowFrameGeometry().size();
|
||||
|
||||
- if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive))
|
||||
+ if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive)
|
||||
+ && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
|
||||
m_xdgSurface->m_window->display()->handleWindowActivated(m_xdgSurface->m_window);
|
||||
|
||||
- if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive))
|
||||
+ if (!(m_pending.states & Qt::WindowActive) && (m_applied.states & Qt::WindowActive)
|
||||
+ && !m_xdgSurface->m_window->display()->isKeyboardAvailable())
|
||||
m_xdgSurface->m_window->display()->handleWindowDeactivated(m_xdgSurface->m_window);
|
||||
|
||||
- // TODO: none of the other plugins send WindowActive either, but is it on purpose?
|
||||
- Qt::WindowStates statesWithoutActive = m_pending.states & ~Qt::WindowActive;
|
||||
-
|
||||
- m_xdgSurface->m_window->handleWindowStatesChanged(statesWithoutActive);
|
||||
+ m_xdgSurface->m_window->handleWindowStatesChanged(m_pending.states);
|
||||
|
||||
if (m_pending.size.isEmpty()) {
|
||||
// An empty size in the configure means it's up to the client to choose the size
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
|
||||
index 8769d971..da0dd6a7 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
|
||||
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
|
||||
@@ -69,20 +69,6 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi
|
||||
return m_xdgShell->getXdgSurface(window);
|
||||
}
|
||||
|
||||
-void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus)
|
||||
-{
|
||||
- if (newFocus) {
|
||||
- auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(newFocus->shellSurface());
|
||||
- if (xdgSurface && !xdgSurface->handlesActiveState())
|
||||
- m_display->handleWindowActivated(newFocus);
|
||||
- }
|
||||
- if (oldFocus && qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface())) {
|
||||
- auto *xdgSurface = qobject_cast<QWaylandXdgSurface *>(oldFocus->shellSurface());
|
||||
- if (xdgSurface && !xdgSurface->handlesActiveState())
|
||||
- m_display->handleWindowDeactivated(oldFocus);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
|
||||
index b6caa6c9..2f929f98 100644
|
||||
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
|
||||
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration_p.h
|
||||
@@ -65,7 +65,6 @@ public:
|
||||
QWaylandXdgShellIntegration() {}
|
||||
bool initialize(QWaylandDisplay *display) override;
|
||||
QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
|
||||
- void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) override;
|
||||
|
||||
private:
|
||||
QScopedPointer<QWaylandXdgShell> m_xdgShell;
|
||||
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
index e2593314..73d1eb9c 100644
|
||||
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <QtGui/QOpenGLWindow>
|
||||
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||
#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
|
||||
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
|
||||
|
||||
using namespace MockCompositor;
|
||||
|
||||
@@ -155,9 +156,12 @@ void tst_xdgshell::configureStates()
|
||||
// Toplevel windows don't know their position on xdg-shell
|
||||
// QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
|
||||
|
||||
-// QEXPECT_FAIL("", "configure has already been acked, we shouldn't have to wait for isActive", Continue);
|
||||
-// QVERIFY(window.isActive());
|
||||
- QTRY_VERIFY(window.isActive()); // Just make sure it eventually get's set correctly
|
||||
+ // window.windowstate() is driven by keyboard focus, however for decorations we want to follow
|
||||
+ // XDGShell this is internal to QtWayland so it is queried directly
|
||||
+ auto waylandWindow = static_cast<QtWaylandClient::QWaylandWindow *>(window.handle());
|
||||
+ Q_ASSERT(waylandWindow);
|
||||
+ QTRY_VERIFY(waylandWindow->windowStates().testFlag(
|
||||
+ Qt::WindowActive)); // Just make sure it eventually get's set correctly
|
||||
|
||||
const QSize screenSize(640, 480);
|
||||
const uint maximizedSerial = exec([=] {
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 167a89d23d4db6f62ef8336002fe306829604a77 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Fri, 16 Jul 2021 13:00:03 +0200
|
||||
Subject: [PATCH 23/40] 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
|
||||
invalidating selection offer when losing focus, because it's still the
|
||||
same client who has the focus and we might not get a new selection offer
|
||||
by the compositor and therefore we would lose clipboard content.
|
||||
|
||||
Fixes: QTBUG-93474
|
||||
Change-Id: Ia2ef826c2967b1daf1cdeb085e8dae66d090dbcf
|
||||
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
|
||||
Reviewed-by: David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
Cherry-pick: 1e57ebd501cfc2255300392cd4565cd034efeed8
|
||||
---
|
||||
src/client/qwaylanddisplay.cpp | 13 +++++++++++++
|
||||
src/client/qwaylandinputdevice.cpp | 8 --------
|
||||
2 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
||||
index 27303110..9f595af3 100644
|
||||
--- a/src/client/qwaylanddisplay.cpp
|
||||
+++ b/src/client/qwaylanddisplay.cpp
|
||||
@@ -597,6 +597,19 @@ void QWaylandDisplay::handleWaylandSync()
|
||||
QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
|
||||
if (activeWindow != QGuiApplication::focusWindow())
|
||||
QWindowSystemInterface::handleWindowActivated(activeWindow);
|
||||
+
|
||||
+ if (!activeWindow) {
|
||||
+ if (lastInputDevice()) {
|
||||
+#if QT_CONFIG(clipboard)
|
||||
+ if (auto *dataDevice = lastInputDevice()->dataDevice())
|
||||
+ dataDevice->invalidateSelectionOffer();
|
||||
+#endif
|
||||
+#if QT_CONFIG(wayland_client_primary_selection)
|
||||
+ if (auto *device = lastInputDevice()->primarySelectionDevice())
|
||||
+ device->invalidateSelectionOffer();
|
||||
+#endif
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
|
||||
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
|
||||
index ae045f4f..514457e9 100644
|
||||
--- a/src/client/qwaylandinputdevice.cpp
|
||||
+++ b/src/client/qwaylandinputdevice.cpp
|
||||
@@ -1300,14 +1300,6 @@ void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
|
||||
void QWaylandInputDevice::Keyboard::handleFocusLost()
|
||||
{
|
||||
mFocus = nullptr;
|
||||
-#if QT_CONFIG(clipboard)
|
||||
- if (auto *dataDevice = mParent->dataDevice())
|
||||
- dataDevice->invalidateSelectionOffer();
|
||||
-#endif
|
||||
-#if QT_CONFIG(wayland_client_primary_selection)
|
||||
- if (auto *device = mParent->primarySelectionDevice())
|
||||
- device->invalidateSelectionOffer();
|
||||
-#endif
|
||||
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
|
||||
mRepeatTimer.stop();
|
||||
}
|
||||
--
|
||||
2.35.1
|
||||
|
29
0024-Set-preedit-cursor-when-cursor-equals-to-0.patch
Normal file
29
0024-Set-preedit-cursor-when-cursor-equals-to-0.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From 5ea11ccde21448f5c61978bf52e2f3db79a7143c Mon Sep 17 00:00:00 2001
|
||||
From: Weng Xuetian <wengxt@gmail.com>
|
||||
Date: Sat, 18 Dec 2021 23:42:49 -0800
|
||||
Subject: [PATCH 24/40] 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
|
||||
|
513
0025-Client-Implement-DataDeviceV3.patch
Normal file
513
0025-Client-Implement-DataDeviceV3.patch
Normal file
@ -0,0 +1,513 @@
|
||||
From 95783492ae8df7f84c3c13351df5dc114288e96e Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Tue, 16 Feb 2021 09:51:47 +0000
|
||||
Subject: [PATCH 25/40] 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
|
||||
|
@ -0,0 +1,67 @@
|
||||
From 8c9e148bb0aa25cbc831e2bd931d3bd54bc0fb46 Mon Sep 17 00:00:00 2001
|
||||
From: Arjen Hiemstra <ahiemstra@heimr.nl>
|
||||
Date: Thu, 18 Nov 2021 13:05:30 +0100
|
||||
Subject: [PATCH 26/40] 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
|
||||
|
@ -0,0 +1,38 @@
|
||||
From b736b4488dcaa1a3c6b0c6059e5b85881f74c52b Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Sun, 14 Nov 2021 13:54:19 +0000
|
||||
Subject: [PATCH 27/40] 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
|
||||
|
85
0028-Handle-registry_global-out-of-constructor.patch
Normal file
85
0028-Handle-registry_global-out-of-constructor.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From 771705eee02b4d752beee22ef5408ccbd72078cc 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 28/40] 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
|
||||
|
47
0029-Connect-flushRequest-after-forceRoundTrip.patch
Normal file
47
0029-Connect-flushRequest-after-forceRoundTrip.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 725c5de6bdd528d1fa03f1de5ec91585eb110d83 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 29/40] 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
|
||||
|
574
0030-Move-the-wayland-socket-polling-to-a-separate-event-.patch
Normal file
574
0030-Move-the-wayland-socket-polling-to-a-separate-event-.patch
Normal file
@ -0,0 +1,574 @@
|
||||
From 91d36a2497f3289996d788c8974583bccac3c842 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 30/40] 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
|
||||
|
30
0031-Check-pointer-for-null-before-use-in-ASSERT.patch
Normal file
30
0031-Check-pointer-for-null-before-use-in-ASSERT.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From ca1d9023b6d40a128faad652f02881b5805e36ba 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 31/40] 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
|
||||
|
@ -0,0 +1,39 @@
|
||||
From e6b30f42f8eec2ecc10395593dbfff354acd5425 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 32/40] 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
|
||||
|
131
0033-Use-wl_surface.damage_buffer-on-the-client-side.patch
Normal file
131
0033-Use-wl_surface.damage_buffer-on-the-client-side.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From 3027c9659866101c06252829d99e7597cef19a40 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 33/40] 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
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 297c4e075068bffe4a396b2553afc4798c97fb4c 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 34/40] 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
|
||||
|
79
0035-Client-Remove-mWaitingForUpdateDelivery.patch
Normal file
79
0035-Client-Remove-mWaitingForUpdateDelivery.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From a97759d032a40045551546ca17300891d4067ee4 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 35/40] 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
|
||||
|
35
0036-Cursor-position-0-should-still-show-the-cursor.patch
Normal file
35
0036-Cursor-position-0-should-still-show-the-cursor.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From d3b794920d643fc5d722f63ad52b91e8143c0de0 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Xuetian <wengxt@gmail.com>
|
||||
Date: Tue, 8 Feb 2022 07:11:25 -0800
|
||||
Subject: [PATCH 36/40] 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
|
||||
|
88
0037-Update-the-preedit-styling-mapping.patch
Normal file
88
0037-Update-the-preedit-styling-mapping.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From 3ddd4dcb1790920ce2598ebdbe14c95bdba55005 Mon Sep 17 00:00:00 2001
|
||||
From: Weng Xuetian <wengxt@gmail.com>
|
||||
Date: Wed, 22 Dec 2021 10:42:38 -0800
|
||||
Subject: [PATCH 37/40] 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
|
||||
|
82
0038-client-Simplify-round-trip-behavior.patch
Normal file
82
0038-client-Simplify-round-trip-behavior.patch
Normal file
@ -0,0 +1,82 @@
|
||||
From 971dbf2d5be743ddeb998f7461ff3e06ccb892c4 Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Wed, 9 Feb 2022 17:20:48 +0000
|
||||
Subject: [PATCH 38/40] 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
|
||||
|
31
0039-Client-Fix-opaque-region-setter.patch
Normal file
31
0039-Client-Fix-opaque-region-setter.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 9930ed9942d2d26211195571673bea35261ad26b Mon Sep 17 00:00:00 2001
|
||||
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Date: Sat, 19 Feb 2022 17:01:04 +0200
|
||||
Subject: [PATCH 39/40] Client: Fix opaque region setter
|
||||
|
||||
The rect is in the global coordinate system, while the opaque region
|
||||
must be in the surface local coordinate system.
|
||||
|
||||
Change-Id: I75042b4d779dfd4dfe610aad1f0387879f11b048
|
||||
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
(cherry picked from commit f9425f573b18c0b66fd9ad9c2805e8b8b9a3ec77)
|
||||
---
|
||||
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 949374b1..fee2ecdd 100644
|
||||
--- a/src/client/qwaylandwindow.cpp
|
||||
+++ b/src/client/qwaylandwindow.cpp
|
||||
@@ -372,7 +372,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
|
||||
mShellSurface->setWindowGeometry(windowContentGeometry());
|
||||
|
||||
if (isOpaque() && mMask.isEmpty())
|
||||
- setOpaqueArea(rect);
|
||||
+ setOpaqueArea(QRect(QPoint(0, 0), rect.size()));
|
||||
}
|
||||
|
||||
void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
|
||||
--
|
||||
2.35.1
|
||||
|
126
0040-Use-proper-dependencies-in-compile-tests.patch
Normal file
126
0040-Use-proper-dependencies-in-compile-tests.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 118674630cdb5933e66a8b4415afe7c716ad4662 Mon Sep 17 00:00:00 2001
|
||||
From: Fabian Vogt <fabian@ritter-vogt.de>
|
||||
Date: Fri, 4 Feb 2022 11:07:36 +0100
|
||||
Subject: [PATCH 40/40] Use proper dependencies in compile tests
|
||||
|
||||
Use the dependencies as found by the "libraries" section instead of relying
|
||||
on them being available in the default location (e.g. "-ldrm").
|
||||
|
||||
Additionally, VK_USE_PLATFORM_WAYLAND_KHR requires <wayland-client.h>, so
|
||||
add the wayland-client dependency.
|
||||
|
||||
This fixes those tests if e.g. wayland-client headers need to be found through
|
||||
pkgconfig.
|
||||
|
||||
This part of the code changed completely in Qt 6, so this is a totally
|
||||
different patch and not a cherry-pick of 5fc2e1915c3a
|
||||
("CMake: Fix qtwayland feature detection").
|
||||
|
||||
Fixes: QTBUG-100475
|
||||
---
|
||||
src/client/configure.json | 8 ++++----
|
||||
src/compositor/configure.json | 34 +++++++++++++++++++++++++++++-----
|
||||
2 files changed, 33 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/client/configure.json b/src/client/configure.json
|
||||
index 2f424580..29222357 100644
|
||||
--- a/src/client/configure.json
|
||||
+++ b/src/client/configure.json
|
||||
@@ -149,8 +149,7 @@
|
||||
"#endif"
|
||||
]
|
||||
},
|
||||
- "libs": "-ldrm",
|
||||
- "use": "egl"
|
||||
+ "use": "drm egl"
|
||||
},
|
||||
"vulkan-server-buffer": {
|
||||
"label": "Vulkan Buffer Sharing",
|
||||
@@ -168,7 +167,8 @@
|
||||
"exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
|
||||
"return 0;"
|
||||
]
|
||||
- }
|
||||
+ },
|
||||
+ "use": "wayland-client"
|
||||
},
|
||||
"egl_1_5-wayland": {
|
||||
"label": "EGL 1.5 with Wayland Platform",
|
||||
@@ -183,7 +183,7 @@
|
||||
"eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, (struct wl_display *)(nullptr), nullptr);"
|
||||
]
|
||||
},
|
||||
- "use": "egl"
|
||||
+ "use": "egl wayland-client"
|
||||
}
|
||||
},
|
||||
|
||||
diff --git a/src/compositor/configure.json b/src/compositor/configure.json
|
||||
index bcfd5215..da95d07b 100644
|
||||
--- a/src/compositor/configure.json
|
||||
+++ b/src/compositor/configure.json
|
||||
@@ -7,6 +7,31 @@
|
||||
"testDir": "../../config.tests",
|
||||
|
||||
"libraries": {
|
||||
+ "wayland-client": {
|
||||
+ "label": "Wayland client library",
|
||||
+ "headers": "wayland-version.h",
|
||||
+ "test": {
|
||||
+ "main": [
|
||||
+ "#if WAYLAND_VERSION_MAJOR < 1",
|
||||
+ "# error Wayland 1.8.0 or higher required",
|
||||
+ "#endif",
|
||||
+ "#if WAYLAND_VERSION_MAJOR == 1",
|
||||
+ "# if WAYLAND_VERSION_MINOR < 8",
|
||||
+ "# error Wayland 1.8.0 or higher required",
|
||||
+ "# endif",
|
||||
+ "# if WAYLAND_VERSION_MINOR == 8",
|
||||
+ "# if WAYLAND_VERSION_MICRO < 0",
|
||||
+ "# error Wayland 1.8.0 or higher required",
|
||||
+ "# endif",
|
||||
+ "# endif",
|
||||
+ "#endif"
|
||||
+ ]
|
||||
+ },
|
||||
+ "sources": [
|
||||
+ { "type": "pkgConfig", "args": "wayland-client" },
|
||||
+ "-lwayland-client"
|
||||
+ ]
|
||||
+ },
|
||||
"wayland-server": {
|
||||
"label": "wayland-server",
|
||||
"headers": "wayland-version.h",
|
||||
@@ -151,8 +176,7 @@
|
||||
"#endif"
|
||||
]
|
||||
},
|
||||
- "libs": "-ldrm",
|
||||
- "use": "egl"
|
||||
+ "use": "drm egl"
|
||||
},
|
||||
"dmabuf-client-buffer": {
|
||||
"label": "Linux Client dma-buf Buffer Sharing",
|
||||
@@ -176,8 +200,7 @@
|
||||
"return 0;"
|
||||
]
|
||||
},
|
||||
- "libs": "-ldrm",
|
||||
- "use": "egl"
|
||||
+ "use": "drm egl"
|
||||
},
|
||||
"vulkan-server-buffer": {
|
||||
"label": "Vulkan Buffer Sharing",
|
||||
@@ -195,7 +218,8 @@
|
||||
"exportAllocInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;",
|
||||
"return 0;"
|
||||
]
|
||||
- }
|
||||
+ },
|
||||
+ "use": "wayland-client"
|
||||
}
|
||||
},
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
Loading…
Reference in New Issue
Block a user