iOS: Add support for hover feature for Apple Pencil 2nd gen or later
Add UIHoverGestureRecognizer to support Hover feature. Task-number: QTBUG-128473 Change-Id: I73bbd1b8cca1ffcb8fcc27f6c26cb4ab8830c690 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
cf674f3845
commit
2429c73cc9
@ -59,6 +59,9 @@ inline ulong getTimeStamp(UIEvent *event)
|
||||
UIPanGestureRecognizer *m_scrollGestureRecognizer;
|
||||
CGPoint m_lastScrollCursorPos;
|
||||
CGPoint m_lastScrollDelta;
|
||||
#if QT_CONFIG(tabletevent)
|
||||
UIHoverGestureRecognizer *m_hoverGestureRecognizer;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (Class)layerClass
|
||||
@ -99,6 +102,13 @@ inline ulong getTimeStamp(UIEvent *event)
|
||||
m_lastScrollCursorPos = CGPointZero;
|
||||
[self addGestureRecognizer:m_scrollGestureRecognizer];
|
||||
|
||||
#if QT_CONFIG(tabletevent)
|
||||
m_hoverGestureRecognizer = [[UIHoverGestureRecognizer alloc]
|
||||
initWithTarget:self
|
||||
action:@selector(handleHover:)];
|
||||
[self addGestureRecognizer:m_hoverGestureRecognizer];
|
||||
#endif
|
||||
|
||||
// Set up layer
|
||||
if ([self.layer isKindOfClass:CAMetalLayer.class]) {
|
||||
QWindow *window = self.platformWindow->window();
|
||||
@ -362,6 +372,39 @@ inline ulong getTimeStamp(UIEvent *event)
|
||||
return [super pointInside:point withEvent:event];
|
||||
}
|
||||
|
||||
#if QT_CONFIG(tabletevent)
|
||||
- (void)handlePencilEventForLocationInView:(CGPoint)locationInView withState:(QEventPoint::State)state withTimestamp:(ulong)timeStamp
|
||||
withForce:(CGFloat)force withMaximumPossibleForce:(CGFloat)maximumPossibleForce withZOffset:(CGFloat)zOffset
|
||||
withAzimuthUnitVector:(CGVector)azimuth withAltitudeAngleRadian:(CGFloat)altitudeAngleRadian
|
||||
{
|
||||
QIOSIntegration *iosIntegration = QIOSIntegration::instance();
|
||||
|
||||
QPointF localViewPosition = QPointF::fromCGPoint(locationInView);
|
||||
QPoint localViewPositionI = localViewPosition.toPoint();
|
||||
QPointF globalScreenPosition = self.platformWindow->mapToGlobal(localViewPositionI) +
|
||||
(localViewPosition - localViewPositionI);
|
||||
qreal pressure = 0;
|
||||
if (force != 0 && maximumPossibleForce != 0)
|
||||
pressure = force / maximumPossibleForce;
|
||||
// azimuth unit vector: +x to the right, +y going downwards
|
||||
// altitudeAngleRadian 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 - qRadiansToDegrees(altitudeAngleRadian);
|
||||
qreal xTilt = qBound(-60.0, altitudeAngle * azimuth.dx, 60.0);
|
||||
qreal yTilt = qBound(-60.0, altitudeAngle * azimuth.dy, 60.0);
|
||||
|
||||
qCDebug(lcQpaTablet) << ":" << timeStamp << localViewPosition << pressure << state << "azimuth" << azimuth.dx << azimuth.dy
|
||||
<< "altitude" << altitudeAngleRadian << "xTilt" << xTilt << "yTilt" << yTilt;
|
||||
QWindowSystemInterface::handleTabletEvent(self.platformWindow->window(), timeStamp,
|
||||
// device, local, global
|
||||
iosIntegration->pencilDevice(), localViewPosition, globalScreenPosition,
|
||||
// buttons
|
||||
state == QEventPoint::State::Released ? Qt::NoButton : Qt::LeftButton,
|
||||
// pressure, xTilt, yTilt, tangentialPressure, rotation, z, modifiers
|
||||
pressure, xTilt, yTilt, 0, 0, zOffset, Qt::NoModifier);
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)handleTouches:(NSSet *)touches withEvent:(UIEvent *)event withState:(QEventPoint::State)state withTimestamp:(ulong)timeStamp
|
||||
{
|
||||
QIOSIntegration *iosIntegration = QIOSIntegration::instance();
|
||||
@ -370,30 +413,11 @@ inline ulong getTimeStamp(UIEvent *event)
|
||||
#if QT_CONFIG(tabletevent)
|
||||
if (m_activePencilTouch && [touches containsObject:m_activePencilTouch]) {
|
||||
NSArray<UITouch *> *cTouches = [event coalescedTouchesForTouch:m_activePencilTouch];
|
||||
int i = 0;
|
||||
for (UITouch *cTouch in cTouches) {
|
||||
QPointF localViewPosition = QPointF::fromCGPoint([cTouch preciseLocationInView:self]);
|
||||
QPoint localViewPositionI = localViewPosition.toPoint();
|
||||
QPointF globalScreenPosition = self.platformWindow->mapToGlobal(localViewPositionI) +
|
||||
(localViewPosition - localViewPositionI);
|
||||
qreal pressure = cTouch.force / cTouch.maximumPossibleForce;
|
||||
// azimuth unit vector: +x to the right, +y going downwards
|
||||
CGVector azimuth = [cTouch azimuthUnitVectorInView:self];
|
||||
// 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 - qRadiansToDegrees(cTouch.altitudeAngle);
|
||||
qreal xTilt = qBound(-60.0, altitudeAngle * azimuth.dx, 60.0);
|
||||
qreal yTilt = qBound(-60.0, altitudeAngle * azimuth.dy, 60.0);
|
||||
qCDebug(lcQpaTablet) << i << ":" << timeStamp << localViewPosition << pressure << state << "azimuth" << azimuth.dx << azimuth.dy
|
||||
<< "altitude" << cTouch.altitudeAngle << "xTilt" << xTilt << "yTilt" << yTilt;
|
||||
QWindowSystemInterface::handleTabletEvent(self.platformWindow->window(), timeStamp,
|
||||
// device, local, global
|
||||
iosIntegration->pencilDevice(), localViewPosition, globalScreenPosition,
|
||||
// buttons
|
||||
state == QEventPoint::State::Released ? Qt::NoButton : Qt::LeftButton,
|
||||
// pressure, xTilt, yTilt, tangentialPressure, rotation, z, modifiers
|
||||
pressure, xTilt, yTilt, 0, 0, 0, Qt::NoModifier);
|
||||
++i;
|
||||
[self handlePencilEventForLocationInView:[cTouch preciseLocationInView:self] withState:state withTimestamp:timeStamp
|
||||
withForce:cTouch.force withMaximumPossibleForce:cTouch.maximumPossibleForce withZOffset:0
|
||||
withAzimuthUnitVector:[cTouch azimuthUnitVectorInView:self]
|
||||
withAltitudeAngleRadian:cTouch.altitudeAngle];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -759,6 +783,28 @@ inline ulong getTimeStamp(UIEvent *event)
|
||||
}
|
||||
#endif // QT_CONFIG(wheelevent)
|
||||
|
||||
#if QT_CONFIG(tabletevent)
|
||||
- (void)handleHover:(UIHoverGestureRecognizer *)recognizer
|
||||
{
|
||||
ulong timeStamp = [[NSProcessInfo processInfo] systemUptime] * 1000;
|
||||
|
||||
CGFloat zOffset = 0;
|
||||
if (@available(ios 16.1, *))
|
||||
zOffset = [recognizer zOffset];
|
||||
|
||||
CGVector azimuth;
|
||||
CGFloat altitudeAngleRadian = 0;
|
||||
if (@available(ios 16.4, *)) {
|
||||
azimuth = [recognizer azimuthUnitVectorInView:self];
|
||||
altitudeAngleRadian = recognizer.altitudeAngle;
|
||||
}
|
||||
|
||||
[self handlePencilEventForLocationInView:[recognizer locationInView:self] withState:QEventPoint::State::Released
|
||||
withTimestamp:timeStamp withForce:0 withMaximumPossibleForce:0 withZOffset:zOffset
|
||||
withAzimuthUnitVector:azimuth withAltitudeAngleRadian:altitudeAngleRadian];
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIView (QtHelpers)
|
||||
|
Loading…
x
Reference in New Issue
Block a user