summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qapplication_s60.cpp13
-rw-r--r--src/gui/kernel/qt_s60_p.h2
-rw-r--r--tests/auto/qapplication/tst_qapplication.cpp63
3 files changed, 78 insertions, 0 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 689429e..30bf99a 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1030,6 +1030,14 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int
void qt_init(QApplicationPrivate * /* priv */, int)
{
if (!CCoeEnv::Static()) {
+ // The S60 framework creates a new trap handler which will render any existing traps
+ // invalid as long as it is active. This means that all code in main() that occurs after
+ // the QApplication construction needs to be surrounded by a new trap, despite having
+ // an outer one already. To avoid this, we save the original trap handler here, and set
+ // it back after the S60 framework is constructed. Then we restore it right before the S60
+ // framework destruction.
+ TTrapHandler *origTrapHandler = User::TrapHandler();
+
// The S60 framework has not been initalized. We need to do it.
TApaApplicationFactory factory(S60->s60ApplicationFactory ?
S60->s60ApplicationFactory : newS60Application);
@@ -1041,6 +1049,8 @@ void qt_init(QApplicationPrivate * /* priv */, int)
QT_TRAP_THROWING(coe->ConstructAppFromCommandLineL(factory,*commandLine));
delete commandLine;
+ S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler);
+
S60->qtOwnsS60Environment = true;
} else {
S60->qtOwnsS60Environment = false;
@@ -1195,6 +1205,9 @@ void qt_cleanup()
S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
if (S60->qtOwnsS60Environment) {
+ // Restore the S60 framework trap handler. See qt_init().
+ User::SetTrapHandler(S60->s60InstalledTrapHandler);
+
CEikonEnv* coe = CEikonEnv::Static();
coe->PrepareToExit();
// The CEikonEnv itself is destroyed in here.
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index e25bc81..789d89e 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -124,6 +124,8 @@ public:
static inline CAknTitlePane* titlePane();
static inline CAknContextPane* contextPane();
static inline CEikButtonGroupContainer* buttonGroupContainer();
+
+ TTrapHandler *s60InstalledTrapHandler;
#endif
};
diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp
index 97aa092..675e559 100644
--- a/tests/auto/qapplication/tst_qapplication.cpp
+++ b/tests/auto/qapplication/tst_qapplication.cpp
@@ -136,6 +136,9 @@ private slots:
void windowsCommandLine();
void touchEventPropagation();
+
+ void symbianNeedForTraps();
+ void symbianLeaveThroughMain();
};
class EventSpy : public QObject
@@ -2011,6 +2014,66 @@ void tst_QApplication::touchEventPropagation()
}
}
+#ifdef Q_OS_SYMBIAN
+class CBaseDummy : public CBase
+{
+public:
+ CBaseDummy(int *numDestroyed) : numDestroyed(numDestroyed)
+ {
+ }
+ ~CBaseDummy()
+ {
+ (*numDestroyed)++;
+ }
+
+private:
+ int *numDestroyed;
+};
+
+static void fakeMain(int *numDestroyed)
+{
+ // Push a few objects, just so that the cleanup stack has something to clean up.
+ CleanupStack::PushL(new (ELeave) CBaseDummy(numDestroyed));
+ int argc = 0;
+ QApplication app(argc, 0);
+ CleanupStack::PushL(new (ELeave) CBaseDummy(numDestroyed));
+
+ User::Leave(KErrGeneral); // Fake error
+}
+#endif
+
+void tst_QApplication::symbianNeedForTraps()
+{
+#ifndef Q_OS_SYMBIAN
+ QSKIP("This is a Symbian-only test", SkipAll);
+#else
+ int argc = 0;
+ QApplication app(argc, 0);
+ int numDestroyed = 0;
+
+ // This next part should not require a trap. If it does, the test will crash.
+ CleanupStack::PushL(new (ELeave) CBaseDummy(&numDestroyed));
+ CleanupStack::PopAndDestroy();
+
+ QCOMPARE(numDestroyed, 1);
+
+ // No other failure condition. The program will crash if it does not pass.
+#endif
+}
+
+void tst_QApplication::symbianLeaveThroughMain()
+{
+#ifndef Q_OS_SYMBIAN
+ QSKIP("This is a Symbian-only test", SkipAll);
+#else
+ int numDestroyed = 0;
+ TInt err;
+ TRAP(err, fakeMain(&numDestroyed));
+
+ QCOMPARE(numDestroyed, 2);
+#endif
+}
+
//QTEST_APPLESS_MAIN(tst_QApplication)
int main(int argc, char *argv[])
{