From 03e9c6f4a62582837fc9f5961ecbccd0a3d1b5d6 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Tue, 16 Feb 2016 14:29:59 +0000 Subject: Add support for Apple tvOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass -xplatform macx-tvos-clang to configure to build. Builds device and simulator by default. Added ‘uikit’ platform with the common setup. Also added QT_PLATFORM_UIKIT define (undocumented). qmake config defines tvos (but not ios). tvOS is 64bits only (QT_ARCH is arm64) and requires bitcode to be embedded in the binary. A new ‘bitcode’ configuration was added. For ReleaseDevice builds (which get archived and push to the store), bitcode is actually embedded (-fembed-bitcode passed to clang). For all other configurations, only using bitcode markers to keep file size down (-fembed-bitcode-marker). Build disables Widgets in qtbase, and qtscript (unsupported, would require fixes to JavaScriptCore source code). Qpa same as on iOS but disables device orientation, status bar, clipboard, menus, dialogs which are not supported on tvOS. Change-Id: I645804fd933be0befddeeb43095a74d2c178b2ba Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/ios.pro | 36 +++++++++++++---------- src/plugins/platforms/ios/plugin.mm | 4 ++- src/plugins/platforms/ios/qiosfileenginefactory.h | 4 +++ src/plugins/platforms/ios/qiosglobal.h | 2 ++ src/plugins/platforms/ios/qiosglobal.mm | 2 ++ src/plugins/platforms/ios/qiosinputcontext.mm | 10 +++++++ src/plugins/platforms/ios/qiosintegration.h | 2 ++ src/plugins/platforms/ios/qiosintegration.mm | 10 +++++++ src/plugins/platforms/ios/qiosscreen.mm | 16 +++++++++- src/plugins/platforms/ios/qiostextresponder.mm | 2 ++ src/plugins/platforms/ios/qiostheme.mm | 12 ++++++++ src/plugins/platforms/ios/qiosviewcontroller.h | 4 +++ src/plugins/platforms/ios/qiosviewcontroller.mm | 13 +++++++- src/plugins/platforms/ios/quiview.mm | 15 ++++++++++ src/plugins/platforms/platforms.pro | 6 ++-- 15 files changed, 116 insertions(+), 22 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro index 7b0a573ffa..2c85a68f0b 100644 --- a/src/plugins/platforms/ios/ios.pro +++ b/src/plugins/platforms/ios/ios.pro @@ -1,7 +1,7 @@ TARGET = qios QT += core-private gui-private platformsupport-private -LIBS += -framework Foundation -framework UIKit -framework QuartzCore -framework AssetsLibrary -framework AudioToolbox +LIBS += -framework Foundation -framework UIKit -framework QuartzCore -framework AudioToolbox OBJECTIVE_SOURCES = \ plugin.mm \ @@ -19,15 +19,9 @@ OBJECTIVE_SOURCES = \ qiosglobal.mm \ qiosservices.mm \ quiview.mm \ - qiosclipboard.mm \ quiaccessibilityelement.mm \ qiosplatformaccessibility.mm \ - qiostextresponder.mm \ - qiosmenu.mm \ - qiosfileengineassetslibrary.mm \ - qiosfiledialog.mm \ - qiosmessagedialog.mm \ - qiostextinputoverlay.mm + qiostextresponder.mm HEADERS = \ qiosintegration.h \ @@ -44,16 +38,28 @@ HEADERS = \ qiosglobal.h \ qiosservices.h \ quiview.h \ - qiosclipboard.h \ quiaccessibilityelement.h \ qiosplatformaccessibility.h \ qiostextresponder.h \ - qiosmenu.h \ - qiosfileenginefactory.h \ - qiosfileengineassetslibrary.h \ - qiosfiledialog.h \ - qiosmessagedialog.h \ - qiostextinputoverlay.h + qiosfileenginefactory.h + +!tvos { + LIBS += -framework AssetsLibrary + OBJECTIVE_SOURCES += \ + qiosclipboard.mm \ + qiosmenu.mm \ + qiosfileengineassetslibrary.mm \ + qiosfiledialog.mm \ + qiosmessagedialog.mm \ + qiostextinputoverlay.mm + HEADERS += \ + qiosclipboard.h \ + qiosmenu.h \ + qiosfileengineassetslibrary.h \ + qiosfiledialog.h \ + qiosmessagedialog.h \ + qiostextinputoverlay.h +} OTHER_FILES = \ quiview_textinput.mm \ diff --git a/src/plugins/platforms/ios/plugin.mm b/src/plugins/platforms/ios/plugin.mm index b854dfdaa0..83760f2f39 100644 --- a/src/plugins/platforms/ios/plugin.mm +++ b/src/plugins/platforms/ios/plugin.mm @@ -54,8 +54,10 @@ class QIOSIntegrationPlugin : public QPlatformIntegrationPlugin QPlatformIntegration * QIOSIntegrationPlugin::create(const QString& system, const QStringList& paramList) { Q_UNUSED(paramList); - if (!system.compare(QLatin1String("ios"), Qt::CaseInsensitive)) + if (!system.compare(QLatin1String("ios"), Qt::CaseInsensitive) + || !system.compare(QLatin1String("tvos"), Qt::CaseInsensitive)) { return new QIOSIntegration; + } return 0; } diff --git a/src/plugins/platforms/ios/qiosfileenginefactory.h b/src/plugins/platforms/ios/qiosfileenginefactory.h index b71fa64460..87665ac603 100644 --- a/src/plugins/platforms/ios/qiosfileenginefactory.h +++ b/src/plugins/platforms/ios/qiosfileenginefactory.h @@ -51,8 +51,12 @@ public: { static QLatin1String assetsScheme("assets-library:"); +#ifndef Q_OS_TVOS if (fileName.toLower().startsWith(assetsScheme)) return new QIOSFileEngineAssetsLibrary(fileName); +#else + Q_UNUSED(fileName); +#endif return 0; } diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index 0fe81ceb91..c374dcfc6b 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -66,8 +66,10 @@ QRectF fromCGRect(const CGRect &rect); CGPoint toCGPoint(const QPointF &point); QPointF fromCGPoint(const CGPoint &point); +#ifndef Q_OS_TVOS Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation); UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation); +#endif int infoPlistValue(NSString* key, int defaultValue); diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index c2f3d6b9e1..57e86538ed 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -78,6 +78,7 @@ QPointF fromCGPoint(const CGPoint &point) return QPointF(point.x, point.y); } +#ifndef Q_OS_TVOS Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation) { Qt::ScreenOrientation qtOrientation; @@ -124,6 +125,7 @@ UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation) } return uiOrientation; } +#endif int infoPlistValue(NSString* key, int defaultValue) { diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index d553d16698..20d1670681 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -84,6 +84,7 @@ static QUIView *focusView() self.cancelsTouchesInView = NO; self.delaysTouchesEnded = NO; +#ifndef Q_OS_TVOS NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self @@ -101,6 +102,7 @@ static QUIView *focusView() [notificationCenter addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil]; +#endif } return self; @@ -342,6 +344,9 @@ void QIOSInputContext::clearCurrentFocusObject() void QIOSInputContext::updateKeyboardState(NSNotification *notification) { +#ifdef Q_OS_TVOS + Q_UNUSED(notification); +#else static CGRect currentKeyboardRect = CGRectZero; KeyboardState previousState = m_keyboardState; @@ -395,6 +400,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification) emitAnimatingChanged(); if (m_keyboardState.keyboardRect != previousState.keyboardRect) emitKeyboardRectChanged(); +#endif } bool QIOSInputContext::isInputPanelVisible() const @@ -514,7 +520,11 @@ void QIOSInputContext::scroll(int y) if (keyboardScrollIsActive && !originalWindowLevels.contains(window)) originalWindowLevels.insert(window, window.windowLevel); +#ifndef Q_OS_TVOS UIWindowLevel windowLevelAdjustment = keyboardScrollIsActive ? UIWindowLevelStatusBar : 0; +#else + UIWindowLevel windowLevelAdjustment = 0; +#endif window.windowLevel = originalWindowLevels.value(window) + windowLevelAdjustment; if (!keyboardScrollIsActive) diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index a50d9aa571..8009a37edb 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -102,7 +102,9 @@ public: private: QPlatformFontDatabase *m_fontDatabase; +#ifndef Q_OS_TVOS QPlatformClipboard *m_clipboard; +#endif QPlatformInputContext *m_inputContext; QTouchDevice *m_touchDevice; QIOSApplicationState m_applicationState; diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index fa12d54b28..297b549ec2 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -45,7 +45,9 @@ #include "qiosscreen.h" #include "qiosplatformaccessibility.h" #include "qioscontext.h" +#ifndef Q_OS_TVOS #include "qiosclipboard.h" +#endif #include "qiosinputcontext.h" #include "qiostheme.h" #include "qiosservices.h" @@ -72,7 +74,9 @@ QIOSIntegration *QIOSIntegration::instance() QIOSIntegration::QIOSIntegration() : m_fontDatabase(new QCoreTextFontDatabase) +#ifndef Q_OS_TVOS , m_clipboard(new QIOSClipboard) +#endif , m_inputContext(0) , m_platformServices(new QIOSServices) , m_accessibility(0) @@ -127,8 +131,10 @@ QIOSIntegration::~QIOSIntegration() delete m_fontDatabase; m_fontDatabase = 0; +#ifndef Q_OS_TVOS delete m_clipboard; m_clipboard = 0; +#endif QMacInternalPasteboardMime::destroyMimeTypes(); delete m_inputContext; @@ -217,7 +223,11 @@ QPlatformFontDatabase * QIOSIntegration::fontDatabase() const QPlatformClipboard *QIOSIntegration::clipboard() const { +#ifndef Q_OS_TVOS return m_clipboard; +#else + return 0; +#endif } QPlatformInputContext *QIOSIntegration::inputContext() const diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index bfd22abaa4..285b90bcd1 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -120,21 +120,25 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) self = [super init]; if (self) { m_screen = screen; +#ifndef Q_OS_TVOS [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; +#endif } return self; } - (void)dealloc { +#ifndef Q_OS_TVOS [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil]; +#endif [super dealloc]; } @@ -228,8 +232,13 @@ void QIOSScreen::updateProperties() QRect previousAvailableGeometry = m_availableGeometry; m_geometry = fromCGRect(m_uiScreen.bounds).toRect(); +#ifndef Q_OS_TVOS m_availableGeometry = fromCGRect(m_uiScreen.applicationFrame).toRect(); +#else + m_availableGeometry = fromCGRect(m_uiScreen.bounds).toRect(); +#endif +#ifndef Q_OS_TVOS if (m_uiScreen == [UIScreen mainScreen]) { Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); @@ -257,6 +266,7 @@ void QIOSScreen::updateProperties() m_availableGeometry = transform.mapRect(m_availableGeometry); } } +#endif if (m_geometry != previousGeometry) { QRectF physicalGeometry; @@ -335,7 +345,7 @@ qreal QIOSScreen::devicePixelRatio() const Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { CGRect nativeBounds = -#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) +#if !defined(Q_OS_TVOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0 ? m_uiScreen.nativeBounds : #endif m_uiScreen.bounds; @@ -348,6 +358,9 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const Qt::ScreenOrientation QIOSScreen::orientation() const { +#ifdef Q_OS_TVOS + return Qt::PrimaryOrientation; +#else // Auxiliary screens are always the same orientation as their primary orientation if (m_uiScreen != [UIScreen mainScreen]) return Qt::PrimaryOrientation; @@ -372,6 +385,7 @@ Qt::ScreenOrientation QIOSScreen::orientation() const } return toQtScreenOrientation(deviceOrientation); +#endif } void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index eb12739e98..ecc8d1ab1c 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -896,6 +896,7 @@ // text instead of just guessing... } +#ifndef Q_OS_TVOS - (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction { Q_UNUSED(position); @@ -915,6 +916,7 @@ return [NSDictionary dictionary]; return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey]; } +#endif - (NSDictionary *)markedTextStyle { diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index 486c146af9..83a8176478 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -51,9 +51,11 @@ #include #include +#ifndef Q_OS_TVOS #include "qiosmenu.h" #include "qiosfiledialog.h" #include "qiosmessagedialog.h" +#endif QT_BEGIN_NAMESPACE @@ -80,12 +82,20 @@ const QPalette *QIOSTheme::palette(QPlatformTheme::Palette type) const QPlatformMenuItem* QIOSTheme::createPlatformMenuItem() const { +#ifdef Q_OS_TVOS + return 0; +#else return new QIOSMenuItem(); +#endif } QPlatformMenu* QIOSTheme::createPlatformMenu() const { +#ifdef Q_OS_TVOS + return 0; +#else return new QIOSMenu(); +#endif } bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const @@ -102,12 +112,14 @@ bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const QPlatformDialogHelper *QIOSTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const { switch (type) { +#ifndef Q_OS_TVOS case FileDialog: return new QIOSFileDialog(); break; case MessageDialog: return new QIOSMessageDialog(); break; +#endif default: return 0; } diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h index e97aeb32ed..92c4e59d1a 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -46,12 +46,16 @@ class QIOSScreen; - (id)initWithQIOSScreen:(QIOSScreen *)screen; - (void)updateProperties; +#ifndef Q_OS_TVOS @property (nonatomic, assign) UIInterfaceOrientation lockedOrientation; +#endif // UIViewController @property (nonatomic, assign) BOOL prefersStatusBarHidden; +#ifndef Q_OS_TVOS @property (nonatomic, assign) UIStatusBarAnimation preferredStatusBarUpdateAnimation; @property (nonatomic, assign) UIStatusBarStyle preferredStatusBarStyle; +#endif @end diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index e975793d9c..77b0716cab 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -37,6 +37,7 @@ ** ****************************************************************************/ +#include "qiosglobal.h" #import "qiosviewcontroller.h" #include @@ -253,13 +254,15 @@ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent]; #endif - self.lockedOrientation = UIInterfaceOrientationUnknown; self.changingOrientation = NO; +#ifndef Q_OS_TVOS + self.lockedOrientation = UIInterfaceOrientationUnknown; // Status bar may be initially hidden at startup through Info.plist self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false); self.preferredStatusBarUpdateAnimation = UIStatusBarAnimationNone; self.preferredStatusBarStyle = UIStatusBarStyle(infoPlistValue(@"UIStatusBarStyle", UIStatusBarStyleDefault)); +#endif m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() { [self updateProperties]; @@ -284,6 +287,7 @@ { [super viewDidLoad]; +#ifndef Q_OS_TVOS NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(willChangeStatusBarFrame:) name:UIApplicationWillChangeStatusBarFrameNotification @@ -292,6 +296,7 @@ [center addObserver:self selector:@selector(didChangeStatusBarOrientation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:[UIApplication sharedApplication]]; +#endif } - (void)viewDidUnload @@ -304,7 +309,11 @@ - (BOOL)shouldAutorotate { +#ifndef Q_OS_TVOS return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation; +#else + return NO; +#endif } #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0) @@ -436,6 +445,7 @@ // All decisions are based on the the top level window focusWindow = qt_window_private(focusWindow)->topLevelWindow(); +#ifndef Q_OS_TVOS UIApplication *uiApplication = [UIApplication sharedApplication]; // -------------- Status bar style and visbility --------------- @@ -513,6 +523,7 @@ [UIViewController attemptRotationToDeviceOrientation]; } } +#endif } @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index e38be68343..b199f28149 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -44,7 +44,9 @@ #include "qiosviewcontroller.h" #include "qiostextresponder.h" #include "qioswindow.h" +#ifndef Q_OS_TVOS #include "qiosmenu.h" +#endif #include #include @@ -78,7 +80,9 @@ if (isQtApplication()) self.hidden = YES; +#ifndef Q_OS_TVOS self.multipleTouchEnabled = YES; +#endif if (QIOSIntegration::instance()->debugWindowManagement()) { static CGFloat hue = 0.0; @@ -324,6 +328,7 @@ // Touch positions are expected to be in QScreen global coordinates, and // as we already have the QWindow positioned at the right place, we can // just map from the local view position to global coordinates. + // tvOS: all touches start at the center of the screen and move from there. QPoint localViewPosition = fromCGPoint([uiTouch locationInView:self]).toPoint(); QPoint globalScreenPosition = m_qioswindow->mapToGlobal(localViewPosition); @@ -439,14 +444,24 @@ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { +#ifndef Q_OS_TVOS // Check first if QIOSMenu should handle the action before continuing up the responder chain return [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender] != 0; +#else + Q_UNUSED(action) + Q_UNUSED(sender) + return false; +#endif } - (id)forwardingTargetForSelector:(SEL)selector { Q_UNUSED(selector) +#ifndef Q_OS_TVOS return QIOSMenu::menuActionTarget(); +#else + return nil; +#endif } @end diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index cb3764f5df..a63fc28a66 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -10,10 +10,8 @@ contains(QT_CONFIG, xcb) { SUBDIRS += xcb } -mac { - ios: SUBDIRS += ios - else: SUBDIRS += cocoa -} +uikit: SUBDIRS += ios +osx: SUBDIRS += cocoa win32:!winrt: SUBDIRS += windows winrt: SUBDIRS += winrt -- cgit v1.2.3