summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/quiview.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/quiview.mm')
-rw-r--r--src/plugins/platforms/ios/quiview.mm302
1 files changed, 202 insertions, 100 deletions
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 5ca4d5ccc8..f1103dae9c 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "quiview.h"
@@ -45,10 +9,12 @@
#include "qiostextresponder.h"
#include "qiosscreen.h"
#include "qioswindow.h"
+#include "qiosinputcontext.h"
#ifndef Q_OS_TVOS
#include "qiosmenu.h"
#endif
+#include <QtCore/qmath.h>
#include <QtGui/qpointingdevice.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
@@ -56,12 +22,41 @@
#include <qpa/qwindowsysteminterface_p.h>
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+Q_LOGGING_CATEGORY(lcQpaInputEvents, "qt.qpa.input.events")
+
+namespace {
+inline ulong getTimeStamp(UIEvent *event)
+{
+#if TARGET_OS_SIMULATOR == 1
+ // We currently build Qt for simulator using X86_64, even on ARM based macs.
+ // This results in the simulator running on ARM, while the app is running
+ // inside it using Rosetta. And with this combination, the event.timestamp, which is
+ // documented to be in seconds, looks to be something else, and is not progressing
+ // in sync with a normal clock.
+ // Sending out mouse events with a timestamp that doesn't follow normal clock time
+ // will cause problems for mouse-, and pointer handlers that uses them to e.g calculate
+ // the time between a press and release, and to decide if the user is performing a tap
+ // or a drag.
+ // For that reason, we choose to ignore UIEvent.timestamp under the mentioned condition, and
+ // instead rely on NSProcessInfo. Note that if we force the whole simulator to use Rosetta
+ // (and not only the Qt app), the timestamps will progress normally.
+#if defined(Q_PROCESSOR_ARM)
+ #warning The timestamp work-around for x86_64 can (probably) be removed when building for ARM
+#endif
+ return ulong(NSProcessInfo.processInfo.systemUptime * 1000);
+#endif
+
+ return ulong(event.timestamp * 1000);
+}
+}
@implementation QUIView {
QHash<NSUInteger, QWindowSystemInterface::TouchPoint> m_activeTouches;
UITouch *m_activePencilTouch;
- int m_nextTouchId;
NSMutableArray<UIAccessibilityElement *> *m_accessibleElements;
+ UIPanGestureRecognizer *m_scrollGestureRecognizer;
+ CGPoint m_lastScrollCursorPos;
+ CGPoint m_lastScrollDelta;
}
+ (void)load
@@ -86,7 +81,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+ (Class)layerClass
{
+#if QT_CONFIG(opengl)
return [CAEAGLLayer class];
+#endif
+ return [super layerClass];
}
- (instancetype)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window
@@ -94,6 +92,32 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if (self = [self initWithFrame:window->geometry().toCGRect()]) {
self.platformWindow = window;
m_accessibleElements = [[NSMutableArray<UIAccessibilityElement *> alloc] init];
+ m_scrollGestureRecognizer = [[UIPanGestureRecognizer alloc]
+ initWithTarget:self
+ action:@selector(handleScroll:)];
+ // The gesture recognizer should only care about scroll gestures (for now)
+ // Set allowedTouchTypes to empty array here to not interfere with touch events
+ // handled by the UIView. Scroll gestures, even those coming from touch devices,
+ // such as trackpads will still be received as they are not touch events
+ m_scrollGestureRecognizer.allowedTouchTypes = [NSArray array];
+ if (@available(ios 13.4, *)) {
+ m_scrollGestureRecognizer.allowedScrollTypesMask = UIScrollTypeMaskAll;
+ }
+ m_scrollGestureRecognizer.maximumNumberOfTouches = 0;
+ m_lastScrollDelta = CGPointZero;
+ m_lastScrollCursorPos = CGPointZero;
+ [self addGestureRecognizer:m_scrollGestureRecognizer];
+
+ if ([self.layer isKindOfClass:CAMetalLayer.class]) {
+ QWindow *window = self.platformWindow->window();
+ if (QColorSpace colorSpace = window->format().colorSpace(); colorSpace.isValid()) {
+ QCFType<CFDataRef> iccData = colorSpace.iccProfile().toCFData();
+ QCFType<CGColorSpaceRef> cgColorSpace = CGColorSpaceCreateWithICCData(iccData);
+ CAMetalLayer *metalLayer = static_cast<CAMetalLayer *>(self.layer);
+ metalLayer.colorspace = cgColorSpace;
+ qCDebug(lcQpaWindow) << "Set" << self << "color space to" << metalLayer.colorspace;
+ }
+ }
}
return self;
@@ -102,6 +126,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
+#if QT_CONFIG(opengl)
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
// Set up EAGL layer
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
@@ -111,6 +136,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
};
}
+#endif
if (isQtApplication())
self.hidden = YES;
@@ -151,6 +177,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (void)dealloc
{
[m_accessibleElements release];
+ [m_scrollGestureRecognizer release];
[super dealloc];
}
@@ -236,6 +263,9 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
Q_UNUSED(layer);
Q_ASSERT(layer == self.layer);
+ if (!self.platformWindow)
+ return;
+
[self sendUpdatedExposeEvent];
}
@@ -265,7 +295,8 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (BOOL)canBecomeFirstResponder
{
- return !(self.platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus);
+ return !(self.platformWindow->window()->flags() & (Qt::WindowDoesNotAcceptFocus
+ | Qt::WindowTransparentForInput));
}
- (BOOL)becomeFirstResponder
@@ -276,7 +307,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// blocked by this guard.
FirstResponderCandidate firstResponderCandidate(self);
- qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
+ qImDebug() << "self:" << self << "first:" << [UIResponder qt_currentFirstResponder];
if (![super becomeFirstResponder]) {
qImDebug() << self << "was not allowed to become first responder";
@@ -287,7 +318,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
}
if (qGuiApp->focusWindow() != self.platformWindow->window())
- QWindowSystemInterface::handleWindowActivated(self.platformWindow->window(), Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(self.platformWindow->window(), Qt::ActiveWindowFocusReason);
else
qImDebug() << self.platformWindow->window() << "already active, not sending window activation";
@@ -303,7 +334,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// Nor do we want to deactivate the Qt window if the new responder
// is temporarily handling text input on behalf of a Qt window.
- if ([responder isKindOfClass:[QIOSTextInputResponder class]]) {
+ if ([responder isKindOfClass:[QIOSTextResponder class]]) {
while ((responder = [responder nextResponder])) {
if ([responder isKindOfClass:[QUIView class]])
return NO;
@@ -315,7 +346,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (BOOL)resignFirstResponder
{
- qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
+ qImDebug() << "self:" << self << "first:" << [UIResponder qt_currentFirstResponder];
if (![super resignFirstResponder])
return NO;
@@ -324,7 +355,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
UIResponder *newResponder = FirstResponderCandidate::currentCandidate();
if ([self responderShouldTriggerWindowDeactivation:newResponder])
- QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr, Qt::ActiveWindowFocusReason);
return YES;
}
@@ -338,7 +369,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if ([self isFirstResponder])
return YES;
- UIResponder *firstResponder = [UIResponder currentFirstResponder];
+ UIResponder *firstResponder = [UIResponder qt_currentFirstResponder];
if ([firstResponder isKindOfClass:[QIOSTextInputResponder class]]
&& [firstResponder nextResponder] == self)
return YES;
@@ -386,10 +417,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// azimuth unit vector: +x to the right, +y going downwards
CGVector azimuth = [cTouch azimuthUnitVectorInView: self];
// azimuthAngle given in radians, zero when the stylus points towards +x axis; converted to degrees with 0 pointing straight up
- qreal azimuthAngle = [cTouch azimuthAngleInView: self] * 180 / M_PI + 90;
+ qreal azimuthAngle = qRadiansToDegrees([cTouch azimuthAngleInView: self]) + 90;
// altitudeAngle given in radians, pi / 2 is with the stylus perpendicular to the iPad, smaller values mean more tilted, but never negative.
// Convert to degrees with zero being perpendicular.
- qreal altitudeAngle = 90 - cTouch.altitudeAngle * 180 / M_PI;
+ qreal altitudeAngle = 90 - qRadiansToDegrees(cTouch.altitudeAngle);
qCDebug(lcQpaTablet) << i << ":" << timeStamp << localViewPosition << pressure << state << "azimuth" << azimuth.dx << azimuth.dy
<< "angle" << azimuthAngle << "altitude" << cTouch.altitudeAngle
<< "xTilt" << qBound(-60.0, altitudeAngle * azimuth.dx, 60.0) << "yTilt" << qBound(-60.0, altitudeAngle * azimuth.dy, 60.0);
@@ -463,7 +494,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::AsynchronousDelivery>(
self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
} else {
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
+ // Send the touch event asynchronously, as the application might spin a recursive
+ // event loop in response to the touch event (a dialog e.g.), which will deadlock
+ // the UIKit event delivery system (QTBUG-98651).
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::AsynchronousDelivery>(
self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
}
}
@@ -486,7 +520,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
{
Q_ASSERT(!m_activeTouches.contains(touch.hash));
#endif
- m_activeTouches[touch.hash].id = m_nextTouchId++;
+ // Use window-independent touch identifiers, so that
+ // multi-touch works across windows.
+ static quint16 nextTouchId = 0;
+ m_activeTouches[touch.hash].id = nextTouchId++;
#if QT_CONFIG(tabletevent)
}
#endif
@@ -500,17 +537,17 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
topLevel->requestActivateWindow();
}
- [self handleTouches:touches withEvent:event withState:QEventPoint::State::Pressed withTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:QEventPoint::State::Pressed withTimestamp:getTimeStamp(event)];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
- [self handleTouches:touches withEvent:event withState:QEventPoint::State::Updated withTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:QEventPoint::State::Updated withTimestamp:getTimeStamp(event)];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
- [self handleTouches:touches withEvent:event withState:QEventPoint::State::Released withTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:QEventPoint::State::Released withTimestamp:getTimeStamp(event)];
// Remove ended touch points from the active set:
#ifndef Q_OS_TVOS
@@ -528,9 +565,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// tvOS only supports single touch
m_activeTouches.clear();
#endif
-
- if (m_activeTouches.isEmpty() && !m_activePencilTouch)
- m_nextTouchId = 0;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
@@ -563,16 +597,20 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
qWarning("Subset of active touches cancelled by UIKit");
m_activeTouches.clear();
- m_nextTouchId = 0;
m_activePencilTouch = nil;
- NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
+ ulong timestamp = event ? getTimeStamp(event) : ([[NSProcessInfo processInfo] systemUptime] * 1000);
QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchCancelEvent(self.platformWindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
+
+ // Send the touch event asynchronously, as the application might spin a recursive
+ // event loop in response to the touch event (a dialog e.g.), which will deadlock
+ // the UIKit event delivery system (QTBUG-98651).
+ QWindowSystemInterface::handleTouchCancelEvent<QWindowSystemInterface::AsynchronousDelivery>(
+ self.platformWindow->window(), timestamp, iosIntegration->touchDevice());
}
-- (int)mapPressTypeToKey:(UIPress*)press withModifiers:(Qt::KeyboardModifiers)qtModifiers
+- (int)mapPressTypeToKey:(UIPress*)press withModifiers:(Qt::KeyboardModifiers)qtModifiers text:(QString &)text
{
switch (press.type) {
case UIPressTypeUpArrow: return Qt::Key_Up;
@@ -583,53 +621,61 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
case UIPressTypeMenu: return Qt::Key_Menu;
case UIPressTypePlayPause: return Qt::Key_MediaTogglePlayPause;
}
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
if (@available(ios 13.4, *)) {
NSString *charactersIgnoringModifiers = press.key.charactersIgnoringModifiers;
Qt::Key key = QAppleKeyMapper::fromUIKitKey(charactersIgnoringModifiers);
if (key != Qt::Key_unknown)
return key;
return QAppleKeyMapper::fromNSString(qtModifiers, press.key.characters,
- charactersIgnoringModifiers);
+ charactersIgnoringModifiers, text);
}
-#endif
return Qt::Key_unknown;
}
-- (bool)processPresses:(NSSet *)presses withType:(QEvent::Type)type {
+- (bool)isControlKey:(Qt::Key)key
+{
+ switch (key) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+- (bool)handlePresses:(NSSet<UIPress *> *)presses eventType:(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.
+ if (!qApp->focusWindow())
+ return false;
+
+ bool eventHandled = false;
+ const bool imEnabled = QIOSInputContext::instance()->inputMethodAccepted();
- bool handled = false;
for (UIPress* press in presses) {
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
if (@available(ios 13.4, *))
qtModifiers = QAppleKeyMapper::fromUIKitModifiers(press.key.modifierFlags);
-#endif
- int key = [self mapPressTypeToKey:press withModifiers:qtModifiers];
+ QString text;
+ int key = [self mapPressTypeToKey:press withModifiers:qtModifiers text:text];
if (key == Qt::Key_unknown)
continue;
- if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key, qtModifiers))
- handled = true;
- }
-
- return handled;
-}
+ if (imEnabled && ![self isControlKey:Qt::Key(key)])
+ continue;
-- (BOOL)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
-{
- bool handlePress = false;
- if (qApp->focusWindow()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (qApp->focusObject() && QCoreApplication::sendEvent(qApp->focusObject(), &queryEvent))
- handlePress = queryEvent.value(Qt::ImEnabled).toBool();
- if (!handlePress && [self processPresses:presses withType:type])
- return true;
+ bool keyHandled = QWindowSystemInterface::handleKeyEvent(
+ self.platformWindow->window(), type, key, qtModifiers, text);
+ eventHandled = eventHandled || keyHandled;
}
- return false;
+
+ return eventHandled;
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
@@ -641,14 +687,14 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyPress])
- [super pressesBegan:presses withEvent:event];
+ [super pressesChanged:presses withEvent:event];
[super pressesChanged:presses withEvent:event];
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyRelease])
- [super pressesBegan:presses withEvent:event];
+ [super pressesEnded:presses withEvent:event];
[super pressesEnded:presses withEvent:event];
}
@@ -682,6 +728,75 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
[super addInteraction:interaction];
}
+- (UIEditingInteractionConfiguration)editingInteractionConfiguration
+{
+ // We only want the three-finger-tap edit menu to be available when there's
+ // actually something to edit. Otherwise the OS will cause a slight delay
+ // before delivering the release of three finger touch input. Note that we
+ // do not do any hit testing here to check that the focus object is the one
+ // being tapped, as the behavior of native iOS apps is to trigger the menu
+ // regardless of where the gesture is being made.
+ return QIOSInputContext::instance()->inputMethodAccepted() ?
+ UIEditingInteractionConfigurationDefault : UIEditingInteractionConfigurationNone;
+}
+
+#if QT_CONFIG(wheelevent)
+- (void)handleScroll:(UIPanGestureRecognizer *)recognizer
+{
+ if (!self.platformWindow->window())
+ return;
+
+ if (!self.canBecomeFirstResponder)
+ return;
+
+ CGPoint translation = [recognizer translationInView:self];
+ CGFloat deltaX = translation.x - m_lastScrollDelta.x;
+ CGFloat deltaY = translation.y - m_lastScrollDelta.y;
+
+ QPoint angleDelta;
+ // From QNSView implementation:
+ // "Since deviceDelta is delivered as pixels rather than degrees, we need to
+ // convert from pixels to degrees in a sensible manner.
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):"
+ const int pixelsToDegrees = 2; // 8 * 1/4
+ angleDelta.setX(deltaX * pixelsToDegrees);
+ angleDelta.setY(deltaY * pixelsToDegrees);
+
+ QPoint pixelDelta;
+ pixelDelta.setX(deltaX);
+ pixelDelta.setY(deltaY);
+
+ NSTimeInterval time_stamp = [[NSProcessInfo processInfo] systemUptime];
+ ulong qt_timestamp = time_stamp * 1000;
+
+ Qt::KeyboardModifiers qt_modifierFlags = Qt::NoModifier;
+ if (@available(ios 13.4, *))
+ qt_modifierFlags = QAppleKeyMapper::fromUIKitModifiers(recognizer.modifierFlags);
+
+ if (recognizer.state == UIGestureRecognizerStateBegan)
+ // locationInView: doesn't return the cursor position at the time of the wheel event,
+ // but rather gives us the position with the deltas applied, so we need to save the
+ // cursor position at the beginning of the gesture
+ m_lastScrollCursorPos = [recognizer locationInView:self];
+
+ if (recognizer.state != UIGestureRecognizerStateEnded) {
+ m_lastScrollDelta.x = translation.x;
+ m_lastScrollDelta.y = translation.y;
+ } else {
+ m_lastScrollDelta = CGPointZero;
+ }
+
+ QPoint qt_local = QPointF::fromCGPoint(m_lastScrollCursorPos).toPoint();
+ QPoint qt_global = self.platformWindow->mapToGlobal(qt_local);
+
+ qCInfo(lcQpaInputEvents).nospace() << "wheel event" << " at " << qt_local
+ << " pixelDelta=" << pixelDelta << " angleDelta=" << angleDelta;
+
+ QWindowSystemInterface::handleWheelEvent(self.platformWindow->window(), qt_timestamp, qt_local, qt_global, pixelDelta, angleDelta, qt_modifierFlags);
+}
+#endif // QT_CONFIG(wheelevent)
+
@end
@implementation UIView (QtHelpers)
@@ -714,11 +829,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return nil;
}
-- (UIEdgeInsets)qt_safeAreaInsets
-{
- return self.safeAreaInsets;
-}
-
@end
#ifdef Q_OS_IOS
@@ -726,21 +836,13 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+ (Class)layerClass
{
-#ifdef TARGET_IPHONE_SIMULATOR
- if (@available(ios 13.0, *))
-#endif
-
return [CAMetalLayer class];
-
-#ifdef TARGET_IPHONE_SIMULATOR
- return nil;
-#endif
}
@end
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// Include category as an alternative to using -ObjC (Apple QA1490)
#include "quiview_accessibility.mm"
#endif