iOS: Compute screen available geometry based on safe area insets

In addition to the (deprecated) applicationFrame property, we
base the available geometry on the root view's safe area, which
also takes into account system-reserved areas on iPhone X, and
the screen's bezel in the case of tvOS.

Change-Id: I252d960a0e486dd0c7e30843f88c0bf5684feb24
Reviewed-by: Jake Petroules <jake.petroules@qt.io>
bb10
Tor Arne Vestbø 2017-11-24 17:11:40 +01:00
parent 109290753b
commit 1a55c92933
3 changed files with 41 additions and 5 deletions

View File

@ -175,6 +175,21 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@end
@interface UIScreen (Compatibility)
@property (nonatomic, readonly) CGRect qt_applicationFrame;
@end
@implementation UIScreen (Compatibility)
- (CGRect)qt_applicationFrame
{
#ifdef Q_OS_IOS
return self.applicationFrame;
#else
return self.bounds;
#endif
}
@end
// -------------------------------------------------------------------------
QT_BEGIN_NAMESPACE
@ -271,11 +286,15 @@ void QIOSScreen::updateProperties()
QRect previousAvailableGeometry = m_availableGeometry;
m_geometry = QRectF::fromCGRect(m_uiScreen.bounds).toRect();
#ifdef Q_OS_TVOS
m_availableGeometry = m_geometry;
#else
m_availableGeometry = QRectF::fromCGRect(m_uiScreen.applicationFrame).toRect();
#endif
// The application frame doesn't take safe area insets into account, and
// the safe area insets are not available before the UIWindow is shown,
// and do not take split-view constraints into account, so we have to
// combine the two to get the correct available geometry.
QRect applicationFrame = QRectF::fromCGRect(m_uiScreen.qt_applicationFrame).toRect();
UIEdgeInsets safeAreaInsets = m_uiWindow.qt_safeAreaInsets;
m_availableGeometry = m_geometry.adjusted(safeAreaInsets.left, safeAreaInsets.top,
-safeAreaInsets.right, -safeAreaInsets.bottom).intersected(applicationFrame);
#ifndef Q_OS_TVOS
if (m_uiScreen == [UIScreen mainScreen]) {

View File

@ -77,5 +77,6 @@ QT_END_NAMESPACE
- (QWindow *)qwindow;
- (UIViewController *)viewController;
- (QIOSViewController*)qtViewController;
@property (nonatomic, readonly) UIEdgeInsets qt_safeAreaInsets;
@end

View File

@ -545,6 +545,22 @@
return nil;
}
- (UIEdgeInsets)qt_safeAreaInsets
{
#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA)
if (__builtin_available(iOS 11, tvOS 11, *))
return self.safeAreaInsets;
#endif
// Fallback for iOS < 11
UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
CGPoint topInset = [self convertPoint:CGPointMake(0, self.viewController.topLayoutGuide.length) fromView:nil];
CGPoint bottomInset = [self convertPoint:CGPointMake(0, self.viewController.bottomLayoutGuide.length) fromView:nil];
safeAreaInsets.top = topInset.y;
safeAreaInsets.bottom = bottomInset.y;
return safeAreaInsets;
}
@end
#ifndef QT_NO_ACCESSIBILITY