From 59601e06d96edb5661a3dd91341d74e16dc6b229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 6 Jun 2013 15:42:16 +0200 Subject: iOS: Interleave Qt application main() with iOS startup sequence Our previous event loop integration had two unfortunate flaws: 1. We would call qt_user_main() from a timer, after returning from didFinishLaunchingWithOptions. This had the effect of showing the iOS application window long before the Qt application UI had been set up, resulting in a 1-2 second flash of black/pink between the launch image disappearing and the actual application showing. 2. We spun a nested event loop, where our implementation of the different event loop modes did not perfectly match the Apple implementation. This resulted in scrolling being busted in some cases such as when showing the virtual keyboard for Emoji characters. These two issues have now been solved by calling the user's main() from didFinishLaunchingWithOptions. Normally this would not work, as the user's main would call QApplication::exec() at the end of their main(), which would block and we would never return back from the didFinishLaunchingWithOptions callback, resulting in no UI on screen. We work around this by longjmp'ing out of QApplication::exec(), back into didFinishLaunchingWithOptions, so that it can return. Again, this would normally not work, as the call stack where QApplication and friends would live would get smashed as the application continued executing. We work around this by allocating a block of stack space at the start of main(), which we then redirect the stack pointer to before calling the user's main. This results in the whole stack of the user's main() and below being preserved, even if we longjmp out of the call stack (which then restores the stack pointer). This approach should work fine together with garbage-collection as well, since the mark-and-sweep phase will walk the stack from the stack pointer to the stack base, including sections of the stack that were part of qt_user_main() and live in the reserved area. One case where GC will fail though is if it happens as part of the qt_user_main() call, where the GC will not mark anything in the 'real' callstack below UIApplicationMain(), but this is not expected to happen. The size of the reserved stack can be controlled through the Info.plist key 'QtRunLoopIntegrationStackSize', as well as the 'QtRunLoopIntegrationDisableSeparateStack' key to disable the separate stack approach completely. This will fall back to the old approach. The amount of stack space used by the user's main can be determined by enabling a special debugging mode, using the 'QtRunLoopIntegrationDebugStackUsage' key. Change-Id: I2af7a6cfe1a006a80fd220ed83d8a66d4c45b523 Reviewed-by: Simon Hausmann --- src/plugins/platforms/ios/ios.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/ios/ios.pro') diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro index 263577d43f..9b53974998 100644 --- a/src/plugins/platforms/ios/ios.pro +++ b/src/plugins/platforms/ios/ios.pro @@ -9,8 +9,8 @@ LIBS += -framework Foundation -framework UIKit -framework QuartzCore OBJECTIVE_SOURCES = \ plugin.mm \ - qiosmain_wrapper.mm \ qiosintegration.mm \ + qioseventdispatcher.mm \ qioswindow.mm \ qiosscreen.mm \ qiosbackingstore.mm \ @@ -24,6 +24,7 @@ OBJECTIVE_SOURCES = \ HEADERS = \ qiosintegration.h \ + qioseventdispatcher.h \ qioswindow.h \ qiosscreen.h \ qiosbackingstore.h \ -- cgit v1.2.3