From 6c694eaae2b40be57c3292f43e085893095d9722 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 14 Oct 2009 13:18:18 +0100 Subject: When reparenting native widget, delayed deletion of Symbian control until control returns to the event loop. This is necessary because reparenting can be triggered from the context of a control's event handler. If reparenting causes that control to be deleted, a crash can result. Task-number: QTBUG-4664 Reviewed-by: axis --- src/gui/kernel/qapplication_s60.cpp | 5 +++++ src/gui/kernel/qwidget.cpp | 7 +++++++ src/gui/kernel/qwidget.h | 3 +++ src/gui/kernel/qwidget_p.h | 1 + src/gui/kernel/qwidget_s60.cpp | 13 ++++++++++++- 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index b1706af..1a8aae0 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1122,6 +1122,11 @@ void qt_init(QApplicationPrivate * /* priv */, int) ; } */ + + // Register WId with the metatype system. This is to enable + // QWidgetPrivate::create_sys to used delayed slot invokation in order + // to destroy WId objects during reparenting. + qRegisterMetaType("WId"); } /***************************************************************************** diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7c11c00..7c9356e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -11994,3 +11994,10 @@ void QWidget::clearMask() XRender extension is not supported on the X11 display, or if the handle could not be created. */ + +#ifdef Q_OS_SYMBIAN +void QWidgetPrivate::_q_delayedDestroy(WId winId) +{ + delete winId; +} +#endif diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 76418af..e7daf9f 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -773,6 +773,9 @@ private: private: Q_DISABLE_COPY(QWidget) Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden()) +#ifdef Q_OS_SYMBIAN + Q_PRIVATE_SLOT(d_func(), void _q_delayedDestroy(WId winId)) +#endif QWidgetData *data; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index a4cc0da..c7b8d42 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -295,6 +295,7 @@ public: #ifdef Q_OS_SYMBIAN void setSoftKeys_sys(const QList &softkeys); void activateSymbianWindow(WId wid = 0); + void _q_delayedDestroy(WId winId); #endif void raise_sys(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 5527cc8..c3686b3 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -56,6 +56,12 @@ #include #endif +// This is necessary in order to be able to perform delayed invokation on slots +// which take arguments of type WId. One example is +// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of +// CCoeControl objects until after the CONE event handler has finished running. +Q_DECLARE_METATYPE(WId) + QT_BEGIN_NAMESPACE extern bool qt_nograb(); @@ -438,7 +444,12 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de if (destroyw) { destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw); - CBase::Delete(destroyw); + + // Delay deletion of the control in case this function is called in the + // context of a CONE event handler such as + // CCoeControl::ProcessPointerEventL + QMetaObject::invokeMethod(q, "_q_delayedDestroy", + Qt::QueuedConnection, Q_ARG(WId, destroyw)); } if (q->testAttribute(Qt::WA_AcceptTouchEvents)) -- cgit v0.12