qt6-wayland rebuild

This commit is contained in:
Rmys
2023-11-19 19:49:37 +03:00
parent 1adea4a5a4
commit fc19c254d4
14 changed files with 202 additions and 808 deletions
@@ -1,122 +0,0 @@
From 36974955d13578071387695adb13a47be33e4d32 Mon Sep 17 00:00:00 2001
From: David Edmundson <davidedmundson@kde.org>
Date: Thu, 28 Nov 2019 02:31:17 +0100
Subject: Avoid animating single frame cursors
Currently to determine if a cursor is animated or not we check the
cursor theme delay.
This doesn't work in practice as by default many cursor themes have a
delay of 50 set even if they don't animate.
This comes from xcursorgen which specifies a delay of 50ms if there
isn't anything set in the config.
(https://github.com/freedesktop/xcursorgen/blob/master/xcursorgen.c#L92)
Given many themes will have a delay we should also check the number of
images in a given cursor.
In order to do that without a double lookup QWaylandCursor needed to
return the native wl_cursor, not wl_cursor_image and move the relevant
logic.
Change-Id: Ie782ace8054910ae76e61cab33ceca0377194929
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
---
src/client/qwaylandcursor.cpp | 12 ++----------
src/client/qwaylandcursor_p.h | 3 +--
src/client/qwaylandinputdevice.cpp | 16 ++++++++++++----
3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
index 4356b23a..1d3d88be 100644
--- a/src/client/qwaylandcursor.cpp
+++ b/src/client/qwaylandcursor.cpp
@@ -219,7 +219,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
-::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation)
+::wl_cursor *QWaylandCursorTheme::cursor(Qt::CursorShape shape)
{
struct wl_cursor *waylandCursor = nullptr;
@@ -237,15 +237,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
return nullptr;
}
- int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation);
- ::wl_cursor_image *image = waylandCursor->images[frame];
- ::wl_buffer *buffer = wl_cursor_image_get_buffer(image);
- if (!buffer) {
- qCWarning(lcQpaWayland) << "Could not find buffer for cursor";
- return nullptr;
- }
-
- return image;
+ return waylandCursor;
}
QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h
index a4605f3d..751ffa68 100644
--- a/src/client/qwaylandcursor_p.h
+++ b/src/client/qwaylandcursor_p.h
@@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme
public:
static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName);
~QWaylandCursorTheme();
- ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0);
+ ::wl_cursor *cursor(Qt::CursorShape shape);
private:
enum WaylandCursor {
@@ -129,7 +129,6 @@ public:
void setPos(const QPoint &pos) override;
static QSharedPointer<QWaylandBuffer> cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor);
- struct wl_cursor_image *cursorImage(Qt::CursorShape shape);
private:
QWaylandDisplay *mDisplay = nullptr;
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index a4098edd..d812918e 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -283,8 +283,8 @@ void QWaylandInputDevice::Pointer::updateCursorTheme()
if (!mCursor.theme)
return; // A warning has already been printed in loadCursorTheme
- if (auto *arrow = mCursor.theme->cursorImage(Qt::ArrowCursor)) {
- int arrowPixelSize = qMax(arrow->width, arrow->height); // Not all cursor themes are square
+ if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) {
+ int arrowPixelSize = qMax(arrow->images[0]->width, arrow->images[0]->height); // Not all cursor themes are square
while (scale > 1 && arrowPixelSize / scale < cursorSize())
--scale;
} else {
@@ -326,12 +326,20 @@ void QWaylandInputDevice::Pointer::updateCursor()
// Set from shape using theme
uint time = seat()->mCursor.animationTimer.elapsed();
- if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) {
+
+ if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
+ int frame = wl_cursor_frame(waylandCursor, time);
+ ::wl_cursor_image *image = waylandCursor->images[frame];
+
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer) {
+ qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape;
+ return;
+ }
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- bool animated = image->delay > 0;
+ bool animated = waylandCursor->image_count > 1 && image->delay > 0;
getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
--
cgit v1.2.1
@@ -1,125 +0,0 @@
From ce15889614f87b5986f997beffd2826471adfe51 Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
Date: Fri, 13 Dec 2019 22:15:32 +0100
Subject: Drive cursor animation with a timer
Using only wl_surface_frame callbacks to update the cursor does so much
more often than needed. In addition, at least GNOME and Weston fire the
callback for the cursor surface immediately, which ends up updating the
cursor at over 3000 Hz here.
Use wl_cursor_frame_and_duration to drive a single shot timer. This
function is also guaranteed to return 0 for single frame cursors, so we
can avoid starting the timer at all.
We wait for both the surface frame callback and the timer to fire before
updating the cursor for the next frame of animation. This reduces our
update rate to the frame rate of the cursor or the rate requested by the
compositor, whichever is lower.
Change-Id: I10277460ebe9b547ebaf7f73424b9ef17614107f
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
---
src/client/qwaylandinputdevice.cpp | 34 +++++++++++++++++++++++++++++++---
src/client/qwaylandinputdevice_p.h | 5 +++++
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 3b26dc42..3f0d61d6 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -143,6 +143,12 @@ QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const
QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
: mParent(seat)
{
+#if QT_CONFIG(cursor)
+ mCursor.frameTimer.setSingleShot(true);
+ mCursor.frameTimer.callOnTimeout([&]() {
+ cursorTimerCallback();
+ });
+#endif
}
QWaylandInputDevice::Pointer::~Pointer()
@@ -224,7 +230,7 @@ public:
if (animated) {
m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
Q_UNUSED(time);
- m_pointer->updateCursor();
+ m_pointer->cursorFrameCallback();
}));
}
commit();
@@ -328,7 +334,8 @@ void QWaylandInputDevice::Pointer::updateCursor()
uint time = seat()->mCursor.animationTimer.elapsed();
if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
- int frame = wl_cursor_frame(waylandCursor, time);
+ uint duration = 0;
+ int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration);
::wl_cursor_image *image = waylandCursor->images[frame];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
@@ -339,7 +346,12 @@ void QWaylandInputDevice::Pointer::updateCursor()
int bufferScale = mCursor.themeBufferScale;
QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
QSize size = QSize(image->width, image->height) / bufferScale;
- bool animated = waylandCursor->image_count > 1 && image->delay > 0;
+ bool animated = duration > 0;
+ if (animated) {
+ mCursor.gotFrameCallback = false;
+ mCursor.gotTimerCallback = false;
+ mCursor.frameTimer.start(duration);
+ }
getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
return;
}
@@ -354,6 +366,22 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface()
return mCursor.surface.get();
}
+void QWaylandInputDevice::Pointer::cursorTimerCallback()
+{
+ mCursor.gotTimerCallback = true;
+ if (mCursor.gotFrameCallback) {
+ updateCursor();
+ }
+}
+
+void QWaylandInputDevice::Pointer::cursorFrameCallback()
+{
+ mCursor.gotFrameCallback = true;
+ if (mCursor.gotTimerCallback) {
+ updateCursor();
+ }
+}
+
#endif // QT_CONFIG(cursor)
QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 60d6f2c1..a567c57b 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -286,6 +286,8 @@ public:
int idealCursorScale() const;
void updateCursorTheme();
void updateCursor();
+ void cursorTimerCallback();
+ void cursorFrameCallback();
CursorSurface *getOrCreateCursorSurface();
#endif
QWaylandInputDevice *seat() const { return mParent; }
@@ -325,6 +327,9 @@ public:
QWaylandCursorTheme *theme = nullptr;
int themeBufferScale = 0;
QScopedPointer<CursorSurface> surface;
+ QTimer frameTimer;
+ bool gotFrameCallback = false;
+ bool gotTimerCallback = false;
} mCursor;
#endif
QPointF mSurfacePos;
--
cgit v1.2.1
@@ -1,32 +0,0 @@
From c2105d8b7e16cc934b886537968228f6300bf4bc Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Fri, 8 Nov 2019 13:58:04 +0100
Subject: Fix compilation of linuxdmabuf compositor plugin
Mesa's eglext.h no longer includes eglmesaext.h, so copy over the typedefs we need.
Fixes: QTBUG-79709
Change-Id: I3190ef56e0e162636efea440dff7e760cf11fcd0
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
---
.../compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
index 8554721e..02b5b6f8 100644
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
+++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
@@ -58,6 +58,10 @@
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
#endif
+// Copied from eglmesaext.h
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
+
QT_BEGIN_NAMESPACE
class QWaylandCompositor;
--
cgit v1.2.1
@@ -1,30 +0,0 @@
From a2be69d47884dd995ac6e9004ba2855f354f7522 Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
Date: Sun, 15 Dec 2019 00:07:08 +0100
Subject: Client: Fix detection of linux-dmabuf
Change I84c8c1008724b49b6bedb4fc3ef398e292f1c6c7 fixed the tests in
compositor/configure.json but missed the test in client/configure.json.
Change-Id: I65ad424406438baa74ca80a9418e133510142118
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
---
src/client/configure.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/client/configure.json b/src/client/configure.json
index e9e16324..06213968 100644
--- a/src/client/configure.json
+++ b/src/client/configure.json
@@ -74,7 +74,7 @@
"label": "Linux dma-buf Buffer Sharing",
"type": "compile",
"test": "dmabuf_server_buffer",
- "use": "egl"
+ "use": "egl drm"
},
"vulkan-server-buffer": {
"label": "Vulkan Buffer Sharing",
--
cgit v1.2.1
@@ -1,67 +0,0 @@
From 09861f0081e6729383808ac4803c7fd1f0ba6dd1 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Fri, 15 Nov 2019 11:52:46 +0100
Subject: Fix detection of linux-dmabuf
On some systems drm_fourcc.h is not in /usr/include, but in
/usr/include/libdrm, and that path can be found through pkg-config. This is
already done with the drm lib in qtbase/src/configure.json so this just tells
the test (and the plugins) to use the include paths for the existing "drm" lib.
Fixes: QTBUG-80075
Change-Id: I84c8c1008724b49b6bedb4fc3ef398e292f1c6c7
Reviewed-by: Andreas Cord-Landwehr <cordlandwehr@kde.org>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
src/compositor/configure.json | 4 ++--
src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri | 2 +-
.../compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/compositor/configure.json b/src/compositor/configure.json
index 46caceff..0dbb3364 100644
--- a/src/compositor/configure.json
+++ b/src/compositor/configure.json
@@ -80,13 +80,13 @@
"label": "Linux dma-buf Buffer Sharing",
"type": "compile",
"test": "dmabuf_server_buffer",
- "use": "egl"
+ "use": "egl drm"
},
"dmabuf-client-buffer": {
"label": "Linux Client dma-buf Buffer Sharing",
"type": "compile",
"test": "dmabuf_client_buffer",
- "use": "egl"
+ "use": "egl drm"
},
"vulkan-server-buffer": {
"label": "Vulkan Buffer Sharing",
diff --git a/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri b/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri
index 2df10109..41f483c4 100644
--- a/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri
+++ b/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri
@@ -1,6 +1,6 @@
INCLUDEPATH += $$PWD
-QMAKE_USE_PRIVATE += egl wayland-server
+QMAKE_USE_PRIVATE += egl drm wayland-server
SOURCES += \
$$PWD/dmabufserverbufferintegration.cpp
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri
index a7630040..4dbbae19 100644
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri
+++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri
@@ -1,6 +1,6 @@
INCLUDEPATH += $$PWD
-QMAKE_USE_PRIVATE += egl wayland-server
+QMAKE_USE_PRIVATE += egl drm wayland-server
CONFIG += wayland-scanner
WAYLANDSERVERSOURCES += $$PWD/../../../3rdparty/protocol/linux-dmabuf-unstable-v1.xml
--
cgit v1.2.1
@@ -0,0 +1,39 @@
From 18f942f3f3a99544f379c66578f14b28cafcef22 Mon Sep 17 00:00:00 2001
From: Weng Xuetian <wengxt@gmail.com>
Date: Fri, 10 Nov 2023 19:43:37 -0800
Subject: client: Always clear queued buffer busy flag when resetting the
window
In 39a003942ebab39a1d3b8bc64f41d0c68e92f4bf, the queued buffer is always
set busy, but it may not be reset correctly if the queued buffer is not
ever attached due to hiding the surface when window visibility is
being updated at a very fast speed.
Fixes: QTBUG-118650
Task-number: QTBUG-118650
Change-Id: Id0bdd3caa69c821bb84927f01b4839f46eee8a10
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: David Redondo <qt@david-redondo.de>
(cherry picked from commit 6fe83f6076423068b652fa4fcb0b5adbd297f2a8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/client/qwaylandwindow.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 4841ba95..b81e00ef 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -310,6 +310,9 @@ void QWaylandWindow::reset()
mOpaqueArea = QRegion();
mMask = QRegion();
+ if (mQueuedBuffer) {
+ mQueuedBuffer->setBusy(false);
+ }
mQueuedBuffer = nullptr;
mQueuedBufferDamage = QRegion();
--
cgit v1.2.3
@@ -0,0 +1,160 @@
From aae65c885d8e38d8abc2959cded7b5e9e5fc88b3 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
Date: Tue, 14 Nov 2023 13:31:28 +0200
Subject: Client: Move topmost grabbing popup tracking to QWaylandWindow
If the effective transient parent is different from
QWaylandWindow::transientParent(), then the popups may be closed in
wrong order and producing an xdg-shell protocol error.
This change lifts topmost popup tracking from the xdg-shell plugin to
QWaylandWindow so it can guess the correct transient parent and the
xdg-shell plugin doesn't have to pick a different parent behind our
back.
Fixes: QTBUG-119110
Change-Id: I7c5f780b7bd4c3362aa7b22762ff336ae908ff70
Reviewed-by: David Edmundson <davidedmundson@kde.org>
(cherry picked from commit cfaae5d910406ef38d124e8e2c9114e2bfe87cb3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
src/client/qwaylandwindow.cpp | 23 ++++++++++++++++++++--
src/client/qwaylandwindow_p.h | 3 ++-
.../xdg-shell/qwaylandxdgshell.cpp | 18 -----------------
.../xdg-shell/qwaylandxdgshell_p.h | 1 -
4 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index b81e00ef..de2cafb6 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -41,6 +41,7 @@ namespace QtWaylandClient {
Q_LOGGING_CATEGORY(lcWaylandBackingstore, "qt.qpa.wayland.backingstore")
QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
+QWaylandWindow *QWaylandWindow::mTopPopup = nullptr;
QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
: QPlatformWindow(window)
@@ -136,7 +137,22 @@ void QWaylandWindow::initWindow()
} else if (shouldCreateShellSurface()) {
Q_ASSERT(!mShellSurface);
Q_ASSERT(mShellIntegration);
- mTransientParent = closestTransientParent();
+ mTransientParent = guessTransientParent();
+ if (mTransientParent) {
+ if (window()->type() == Qt::Popup) {
+ if (mTopPopup && mTopPopup != mTransientParent) {
+ qCWarning(lcQpaWayland) << "Creating a popup with a parent," << mTransientParent->window()
+ << "which does not match the current topmost grabbing popup,"
+ << mTopPopup->window() << "With some shell surface protocols, this"
+ << "is not allowed. The wayland QPA plugin is currently handling"
+ << "it by setting the parent to the topmost grabbing popup."
+ << "Note, however, that this may cause positioning errors and"
+ << "popups closing unxpectedly. Please fix the transient parent of the popup.";
+ mTransientParent = mTopPopup;
+ }
+ mTopPopup = this;
+ }
+ }
mShellSurface = mShellIntegration->createShellSurface(this);
if (mShellSurface) {
@@ -271,6 +287,9 @@ void QWaylandWindow::reset()
{
closeChildPopups();
+ if (mTopPopup == this)
+ mTopPopup = mTransientParent && (mTransientParent->window()->type() == Qt::Popup) ? mTransientParent : nullptr;
+
if (mSurface) {
emit wlSurfaceDestroyed();
QWriteLocker lock(&mSurfaceLock);
@@ -1120,7 +1139,7 @@ QWaylandWindow *QWaylandWindow::transientParent() const
return mTransientParent;
}
-QWaylandWindow *QWaylandWindow::closestTransientParent() const
+QWaylandWindow *QWaylandWindow::guessTransientParent() const
{
// Take the closest window with a shell surface, since the transient parent may be a
// QWidgetWindow or some other window without a shell surface, which is then not able to
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index fbf62906..862366ea 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -349,7 +349,7 @@ private:
void handleScreensChanged();
void sendRecursiveExposeEvent();
- QWaylandWindow *closestTransientParent() const;
+ QWaylandWindow *guessTransientParent() const;
void addChildPopup(QWaylandWindow *child);
void removeChildPopup(QWaylandWindow *child);
@@ -361,6 +361,7 @@ private:
void handleFrameCallback(struct ::wl_callback* callback);
static QWaylandWindow *mMouseGrab;
+ static QWaylandWindow *mTopPopup;
friend class QWaylandSubSurface;
};
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index e5dde262..f6e3e08a 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -221,9 +221,6 @@ QWaylandXdgSurface::Popup::~Popup()
destroy();
if (m_grabbing) {
- auto *shell = m_xdgSurface->m_shell;
- Q_ASSERT(shell->m_topmostGrabbingPopup == this);
- shell->m_topmostGrabbingPopup = m_parentXdgSurface ? m_parentXdgSurface->m_popup : nullptr;
m_grabbing = false;
// Synthesize Qt enter/leave events for popup
@@ -255,7 +252,6 @@ void QWaylandXdgSurface::Popup::resetConfiguration()
void QWaylandXdgSurface::Popup::grab(QWaylandInputDevice *seat, uint serial)
{
- m_xdgSurface->m_shell->m_topmostGrabbingPopup = this;
xdg_popup::grab(seat->wl_seat(), serial);
m_grabbing = true;
}
@@ -566,20 +562,6 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
void QWaylandXdgSurface::setGrabPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial)
{
- auto parentXdgSurface = qobject_cast<QWaylandXdgSurface *>(parent->shellSurface());
- auto *top = m_shell->m_topmostGrabbingPopup;
-
- if (top && top->m_xdgSurface != parentXdgSurface) {
- qCWarning(lcQpaWayland) << "setGrabPopup called with a parent," << parentXdgSurface
- << "which does not match the current topmost grabbing popup,"
- << top->m_xdgSurface << "According to the xdg-shell protocol, this"
- << "is not allowed. The wayland QPA plugin is currently handling"
- << "it by setting the parent to the topmost grabbing popup."
- << "Note, however, that this may cause positioning errors and"
- << "popups closing unxpectedly because xdg-shell mandate that child"
- << "popups close before parents";
- parent = top->m_xdgSurface->m_window;
- }
setPopup(parent);
m_popup->grab(device, serial);
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
index 951e8234..e2dc12dd 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
@@ -171,7 +171,6 @@ private:
QScopedPointer<QWaylandXdgDecorationManagerV1> m_xdgDecorationManager;
QScopedPointer<QWaylandXdgActivationV1> m_xdgActivation;
QScopedPointer<QWaylandXdgExporterV2> m_xdgExporter;
- QWaylandXdgSurface::Popup *m_topmostGrabbingPopup = nullptr;
friend class QWaylandXdgSurface;
};
--
cgit v1.2.3
@@ -1,50 +0,0 @@
From fd9fec4fc7f43fb939e8e5a946c7858390bbd9d3 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Thu, 8 Feb 2018 16:53:39 +0100
Subject: [PATCH] Fix crash when connecting a new screen
In QWaylandWindow::virtualSiblings, don't include screens that have not been
added yet. I.e. QWaylandScreens for which QPlatformIntegration::screenAdded has
not yet been called.
There are two reasons why this crash wasn't covered by the
removePrimaryScreen() test. First of all, the mock output didn't send
wl_output.done events when updating the mode/geometry. These wayland events are
what causes QWindowSystemInterface::handleScreenGeometryChange() to be called
(where virtualSiblings are called).
Furthermore, virtualSiblings is only called when the geometry actually changes,
so add a new test that changes the screen geometry of the existing screen while
a new one is being added (i.e. moves it to the right).
Task-number: QTBUG-62044
Change-Id: I623fbf8799d21c6b9293e7120ded301277639cc6
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Aleix Pol
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
src/client/qwaylandscreen.cpp | 6 ++++--
tests/auto/client/client/tst_client.cpp | 25 +++++++++++++++++++++++++
tests/auto/client/shared/mockcompositor.cpp | 8 ++++++++
tests/auto/client/shared/mockcompositor.h | 2 ++
tests/auto/client/shared/mockoutput.cpp | 27 +++++++++++++++++++++++++--
tests/auto/client/shared/mockoutput.h | 1 +
6 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index fba75557..1c9ce23b 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -138,8 +138,10 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const
QList<QPlatformScreen *> list;
const QList<QWaylandScreen*> screens = mWaylandDisplay->screens();
list.reserve(screens.count());
- foreach (QWaylandScreen *screen, screens)
- list << screen;
+ for (QWaylandScreen *screen : qAsConst(screens)) {
+ if (screen->screen())
+ list << screen;
+ }
return list;
}
@@ -1,30 +0,0 @@
From e283cc059c83cbb4fe677beaca8aebb99156ccc5 Mon Sep 17 00:00:00 2001
From: Antonio Larrosa <alarrosa@suse.com>
Date: Mon, 5 Mar 2018 13:56:15 +0100
Subject: Test for null pointer before using it
Task-number: QTBUG-66867
Change-Id: Ibbe407fa3ac32141b52fa0086e9f1ebfd27052ba
Done-with: Fabian Vogt <fvogt@suse.de>
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
Reviewed-by: Jan Grulich <jgrulich@redhat.com>
---
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 ecab8ffc..7d868b30 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -785,7 +785,7 @@ static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
{
while (window) {
auto w = static_cast<QWaylandWindow *>(window->handle());
- if (w->shellSurface())
+ if (w && w->shellSurface())
return w;
window = window->transientParent() ? window->transientParent() : window->parent();
}
--
cgit v1.2.1
@@ -1,91 +0,0 @@
From 26a6372bb0c6528358e34f8175a14ff0be47fb12 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Mon, 19 Mar 2018 10:21:47 +0100
Subject: xdg-shell v5,v6 shell integrations: Fix crash when showing popups
If a popup was shown without any input events happening first, it would cause
nullptr dereferences in both xdg-shell v5 and v6.
Fixes crashes in:
- tst_QAccessibility::comboBoxTest
- tst_QAccessibility::menuTest
- tst_QWindow::touchInterruptedByPopup
- tst_QFocusEvent::checkReason_Popup
Task-number: QTBUG-67150
Change-Id: Ib3e06326f71e4ab5f74727cb4f79626a21c34d55
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
src/client/qwaylandxdgshell.cpp | 3 +--
src/client/qwaylandxdgshell_p.h | 2 +-
src/client/qwaylandxdgshellintegration.cpp | 5 +++--
src/client/qwaylandxdgshellv6.cpp | 5 +++--
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/client/qwaylandxdgshell.cpp b/src/client/qwaylandxdgshell.cpp
index 8b252b95..9a34e72d 100644
--- a/src/client/qwaylandxdgshell.cpp
+++ b/src/client/qwaylandxdgshell.cpp
@@ -73,12 +73,11 @@ QWaylandXdgSurface *QWaylandXdgShell::createXdgSurface(QWaylandWindow *window)
return new QWaylandXdgSurface(this, window);
}
-QWaylandXdgPopup *QWaylandXdgShell::createXdgPopup(QWaylandWindow *window)
+QWaylandXdgPopup *QWaylandXdgShell::createXdgPopup(QWaylandWindow *window, QWaylandInputDevice *inputDevice)
{
QWaylandWindow *parentWindow = m_popups.empty() ? window->transientParent() : m_popups.last();
::wl_surface *parentSurface = parentWindow->object();
- QWaylandInputDevice *inputDevice = window->display()->lastInputDevice();
if (m_popupSerial == 0)
m_popupSerial = inputDevice->serial();
::wl_seat *seat = inputDevice->wl_seat();
diff --git a/src/client/qwaylandxdgshell_p.h b/src/client/qwaylandxdgshell_p.h
index afbd9c59..761f2521 100644
--- a/src/client/qwaylandxdgshell_p.h
+++ b/src/client/qwaylandxdgshell_p.h
@@ -79,7 +79,7 @@ public:
~QWaylandXdgShell() override;
QWaylandXdgSurface *createXdgSurface(QWaylandWindow *window);
- QWaylandXdgPopup *createXdgPopup(QWaylandWindow *window);
+ QWaylandXdgPopup *createXdgPopup(QWaylandWindow *window, QWaylandInputDevice *inputDevice);
private:
void xdg_shell_ping(uint32_t serial) override;
diff --git a/src/client/qwaylandxdgshellintegration.cpp b/src/client/qwaylandxdgshellintegration.cpp
index 5fa4385d..ee72c2d5 100644
--- a/src/client/qwaylandxdgshellintegration.cpp
+++ b/src/client/qwaylandxdgshellintegration.cpp
@@ -74,8 +74,9 @@ bool QWaylandXdgShellIntegration::initialize(QWaylandDisplay *display)
QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWindow *window)
{
- if (window->window()->type() == Qt::WindowType::Popup)
- return m_xdgShell->createXdgPopup(window);
+ QWaylandInputDevice *inputDevice = window->display()->lastInputDevice();
+ if (window->window()->type() == Qt::WindowType::Popup && inputDevice)
+ return m_xdgShell->createXdgPopup(window, inputDevice);
else
return m_xdgShell->createXdgSurface(window);
}
diff --git a/src/client/qwaylandxdgshellv6.cpp b/src/client/qwaylandxdgshellv6.cpp
index c89c8316..a166a3bc 100644
--- a/src/client/qwaylandxdgshellv6.cpp
+++ b/src/client/qwaylandxdgshellv6.cpp
@@ -165,8 +165,9 @@ void QWaylandXdgSurfaceV6::setAppId(const QString &appId)
void QWaylandXdgSurfaceV6::setType(Qt::WindowType type, QWaylandWindow *transientParent)
{
- if ((type == Qt::Popup || type == Qt::ToolTip) && transientParent) {
- setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial(), type == Qt::Popup);
+ QWaylandDisplay *display = m_window->display();
+ if ((type == Qt::Popup || type == Qt::ToolTip) && transientParent && display->lastInputDevice()) {
+ setPopup(transientParent, display->lastInputDevice(), display->lastInputSerial(), type == Qt::Popup);
} else {
setToplevel();
if (transientParent) {
--
cgit v1.2.1
@@ -1,39 +0,0 @@
From 80ed5501cf5dcc4b6ef2a1a126d9d564c1c73851 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Mon, 9 Dec 2019 11:06:18 +0100
Subject: Client: Fix inverse repeat rate implementation
The rate from wl_keyboard.repeat_info was used as if it was an interval. Fixed
by converting from key strokes per second to milliseconds per key stroke.
This fixes a regression, as repeat rate used to be hard-coded to something
sensible before.
[ChangeLog][QPA plugin] Fixed keyboard repeat rate being set inversely, so
higher rates would actually result in fewer characters per second, and vice
versa.
Fixes: QTBUG-80613
Change-Id: Ie783b90cba13dde6f37c0cd1be584d352cddfe7c
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
src/client/qwaylandinputdevice.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index d812918e..3b26dc42 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -88,7 +88,7 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
// or the server didn't send an enter event first.
return;
}
- mRepeatTimer.setInterval(mRepeatRate);
+ mRepeatTimer.setInterval(1000 / mRepeatRate);
handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
mRepeatKey.text, true);
--
cgit v1.2.1
@@ -1,44 +0,0 @@
From 7ce033cbf9a80d2ea5d687956da668cf4567d361 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Fri, 9 Mar 2018 10:30:52 +0100
Subject: Don't try to create compatibility GL context when profile is unset
Context creation would sometimes fail because of this.
Change-Id: Icf73a42ee2bb984ebfc09b7ed98f094d544134b8
Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@liri.io>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
---
.../client/wayland-egl/qwaylandglcontext.cpp | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
index 740e9641..6e48659d 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
@@ -259,10 +259,18 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis
}
// Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2.
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
- eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
- eglContextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile
- ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
- : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
+ switch (format.profile()) {
+ case QSurfaceFormat::NoProfile:
+ break;
+ case QSurfaceFormat::CoreProfile:
+ eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+ eglContextAttrs.append(EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
+ break;
+ case QSurfaceFormat::CompatibilityProfile:
+ eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+ eglContextAttrs.append(EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
+ break;
+ }
}
}
eglContextAttrs.append(EGL_NONE);
--
cgit v1.2.1
@@ -1,176 +0,0 @@
From 57c4af2b18c0fb1d266b245a107fa6cb876b9d9e Mon Sep 17 00:00:00 2001
From: Giulio Camuffo <giulio.camuffo@jollamobile.com>
Date: Fri, 1 May 2015 17:12:22 +0300
Subject: Implement basic key composition support
Use xkbcommon-compose to handle basic compose key support. We should expand on
it in the future to handle things like resetting the compose state on text
field switching.
Task-number: QTBUG-54792
Task-number: QTBUG-64572
Change-Id: I9d1d5ca4c9991928e12979f69eaa477e0cb28ada
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
src/client/qwaylandinputdevice.cpp | 65 +++++++++++++++++++++++++++++++++++++-
src/client/qwaylandinputdevice_p.h | 9 ++++++
2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index f6287ba8..115d6dbc 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -70,6 +70,10 @@
#include <QtGui/QGuiApplication>
+#if QT_CONFIG(xkbcommon_evdev)
+#include <xkbcommon/xkbcommon-compose.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -113,6 +117,7 @@ bool QWaylandInputDevice::Keyboard::createDefaultKeyMap()
qWarning() << "xkb_map_new_from_names failed, no key input";
return false;
}
+ createComposeState();
return true;
}
@@ -125,11 +130,41 @@ void QWaylandInputDevice::Keyboard::releaseKeyMap()
if (mXkbContext)
xkb_context_unref(mXkbContext);
}
+
+void QWaylandInputDevice::Keyboard::createComposeState()
+{
+ static const char *locale = nullptr;
+ if (!locale) {
+ locale = getenv("LC_ALL");
+ if (!locale)
+ locale = getenv("LC_CTYPE");
+ if (!locale)
+ locale = getenv("LANG");
+ if (!locale)
+ locale = "C";
+ }
+
+ mXkbComposeTable = xkb_compose_table_new_from_locale(mXkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (mXkbComposeTable)
+ mXkbComposeState = xkb_compose_state_new(mXkbComposeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+}
+
+void QWaylandInputDevice::Keyboard::releaseComposeState()
+{
+ if (mXkbComposeState)
+ xkb_compose_state_unref(mXkbComposeState);
+ if (mXkbComposeTable)
+ xkb_compose_table_unref(mXkbComposeTable);
+ mXkbComposeState = nullptr;
+ mXkbComposeTable = nullptr;
+}
+
#endif
QWaylandInputDevice::Keyboard::~Keyboard()
{
#if QT_CONFIG(xkbcommon_evdev)
+ releaseComposeState();
releaseKeyMap();
#endif
if (mFocus)
@@ -626,6 +661,7 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
// Release the old keymap resources in the case they were already created in
// the key event or when the compositor issues a new map
+ releaseComposeState();
releaseKeyMap();
mXkbContext = xkb_context_new(xkb_context_flags(0));
@@ -634,6 +670,8 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
close(fd);
mXkbState = xkb_state_new(mXkbMap);
+ createComposeState();
+
#else
Q_UNUSED(format);
Q_UNUSED(fd);
@@ -717,12 +755,37 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
return;
}
- const xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code);
+ QString composedText;
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code);
+ if (mXkbComposeState) {
+ if (isDown)
+ xkb_compose_state_feed(mXkbComposeState, sym);
+ xkb_compose_status status = xkb_compose_state_get_status(mXkbComposeState);
+
+ switch (status) {
+ case XKB_COMPOSE_COMPOSED: {
+ int size = xkb_compose_state_get_utf8(mXkbComposeState, nullptr, 0);
+ QVarLengthArray<char, 32> buffer(size + 1);
+ xkb_compose_state_get_utf8(mXkbComposeState, buffer.data(), buffer.size());
+ composedText = QString::fromUtf8(buffer.constData());
+ sym = xkb_compose_state_get_one_sym(mXkbComposeState);
+ xkb_compose_state_reset(mXkbComposeState);
+ } break;
+ case XKB_COMPOSE_COMPOSING:
+ case XKB_COMPOSE_CANCELLED:
+ return;
+ case XKB_COMPOSE_NOTHING:
+ break;
+ }
+ }
Qt::KeyboardModifiers modifiers = mParent->modifiers();
std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers);
+ if (!composedText.isNull())
+ text = composedText;
+
sendKey(window->window(), time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);
#else
// Generic fallback for single hard keys: Assume 'key' is a Qt key code.
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index adff3f11..07d261f3 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -77,6 +77,11 @@
struct wl_cursor_image;
#endif
+#if QT_CONFIG(xkbcommon_evdev)
+struct xkb_compose_state;
+struct xkb_compose_table;
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -208,6 +213,8 @@ public:
xkb_context *mXkbContext;
xkb_keymap *mXkbMap;
xkb_state *mXkbState;
+ xkb_compose_table *mXkbComposeTable = nullptr;
+ xkb_compose_state *mXkbComposeState = nullptr;
#endif
uint32_t mNativeModifiers;
@@ -229,6 +236,8 @@ private:
#if QT_CONFIG(xkbcommon_evdev)
bool createDefaultKeyMap();
void releaseKeyMap();
+ void createComposeState();
+ void releaseComposeState();
#endif
};
--
cgit v1.2.1
+3 -2
View File
@@ -24,7 +24,8 @@
<Dependency versionFrom="6.6.0">qt6-declarative-devel</Dependency>
</BuildDependencies>
<Patches>
<!-- <Patch level="1">qt6-wayland-animate-cursor.patch</Patch> -->
<Patch level="1">qtbug-119110.patch</Patch>
<Patch level="1">qtbug-118650.patch</Patch>
</Patches>
</Source>
@@ -78,7 +79,7 @@
<History>
<Update release="6">
<Date>2023-11-17</Date>
<Date>2023-11-19</Date>
<Version>6.6.0</Version>
<Comment>Version bump.</Comment>
<Name>Mustafa Cinasal</Name>