From 11e7bf2076aa4776857ceb0ce6bdba5688002831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 23 Jan 2025 10:32:26 +0200 Subject: [PATCH] Don't pass along expose events for destroying QWidgets When closing a popup window on macOS, and the NSView needs display, for example due to the frame geometry having changed, the system will ask our NSView to display one last frame, via NSOrderOutAnimationProxyWindow initWithSnapshotOfWindow. If this happens during the close() that the QWidget destructor does, we no longer have a QWidget subclass to handle the corresponding paint event, so we'll end up flushing an empty frame, using that for the animation transition instead of the last valid frame of the widget. Worse, if the top level is using RHI to flush, the texture list might be stale, as there is currently no plumbing for a widget to tell QWidgetRepaintManager about it deleting a texture that was previously picked up and placed in the QPlatformTextureList. When this happens we end up crashing on dereferencing the stale texture. To mitigate these issues we now skip the expose event if the widget is already in ~QWidget. This potentially means the close animation will use a stale frame, but we can live with that. Pick-to: 6.5 Change-Id: Iabe1d97019923ee3a1a86039630095d00c966156 Reviewed-by: Volker Hilsheimer (cherry picked from commit 9509434ecb4a11409d8c2bea9c010b40f8f7894d) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit abbbfa27bda2395be6b45916e4e712f6ed206094) --- src/widgets/kernel/qwidgetwindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index ca465615f5..c2f8af001e 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -1029,6 +1029,13 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event) QWidgetPrivate *wPriv = m_widget->d_func(); const bool exposed = isExposed(); + // We might get an expose event from the platform as part of + // closing the window from ~QWidget, to support animated close + // transitions. But at that point we no longer have a widget + // subclass to draw a new frame, so skip the expose event. + if (exposed && wPriv->data.in_destructor) + return; + if (wPriv->childrenHiddenByWState) { // If widgets has been previously hidden by window state change event // and they aren't yet shown...