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 <davidedmundson@kde.org>
This commit is contained in:
David Redondo 2024-10-30 16:57:55 +01:00
parent 9aa5f633d4
commit 2753bf6b6b
3 changed files with 21 additions and 9 deletions

View File

@ -455,18 +455,21 @@ void QWaylandDisplay::reconnect()
mActiveWindows.clear(); mActiveWindows.clear();
const auto windows = QGuiApplication::allWindows(); const auto windows = QGuiApplication::allWindows();
QList<QWaylandWindow *> allPlatformWindows;
for (auto window : windows) { for (auto window : windows) {
if (auto waylandWindow = static_cast<QWaylandWindow *>(window->handle())) if (auto waylandWindow = static_cast<QWaylandWindow *>(window->handle())) {
waylandWindow->closeChildPopups(); waylandWindow->closeChildPopups();
allPlatformWindows.push_back(waylandWindow);
} }
}
// Remove windows that do not need to be recreated and now closed popups // Remove windows that do not need to be recreated and now closed popups
QList<QWaylandWindow *> recreateWindows; QList<QWaylandWindow *> recreateWindows;
for (auto window : std::as_const(windows)) { for (auto window : std::as_const(allPlatformWindows)) {
auto waylandWindow = static_cast<QWaylandWindow*>(window->handle()); if (window->subSurfaceWindow() || window->shellSurface()) {
if (waylandWindow && waylandWindow->wlSurface()) { recreateWindows.push_back(window);
waylandWindow->reset();
recreateWindows.push_back(waylandWindow);
} }
window->reset();
} }
if (mSyncCallback) { if (mSyncCallback) {
@ -480,6 +483,15 @@ void QWaylandDisplay::reconnect()
if (!mDisplay) if (!mDisplay)
_exit(1); _exit(1);
connect(
this, &QWaylandDisplay::connected, this,
[&allPlatformWindows] {
for (auto &window : std::as_const(allPlatformWindows)) {
window->initializeWlSurface();
}
},
Qt::SingleShotConnection);
setupConnection(); setupConnection();
initialize(); initialize();
@ -488,7 +500,8 @@ void QWaylandDisplay::reconnect()
initEventThread(); initEventThread();
auto needsRecreate = [](QPlatformWindow *window) { auto needsRecreate = [](QPlatformWindow *window) {
return window && !static_cast<QWaylandWindow *>(window)->wlSurface(); auto waylandWindow = static_cast<QWaylandWindow *>(window);
return waylandWindow && !waylandWindow->subSurfaceWindow() && !waylandWindow->shellSurface();
}; };
auto window = recreateWindows.begin(); auto window = recreateWindows.begin();
while (!recreateWindows.isEmpty()) { while (!recreateWindows.isEmpty()) {

View File

@ -1803,7 +1803,6 @@ void QWaylandWindow::closeChildPopups() {
void QWaylandWindow::reinit() void QWaylandWindow::reinit()
{ {
initializeWlSurface();
if (window()->isVisible()) { if (window()->isVisible()) {
initWindow(); initWindow();
if (hasPendingUpdateRequest()) if (hasPendingUpdateRequest())

View File

@ -239,6 +239,7 @@ public:
virtual void reinit(); virtual void reinit();
void reset(); void reset();
void initializeWlSurface();
bool windowEvent(QEvent *event) override; bool windowEvent(QEvent *event) override;
@ -340,7 +341,6 @@ protected:
private: private:
void setGeometry_helper(const QRect &rect); void setGeometry_helper(const QRect &rect);
void initWindow(); void initWindow();
void initializeWlSurface();
bool shouldCreateShellSurface() const; bool shouldCreateShellSurface() const;
bool shouldCreateSubSurface() const; bool shouldCreateSubSurface() const;
void resetSurfaceRole(); void resetSurfaceRole();