summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/qiosviewcontroller.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/qiosviewcontroller.mm')
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm132
1 files changed, 90 insertions, 42 deletions
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 01bc84ae68..02c3a2d28d 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -1,40 +1,32 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -56,11 +48,55 @@
// -------------------------------------------------------------------------
+@interface QIOSViewController () {
+ @public
+ QPointer<QIOSScreen> m_screen;
+ BOOL m_updatingProperties;
+ QMetaObject::Connection m_focusWindowChangeConnection;
+}
+@property (nonatomic, assign) BOOL changingOrientation;
+@end
+
+// -------------------------------------------------------------------------
+
@interface QIOSDesktopManagerView : UIView
@end
@implementation QIOSDesktopManagerView
+- (void)didAddSubview:(UIView *)subview
+{
+ Q_UNUSED(subview);
+
+ QIOSScreen *screen = self.qtViewController->m_screen;
+
+ // The 'window' property of our view is not valid until the window
+ // has been shown, so we have to access it through the QIOSScreen.
+ UIWindow *uiWindow = screen->uiWindow();
+
+ if (uiWindow.hidden) {
+ // Associate UIWindow to screen and show it the first time a QWindow
+ // is mapped to the screen. For external screens this means disabling
+ // mirroring mode and presenting alternate content on the screen.
+ uiWindow.screen = screen->uiScreen();
+ uiWindow.hidden = NO;
+ }
+}
+
+- (void)willRemoveSubview:(UIView *)subview
+{
+ Q_UNUSED(subview);
+
+ Q_ASSERT(self.window);
+ UIWindow *uiWindow = self.window;
+
+ if (uiWindow.screen != [UIScreen mainScreen] && self.subviews.count == 1) {
+ // Removing the last view of an external screen, go back to mirror mode
+ uiWindow.screen = nil;
+ uiWindow.hidden = YES;
+ }
+}
+
- (void)layoutSubviews
{
for (int i = int(self.subviews.count) - 1; i >= 0; --i) {
@@ -75,7 +111,11 @@
- (void)layoutView:(QUIView *)view
{
QWindow *window = view.qwindow;
- Q_ASSERT(window->handle());
+
+ // Return early if the QIOSWindow is still constructing, as we'll
+ // take care of setting the correct window state in the constructor.
+ if (!window->handle())
+ return;
// Re-apply window states to update geometry
if (window->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
@@ -121,13 +161,6 @@
// -------------------------------------------------------------------------
-@interface QIOSViewController () {
- QIOSScreen *m_screen;
- BOOL m_updatingProperties;
-}
-@property (nonatomic, assign) BOOL changingOrientation;
-@end
-
@implementation QIOSViewController
- (id)initWithQIOSScreen:(QIOSScreen *)screen
@@ -155,14 +188,14 @@
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
#endif
+ self.lockedOrientation = UIInterfaceOrientationUnknown;
self.changingOrientation = NO;
- self.shouldAutorotate = [super shouldAutorotate];
// Status bar may be initially hidden at startup through Info.plist
self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false);
self.preferredStatusBarUpdateAnimation = UIStatusBarAnimationNone;
- QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
+ m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties];
});
}
@@ -170,6 +203,12 @@
return self;
}
+- (void)dealloc
+{
+ QObject::disconnect(m_focusWindowChangeConnection);
+ [super dealloc];
+}
+
- (void)loadView
{
self.view = [[[QIOSDesktopManagerView alloc] init] autorelease];
@@ -197,6 +236,11 @@
// -------------------------------------------------------------------------
+-(BOOL)shouldAutorotate
+{
+ return m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
+}
+
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0)
-(NSUInteger)supportedInterfaceOrientations
{
@@ -282,7 +326,8 @@
if (!QCoreApplication::instance())
return;
- m_screen->updateProperties();
+ if (m_screen)
+ m_screen->updateProperties();
}
// -------------------------------------------------------------------------
@@ -292,6 +337,14 @@
if (!isQtApplication())
return;
+ if (!m_screen || !m_screen->screen())
+ return;
+
+ // For now we only care about the main screen, as both the statusbar
+ // visibility and orientation is only appropriate for the main screen.
+ if (m_screen->uiScreen() != [UIScreen mainScreen])
+ return;
+
// Prevent recursion caused by updating the status bar appearance (position
// or visibility), which in turn may cause a layout of our subviews, and
// a reset of window-states, which themselves affect the view controller
@@ -347,16 +400,12 @@
// so we keep the status bar in sync with content orientation. This will ensure
// that the task bar (and associated gestures) are also rotated accordingly.
- if (self.shouldAutorotate) {
+ if (!self.lockedOrientation) {
// We are moving from Qt::PrimaryOrientation to an explicit orientation,
// so we need to store the current statusbar orientation, as we need it
// later when mapping screen coordinates for QScreen and for returning
// to Qt::PrimaryOrientation.
self.lockedOrientation = uiApplication.statusBarOrientation;
-
- // Calling setStatusBarOrientation only has an effect when auto-rotation is
- // disabled, which makes sense when there's an explicit content orientation.
- self.shouldAutorotate = NO;
}
[uiApplication setStatusBarOrientation:
@@ -368,16 +417,15 @@
// that auto-rotation should be enabled. But we may be coming out of
// a state of locked orientation, which needs some cleanup before we
// can enable auto-rotation again.
- if (!self.shouldAutorotate) {
+ if (self.lockedOrientation) {
// First we need to restore the statusbar to what it was at the
// time of locking the orientation, otherwise iOS will be very
// confused when it starts doing auto-rotation again.
- [uiApplication setStatusBarOrientation:
- UIInterfaceOrientation(self.lockedOrientation)
+ [uiApplication setStatusBarOrientation:self.lockedOrientation
animated:kAnimateContentOrientationChanges];
// Then we can re-enable auto-rotation
- self.shouldAutorotate = YES;
+ self.lockedOrientation = UIInterfaceOrientationUnknown;
// And finally let iOS rotate the root view to match the device orientation
[UIViewController attemptRotationToDeviceOrientation];