client: Avoid roundtrip to handle xdgoutput race condition

The original bug was that we could get a surface enter event before the
xdg output was fully ready, where we had a QPlatformScreen but no
QScreen announced.

A solution with a roundtrip was added, which works, but roundtrips cause
other problems processing messages out of order and inhibts a move to
synchronous delivery.

As an alternative fix we move the problem from QWaylandWindow to
QWaylandSurface and have that filter out not-ready QScreens.
The best output is then re-evaluated whenever a screen is added.

Change-Id: Iabc78917112aa8c58cad8e128c5bb3030f8c8f65
Reviewed-by: David Redondo <qt@david-redondo.de>
This commit is contained in:
David Edmundson 2024-02-09 13:03:18 +00:00
parent 2f7a86fac3
commit 8457dd76e3
2 changed files with 9 additions and 4 deletions

View File

@ -15,6 +15,7 @@ QWaylandSurface::QWaylandSurface(QWaylandDisplay *display)
: wl_surface(display->createSurface(this))
{
connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandSurface::handleScreenRemoved);
connect(qApp, &QGuiApplication::screenAdded, this, &QWaylandSurface::screensChanged);
}
QWaylandSurface::~QWaylandSurface()
@ -24,7 +25,14 @@ QWaylandSurface::~QWaylandSurface()
QWaylandScreen *QWaylandSurface::oldestEnteredScreen()
{
return m_screens.value(0, nullptr);
for (auto *screen : std::as_const(m_screens)) {
// only report valid screens
// we can have some ouptuts waiting for xdg output information
// that are valid QPlatformScreens, but not valid QScreens
if (screen->screen())
return screen;
}
return nullptr;
}
QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface)

View File

@ -557,7 +557,6 @@ QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
if (auto *screen = mSurface->oldestEnteredScreen())
return screen;
}
return QPlatformWindow::screen();
}
@ -1440,8 +1439,6 @@ void QWaylandWindow::handleScreensChanged()
if (newScreen->screen() == window()->screen())
return;
if (!newScreen->isPlaceholder() && !newScreen->QPlatformScreen::screen())
mDisplay->forceRoundTrip();
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup