diff options
author | Gabriel de Dietrich <gabriel.dietrich-de@nokia.com> | 2010-02-09 08:56:25 (GMT) |
---|---|---|
committer | Gabriel de Dietrich <gabriel.dietrich-de@nokia.com> | 2010-02-10 08:57:17 (GMT) |
commit | b7af368e86874d71ffc9071c9ef009814d6a3467 (patch) | |
tree | 34bc36dbbde9fcdb20ab04a7b68b77c9f7077223 /src/gui/widgets | |
parent | 6f155d010b6dd5ae3c04e62b3a29f8c0ed9f0a36 (diff) | |
download | Qt-b7af368e86874d71ffc9071c9ef009814d6a3467.zip Qt-b7af368e86874d71ffc9071c9ef009814d6a3467.tar.gz Qt-b7af368e86874d71ffc9071c9ef009814d6a3467.tar.bz2 |
Crash when deleting the parent of a context menu while it is being displayed
Asynchronous deletion of a widget (e.g. calling deleteLater() after a timeout)
could be caught by the context menu's event loop if called with exec() instead
of popup(). This causes the context menu to be deleted twice in some cases,
and a crash generally follows.
Although this introduces a minor behaviour change, we now use popup() with the
WA_DeleteOnClose attribute to display the context menu in all the
contextMenuEvent() bodies, except in those where the menu was already
protected by a QPointer. In QDialog::contextMenuEvent(), we use QWeakPointer
to reflect the fact that the menu was previously allocated in the stack.
QAbstractSpinBox, QDialog and QMdiSubWindow keep using QMenu::exec() in
contextMenuEvent() as they need the QAction returned.
Some auto-tests included.
Reviewed-by: Olivier
Task-number: QTBUG-7902
Diffstat (limited to 'src/gui/widgets')
-rw-r--r-- | src/gui/widgets/qlabel.cpp | 4 | ||||
-rw-r--r-- | src/gui/widgets/qlineedit.cpp | 6 | ||||
-rw-r--r-- | src/gui/widgets/qmainwindow.cpp | 12 |
3 files changed, 13 insertions, 9 deletions
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index c779312..b81f04f 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -951,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev) return; } ev->accept(); - menu->exec(ev->globalPos()); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(ev->globalPos()); #endif } diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2d2df92..141f844 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e) */ void QLineEdit::contextMenuEvent(QContextMenuEvent *event) { - QPointer<QMenu> menu = createStandardContextMenu(); - menu->exec(event->globalPos()); - delete menu; + QMenu *menu = createStandardContextMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(event->globalPos()); } #if defined(Q_WS_WIN) diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index eb25417..a63f3bf 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1555,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event) #ifndef QT_NO_MENU QMenu *popup = createPopupMenu(); - if (popup && !popup->isEmpty()) { - popup->exec(event->globalPos()); - event->accept(); + if (popup) { + if (!popup->isEmpty()) { + popup->setAttribute(Qt::WA_DeleteOnClose); + popup->popup(event->globalPos()); + event->accept(); + } else { + delete popup; + } } - delete popup; #endif } #endif // QT_NO_CONTEXTMENU |