diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 02169e77..a1f3befe 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -423,8 +423,10 @@ void QWaylandDisplay::reconnect() m_eventThread->wait(); m_frameEventQueueThread->wait(); - qDeleteAll(mWaitingScreens); - mWaitingScreens.clear(); + for (auto *screen : std::exchange(mWaitingScreens, {})) { + forgetScreenForSurfaces(screen); + delete screen; + } while (!mScreens.isEmpty()) { auto screen = mScreens.takeLast(); @@ -603,6 +605,22 @@ QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const return nullptr; } +void QWaylandDisplay::registerSurface(QWaylandSurface *surface) +{ + mSurfaces.append(surface); +} + +void QWaylandDisplay::unregisterSurface(QWaylandSurface *surface) +{ + mSurfaces.removeOne(surface); +} + +void QWaylandDisplay::forgetScreenForSurfaces(QWaylandScreen *screen) +{ + for (auto *surface : std::as_const(mSurfaces)) + surface->m_screens.removeAll(screen); +} + void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen) { if (!mWaitingScreens.removeOne(screen)) @@ -823,6 +841,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id) for (auto *screen : mWaitingScreens) { if (screen->outputId() == id) { mWaitingScreens.removeOne(screen); + forgetScreenForSurfaces(screen); delete screen; break; } @@ -831,6 +850,7 @@ void QWaylandDisplay::registry_global_remove(uint32_t id) for (QWaylandScreen *screen : std::as_const(mScreens)) { if (screen->outputId() == id) { mScreens.removeOne(screen); + forgetScreenForSurfaces(screen); // If this is the last screen, we have to add a fake screen, or Qt will break. ensureScreen(); QWindowSystemInterface::handleScreenRemoved(screen); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 29952886..0baa378f 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -116,6 +116,9 @@ public: QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; } void ensureScreen(); + void registerSurface(QWaylandSurface *surface); + void unregisterSurface(QWaylandSurface *surface); + QWaylandScreen *screenForOutput(struct wl_output *output) const; void handleScreenInitialized(QWaylandScreen *screen); @@ -289,6 +292,7 @@ private: void checkWaylandError(); void reconnect(); void setupConnection(); + void forgetScreenForSurfaces(QWaylandScreen *screen); void handleWaylandSync(); void requestWaylandSync(); @@ -311,6 +315,7 @@ private: QList mScreens; QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr; QList mInputDevices; + QList mSurfaces; QList mRegistryListeners; QWaylandIntegration *mWaylandIntegration = nullptr; #if QT_CONFIG(cursor) diff --git a/src/plugins/platforms/wayland/qwaylandsurface.cpp b/src/plugins/platforms/wayland/qwaylandsurface.cpp index 274fdda8..b37e9265 100644 --- a/src/plugins/platforms/wayland/qwaylandsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandsurface.cpp @@ -13,13 +13,16 @@ namespace QtWaylandClient { QWaylandSurface::QWaylandSurface(QWaylandDisplay *display) : wl_surface(display->createSurface(this)) + , m_display(display) { + display->registerSurface(this); connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandSurface::handleScreenRemoved); connect(qApp, &QGuiApplication::screenAdded, this, &QWaylandSurface::screensChanged); } QWaylandSurface::~QWaylandSurface() { + m_display->unregisterSurface(this); destroy(); } diff --git a/src/plugins/platforms/wayland/qwaylandsurface_p.h b/src/plugins/platforms/wayland/qwaylandsurface_p.h index 41860297..ddb63b04 100644 --- a/src/plugins/platforms/wayland/qwaylandsurface_p.h +++ b/src/plugins/platforms/wayland/qwaylandsurface_p.h @@ -57,10 +57,12 @@ protected: QList m_screens; //As seen by wl_surface.enter/leave events. Chronological order. QWaylandWindow *m_window = nullptr; + QWaylandDisplay *m_display = nullptr; std::optional m_preferredBufferScale; std::optional m_preferredBufferTransform; friend class QWaylandWindow; // TODO: shouldn't need to be friends + friend class QWaylandDisplay; }; } // namespace QtWaylandClient