Cocoa: Use sheetParent to close sheet instead of transientParent

If the window that the sheet (as created for a modal dialog) lives in
has already been destroyed by the time the sheet is hidden, then we used
to trip an assertion. Instead, always use the sheetParent, which is
still alive.

Add a test case that asserts without the fix.

Fixes: QTBUG-128302
Change-Id: I4c399b73e2552bab79358c5505f403efa8e4f80b
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 332f49f2d8c5675bab8bde6acfb377d567961d4a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-11-01 14:45:28 +01:00 committed by Qt Cherry-pick Bot
parent 076f89744e
commit 945c8bf54d
2 changed files with 23 additions and 7 deletions

View File

@ -472,14 +472,10 @@ void QCocoaWindow::setVisible(bool visible)
} else {
// Window not visible, hide it
if (isContentView()) {
if (eventDispatcher()->hasModalSession()) {
if (eventDispatcher()->hasModalSession())
eventDispatcher()->endModalSession(window());
} else {
if ([m_view.window isSheet]) {
Q_ASSERT_X(parentCocoaWindow, "QCocoaWindow", "Window modal dialog has no transient parent.");
[parentCocoaWindow->nativeWindow() endSheet:m_view.window];
}
}
else if ([m_view.window isSheet])
[m_view.window.sheetParent endSheet:m_view.window];
// Note: We do not guard the order out by checking NSWindow.visible, as AppKit will
// in some cases, such as when hiding the application, order out and make a window

View File

@ -66,6 +66,8 @@ private slots:
void deleteOnDone();
void quitOnDone();
void focusWidgetAfterOpen();
void closeParentOfVisibleDialog();
};
// Testing get/set functions
@ -768,5 +770,23 @@ void tst_QDialog::focusWidgetAfterOpen()
QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(pb2));
}
void tst_QDialog::closeParentOfVisibleDialog()
{
QWidget widget;
widget.show();
// On macOS, this dialog becomes a sheet and triggered an assert when
// the widget it lived in was already gone by the time the sheet
// got closed. QTBUG-128302
QDialog dialog(&widget);
dialog.open();
QTimer::singleShot(0, &widget, [&]{
widget.close();
});
QTRY_VERIFY(!widget.isVisible());
}
QTEST_MAIN(tst_QDialog)
#include "tst_qdialog.moc"