diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2024-04-24 12:31:26 +0800 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2024-04-26 15:58:32 +0800 |
commit | 468cb035efe4890c388069eb373a7ae8ef178146 (patch) | |
tree | 5704647b8ad2c65842ca9d78aa3f63113c70b9b1 | |
parent | f83206229e246c3e9ccd1ea2a64b0e003b2cdbc5 (diff) |
QCocoaMenu: fix crash when app quits while menu is open
Consider the following QML code:
import QtQuick
import QtQuick.Controls
ApplicationWindow {
visible: true
Menu {
id: menu
MenuItem {
text: "Some action"
}
}
TapHandler {
acceptedButtons: Qt.RightButton
onTapped: {
exitAppTimer.start()
menu.open()
}
}
Timer {
id: exitAppTimer
interval: 1000
onTriggered: Qt.quit()
}
}
With the new native Qt Quick Menu, this will create a native menu on
platforms like macOS. When the user right clicks on the window, a timer
is started and a native menu opened. After 1 second, Qt.quit() is
called while the menu is still open. As popUpContextMenu is blocking,
when the menu is finally closed (by user interaction), control returns
to QCocoaMenu::showPopup, but the QCocoaWindow has since been
destroyed.
Account for this by storing the window in a QPointer.
It's not possible to test this as native menus can't be auto-tested.
Fixes: QTBUG-124551
Pick-to: 6.5 6.7
Change-Id: I14a97073f350c38828b3e16bb157439aeeeb6529
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenu.mm | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 7a6999c2cc..fa88a19d45 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -326,7 +326,9 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, QPointer<QCocoaMenu> guard = this; QPoint pos = QPoint(targetRect.left(), targetRect.top() + targetRect.height()); - QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : nullptr; + // If the app quits while the menu is open (e.g. through a timer that starts before the menu was opened), + // then the window will have been destroyed before this function finishes executing. Account for that with QPointer. + QPointer<QCocoaWindow> cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : nullptr; NSView *view = cocoaWindow ? cocoaWindow->view() : nil; NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil; |