iOS: Move statusbar visibility handling to QIOSViewController

It doesn't belong in QIOScreen, and simplifies the flow when changing
the focus window or the window state of the focus window. Both will
result in calling updateProperties on the view-controller, which will
re-configure the statusbar visibility and hide/show it as appropriate,
before triggering a re-layout of its own view, which will in turn
trigger an update of the screen properties based on the new statusbar
state, before re-layouting of QWindow based on the new screen state.

Change-Id: I89077a3fb5f843949ce833e4e727d2c753ea2eb6
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
Tor Arne Vestbø 2014-09-26 15:06:46 +02:00
parent c027175021
commit 231a4a1101
7 changed files with 71 additions and 59 deletions

View File

@ -66,9 +66,6 @@ public:
void updateProperties();
public slots:
void updateStatusBarVisibility();
private:
UIScreen *m_uiScreen;
UIWindow *m_uiWindow;

View File

@ -225,8 +225,6 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
}
}
connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSScreen::updateStatusBarVisibility);
updateProperties();
}
@ -254,44 +252,6 @@ void QIOSScreen::updateProperties()
}
}
void QIOSScreen::updateStatusBarVisibility()
{
if (!isQtApplication())
return;
QWindow *focusWindow = QGuiApplication::focusWindow();
// If we don't have a focus window we leave the status
// bar as is, so that the user can activate a new window
// with the same window state without the status bar jumping
// back and forth.
if (!focusWindow)
return;
UIView *view = reinterpret_cast<UIView *>(focusWindow->handle()->winId());
QIOSViewController *viewController = static_cast<QIOSViewController *>(view.viewController);
bool currentStatusBarVisibility = [UIApplication sharedApplication].statusBarHidden;
if (viewController.prefersStatusBarHidden == currentStatusBarVisibility)
return;
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
[viewController setNeedsStatusBarAppearanceUpdate];
dispatch_async(dispatch_get_main_queue(), ^{
updateProperties();
});
} else
#endif
{
[[UIApplication sharedApplication]
setStatusBarHidden:[viewController prefersStatusBarHidden]
withAnimation:UIStatusBarAnimationNone];
updateProperties();
}
}
QRect QIOSScreen::geometry() const
{
return m_geometry;

View File

@ -40,8 +40,9 @@ class QIOSScreen;
}
@property (nonatomic, assign) BOOL changingOrientation;
@property (nonatomic, assign) BOOL prefersStatusBarHidden;
- (id)initWithQIOSScreen:(QIOSScreen *)screen;
- (BOOL)prefersStatusBarHidden;
- (void)updateProperties;
@end

View File

@ -147,6 +147,13 @@
#endif
self.changingOrientation = NO;
// Status bar may be initially hidden at startup through Info.plist
self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false);
QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties];
});
}
return self;
@ -173,6 +180,49 @@
[super viewDidUnload];
}
// -------------------------------------------------------------------------
- (void)updateProperties
{
if (!isQtApplication())
return;
QWindow *focusWindow = QGuiApplication::focusWindow();
// If we don't have a focus window we leave the statusbar
// as is, so that the user can activate a new window with
// the same window state without the status bar jumping
// back and forth.
if (!focusWindow)
return;
// We only care about changes to focusWindow that involves our screen
if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen)
return;
// All decisions are based on the the top level window
focusWindow = qt_window_private(focusWindow)->topLevelWindow();
bool currentStatusBarVisibility = self.prefersStatusBarHidden;
self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen;
if (self.prefersStatusBarHidden != currentStatusBarVisibility) {
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
[self setNeedsStatusBarAppearanceUpdate];
} else
#endif
{
[[UIApplication sharedApplication]
setStatusBarHidden:self.prefersStatusBarHidden
withAnimation:UIStatusBarAnimationNone];
}
[self.view setNeedsLayout];
}
}
// -------------------------------------------------------------------------
-(BOOL)shouldAutorotate
{
// Until a proper orientation and rotation API is in place, we always auto rotate.
@ -261,17 +311,5 @@
}
#endif
- (BOOL)prefersStatusBarHidden
{
static bool hiddenFromPlist = infoPlistValue(@"UIStatusBarHidden", false);
if (hiddenFromPlist)
return YES;
QWindow *focusWindow = QGuiApplication::focusWindow();
if (!focusWindow)
return [UIApplication sharedApplication].statusBarHidden;
return qt_window_private(focusWindow)->topLevelWindow()->windowState() == Qt::WindowFullScreen;
}
@end

View File

@ -119,7 +119,6 @@ void QIOSWindow::setVisible(bool visible)
if (visible) {
requestActivateWindow();
static_cast<QIOSScreen *>(screen())->updateStatusBarVisibility();
} else {
// Activate top-most visible QWindow:
NSArray *subviews = m_view.viewController.view.subviews;
@ -202,7 +201,7 @@ void QIOSWindow::setWindowState(Qt::WindowState state)
qt_window_private(window())->windowState = state;
if (window()->isTopLevel() && window()->isVisible() && window()->isActive())
static_cast<QIOSScreen *>(screen())->updateStatusBarVisibility();
[m_view.qtViewController updateProperties];
switch (state) {
case Qt::WindowNoState:

View File

@ -40,6 +40,8 @@
class QIOSWindow;
@class QIOSViewController;
@interface QUIView : UIView
{
@public
@ -50,7 +52,7 @@ class QIOSWindow;
@private
NSMutableArray *m_accessibleElements;
}
};
- (id)initWithQIOSWindow:(QIOSWindow *)window;
- (void)sendUpdatedExposeEvent;
@ -59,3 +61,8 @@ class QIOSWindow;
@interface QUIView (Accessibility)
- (void)clearAccessibleCache;
@end
@interface QUIView (QtHelpers)
- (QIOSViewController*)qtViewController;
@end

View File

@ -43,6 +43,7 @@
#include "qiosglobal.h"
#include "qiosintegration.h"
#include "qiosviewcontroller.h"
#include "qioswindow.h"
#include "qiosmenu.h"
@ -368,6 +369,15 @@
return nil;
}
- (QIOSViewController*)qtViewController
{
UIViewController *vc = self.viewController;
if ([vc isKindOfClass:QIOSViewController.class])
return static_cast<QIOSViewController *>(vc);
return nil;
}
@end
// Include category as an alternative to using -ObjC (Apple QA1490)