diff options
Diffstat (limited to 'src/plugins/platforms/ios')
35 files changed, 379 insertions, 170 deletions
diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro index 955f8d9642..5485ccc374 100644 --- a/src/plugins/platforms/ios/kernel.pro +++ b/src/plugins/platforms/ios/kernel.pro @@ -1,6 +1,9 @@ TARGET = qios -QT += core-private gui-private platformsupport-private +QT += \ + core-private gui-private \ + clipboard_support-private fontdatabase_support-private graphics_support-private + LIBS += -framework Foundation -framework UIKit -framework QuartzCore -framework AudioToolbox OBJECTIVE_SOURCES = \ @@ -19,14 +22,9 @@ OBJECTIVE_SOURCES = \ qiosglobal.mm \ qiosservices.mm \ quiview.mm \ - qiosclipboard.mm \ quiaccessibilityelement.mm \ qiosplatformaccessibility.mm \ - qiostextresponder.mm \ - qiosmenu.mm \ - qiosfiledialog.mm \ - qiosmessagedialog.mm \ - qiostextinputoverlay.mm + qiostextresponder.mm HEADERS = \ qiosintegration.h \ @@ -43,15 +41,26 @@ HEADERS = \ qiosglobal.h \ qiosservices.h \ quiview.h \ - qiosclipboard.h \ quiaccessibilityelement.h \ qiosplatformaccessibility.h \ qiostextresponder.h \ - qiosmenu.h \ - qiosfiledialog.h \ - qiosmessagedialog.h \ - qiostextinputoverlay.h + qiosfileenginefactory.h +!tvos { + LIBS += -framework AssetsLibrary + OBJECTIVE_SOURCES += \ + qiosclipboard.mm \ + qiosmenu.mm \ + qiosfiledialog.mm \ + qiosmessagedialog.mm \ + qiostextinputoverlay.mm + HEADERS += \ + qiosclipboard.h \ + qiosmenu.h \ + qiosfiledialog.h \ + qiosmessagedialog.h \ + qiostextinputoverlay.h +} OTHER_FILES = \ quiview_textinput.mm \ diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileenginefactory.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileenginefactory.h index 0397b20dfa..b143357aa5 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileenginefactory.h +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileenginefactory.h @@ -53,8 +53,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/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/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h index 5c37be5d38..1c072c0935 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.h +++ b/src/plugins/platforms/ios/qiosbackingstore.h @@ -42,7 +42,7 @@ #include <qpa/qplatformbackingstore.h> -#include <QtPlatformSupport/private/qrasterbackingstore_p.h> +#include <QtGraphicsSupport/private/qrasterbackingstore_p.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index fb0c9805f9..076e34c1a5 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -49,6 +49,8 @@ #include <QtDebug> +QT_BEGIN_NAMESPACE + class QIOSPaintDevice : public QOpenGLPaintDevice { public: @@ -64,6 +66,33 @@ void QIOSPaintDevice::ensureActiveTarget() m_backingStore->makeCurrent(); } +/*! + \class QIOSBackingStore + + \brief The QPlatformBackingStore on iOS. + + QBackingStore enables the use of QPainter to paint on a QWindow, as opposed + to rendering to a QWindow through the use of OpenGL with QOpenGLContext. + + Historically, the iOS port initially implemented the backing store by using + an QOpenGLPaintDevice as its paint device, triggering the use of the OpenGL + paint engine for QPainter based drawing. This was due to raster drawing + operations being too slow when not being NEON-optimized, and got the port + up and running quickly. + + As of 3e892e4a97, released in Qt 5.7, the backing store now uses a QImage, + for its paint device, giving normal raster-based QPainter operations, and + enabling features such as antialiased drawing. + + To account for regressions in performance, the old code path is still + available by setting the surface type of the QWindow to OpenGLSurface. + This surface type is normally used when rendering though QOpenGLContext, + but will in the case of QIOSBackingStore trigger the old OpenGL based + painter. + + This fallback path is not too intrusive, as the QImage based path still + uses OpenGL to composite the image at flush() time using composeAndFlush. +*/ QIOSBackingStore::QIOSBackingStore(QWindow *window) : QRasterBackingStore(window) , m_context(new QOpenGLContext) diff --git a/src/plugins/platforms/ios/qiosclipboard.h b/src/plugins/platforms/ios/qiosclipboard.h index b9ba4a2669..f3ccfcace0 100644 --- a/src/plugins/platforms/ios/qiosclipboard.h +++ b/src/plugins/platforms/ios/qiosclipboard.h @@ -40,10 +40,13 @@ #ifndef QIOSCLIPBOARD_H #define QIOSCLIPBOARD_H +#include <qpa/qplatformclipboard.h> + +#ifndef QT_NO_CLIPBOARD + #import <UIKit/UIKit.h> #include <QMimeData> -#include <qpa/qplatformclipboard.h> @class QUIClipboard; @@ -67,4 +70,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_CLIPBOARD + #endif // QIOSCLIPBOARD_H diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm index fb75cc793c..ef3b453bbf 100644 --- a/src/plugins/platforms/ios/qiosclipboard.mm +++ b/src/plugins/platforms/ios/qiosclipboard.mm @@ -39,7 +39,9 @@ #include "qiosclipboard.h" -#include <QtPlatformSupport/private/qmacmime_p.h> +#ifndef QT_NO_CLIPBOARD + +#include <QtClipboardSupport/private/qmacmime_p.h> #include <QtCore/QMimeData> #include <QtGui/QGuiApplication> @@ -247,3 +249,5 @@ bool QIOSClipboard::ownsMode(QClipboard::Mode mode) const } QT_END_NAMESPACE + +#endif // QT_NO_CLIPBOARD diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 50374dc951..2d5286e971 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -48,6 +48,8 @@ #import <OpenGLES/ES2/glext.h> #import <QuartzCore/CAEAGLLayer.h> +QT_BEGIN_NAMESPACE + Q_LOGGING_CATEGORY(lcQpaGLContext, "qt.qpa.glcontext"); QIOSContext::QIOSContext(QOpenGLContext *context) @@ -314,3 +316,4 @@ bool QIOSContext::isSharing() const #include "moc_qioscontext.cpp" +QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index 8d82364cc0..f49f81912e 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -493,7 +493,7 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) Q_UNUSED(activity); Q_ASSERT(activity == kCFRunLoopExit); - if (m_processEventLevel == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) { + if (m_processEventLevel == 1 && !currentEventLoop()->isRunning()) { qEventDispatcherDebug() << "Root runloop level exited"; interruptEventLoopExec(); } diff --git a/src/plugins/platforms/ios/qiosfiledialog.h b/src/plugins/platforms/ios/qiosfiledialog.h index 937b56e2f6..0b56bd20bf 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.h +++ b/src/plugins/platforms/ios/qiosfiledialog.h @@ -43,10 +43,10 @@ #include <QtCore/qeventloop.h> #include <qpa/qplatformdialoghelper.h> -QT_BEGIN_NAMESPACE - Q_FORWARD_DECLARE_OBJC_CLASS(UIViewController); +QT_BEGIN_NAMESPACE + class QIOSFileDialog : public QPlatformFileDialogHelper { public: diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index 0fe81ceb91..f74e3004cc 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -61,13 +61,10 @@ class QPlatformScreen; bool isQtApplication(); -CGRect toCGRect(const QRectF &rect); -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); @@ -77,6 +74,8 @@ QT_END_NAMESPACE + (id)currentFirstResponder; @end +QT_BEGIN_NAMESPACE + class FirstResponderCandidate : public QScopedValueRollback<UIResponder *> { public: @@ -87,4 +86,6 @@ private: static UIResponder *s_firstResponderCandidate; }; +QT_END_NAMESPACE + #endif // QIOSGLOBAL_H diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index c2f3d6b9e1..1482ffc7af 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -58,26 +58,7 @@ bool isQtApplication() return isQt; } -CGRect toCGRect(const QRectF &rect) -{ - return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); -} - -QRectF fromCGRect(const CGRect &rect) -{ - return QRectF(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); -} - -CGPoint toCGPoint(const QPointF &point) -{ - return CGPointMake(point.x(), point.y()); -} - -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 +105,7 @@ UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation) } return uiOrientation; } +#endif int infoPlistValue(NSString* key, int defaultValue) { @@ -132,6 +114,8 @@ int infoPlistValue(NSString* key, int defaultValue) return value ? [value intValue] : defaultValue; } +QT_END_NAMESPACE + // ------------------------------------------------------------------------- @interface QtFirstResponderEvent : UIEvent @@ -182,6 +166,8 @@ int infoPlistValue(NSString* key, int defaultValue) } @end +QT_BEGIN_NAMESPACE + FirstResponderCandidate::FirstResponderCandidate(UIResponder *responder) : QScopedValueRollback<UIResponder *>(s_firstResponderCandidate, responder) { diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h index ffb21d6afe..966d1a7e80 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.h +++ b/src/plugins/platforms/ios/qiosinputcontext.h @@ -52,13 +52,13 @@ const char kImePlatformDataInputAccessoryView[] = "inputAccessoryView"; const char kImePlatformDataHideShortcutsBar[] = "hideShortcutsBar"; const char kImePlatformDataReturnKeyType[] = "returnKeyType"; -QT_BEGIN_NAMESPACE - @class QIOSLocaleListener; @class QIOSKeyboardListener; @class QIOSTextInputResponder; @protocol KeyboardState; +QT_BEGIN_NAMESPACE + struct KeyboardState { KeyboardState() : diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index ef93d68cf0..68088540c6 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -97,14 +97,14 @@ static QUIView *focusView() @interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate> { @private - QIOSInputContext *m_context; + QT_PREPEND_NAMESPACE(QIOSInputContext) *m_context; } @property BOOL hasDeferredScrollToCursor; @end @implementation QIOSKeyboardListener -- (id)initWithQIOSInputContext:(QIOSInputContext *)context +- (id)initWithQIOSInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context { if (self = [super initWithTarget:self action:@selector(gestureStateChanged:)]) { @@ -117,6 +117,7 @@ static QUIView *focusView() self.cancelsTouchesInView = NO; self.delaysTouchesEnded = NO; +#ifndef Q_OS_TVOS NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self @@ -134,6 +135,7 @@ static QUIView *focusView() [notificationCenter addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil]; +#endif } return self; @@ -289,6 +291,8 @@ static QUIView *focusView() // ------------------------------------------------------------------------- +QT_BEGIN_NAMESPACE + Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties) { if (!properties) @@ -377,6 +381,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; @@ -412,7 +419,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification) m_keyboardState.animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; m_keyboardState.keyboardAnimating = m_keyboardState.animationDuration > 0 && !atEndOfKeyboardTransition; - qImDebug() << qPrintable(QString::fromNSString(notification.name)) << "from" << fromCGRect(frameBegin) << "to" << fromCGRect(frameEnd) + qImDebug() << qPrintable(QString::fromNSString(notification.name)) << "from" << QRectF::fromCGRect(frameBegin) << "to" << QRectF::fromCGRect(frameEnd) << "(curve =" << m_keyboardState.animationCurve << "duration =" << m_keyboardState.animationDuration << "s)"; } else { qImDebug("No notification to update keyboard state based on, just updating keyboard rect"); @@ -421,7 +428,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification) if (!focusView() || CGRectIsEmpty(currentKeyboardRect)) m_keyboardState.keyboardRect = QRectF(); else // QInputmethod::keyboardRectangle() is documented to be in window coordinates. - m_keyboardState.keyboardRect = fromCGRect([focusView() convertRect:currentKeyboardRect fromView:nil]); + m_keyboardState.keyboardRect = QRectF::fromCGRect([focusView() convertRect:currentKeyboardRect fromView:nil]); // Emit for all changed properties if (m_keyboardState.keyboardVisible != previousState.keyboardVisible) @@ -430,6 +437,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification) emitAnimatingChanged(); if (m_keyboardState.keyboardRect != previousState.keyboardRect) emitKeyboardRectChanged(); +#endif } bool QIOSInputContext::isInputPanelVisible() const @@ -549,7 +557,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) @@ -703,3 +715,5 @@ QLocale QIOSInputContext::locale() const { return QLocale(QString::fromNSString([[NSLocale currentLocale] objectForKey:NSLocaleIdentifier])); } + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h index 35f12bcb56..54c1a1dcb7 100644 --- a/src/plugins/platforms/ios/qiosintegration.h +++ b/src/plugins/platforms/ios/qiosintegration.h @@ -47,7 +47,9 @@ #include <QtCore/private/qfactoryloader_p.h> #include "qiosapplicationstate.h" +#ifndef Q_OS_TVOS #include "qiostextinputoverlay.h" +#endif QT_BEGIN_NAMESPACE @@ -71,7 +73,9 @@ public: QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; +#ifndef QT_NO_CLIPBOARD QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; +#endif QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; QPlatformServices *services() const Q_DECL_OVERRIDE; @@ -84,7 +88,9 @@ public: QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; QTouchDevice *touchDevice(); +#ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE; +#endif // Called from Objective-C class QIOSScreenTracker, which can't be friended void addScreen(QPlatformScreen *screen) { screenAdded(screen); } @@ -105,14 +111,18 @@ public: private: QPlatformFontDatabase *m_fontDatabase; +#ifndef Q_OS_TVOS QPlatformClipboard *m_clipboard; +#endif QPlatformInputContext *m_inputContext; QTouchDevice *m_touchDevice; QIOSApplicationState m_applicationState; QIOSServices *m_platformServices; mutable QPlatformAccessibility *m_accessibility; QFactoryLoader *m_optionalPlugins; +#ifndef Q_OS_TVOS QIOSTextInputOverlay m_textInputOverlay; +#endif bool m_debugWindowManagement; }; @@ -120,4 +130,3 @@ private: QT_END_NAMESPACE #endif - diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index a9435ef15a..e5b4d6da85 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" @@ -56,8 +58,8 @@ #include <qoffscreensurface.h> #include <qpa/qplatformoffscreensurface.h> -#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h> -#include <QtPlatformSupport/private/qmacmime_p.h> +#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h> +#include <QtClipboardSupport/private/qmacmime_p.h> #include <QDir> #import <AudioToolbox/AudioServices.h> @@ -73,7 +75,9 @@ QIOSIntegration *QIOSIntegration::instance() QIOSIntegration::QIOSIntegration() : m_fontDatabase(new QCoreTextFontDatabase) +#if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD) , m_clipboard(new QIOSClipboard) +#endif , m_inputContext(0) , m_platformServices(new QIOSServices) , m_accessibility(0) @@ -132,8 +136,10 @@ QIOSIntegration::~QIOSIntegration() delete m_fontDatabase; m_fontDatabase = 0; +#if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD) delete m_clipboard; m_clipboard = 0; +#endif QMacInternalPasteboardMime::destroyMimeTypes(); delete m_inputContext; @@ -223,10 +229,16 @@ QPlatformFontDatabase * QIOSIntegration::fontDatabase() const return m_fontDatabase; } +#ifndef QT_NO_CLIPBOARD QPlatformClipboard *QIOSIntegration::clipboard() const { +#ifndef Q_OS_TVOS return m_clipboard; +#else + return QPlatformIntegration::clipboard(); +#endif } +#endif QPlatformInputContext *QIOSIntegration::inputContext() const { @@ -274,12 +286,14 @@ QTouchDevice *QIOSIntegration::touchDevice() return m_touchDevice; } +#ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *QIOSIntegration::accessibility() const { if (!m_accessibility) m_accessibility = new QIOSPlatformAccessibility; return m_accessibility; } +#endif QPlatformNativeInterface *QIOSIntegration::nativeInterface() const { diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h index dab5720d48..b7371a5f49 100644 --- a/src/plugins/platforms/ios/qiosmenu.h +++ b/src/plugins/platforms/ios/qiosmenu.h @@ -68,7 +68,9 @@ public: void setRole(MenuRole role) Q_DECL_OVERRIDE; void setCheckable(bool) Q_DECL_OVERRIDE {} void setChecked(bool) Q_DECL_OVERRIDE {} +#ifndef QT_NO_SHORTCUT void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE; +#endif void setEnabled(bool enabled) Q_DECL_OVERRIDE; void setIconSize(int) Q_DECL_OVERRIDE {} diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 24d8559cc8..01cb3badea 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -304,10 +304,12 @@ void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role) m_role = role; } +#ifndef QT_NO_SHORTCUT void QIOSMenuItem::setShortcut(const QKeySequence &sequence) { m_shortcut = sequence; } +#endif void QIOSMenuItem::setEnabled(bool enabled) { @@ -551,6 +553,7 @@ QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &m for (int i = 0; i < menuItems.count(); ++i) { QIOSMenuItem *menuItem = menuItems.at(i); +#ifndef QT_NO_SHORTCUT QKeySequence shortcut = menuItem->m_shortcut; if ((shortcut == QKeySequence::Cut && [responder canPerformAction:@selector(cut:) withSender:nil]) || (shortcut == QKeySequence::Copy && [responder canPerformAction:@selector(copy:) withSender:nil]) @@ -564,6 +567,7 @@ QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &m || (shortcut == QKeySequence::Underline && [responder canPerformAction:@selector(toggleUnderline:) withSender:nil])) { continue; } +#endif filteredMenuItems.append(menuItem); } return filteredMenuItems; @@ -574,7 +578,7 @@ void QIOSMenu::repositionMenu() switch (m_effectiveMenuType) { case EditMenu: { UIView *view = reinterpret_cast<UIView *>(m_parentWindow->winId()); - [[UIMenuController sharedMenuController] setTargetRect:toCGRect(m_targetRect) inView:view]; + [[UIMenuController sharedMenuController] setTargetRect:m_targetRect.toCGRect() inView:view]; [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES]; break; } default: diff --git a/src/plugins/platforms/ios/qiosmessagedialog.h b/src/plugins/platforms/ios/qiosmessagedialog.h index 971c8d8b4d..e67e10a5e1 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.h +++ b/src/plugins/platforms/ios/qiosmessagedialog.h @@ -43,11 +43,11 @@ #include <QtCore/qeventloop.h> #include <qpa/qplatformdialoghelper.h> -QT_BEGIN_NAMESPACE - Q_FORWARD_DECLARE_OBJC_CLASS(UIAlertController); Q_FORWARD_DECLARE_OBJC_CLASS(UIAlertAction); +QT_BEGIN_NAMESPACE + class QIOSMessageDialog : public QPlatformMessageDialogHelper { public: diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.h b/src/plugins/platforms/ios/qiosplatformaccessibility.h index 2374457591..989eaa4fb8 100644 --- a/src/plugins/platforms/ios/qiosplatformaccessibility.h +++ b/src/plugins/platforms/ios/qiosplatformaccessibility.h @@ -42,6 +42,8 @@ #include <qpa/qplatformaccessibility.h> +#ifndef QT_NO_ACCESSIBILITY + QT_BEGIN_NAMESPACE class QIOSPlatformAccessibility: public QPlatformAccessibility @@ -56,3 +58,5 @@ public: QT_END_NAMESPACE #endif + +#endif diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm index 2ebe23c939..aef4216e03 100644 --- a/src/plugins/platforms/ios/qiosplatformaccessibility.mm +++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm @@ -39,6 +39,8 @@ #include "qiosplatformaccessibility.h" +#ifndef QT_NO_ACCESSIBILITY + #include <QtGui/QtGui> #include "qioswindow.h" @@ -63,7 +65,7 @@ void invalidateCache(QAccessibleInterface *iface) // when items get added or removed from the screen foreach (QWindow *win, QGuiApplication::topLevelWindows()) { if (win && win->handle()) { - QIOSWindow *window = static_cast<QIOSWindow*>(win->handle()); + QT_PREPEND_NAMESPACE(QIOSWindow) *window = static_cast<QT_PREPEND_NAMESPACE(QIOSWindow) *>(win->handle()); window->clearAccessibleCache(); } } @@ -85,3 +87,5 @@ void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *even break; } } + +#endif diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index cc83e7f3d2..9fcce42825 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -68,6 +68,8 @@ public: Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; void setOrientationUpdateMask(Qt::ScreenOrientations mask) Q_DECL_OVERRIDE; + QPixmap grabWindow(WId window, int x, int y, int width, int height) const override; + UIScreen *uiScreen() const; UIWindow *uiWindow() const; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index dc14698146..c518f9111d 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -47,6 +47,7 @@ #include "quiview.h" #include <QtGui/private/qwindow_p.h> +#include <private/qcoregraphics_p.h> #include <sys/sysctl.h> @@ -143,21 +144,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]; } @@ -171,6 +176,8 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) // ------------------------------------------------------------------------- +QT_BEGIN_NAMESPACE + /*! Returns the model identifier of the device. @@ -256,9 +263,14 @@ void QIOSScreen::updateProperties() QRect previousGeometry = m_geometry; QRect previousAvailableGeometry = m_availableGeometry; - m_geometry = fromCGRect(m_uiScreen.bounds).toRect(); - m_availableGeometry = fromCGRect(m_uiScreen.applicationFrame).toRect(); + 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 +#ifndef Q_OS_TVOS if (m_uiScreen == [UIScreen mainScreen]) { Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); @@ -286,6 +298,7 @@ void QIOSScreen::updateProperties() m_availableGeometry = transform.mapRect(m_availableGeometry); } } +#endif if (m_geometry != previousGeometry) { QRectF physicalGeometry; @@ -298,7 +311,7 @@ void QIOSScreen::updateProperties() // before being output on the physical display. We have to take this into account when // computing the physical size. Note that unlike the native bounds, the physical size // follows the primary orientation of the screen. - physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, fromCGRect(m_uiScreen.nativeBounds).toRect()); + physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, QRectF::fromCGRect(m_uiScreen.nativeBounds).toRect()); } else { physicalGeometry = QRectF(0, 0, m_geometry.width() * devicePixelRatio(), m_geometry.height() * devicePixelRatio()); } @@ -393,7 +406,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; @@ -406,6 +419,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; @@ -430,6 +446,7 @@ Qt::ScreenOrientation QIOSScreen::orientation() const } return toQtScreenOrientation(deviceOrientation); +#endif } void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) @@ -443,6 +460,38 @@ void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) } } +QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height) const +{ + if (window && ![reinterpret_cast<id>(window) isKindOfClass:[UIView class]]) + return QPixmap(); + + UIView *view = window ? reinterpret_cast<UIView *>(window) : m_uiWindow; + + if (width < 0) + width = qMax(view.bounds.size.width - x, CGFloat(0)); + if (height < 0) + height = qMax(view.bounds.size.height - y, CGFloat(0)); + + CGRect captureRect = [m_uiWindow convertRect:CGRectMake(x, y, width, height) fromView:view]; + captureRect = CGRectIntersection(captureRect, m_uiWindow.bounds); + + UIGraphicsBeginImageContextWithOptions(captureRect.size, NO, 0.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); + + // Draws the complete view hierarchy of m_uiWindow into the given rect, which + // needs to be the same aspect ratio as the m_uiWindow's size. Since we've + // translated the graphics context, and are potentially drawing into a smaller + // context than the full window, the resulting image will be a subsection of the + // full screen. + [m_uiWindow drawViewHierarchyInRect:m_uiWindow.bounds afterScreenUpdates:NO]; + + UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return QPixmap::fromImage(qt_mac_toQImage(screenshot.CGImage)); +} + UIScreen *QIOSScreen::uiScreen() const { return m_uiScreen; diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index 54c2e98d71..238d7addf6 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -136,7 +136,7 @@ static void executeBlockWithoutAnimation(Block block) // first responder, which is normally QIOSTextResponder. QRectF cr = qApp->inputMethod()->cursorRectangle(); QRectF ar = qApp->inputMethod()->anchorRectangle(); - CGRect targetRect = toCGRect(cr.united(ar)); + CGRect targetRect = cr.united(ar).toCGRect(); UIView *focusView = reinterpret_cast<UIView *>(qApp->focusWindow()->winId()); [[UIMenuController sharedMenuController] setTargetRect:targetRect inView:focusView]; [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES]; @@ -500,12 +500,12 @@ static void executeBlockWithoutAnimation(Block block) QGuiApplication::styleHints()->setCursorFlashTime(0); if (!_loupeLayer) [self createLoupe]; - [self updateFocalPoint:fromCGPoint(_lastTouchPoint)]; + [self updateFocalPoint:QPointF::fromCGPoint(_lastTouchPoint)]; _loupeLayer.visible = YES; break; case UIGestureRecognizerStateChanged: // Tell the sub class to move the loupe to the correct position - [self updateFocalPoint:fromCGPoint(_lastTouchPoint)]; + [self updateFocalPoint:QPointF::fromCGPoint(_lastTouchPoint)]; break; case UIGestureRecognizerStateEnded: // Restore cursor blinking, and hide the loupe @@ -530,12 +530,12 @@ static void executeBlockWithoutAnimation(Block block) - (QPointF)focalPoint { - return fromCGPoint([_loupeLayer.targetView convertPoint:_loupeLayer.focalPoint toView:_focusView]); + return QPointF::fromCGPoint([_loupeLayer.targetView convertPoint:_loupeLayer.focalPoint toView:_focusView]); } - (void)setFocalPoint:(QPointF)point { - _loupeLayer.focalPoint = [_loupeLayer.targetView convertPoint:toCGPoint(point) fromView:_focusView]; + _loupeLayer.focalPoint = [_loupeLayer.targetView convertPoint:point.toCGPoint() fromView:_focusView]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -552,7 +552,7 @@ static void executeBlockWithoutAnimation(Block block) // If the touch point is accepted by the sub class (e.g touch on cursor), we start a // press'n'hold timer that eventually will move the state to UIGestureRecognizerStateBegan. - if ([self acceptTouchesBegan:fromCGPoint(_firstTouchPoint)]) + if ([self acceptTouchesBegan:QPointF::fromCGPoint(_firstTouchPoint)]) _triggerStateBeganTimer.start(); else self.state = UIGestureRecognizerStateFailed; @@ -860,8 +860,8 @@ static void executeBlockWithoutAnimation(Block block) // Adjust handles and input rect to match the new selection QRectF inputRect = QGuiApplication::inputMethod()->inputItemClipRectangle(); - CGRect cursorRect = toCGRect(QGuiApplication::inputMethod()->cursorRectangle()); - CGRect anchorRect = toCGRect(QGuiApplication::inputMethod()->anchorRectangle()); + CGRect cursorRect = QGuiApplication::inputMethod()->cursorRectangle().toCGRect(); + CGRect anchorRect = QGuiApplication::inputMethod()->anchorRectangle().toCGRect(); if (!_multiLine) { // Resize the layer a bit bigger to ensure that the handles are @@ -870,7 +870,7 @@ static void executeBlockWithoutAnimation(Block block) inputRect.adjust(-margin / 2, -margin, margin / 2, margin); } - executeBlockWithoutAnimation(^{ _clipRectLayer.frame = toCGRect(inputRect); }); + executeBlockWithoutAnimation(^{ _clipRectLayer.frame = inputRect.toCGRect(); }); _cursorLayer.cursorRectangle = [self.focusView.layer convertRect:cursorRect toLayer:_clipRectLayer]; _anchorLayer.cursorRectangle = [self.focusView.layer convertRect:anchorRect toLayer:_clipRectLayer]; _cursorLayer.visible = YES; @@ -938,7 +938,7 @@ static void executeBlockWithoutAnimation(Block block) } QRectF inputRect = QGuiApplication::inputMethod()->inputItemClipRectangle(); - QPointF touchPos = fromCGPoint([static_cast<UITouch *>([touches anyObject]) locationInView:_focusView]); + QPointF touchPos = QPointF::fromCGPoint([static_cast<UITouch *>([touches anyObject]) locationInView:_focusView]); if (!inputRect.contains(touchPos)) self.state = UIGestureRecognizerStateFailed; @@ -947,7 +947,7 @@ static void executeBlockWithoutAnimation(Block block) - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - QPointF touchPos = fromCGPoint([static_cast<UITouch *>([touches anyObject]) locationInView:_focusView]); + QPointF touchPos = QPointF::fromCGPoint([static_cast<UITouch *>([touches anyObject]) locationInView:_focusView]); const QTransform mapToLocal = QGuiApplication::inputMethod()->inputItemTransform().inverted(); int cursorPosOnRelease = QInputMethod::queryFocusObject(Qt::ImCursorPosition, touchPos * mapToLocal).toInt(); diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h index f7450df4c8..77be2cf2fe 100644 --- a/src/plugins/platforms/ios/qiostextresponder.h +++ b/src/plugins/platforms/ios/qiostextresponder.h @@ -42,19 +42,23 @@ #include <QtCore/qstring.h> #include <QtGui/qevent.h> +QT_BEGIN_NAMESPACE + class QIOSInputContext; +QT_END_NAMESPACE + @interface QIOSTextInputResponder : UIResponder <UITextInputTraits, UIKeyInput, UITextInput> { @private - QIOSInputContext *m_inputContext; - QInputMethodQueryEvent *m_configuredImeState; + QT_PREPEND_NAMESPACE(QIOSInputContext) *m_inputContext; + QT_PREPEND_NAMESPACE(QInputMethodQueryEvent) *m_configuredImeState; QString m_markedText; BOOL m_inSendEventToFocusObject; BOOL m_inSelectionChange; } -- (id)initWithInputContext:(QIOSInputContext *)context; +- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context; - (BOOL)needsKeyboardReconfigure:(Qt::InputMethodQueries)updatedProperties; - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties; diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index e31584d581..e8d216fbc2 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -163,7 +163,7 @@ @implementation QIOSTextInputResponder -- (id)initWithInputContext:(QIOSInputContext *)inputContext +- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)inputContext { if (!(self = [self init])) return self; @@ -236,6 +236,8 @@ self.inputView = [[[WrapperView alloc] initWithView:inputView] autorelease]; if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>())) self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease]; + +#ifndef Q_OS_TVOS if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) { // According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar. @@ -247,6 +249,7 @@ self.inputAssistantItem.trailingBarButtonGroups = @[trailing]; } } +#endif self.undoManager.groupsByEvent = NO; [self rebuildUndoStack]; @@ -691,11 +694,7 @@ if (markedTextFormat.isEmpty()) { // There seems to be no way to query how the preedit text // should be drawn. So we need to hard-code the color. - QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; - if (iosVersion < QSysInfo::MV_IOS_7_0) - markedTextFormat.setBackground(QColor(235, 239, 247)); - else - markedTextFormat.setBackground(QColor(206, 221, 238)); + markedTextFormat.setBackground(QColor(206, 221, 238)); } QList<QInputMethodEvent::Attribute> attrs; @@ -823,7 +822,7 @@ [self sendEventToFocusObject:e]; } - return toCGRect(startRect.united(endRect)); + return startRect.united(endRect).toCGRect(); } - (NSArray *)selectionRectsForRange:(UITextRange *)range @@ -841,7 +840,7 @@ // Assume for now that position is always the same as // cursor index until a better API is in place: QRectF cursorRect = qApp->inputMethod()->cursorRectangle(); - return toCGRect(cursorRect); + return cursorRect.toCGRect(); } - (void)replaceRange:(UITextRange *)range withText:(NSString *)text @@ -908,6 +907,7 @@ // text instead of just guessing... } +#ifndef Q_OS_TVOS - (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction { Q_UNUSED(position); @@ -927,6 +927,7 @@ return [NSDictionary dictionary]; return [NSDictionary dictionaryWithObject:uifont forKey:NSFontAttributeName]; } +#endif - (NSDictionary *)markedTextStyle { diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index 486c146af9..91980d3f35 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -44,16 +44,18 @@ #include <QtGui/QFont> -#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h> +#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> #include <UIKit/UIFont.h> #include <UIKit/UIInterface.h> +#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..07d5535e1a 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -38,20 +38,27 @@ ****************************************************************************/ #import <UIKit/UIKit.h> +#include <QtCore/QtGlobal> + +QT_BEGIN_NAMESPACE class QIOSScreen; +QT_END_NAMESPACE + @interface QIOSViewController : UIViewController -- (id)initWithQIOSScreen:(QIOSScreen *)screen; +- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen; - (void)updateProperties; +#ifndef Q_OS_TVOS @property (nonatomic, assign) UIInterfaceOrientation lockedOrientation; // UIViewController @property (nonatomic, assign) BOOL prefersStatusBarHidden; @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 fd88664d15..c47b6d68b1 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 <QtCore/qscopedvaluerollback.h> @@ -57,7 +58,7 @@ @interface QIOSViewController () { @public - QPointer<QIOSScreen> m_screen; + QPointer<QT_PREPEND_NAMESPACE(QIOSScreen)> m_screen; BOOL m_updatingProperties; QMetaObject::Connection m_focusWindowChangeConnection; } @@ -125,7 +126,7 @@ { Q_UNUSED(subview); - QIOSScreen *screen = self.qtViewController->m_screen; + QT_PREPEND_NAMESPACE(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. @@ -228,42 +229,27 @@ @implementation QIOSViewController +#ifndef Q_OS_TVOS @synthesize prefersStatusBarHidden; @synthesize preferredStatusBarUpdateAnimation; @synthesize preferredStatusBarStyle; +#endif -- (id)initWithQIOSScreen:(QIOSScreen *)screen +- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen { if (self = [self init]) { m_screen = screen; -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0) - QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion; - - // We prefer to keep the root viewcontroller in fullscreen layout, so that - // we don't have to compensate for the viewcontroller position. This also - // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout - // is the only way. - if (iosVersion < QSysInfo::MV_IOS_7_0) - self.wantsFullScreenLayout = YES; - - // Use translucent statusbar by default on iOS6 iPhones (unless the user changed - // the default in the Info.plist), so that windows placed under the stausbar are - // still visible, just like on iOS7. - if (screen->uiScreen() == [UIScreen mainScreen] - && iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0 - && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone - && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault) - [[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]; @@ -288,6 +274,7 @@ { [super viewDidLoad]; +#ifndef Q_OS_TVOS NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(willChangeStatusBarFrame:) name:UIApplicationWillChangeStatusBarFrameNotification @@ -296,6 +283,7 @@ [center addObserver:self selector:@selector(didChangeStatusBarOrientation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:[UIApplication sharedApplication]]; +#endif } - (void)viewDidUnload @@ -308,10 +296,13 @@ - (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) - (NSUInteger)supportedInterfaceOrientations { // As documented by Apple in the iOS 6.0 release notes, setStatusBarOrientation:animated: @@ -322,15 +313,6 @@ // supportedInterfaceOrientations says, which states that the method should not return 0. return [self shouldAutorotate] ? UIInterfaceOrientationMaskAll : 0; } -#endif - -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - Q_UNUSED(interfaceOrientation); - return [self shouldAutorotate]; -} -#endif - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration { @@ -439,6 +421,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 --------------- @@ -447,30 +430,16 @@ if (focusWindow->flags() & Qt::MaximizeUsingFullscreenGeometryHint) self.preferredStatusBarStyle = UIStatusBarStyleDefault; else - self.preferredStatusBarStyle = QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 ? - UIStatusBarStyleLightContent : UIStatusBarStyleBlackTranslucent; - - if (self.preferredStatusBarStyle != oldStatusBarStyle) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) - [self setNeedsStatusBarAppearanceUpdate]; - else - [uiApplication setStatusBarStyle:self.preferredStatusBarStyle]; - } + self.preferredStatusBarStyle = UIStatusBarStyleLightContent; + + if (self.preferredStatusBarStyle != oldStatusBarStyle) + [self setNeedsStatusBarAppearanceUpdate]; 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 setStatusBarHidden:self.prefersStatusBarHidden - withAnimation:self.preferredStatusBarUpdateAnimation]; - } - + [self setNeedsStatusBarAppearanceUpdate]; [self.view setNeedsLayout]; } @@ -516,6 +485,7 @@ [UIViewController attemptRotationToDeviceOrientation]; } } +#endif } @end diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index afc2f0f89d..81fad420f6 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -48,10 +48,10 @@ class QIOSContext; class QIOSWindow; -QT_BEGIN_NAMESPACE - @class QUIView; +QT_BEGIN_NAMESPACE + class QIOSWindow : public QObject, public QPlatformWindow { Q_OBJECT diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 8099d13147..8ff0dfbd5f 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -54,6 +54,8 @@ #include <QtDebug> +QT_BEGIN_NAMESPACE + QIOSWindow::QIOSWindow(QWindow *window) : QPlatformWindow(window) , m_view([[QUIView alloc] initWithQIOSWindow:this]) @@ -211,7 +213,7 @@ void QIOSWindow::applyGeometry(const QRect &rect) // The baseclass takes care of persisting this for us. QPlatformWindow::setGeometry(rect); - m_view.frame = toCGRect(rect); + m_view.frame = rect.toCGRect(); // iOS will automatically trigger -[layoutSubviews:] for resize, // but not for move, so we force it just in case. diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h index 1a9ae2a1a7..03abf5407e 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.h +++ b/src/plugins/platforms/ios/quiaccessibilityelement.h @@ -43,6 +43,8 @@ #import <UIKit/UIKit.h> #import <QtGui/QtGui> +#ifndef QT_NO_ACCESSIBILITY + @interface QMacAccessibilityElement : UIAccessibilityElement {} @@ -54,3 +56,4 @@ @end #endif +#endif diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm index 39a879fc23..a26ba61b3c 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.mm +++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm @@ -39,6 +39,8 @@ #include "quiaccessibilityelement.h" +#ifndef QT_NO_ACCESSIBILITY + #include "private/qaccessiblecache_p.h" @implementation QMacAccessibilityElement @@ -61,7 +63,7 @@ QAccessibleCache *cache = QAccessibleCache::instance(); - QMacAccessibilityElement *element = cache->elementForId(anId); + QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element = cache->elementForId(anId); if (!element) { Q_ASSERT(QAccessible::accessibleInterface(anId)); element = [[self alloc] initWithId:anId withAccessibilityContainer: view]; @@ -221,3 +223,5 @@ } @end + +#endif diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index fdaae943d8..1500f0b41c 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -44,14 +44,18 @@ #include <qpa/qwindowsysteminterface.h> +QT_BEGIN_NAMESPACE + class QIOSWindow; +QT_END_NAMESPACE + @class QIOSViewController; @interface QUIView : UIView { @public - QIOSWindow *m_qioswindow; + QT_PREPEND_NAMESPACE(QIOSWindow) *m_qioswindow; @private QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches; int m_nextTouchId; @@ -60,7 +64,7 @@ class QIOSWindow; NSMutableArray *m_accessibleElements; }; -- (id)initWithQIOSWindow:(QIOSWindow *)window; +- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window; - (void)sendUpdatedExposeEvent; - (BOOL)isActiveWindow; @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 9c7acc9278..2a1444e9e5 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -44,10 +44,13 @@ #include "qiosviewcontroller.h" #include "qiostextresponder.h" #include "qioswindow.h" +#ifndef Q_OS_TVOS #include "qiosmenu.h" +#endif #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qwindow_p.h> +#include <qpa/qwindowsysteminterface_p.h> @implementation QUIView @@ -56,9 +59,9 @@ return [CAEAGLLayer class]; } -- (id)initWithQIOSWindow:(QIOSWindow *)window +- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window { - if (self = [self initWithFrame:toCGRect(window->geometry())]) + if (self = [self initWithFrame:window->geometry().toCGRect()]) m_qioswindow = window; m_accessibleElements = [[NSMutableArray alloc] init]; @@ -78,7 +81,9 @@ if (isQtApplication()) self.hidden = YES; +#ifndef Q_OS_TVOS self.multipleTouchEnabled = YES; +#endif if (QIOSIntegration::instance()->debugWindowManagement()) { static CGFloat hue = 0.0; @@ -149,7 +154,7 @@ // from what we end up with after applying window constraints. QRect requestedGeometry = m_qioswindow->geometry(); - QRect actualGeometry = fromCGRect(self.frame).toRect(); + QRect actualGeometry = QRectF::fromCGRect(self.frame).toRect(); // Persist the actual/new geometry so that QWindow::geometry() can // be queried on the resize event. @@ -159,8 +164,7 @@ requestedGeometry : qt_window_private(m_qioswindow->window())->geometry; QWindow *window = m_qioswindow->window(); - QWindowSystemInterface::handleGeometryChange(window, actualGeometry, previousGeometry); - QWindowSystemInterface::flushWindowSystemEvents(window->inherits("QWidgetWindow") ? QEventLoop::ExcludeUserInputEvents : QEventLoop::AllEvents); + QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, actualGeometry, previousGeometry); if (actualGeometry.size() != previousGeometry.size()) { // Trigger expose event on resize @@ -184,7 +188,7 @@ QRegion region; if (m_qioswindow->isExposed()) { - QSize bounds = fromCGRect(self.layer.bounds).toRect().size(); + QSize bounds = QRectF::fromCGRect(self.layer.bounds).toRect().size(); Q_ASSERT(m_qioswindow->geometry().size() == bounds); Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible()); @@ -192,8 +196,7 @@ region = QRect(QPoint(), bounds); } - QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), region); } // ------------------------------------------------------------------------- @@ -218,13 +221,10 @@ qImDebug() << m_qioswindow->window() << "became first responder"; - if (qGuiApp->focusWindow() != m_qioswindow->window()) { - QWindowSystemInterface::handleWindowActivated(m_qioswindow->window()); - QWindowSystemInterface::flushWindowSystemEvents(); - } else { - qImDebug() << m_qioswindow->window() - << "already active, not sending window activation"; - } + if (qGuiApp->focusWindow() != m_qioswindow->window()) + QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window()); + else + qImDebug() << m_qioswindow->window() << "already active, not sending window activation"; return YES; } @@ -259,10 +259,8 @@ qImDebug() << m_qioswindow->window() << "resigned first responder"; UIResponder *newResponder = FirstResponderCandidate::currentCandidate(); - if ([self responderShouldTriggerWindowDeactivation:newResponder]) { - QWindowSystemInterface::handleWindowActivated(0); - QWindowSystemInterface::flushWindowSystemEvents(); - } + if ([self responderShouldTriggerWindowDeactivation:newResponder]) + QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(0); return YES; } @@ -324,7 +322,8 @@ // 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. - QPoint localViewPosition = fromCGPoint([uiTouch locationInView:self]).toPoint(); + // tvOS: all touches start at the center of the screen and move from there. + QPoint localViewPosition = QPointF::fromCGPoint([uiTouch locationInView:self]).toPoint(); QPoint globalScreenPosition = m_qioswindow->mapToGlobal(localViewPosition); touchPoint.area = QRectF(globalScreenPosition, QSize(0, 0)); @@ -351,10 +350,8 @@ - (void)sendTouchEventWithTimestamp:(ulong)timeStamp { - // Send touch event synchronously QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -432,22 +429,80 @@ NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime]; - // Send cancel touch event synchronously QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration()); - QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice()); - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::handleTouchCancelEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice()); +} + +- (int)mapPressTypeToKey:(UIPress*)press +{ + switch (press.type) { + case UIPressTypeUpArrow: return Qt::Key_Up; + case UIPressTypeDownArrow: return Qt::Key_Down; + case UIPressTypeLeftArrow: return Qt::Key_Left; + case UIPressTypeRightArrow: return Qt::Key_Right; + case UIPressTypeSelect: return Qt::Key_Select; + case UIPressTypeMenu: return Qt::Key_Menu; + case UIPressTypePlayPause: return Qt::Key_MediaTogglePlayPause; + } + return Qt::Key_unknown; +} + +- (bool)processPresses:(NSSet *)presses withType:(QEvent::Type)type { + // Presses on Menu button will generate a Menu key event. By default, not handling + // this event will cause the application to return to Headboard (tvOS launcher). + // When handling the event (for example, as a back button), both press and + // release events must be handled accordingly. + + bool handled = false; + for (UIPress* press in presses) { + int key = [self mapPressTypeToKey:press]; + if (key == Qt::Key_unknown) + continue; + if (QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), type, key, Qt::NoModifier)) + handled = true; + } + + return handled; +} + +- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event +{ + if (![self processPresses:presses withType:QEvent::KeyPress]) + [super pressesBegan:presses withEvent:event]; +} + +- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event +{ + if (![self processPresses:presses withType:QEvent::KeyPress]) + [super pressesChanged:presses withEvent:event]; +} + +- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event +{ + if (![self processPresses:presses withType:QEvent::KeyRelease]) + [super pressesEnded:presses withEvent:event]; } - (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 @@ -457,7 +512,7 @@ - (QWindow *)qwindow { if ([self isKindOfClass:[QUIView class]]) { - if (QIOSWindow *w = static_cast<QUIView *>(self)->m_qioswindow) + if (QT_PREPEND_NAMESPACE(QIOSWindow) *w = static_cast<QUIView *>(self)->m_qioswindow) return w->window(); } return nil; @@ -484,5 +539,7 @@ @end +#ifndef QT_NO_ACCESSIBILITY // Include category as an alternative to using -ObjC (Apple QA1490) #include "quiview_accessibility.mm" +#endif |