From 36caeadb4db9fab1cf581f9a3bb3c4a2e14de49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 6 May 2014 16:37:54 +0200 Subject: iOS: Gracefully handle cancelling of subset of active touches When applying the five-finger pinch gesture, we get a touchesCancelled callback with all five touch points, but the pinch gesture ends when the second to last finger is released from the screen. The last finger will not emit any more touch events, _but_, will contribute to starting another pinch gesture. That second pinch gesture will _not_ trigger a touchesCancelled event when starting, but as each finger is released, and we may get touchesMoved events for the remaining fingers. The event property 'allTouches' contains one less touch point than it should, so this behavior is likely a bug in the iOS system gesture recognizer, but have to take it into account when maintaining the Qt touch state. We do this by assuming that there are no cases where a sub-set of the active touch events are intentionally cancelled, and always clear the list of active touches. Task-number: QTBUG-37304 Change-Id: Icee79978508ecbc6854c0fb55d2da48b99d92f96 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qioswindow.mm | 36 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index ebff2c25a1..6f5c96cfc1 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -292,19 +292,33 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - if (!touches && m_activeTouches.isEmpty()) + if (m_activeTouches.isEmpty()) return; - if (!touches) { - m_activeTouches.clear(); - } else { - for (UITouch *touch in touches) - m_activeTouches.remove(touch); - - Q_ASSERT_X(m_activeTouches.isEmpty(), Q_FUNC_INFO, - "Subset of active touches cancelled by UIKit"); - } - + // When four-finger swiping, we get a touchesCancelled callback + // which includes all four touch points. The swipe gesture is + // then active until all four touches have been released, and + // we start getting touchesBegan events again. + + // When five-finger pinching, we also get a touchesCancelled + // callback with all five touch points, but the pinch gesture + // ends when the second to last finger is released from the + // screen. The last finger will not emit any more touch + // events, _but_, will contribute to starting another pinch + // gesture. That second pinch gesture will _not_ trigger a + // touchesCancelled event when starting, but as each finger + // is released, and we may get touchesMoved events for the + // remaining fingers. [event allTouches] also contains one + // less touch point than it should, so this behavior is + // likely a bug in the iOS system gesture recognizer, but we + // have to take it into account when maintaining the Qt state. + // We do this by assuming that there are no cases where a + // sub-set of the active touch events are intentionally cancelled. + + if (touches && (static_cast([touches count]) != m_activeTouches.count())) + qWarning("Subset of active touches cancelled by UIKit"); + + m_activeTouches.clear(); m_nextTouchId = 0; NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime]; -- cgit v1.2.3