summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios')
-rw-r--r--src/plugins/platforms/ios/kernel.pro5
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro6
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.mm12
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm49
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm3
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm3
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm12
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm4
-rw-r--r--src/plugins/platforms/ios/quiview.mm26
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