QWindowsScreenManager::removeScreen() - don't leave stale screen behind

QWindowsScreenManager::removeScreen() read an element from m_screens
and removed it. If the removed screen was not the primary screen,
QWindowSystemInterface::flushWindowSystemEvents() is called.

When removeScreen() is called from handleScreenChanges() in the same
class, flushing window events can lead to a re-entry. That is e.g. the
case when a RDP connection is closed and the server removes the virtual
screen.

QWindowScreenManager::removeScreen() removes the platform screen only
at the very end, which means that m_screens contains a stale pointer.
The re-entry can therefore crash with a double delete.

Take the platform screen at the beginning of the method, to make it
safe for re-entry.

Fixes: QTBUG-135337
Pick-to: 6.8 6.5
Change-Id: Id18a6fb3e72922bcdb62c9e79857b6bb713c0c1b
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
(cherry picked from commit 3416d28c8b0fa8e5cd6622fc86fe6fc5aae9222b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 0e0db3eefdfdde8480bf80304056d6e129168bf8)
This commit is contained in:
Axel Spoerl 2025-06-12 20:41:31 +02:00 committed by Qt Cherry-pick Bot
parent d28f3605ff
commit a3839e8b32

View File

@ -765,7 +765,8 @@ static void moveToVirtualScreen(QWindow *w, const QScreen *newScreen)
void QWindowsScreenManager::removeScreen(int index)
{
qCDebug(lcQpaScreen) << "Removing Monitor:" << m_screens.at(index)->data();
QScreen *screen = m_screens.at(index)->screen();
QPlatformScreen *platformScreen = m_screens.takeAt(index);
QScreen *screen = platformScreen->screen();
QScreen *primaryScreen = QGuiApplication::primaryScreen();
// QTBUG-38650: When a screen is disconnected, Windows will automatically
// move the Window to another screen. This will trigger a geometry change
@ -791,7 +792,7 @@ void QWindowsScreenManager::removeScreen(int index)
if (movedWindowCount)
QWindowSystemInterface::flushWindowSystemEvents();
}
QWindowSystemInterface::handleScreenRemoved(m_screens.takeAt(index));
QWindowSystemInterface::handleScreenRemoved(platformScreen);
}
/*!