From 2753bf6b6b1ed4c0b51bb257559f44d60a3a9497 Mon Sep 17 00:00:00 2001 From: David Redondo Date: Wed, 30 Oct 2024 16:57:55 +0100 Subject: [PATCH] Adapt window recreation to wl_surface as winId and lifetime changes Returning wl_surface as winId broke widget windows after reconnect. When fetching globals from the new connection new screens are added, this results in QWidget being notified of a screen change. It then refreshes its cached winId which at this point in time will be 0 since the window does not have a new window yet. Then when a widget repainting the backing store will never be flushed because it doesnt find a native parent anymore by going up the parent chain and looking for a widget with non-null winId. Fix this by recreating the wl_surface after fetching the globals but before the initital roundtrip. While at it dont recreate role objects for windows that dont need them. With the changes that also now hidden windows have wl_surfaces we would recreate them along with closed popups. Change-Id: Ib7ed27d1f25df84c85cce4802726178586c19d55 Reviewed-by: David Edmundson --- .../platforms/wayland/qwaylanddisplay.cpp | 27 ++++++++++++++----- .../platforms/wayland/qwaylandwindow.cpp | 1 - .../platforms/wayland/qwaylandwindow_p.h | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index dfdf88c0b4a..d585c194bd6 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -455,18 +455,21 @@ void QWaylandDisplay::reconnect() mActiveWindows.clear(); const auto windows = QGuiApplication::allWindows(); + QList allPlatformWindows; for (auto window : windows) { - if (auto waylandWindow = static_cast(window->handle())) + if (auto waylandWindow = static_cast(window->handle())) { waylandWindow->closeChildPopups(); + allPlatformWindows.push_back(waylandWindow); + } } + // Remove windows that do not need to be recreated and now closed popups QList recreateWindows; - for (auto window : std::as_const(windows)) { - auto waylandWindow = static_cast(window->handle()); - if (waylandWindow && waylandWindow->wlSurface()) { - waylandWindow->reset(); - recreateWindows.push_back(waylandWindow); + for (auto window : std::as_const(allPlatformWindows)) { + if (window->subSurfaceWindow() || window->shellSurface()) { + recreateWindows.push_back(window); } + window->reset(); } if (mSyncCallback) { @@ -480,6 +483,15 @@ void QWaylandDisplay::reconnect() if (!mDisplay) _exit(1); + connect( + this, &QWaylandDisplay::connected, this, + [&allPlatformWindows] { + for (auto &window : std::as_const(allPlatformWindows)) { + window->initializeWlSurface(); + } + }, + Qt::SingleShotConnection); + setupConnection(); initialize(); @@ -488,7 +500,8 @@ void QWaylandDisplay::reconnect() initEventThread(); auto needsRecreate = [](QPlatformWindow *window) { - return window && !static_cast(window)->wlSurface(); + auto waylandWindow = static_cast(window); + return waylandWindow && !waylandWindow->subSurfaceWindow() && !waylandWindow->shellSurface(); }; auto window = recreateWindows.begin(); while (!recreateWindows.isEmpty()) { diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index cb6c07f9799..6d4f11e8d83 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -1803,7 +1803,6 @@ void QWaylandWindow::closeChildPopups() { void QWaylandWindow::reinit() { - initializeWlSurface(); if (window()->isVisible()) { initWindow(); if (hasPendingUpdateRequest()) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index e4ce2af700f..592125c6839 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -239,6 +239,7 @@ public: virtual void reinit(); void reset(); + void initializeWlSurface(); bool windowEvent(QEvent *event) override; @@ -340,7 +341,6 @@ protected: private: void setGeometry_helper(const QRect &rect); void initWindow(); - void initializeWlSurface(); bool shouldCreateShellSurface() const; bool shouldCreateSubSurface() const; void resetSurfaceRole();