diff options
Diffstat (limited to 'src/plugins/platforms/ios')
-rw-r--r-- | src/plugins/platforms/ios/kernel.pro | 5 | ||||
-rw-r--r-- | src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro | 6 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosbackingstore.mm | 12 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosinputcontext.mm | 49 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosintegration.mm | 3 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosmessagedialog.mm | 3 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosscreen.mm | 12 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiostextinputoverlay.mm | 4 | ||||
-rw-r--r-- | src/plugins/platforms/ios/quiview.mm | 26 |
9 files changed, 89 insertions, 31 deletions
diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro index caafe89730..71257d09f7 100644 --- a/src/plugins/platforms/ios/kernel.pro +++ b/src/plugins/platforms/ios/kernel.pro @@ -1,5 +1,10 @@ TARGET = qios +# QTBUG-42937: Work around linker errors caused by circular +# dependencies between the iOS platform plugin and the user +# application's main() when the plugin is a shared library. +qtConfig(shared): CONFIG += static + QT += \ core-private gui-private \ clipboard_support-private fontdatabase_support-private graphics_support-private diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro index f4588dda03..7379765599 100644 --- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro +++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro @@ -1,7 +1,11 @@ TARGET = qiosnsphotolibrarysupport +# QTBUG-42937: Since the iOS plugin (kernel) is +# static, this plugin needs to be static as well. +qtConfig(shared): CONFIG += static + QT += core gui gui-private -LIBS += -framework UIKit -framework AssetsLibrary +LIBS += -framework Foundation -framework UIKit -framework AssetsLibrary HEADERS = \ qiosfileengineassetslibrary.h \ diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index 076e34c1a5..96be28af81 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -122,7 +122,17 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window) QIOSBackingStore::~QIOSBackingStore() { - delete m_context; + if (window()->surfaceType() == QSurface::RasterGLSurface) { + // We're using composeAndFlush from QPlatformBackingStore, which + // need to clean up any textures in its destructor, so make the + // context current and keep it alive until QPlatformBackingStore + // has cleaned up everything. + makeCurrent(); + m_context->deleteLater(); + } else { + delete m_context; + } + delete m_glDevice; } diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 68088540c6..237077400b 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -498,15 +498,32 @@ void QIOSInputContext::scrollToCursor() return; } - const int margin = 20; - QRectF translatedCursorPos = qApp->inputMethod()->cursorRectangle(); - translatedCursorPos.translate(focusView().qwindow->geometry().topLeft()); - - qreal keyboardY = [rootView convertRect:m_keyboardState.keyboardEndRect fromView:nil].origin.y; - int statusBarY = qGuiApp->primaryScreen()->availableGeometry().y(); + QWindow *focusWindow = qApp->focusWindow(); + QRect cursorRect = qApp->inputMethod()->cursorRectangle().translated(focusWindow->geometry().topLeft()).toRect(); + if (cursorRect.isNull()) { + scroll(0); + return; + } - scroll((translatedCursorPos.bottomLeft().y() < keyboardY - margin) ? 0 - : qMin(rootView.bounds.size.height - keyboardY, translatedCursorPos.y() - statusBarY - margin)); + // Add some padding so that the cusor does not end up directly above the keyboard + static const int kCursorRectPadding = 20; + cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding); + + // We explicitly ask for the geometry of the screen instead of the availableGeometry, + // as we hide the statusbar when scrolling the screen, so the available geometry will + // include the space taken by the status bar at the moment. + QRect screenGeometry = focusWindow->screen()->geometry(); + QRect keyboardGeometry = QRectF::fromCGRect(m_keyboardState.keyboardEndRect).toRect(); + QRect availableGeometry = (QRegion(screenGeometry) - keyboardGeometry).boundingRect(); + + if (!availableGeometry.contains(cursorRect, true)) { + qImDebug() << "cursor rect" << cursorRect << "not fully within" << availableGeometry; + int scrollToCenter = -(availableGeometry.center() - cursorRect.center()).y(); + int scrollToBottom = focusWindow->screen()->geometry().bottom() - availableGeometry.bottom(); + scroll(qMin(scrollToCenter, scrollToBottom)); + } else { + scroll(0); + } } void QIOSInputContext::scroll(int y) @@ -519,6 +536,8 @@ void QIOSInputContext::scroll(int y) if (CATransform3DEqualToTransform(translationTransform, rootView.layer.sublayerTransform)) return; + qImDebug() << "scrolling root view to y =" << -y; + QPointer<QIOSInputContext> self = this; [UIView animateWithDuration:m_keyboardState.animationDuration delay:0 options:(m_keyboardState.animationCurve << 16) | UIViewAnimationOptionBeginFromCurrentState @@ -631,11 +650,21 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow) */ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties) { + qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject(); + + // Changes to the focus object should always result in a call to setFocusObject(), + // triggering a reset() which will update all the properties based on the new + // focus object. We try to detect code paths that fail this assertion and smooth + // over the situation by doing a manual update of the focus object. + if (qApp->focusObject() != m_imeState.focusObject && updatedProperties != Qt::ImQueryAll) { + qWarning() << "stale focus object" << m_imeState.focusObject << ", doing manual update"; + setFocusObject(qApp->focusObject()); + return; + } + // Mask for properties that we are interested in and see if any of them changed updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImEnterKeyType | Qt::ImPlatformData); - qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject(); - // Perform update first, so we can trust the value of inputMethodAccepted() Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties); diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index e5b4d6da85..fbf167b514 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -61,6 +61,7 @@ #include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h> #include <QtClipboardSupport/private/qmacmime_p.h> #include <QDir> +#include <QOperatingSystemVersion> #import <AudioToolbox/AudioServices.h> @@ -119,7 +120,7 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; } diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm index 50d5442f17..4f0c667861 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.mm +++ b/src/plugins/platforms/ios/qiosmessagedialog.mm @@ -39,6 +39,7 @@ #import <UIKit/UIKit.h> +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/qwindow.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> @@ -109,7 +110,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win if (m_alertController // Ensure that the dialog is not showing already || !options() // Some message dialogs don't have options (QErrorMessage) || windowModality == Qt::NonModal // We can only do modal dialogs - || QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) // API limitation + || QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) // API limitation return false; m_alertController = [[UIAlertController diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index c518f9111d..3514bf63bb 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -45,6 +45,7 @@ #include "qiosapplicationdelegate.h" #include "qiosviewcontroller.h" #include "quiview.h" +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/private/qwindow_p.h> #include <private/qcoregraphics_p.h> @@ -274,7 +275,7 @@ void QIOSScreen::updateProperties() if (m_uiScreen == [UIScreen mainScreen]) { Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { // On iOS < 8.0 the UIScreen geometry is always in portait, and the system applies // the screen rotation to the root view-controller's view instead of directly to the // screen, like iOS 8 and above does. @@ -302,7 +303,7 @@ void QIOSScreen::updateProperties() if (m_geometry != previousGeometry) { QRectF physicalGeometry; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation; @@ -406,10 +407,11 @@ qreal QIOSScreen::devicePixelRatio() const Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { CGRect nativeBounds = -#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 +#if defined(Q_OS_IOS) + m_uiScreen.nativeBounds; +#else m_uiScreen.bounds; +#endif // All known iOS devices have a native orientation of portrait, but to // be on the safe side we compare the width and height of the bounds. diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index 238d7addf6..48262dad10 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -219,7 +219,7 @@ static void executeBlockWithoutAnimation(Block block) borderLayer.borderColor = [[UIColor lightGrayColor] CGColor]; [self addSublayer:borderLayer]; - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) { // [UIView snapshotViewAfterScreenUpdates:] is available since iOS 7.0. // Just silently ignore showing the loupe for older versions. self.hidden = YES; @@ -267,7 +267,7 @@ static void executeBlockWithoutAnimation(Block block) - (void)display { - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) return; // Take a snapshow of the target view, magnify the area around the focal diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 2a1444e9e5..9966bd50a3 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -48,6 +48,7 @@ #include "qiosmenu.h" #endif +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qwindow_p.h> #include <qpa/qwindowsysteminterface_p.h> @@ -208,18 +209,23 @@ - (BOOL)becomeFirstResponder { - FirstResponderCandidate firstResponderCandidate(self); + { + // Scope for the duration of becoming first responder only, as the window + // activation event may trigger new responders, which we don't want to be + // blocked by this guard. + FirstResponderCandidate firstResponderCandidate(self); - qImDebug() << "win:" << m_qioswindow->window() << "self:" << self - << "first:" << [UIResponder currentFirstResponder]; + qImDebug() << "win:" << m_qioswindow->window() << "self:" << self + << "first:" << [UIResponder currentFirstResponder]; - if (![super becomeFirstResponder]) { - qImDebug() << m_qioswindow->window() - << "was not allowed to become first responder"; - return NO; - } + if (![super becomeFirstResponder]) { + qImDebug() << m_qioswindow->window() + << "was not allowed to become first responder"; + return NO; + } - qImDebug() << m_qioswindow->window() << "became first responder"; + qImDebug() << m_qioswindow->window() << "became first responder"; + } if (qGuiApp->focusWindow() != m_qioswindow->window()) QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window()); @@ -291,7 +297,7 @@ QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice(); QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities(); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; else |