diff --git a/Limelight/Input/CustomTapGestureRecognizer.h b/Limelight/Input/CustomTapGestureRecognizer.h index 68f74173..687e8596 100644 --- a/Limelight/Input/CustomTapGestureRecognizer.h +++ b/Limelight/Input/CustomTapGestureRecognizer.h @@ -11,12 +11,16 @@ -@interface CustomTapGestureRecognizer : UIGestureRecognizer +@interface CustomTapGestureRecognizer : UIGestureRecognizer{ + CGFloat lowestTouchPointYCoord; +} + @property (nonatomic, assign) uint8_t numberOfTouchesRequired; -@property (nonatomic, assign) double tapDownTimeThreshold; -@property (atomic, readonly) CGFloat lowestTouchPointHeight; - +@property (nonatomic, assign) double tapDownTimeThreshold; // tap down threshold in seconds. +@property (nonatomic, readonly) CGFloat lowestTouchPointHeight; +@property (nonatomic, readonly) bool gestureCaptured; +@property (nonatomic, readonly) NSTimeInterval gestureCapturedTime; @end #endif /* CustomTapGestureRecognizer_h */ diff --git a/Limelight/Input/CustomTapGestureRecognizer.m b/Limelight/Input/CustomTapGestureRecognizer.m index 9962f890..e077c5ff 100644 --- a/Limelight/Input/CustomTapGestureRecognizer.m +++ b/Limelight/Input/CustomTapGestureRecognizer.m @@ -12,46 +12,48 @@ @implementation CustomTapGestureRecognizer -static NSTimeInterval multiFingerDownTime; -static bool multiFingerDown; static CGFloat screenHeightInPoints; -static CGFloat lowestTouchPointYCoord = 0.0; - (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action { self = [super initWithTarget:target action:action]; screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]); + lowestTouchPointYCoord = 0.0; return self; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // Check if the number of touches and taps meets the required criteria if ([[event allTouches] count] == _numberOfTouchesRequired) { - multiFingerDownTime = CACurrentMediaTime(); - multiFingerDown = true; - + _gestureCapturedTime = CACurrentMediaTime(); + _gestureCaptured = true; for(UITouch *touch in [event allTouches]){ if(lowestTouchPointYCoord < [touch locationInView:self.view].y) lowestTouchPointYCoord = [touch locationInView:self.view].y; } _lowestTouchPointHeight = screenHeightInPoints - lowestTouchPointYCoord; self.state = UIGestureRecognizerStatePossible; } + if ([[event allTouches] count] > _numberOfTouchesRequired) { + _gestureCaptured = false; + self.state = UIGestureRecognizerStateFailed; + } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // [super touchesEnded:touches withEvent:event]; - if(multiFingerDown && [[event allTouches] count] == [touches count]){ - multiFingerDown = false; - if((CACurrentMediaTime() - multiFingerDownTime) < _tapDownTimeThreshold / 1000){ + if(_gestureCaptured && [[event allTouches] count] == [touches count]){ + _gestureCaptured = false; + if((CACurrentMediaTime() - _gestureCapturedTime) < _tapDownTimeThreshold){ lowestTouchPointYCoord = 0.0; //reset for next recognition self.state = UIGestureRecognizerStateRecognized; } } } +/* + (CGFloat)lowestTouchPointHeight{ @synchronized (self){ return self.lowestTouchPointHeight; } -} +}*/ @end diff --git a/Limelight/Input/RelativeTouchHandler.m b/Limelight/Input/RelativeTouchHandler.m index 64d7da46..db020714 100644 --- a/Limelight/Input/RelativeTouchHandler.m +++ b/Limelight/Input/RelativeTouchHandler.m @@ -7,8 +7,11 @@ // #import "RelativeTouchHandler.h" +#import "CustomTapGestureRecognizer.h" #include +#define RIGHTCLICK_TAP_DOWN_TIME_THRESHOLD_S 0.1 + static const int REFERENCE_WIDTH = 1280; static const int REFERENCE_HEIGHT = 720; @@ -19,6 +22,7 @@ static const int REFERENCE_HEIGHT = 720; BOOL isDragging; NSTimer* dragTimer; NSUInteger peakTouchCount; + CustomTapGestureRecognizer* rightClickTapRecognizer; #if TARGET_OS_TV UIGestureRecognizer* remotePressRecognizer; @@ -32,6 +36,16 @@ static const int REFERENCE_HEIGHT = 720; self = [self init]; self->view = view; + // replace righclick recoginizing with my CustomTapGestureRecognizer for better experience, higher recoginizing rate. + rightClickTapRecognizer = [[CustomTapGestureRecognizer alloc] initWithTarget:self action:@selector(mouseRightClick)]; + rightClickTapRecognizer.numberOfTouchesRequired = 2; + rightClickTapRecognizer.tapDownTimeThreshold = RIGHTCLICK_TAP_DOWN_TIME_THRESHOLD_S; // tap down time in seconds. + rightClickTapRecognizer.delaysTouchesBegan = NO; + rightClickTapRecognizer.delaysTouchesEnded = NO; + [self->view addGestureRecognizer:rightClickTapRecognizer]; + + + #if TARGET_OS_TV remotePressRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonPressed:)]; remotePressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)]; @@ -46,6 +60,16 @@ static const int REFERENCE_HEIGHT = 720; return self; } +- (void)mouseRightClick { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + Log(LOG_D, @"Sending right mouse button press"); + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); + // Wait 100 ms to simulate a real button press + usleep(100 * 1000); + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); + }); +} + - (BOOL)isConfirmedMove:(CGPoint)currentPoint from:(CGPoint)originalPoint { // Movements of greater than 5 pixels are considered confirmed return hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) >= 5; @@ -102,12 +126,13 @@ static const int REFERENCE_HEIGHT = 720; } } } - } else if ([[event allTouches] count] == 2) { + } else if ([[event allTouches] count] == 2) { // mouse wheel scroll & right button click are both triggered by 2 finger gesture, some times cause competing (right click fails & scroll view jumps around). + //I'll deal with this in coming code. CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:view]; CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:view]; CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2); - if (touchLocation.y != avgLocation.y) { + if ((CACurrentMediaTime() - rightClickTapRecognizer.gestureCapturedTime > RIGHTCLICK_TAP_DOWN_TIME_THRESHOLD_S) && touchLocation.y != avgLocation.y) { //prevent sending scrollevent while right click gesture is being recognized. The time threshold is only 100ms, resulting in a barely noticeable delay before the scroll event is activated. LiSendHighResScrollEvent((avgLocation.y - touchLocation.y) * 10); } @@ -128,7 +153,7 @@ static const int REFERENCE_HEIGHT = 720; isDragging = false; LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); } else if (!touchMoved) { - if (peakTouchCount == 2) { + /*if (peakTouchCount == 2) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ Log(LOG_D, @"Sending right mouse button press"); @@ -139,7 +164,7 @@ static const int REFERENCE_HEIGHT = 720; LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); }); - } else if (peakTouchCount == 1) { + } else */if (peakTouchCount == 1) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ if (!self->isDragging){ Log(LOG_D, @"Sending left mouse button press"); diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 3e385b1b..be1efbb0 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -75,7 +75,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; isInputingText = false; keyboardToggleRecognizer = [[CustomTapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleKeyboard)]; keyboardToggleRecognizer.numberOfTouchesRequired = settings.keyboardToggleFingers.intValue; - keyboardToggleRecognizer.tapDownTimeThreshold = 300.0; // tap down time threshold in milli seconds. + keyboardToggleRecognizer.tapDownTimeThreshold = 0.3; // tap down time threshold in seconds. keyboardToggleRecognizer.delaysTouchesBegan = NO; keyboardToggleRecognizer.delaysTouchesEnded = NO; [[NSNotificationCenter defaultCenter] addObserver:self