support force touch in trackpad mode

This commit is contained in:
Jesús A. Álvarez 2016-11-18 23:41:04 +01:00
parent 2193780656
commit f90ef9b92f

View File

@ -8,6 +8,7 @@
#import "TrackPad.h" #import "TrackPad.h"
#import "AppDelegate.h" #import "AppDelegate.h"
@import AudioToolbox;
#define TRACKPAD_ACCEL_N 1 #define TRACKPAD_ACCEL_N 1
#define TRACKPAD_ACCEL_T 0.2 #define TRACKPAD_ACCEL_T 0.2
@ -21,6 +22,7 @@
CGPoint previousTouchLoc; CGPoint previousTouchLoc;
BOOL shouldClick; BOOL shouldClick;
BOOL isDragging; BOOL isDragging;
BOOL supportsForceTouch, didForceClick;
NSMutableSet *currentTouches; NSMutableSet *currentTouches;
} }
@ -34,6 +36,15 @@
return self; return self;
} }
- (void)willMoveToSuperview:(UIView *)newSuperview {
[super willMoveToSuperview:newSuperview];
@try {
supportsForceTouch = (newSuperview.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable);
} @catch (NSException *exception) {
supportsForceTouch = NO;
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[currentTouches unionSet:touches]; [currentTouches unionSet:touches];
if (currentTouches.count == 1) { if (currentTouches.count == 1) {
@ -45,11 +56,14 @@
- (void)firstTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { - (void)firstTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInView:self]; CGPoint touchLoc = [touch locationInView:self];
shouldClick = YES;
if (!isDragging && (event.timestamp - previousTouchTime < touchTimeThreshold) && if (!isDragging && (event.timestamp - previousTouchTime < touchTimeThreshold) &&
fabs(previousTouchLoc.x - touchLoc.x) < touchDistanceThreshold && fabs(previousTouchLoc.x - touchLoc.x) < touchDistanceThreshold &&
fabs(previousTouchLoc.y - touchLoc.y) < touchDistanceThreshold) { fabs(previousTouchLoc.y - touchLoc.y) < touchDistanceThreshold) {
[self startDragging]; [self startDragging];
} }
previousTouchTime = event.timestamp;
previousTouchLoc = touchLoc;
} }
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
@ -62,21 +76,34 @@
NSTimeInterval accel = TRACKPAD_ACCEL_N / (TRACKPAD_ACCEL_T + ((timeDiff * timeDiff)/TRACKPAD_ACCEL_D)); NSTimeInterval accel = TRACKPAD_ACCEL_N / (TRACKPAD_ACCEL_T + ((timeDiff * timeDiff)/TRACKPAD_ACCEL_D));
locDiff.x *= accel; locDiff.x *= accel;
locDiff.y *= accel; locDiff.y *= accel;
shouldClick = NO;
[[AppDelegate sharedEmulator] moveMouseX:locDiff.x Y:locDiff.y]; if (!CGPointEqualToPoint(touchLoc, previousTouchLoc)) {
shouldClick = NO;
[[AppDelegate sharedEmulator] moveMouseX:locDiff.x Y:locDiff.y];
}
previousTouchTime = event.timestamp; previousTouchTime = event.timestamp;
previousTouchLoc = touchLoc; previousTouchLoc = touchLoc;
if (supportsForceTouch) {
[self handleForceClick:touch];
}
} }
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[currentTouches minusSet:touches]; [currentTouches minusSet:touches];
if (currentTouches.count > 0) { if (currentTouches.count > 0) {
return; return;
} else if (didForceClick) {
AudioServicesPlaySystemSound(1519);
didForceClick = NO;
[self cancelScheduledClick];
[self mouseUp];
return;
} }
CGPoint touchLoc = [touches.anyObject locationInView:self]; CGPoint touchLoc = [touches.anyObject locationInView:self];
if (shouldClick && (event.timestamp - previousTouchTime < touchTimeThreshold)) { if (shouldClick && (event.timestamp - previousTouchTime < touchTimeThreshold)) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(mouseClick) object:nil]; [self cancelScheduledClick];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(mouseUp) object:nil];
[self performSelector:@selector(mouseClick) withObject:nil afterDelay:touchTimeThreshold]; [self performSelector:@selector(mouseClick) withObject:nil afterDelay:touchTimeThreshold];
} }
shouldClick = NO; shouldClick = NO;
@ -90,7 +117,10 @@
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[currentTouches minusSet:touches]; [currentTouches minusSet:touches];
[self stopDragging]; isDragging = NO;
shouldClick = NO;
didForceClick = NO;
[self mouseUp];
} }
- (void)startDragging { - (void)startDragging {
@ -105,6 +135,14 @@
[[AppDelegate sharedEmulator] setMouseButton:NO]; [[AppDelegate sharedEmulator] setMouseButton:NO];
} }
- (void)handleForceClick:(UITouch *)touch {
if (touch.force > 3.0 && !didForceClick) {
AudioServicesPlaySystemSound(1519);
didForceClick = YES;
[self startDragging];
}
}
- (void)mouseClick { - (void)mouseClick {
if (isDragging) { if (isDragging) {
return; return;
@ -113,6 +151,11 @@
[self performSelector:@selector(mouseUp) withObject:nil afterDelay:2.0/60.0]; [self performSelector:@selector(mouseUp) withObject:nil afterDelay:2.0/60.0];
} }
- (void)cancelScheduledClick {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(mouseClick) object:nil];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(mouseUp) object:nil];
}
- (void)mouseUp { - (void)mouseUp {
[[AppDelegate sharedEmulator] setMouseButton:NO]; [[AppDelegate sharedEmulator] setMouseButton:NO];
} }