UIKit: Treat windows as exposed only during Qt::ApplicationStateActive

We previously treated Qt::ApplicationStateInactive as a valid state to
expose windows in, to prevent a visible flash of black screen at app
startup between iOS hiding the launch screen and Qt drawing it's first
frame, but this lag is no longer an issue, so we can apply the best
practice of only rendering during Qt::ApplicationStateActive. This may
prevent crashes during application suspension.

Task-number: QTBUG-52493
Change-Id: I271281ed6fb857e6849cdb88cc2d8251d1bba1df
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Tor Arne Vestbø 2016-06-20 14:43:13 +02:00 committed by Tor Arne Vestbø
parent bf8014a269
commit 1a7e577669
2 changed files with 6 additions and 21 deletions

View File

@ -211,8 +211,12 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface)
if (surface->surface()->surfaceClass() == QSurface::Offscreen)
return; // Nothing to do
// When using threaded rendering, the render-thread may not have picked up
// yet on the fact that a window is no longer exposed, and will try to swap
// a non-exposed window. This may in some cases result in crashes, e.g. when
// iOS is suspending an application, so we have an extra guard here.
if (!static_cast<QIOSWindow *>(surface)->isExposed()) {
qCWarning(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush");
qCDebug(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush");
return;
}

View File

@ -217,26 +217,7 @@ void QIOSWindow::applyGeometry(const QRect &rect)
bool QIOSWindow::isExposed() const
{
// Note: At startup of an iOS app it will enter UIApplicationStateInactive
// while showing the launch screen, and once the application returns from
// applicationDidFinishLaunching it will hide the launch screen and enter
// UIApplicationStateActive. Technically, a window is not exposed until
// it's actually visible on screen, and Apple also documents that "Apps
// that use OpenGL ES for drawing must not use didFinishLaunching to
// prepare their drawing environment. Instead, defer any OpenGL ES
// drawing calls to applicationDidBecomeActive". Unfortunately, if we
// wait until the applicationState reaches ApplicationActive to signal
// that the window is exposed, we get a lag between hiding the launch
// screen and blitting the first pixels of the application, as Qt
// spends some time drawing those pixels in response to the expose.
// In practice there doesn't seem to be any issues starting GL setup
// and drawing from within applicationDidFinishLaunching, and this is
// also the recommended approach for other 3rd party GL toolkits on iOS,
// so we 'cheat', and report that a window is exposed even if the app
// is in UIApplicationStateInactive, so that the startup transition
// between the launch screen and the application content is smooth.
return qApp->applicationState() > Qt::ApplicationHidden
return qApp->applicationState() >= Qt::ApplicationActive
&& window()->isVisible() && !window()->geometry().isEmpty();
}