Skip to content

Commit

Permalink
Don't pass along expose events for destroying QWidgets
Browse files Browse the repository at this point in the history
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.9 6.8 6.5
Change-Id: Iabe1d97019923ee3a1a86039630095d00c966156
Reviewed-by: Volker Hilsheimer <[email protected]>
  • Loading branch information
torarnv committed Jan 26, 2025
1 parent 81ed068 commit 9509434
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/widgets/kernel/qwidgetwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,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...
Expand Down

0 comments on commit 9509434

Please sign in to comment.