summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorDoris Verria <doris.verria@qt.io>2022-06-15 14:57:04 +0200
committerDoris Verria <doris.verria@qt.io>2022-07-05 19:23:56 +0200
commit77fcd47febec58eaf35610c72f2d9bdfb1ee4174 (patch)
treee46a788ca0fb407441f70d8a70dea56155615c5b /src/plugins/platforms
parentac984bd8768b3d7e6439e0ffd98fd8b53e16b922 (diff)
iOS plugin: Add support for wheel events
Use UIPanGestureRecognizer to handle mouse and trackpad scroll. Task-number: QTBUG-99795 Change-Id: I5db7fabf55b6f2e6f7ba90a0b90ecb08734e2329 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/ios/quiview.mm81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 32f27587c6..cd4e900d89 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -22,12 +22,16 @@
#include <qpa/qwindowsysteminterface_p.h>
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+Q_LOGGING_CATEGORY(lcQpaInputEvents, "qt.qpa.input.events")
@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
@@ -60,6 +64,23 @@ 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 QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
+ if (@available(ios 13.4, *)) {
+ m_scrollGestureRecognizer.allowedScrollTypesMask = UIScrollTypeMaskAll;
+ }
+#endif
+ m_scrollGestureRecognizer.maximumNumberOfTouches = 0;
+ m_lastScrollDelta = CGPointZero;
+ m_lastScrollCursorPos = CGPointZero;
+ [self addGestureRecognizer:m_scrollGestureRecognizer];
}
return self;
@@ -117,6 +138,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (void)dealloc
{
[m_accessibleElements release];
+ [m_scrollGestureRecognizer release];
[super dealloc];
}
@@ -672,6 +694,65 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
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 QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
+ if (@available(ios 13.4, *))
+ qt_modifierFlags = QAppleKeyMapper::fromUIKitModifiers(recognizer.modifierFlags);
+#endif
+
+ 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)