Skip to content

Commit

Permalink
dev-qt/qtwayland: Add 2 pending upstream fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
  • Loading branch information
a17r committed Nov 12, 2022
1 parent 5dc6574 commit d541b52
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 0 deletions.
89 changes: 89 additions & 0 deletions dev-qt/qtwayland/files/qtwayland-5.15.7-QTBUG-85297.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
From c48e4e472e02410f1ebca52be98f9c99fe18b551 Mon Sep 17 00:00:00 2001
From: David Redondo <qt@david-redondo.de>
Date: Wed, 8 Jun 2022 11:25:59 +0200
Subject: [PATCH] Keep toplevel windows in the top left corner of the screen

We can't know the actual position of a window on the screen. This causes
an issue when Widgets try to position a popup/menu absolutely and keep
it on the screen when the screen geometry doesn't include (0,0).
Instead report their positions always as the top left corner of
the screen that they are on.
This new behavior can be disabled for qt-shell or via an environment
variable by users that rely on the old behavior.

Fixes: QTBUG-85297
Change-Id: Iacb91cb03a0df87af950115760d2f41124ac06a3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
---
src/client/qwaylandintegration.cpp | 4 ++++
src/client/qwaylandwindow.cpp | 14 +++++++++++++-
src/client/qwaylandwindow_p.h | 3 +++
3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index fbf00c6b..5cd414e5 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -117,6 +117,10 @@ QWaylandIntegration::QWaylandIntegration()
mFailed = true;
return;
}
+
+ QWaylandWindow::fixedToplevelPositions =
+ !qEnvironmentVariableIsSet("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
+
#if QT_CONFIG(clipboard)
mClipboard.reset(new QWaylandClipboard(mDisplay.data()));
#endif
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 771c96cc..d4083121 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -350,8 +350,13 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
}
}

-void QWaylandWindow::setGeometry(const QRect &rect)
+void QWaylandWindow::setGeometry(const QRect &r)
{
+ auto rect = r;
+ if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+ && window()->type() != Qt::ToolTip) {
+ rect.moveTo(screen()->geometry().topLeft());
+ }
setGeometry_helper(rect);

if (window()->isVisible() && rect.isValid()) {
@@ -1033,6 +1038,13 @@ void QWaylandWindow::handleScreensChanged()

QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
mLastReportedScreen = newScreen;
+ if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
+ && window()->type() != Qt::ToolTip
+ && geometry().topLeft() != newScreen->geometry().topLeft()) {
+ auto geometry = this->geometry();
+ geometry.moveTo(newScreen->geometry().topLeft());
+ setGeometry(geometry);
+ }

int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
if (scale != mScale) {
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index ea3d1995..487a91a6 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -98,6 +98,9 @@ public:
QWaylandWindow(QWindow *window, QWaylandDisplay *display);
~QWaylandWindow() override;

+ // Keep Toplevels position on the top left corner of their screen
+ static inline bool fixedToplevelPositions = true;
+
virtual WindowType windowType() const = 0;
virtual void ensureSize();
WId winId() const override;
--
GitLab

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
From 81a7702a87f386a60a0ac8c902e203daae044d81 Mon Sep 17 00:00:00 2001
From: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
Date: Tue, 8 Nov 2022 16:10:18 +0200
Subject: [PATCH] Client: Ensure that wl_surface lives as long as qtquick
render thread needs it

wl_surface can be destroyed while qtquick render thread still uses it.
That can end up in eglSwapBuffers() using defunct wl_surface, which will
eventually lead to a crash due to the compositor posting an error.

This is partially cherry-pick of dff579147b07cd15888a47c303e36684e9930f9f

Change-Id: I044f40dd64e6672027a833379b57ccd9973d8305
---
src/client/qwaylandwindow.cpp | 13 ++++++++++++-
src/client/qwaylandwindow_p.h | 3 +++
.../client/wayland-egl/qwaylandglcontext.cpp | 6 +++++-
3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 771c96cc..5b97cd55 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -76,6 +76,7 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display)
: QPlatformWindow(window)
, mDisplay(display)
+ , mSurfaceLock(QReadWriteLock::Recursive)
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
{
{
@@ -237,6 +238,16 @@ bool QWaylandWindow::shouldCreateSubSurface() const
return QPlatformWindow::parent() != nullptr;
}

+void QWaylandWindow::beginFrame()
+{
+ mSurfaceLock.lockForRead();
+}
+
+void QWaylandWindow::endFrame()
+{
+ mSurfaceLock.unlock();
+}
+
void QWaylandWindow::reset()
{
closeChildPopups();
@@ -245,10 +256,10 @@ void QWaylandWindow::reset()
delete mSubSurfaceWindow;
mSubSurfaceWindow = nullptr;

- invalidateSurface();
if (mSurface) {
emit wlSurfaceDestroyed();
QWriteLocker lock(&mSurfaceLock);
+ invalidateSurface();
mSurface.reset();
}

diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index ea3d1995..e18609d9 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -207,6 +207,9 @@ public:
void handleUpdate();
void deliverUpdateRequest() override;

+ void beginFrame();
+ void endFrame();
+
void addChildPopup(QWaylandWindow* child);
void removeChildPopup(QWaylandWindow* child);
void closeChildPopups();
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
index c1f45fa6..5d6fb2bf 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
@@ -432,8 +432,10 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
return true;
}

- if (window->isExposed())
+ if (window->isExposed()) {
+ window->beginFrame();
window->setCanResize(false);
+ }
if (m_decorationsContext != EGL_NO_CONTEXT && !window->decoration())
window->createDecoration();

@@ -449,6 +451,7 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
if (!eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) {
qWarning("QWaylandGLContext::makeCurrent: eglError: %x, this: %p \n", eglGetError(), this);
window->setCanResize(true);
+ window->endFrame();
return false;
}

@@ -502,6 +505,7 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
eglSwapBuffers(m_eglDisplay, eglSurface);

window->setCanResize(true);
+ window->endFrame();
}

GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
--
GitLab

8 changes: 8 additions & 0 deletions dev-qt/qtwayland/qtwayland-5.15.7.ebuild
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ DEPEND="
RDEPEND="${DEPEND}"
BDEPEND="dev-util/wayland-scanner"

PATCHES=(
# Pending upstream:
# https://invent.kde.org/qt/qt/qtwayland/-/merge_requests/47
"${FILESDIR}/${P}-QTBUG-85297.patch"
# https://invent.kde.org/qt/qt/qtwayland/-/merge_requests/57/commits
"${FILESDIR}/${P}-ensure-wl_surface-longevity.patch"
)

src_configure() {
local myqmakeargs=(
--
Expand Down

0 comments on commit d541b52

Please sign in to comment.