From db75cac9bc8f0a56e2b35eff091cab71613d5d54 Mon Sep 17 00:00:00 2001 From: True Zhuanjia Date: Tue, 20 Aug 2024 23:16:26 +0800 Subject: [PATCH] Build 31 touches spawned at the upper 40% screen edge (left or right) will not be sent to the remote PC --- Limelight/Input/NativeTouchHandler.m | 32 +++++++++++++++---- .../CustomEdgeSwipeGestureRecognizer.h | 2 +- .../CustomEdgeSwipeGestureRecognizer.m | 10 +++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Limelight/Input/NativeTouchHandler.m b/Limelight/Input/NativeTouchHandler.m index d44a1f91..89168b4d 100644 --- a/Limelight/Input/NativeTouchHandler.m +++ b/Limelight/Input/NativeTouchHandler.m @@ -23,6 +23,7 @@ TemporarySettings* currentSettings; bool activateCoordSelector; bool notPureNativeTouchMode; + // Use a Dictionary to store UITouch object's memory address as key, and pointerId as value,字典存放UITouch对象地址和pointerId映射关系 // pointerId will be generated from a pre-defined pool // Use a NSSet store active pointerId, @@ -30,23 +31,30 @@ NSMutableSet *activePointerIds; //pointerId Set for active touches. NSMutableSet *pointerIdPool; //pre-defined pool of pointerIds. NSMutableSet *unassignedPointerIds; + NSMutableSet *excludedPointerIds; // a NSSet of pointerIds of touches that will not be sent to the remote PC for better swipe gesture handling + CGFloat slideGestureVerticalThreshold; + CGFloat screenWidthWithThreshold; + CGFloat EDGE_TOLERANCE; } - - (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{ self = [super init]; self->streamView = view; self->currentSettings = settings; self->activateCoordSelector = currentSettings.pointerVelocityModeDivider.floatValue != 1.0; self->notPureNativeTouchMode = !(currentSettings.touchMode.intValue == PURE_NATIVE_TOUCH); - //_touchesCapturedByOnScreenButtons = [[NSMutableSet alloc] init]; - pointerIdDict = [NSMutableDictionary dictionary]; - pointerIdPool = [NSMutableSet set]; + self->pointerIdDict = [NSMutableDictionary dictionary]; + self->pointerIdPool = [NSMutableSet set]; for (uint8_t i = 0; i <= 10; i++) { //ipadOS supports upto 11 finger touches - [pointerIdPool addObject:@(i)]; + [self->pointerIdPool addObject:@(i)]; } - activePointerIds = [NSMutableSet set]; + self->activePointerIds = [NSMutableSet set]; + self->excludedPointerIds = [[NSMutableSet alloc] init]; + + EDGE_TOLERANCE = 5.0; + slideGestureVerticalThreshold = CGRectGetHeight([[UIScreen mainScreen] bounds]) * 0.4; + screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - EDGE_TOLERANCE; [NativeTouchPointer setPointerVelocityDivider:settings.pointerVelocityModeDivider.floatValue]; [NativeTouchPointer setPointerVelocityFactor:settings.touchPointerVelocityFactor.floatValue]; @@ -56,14 +64,20 @@ } + // generate & populate pointerId into NSDict & NSSet, called in touchesBegan - (void)populatePointerId:(UITouch*)touch{ + //populate pointerId uintptr_t memAddrValue = (uintptr_t)touch; unassignedPointerIds = [pointerIdPool mutableCopy]; //reset unassignedPointerIds [unassignedPointerIds minusSet:activePointerIds]; uint8_t pointerId = [[unassignedPointerIds anyObject] unsignedIntValue]; [pointerIdDict setObject:@(pointerId) forKey:@(memAddrValue)]; [activePointerIds addObject:@(pointerId)]; + + //check if touch point is spawned on the left or right upper half screen edges, if so we'll populate the excluded pointer id NSSet and not send the touch event to remote PC. this is for better handling in-stream slide gesture + CGPoint initialPoint = [touch locationInView:self->streamView]; + if(initialPoint.y < slideGestureVerticalThreshold && (initialPoint.x < EDGE_TOLERANCE || initialPoint.x > screenWidthWithThreshold)) [excludedPointerIds addObject:@(pointerId)]; } // remove pointerId in touchesEnded or touchesCancelled @@ -73,6 +87,7 @@ if(pointerIdObj != nil){ [activePointerIds removeObject:pointerIdObj]; [pointerIdDict removeObjectForKey:@(memAddrValue)]; + if([excludedPointerIds containsObject:pointerIdObj]) [excludedPointerIds removeObject:pointerIdObj]; // remove pointer id from excludedPointerId NSSet } } @@ -85,13 +100,16 @@ - (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType{ CGPoint targetCoords; + uint8_t pointerId = [self retrievePointerIdFromDict:touch]; + NSLog(@"excluded count: %d", (uint32_t)[excludedPointerIds count]); if(activateCoordSelector && touch.phase == UITouchPhaseMoved) targetCoords = [NativeTouchPointer selectCoordsFor:touch]; // coordinates of touch pointer replaced to relative ones here. + + if([excludedPointerIds containsObject:@(pointerId)]) return; // if the pointerId has been excluded by edge check, we're done here. this touch event will not be sent to the remote PC. and this must be checked after coord selector finishes populating new relative coords, or the app will crash! else targetCoords = [touch locationInView:streamView]; CGPoint location = [streamView adjustCoordinatesForVideoArea:targetCoords]; CGSize videoSize = [streamView getVideoAreaSize]; CGFloat normalizedX = location.x / videoSize.width; CGFloat normalizedY = location.y / videoSize.height; - uint8_t pointerId = [self retrievePointerIdFromDict:touch]; if([NativeTouchPointer getPointerObjFromDict:touch].needResetCoords){ // access whether the current pointer has reached the boundary, and need a coord reset. LiSendTouchEvent(LI_TOUCH_EVENT_UP, pointerId, normalizedX, normalizedY, 0, 0, 0, 0); //event must sent from the lowest level directy by LiSendTouchEvent to simulate continous dragging to another point on screen diff --git a/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.h b/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.h index 64233180..d87308a1 100644 --- a/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.h +++ b/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.h @@ -16,7 +16,7 @@ @property (nonatomic, assign) UIRectEdge edges; // Specify the edge(s) you want to recognize the swipe gesture on @property (nonatomic, assign) CGFloat normalizedThresholdDistance; // Distance from the edge to start recognizing the gesture @property (nonatomic, assign) bool immediateTriggering; -@property (nonatomic, assign) CGFloat edgeTolerancePoints; +@property (nonatomic, assign) CGFloat EDGE_TOLERANCE; @end #endif /* CustomEdgeSwipeGestureRecognizer_h */ diff --git a/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.m b/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.m index 9e9cd431..68baa202 100644 --- a/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.m +++ b/Limelight/ViewControllers/CustomEdgeSwipeGestureRecognizer.m @@ -20,7 +20,7 @@ static CGFloat screenWidthInPoints; self = [super initWithTarget:target action:action]; screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); // Get the screen's bounds (in points) _immediateTriggering = false; - _edgeTolerancePoints = 50.0f; + _EDGE_TOLERANCE = 15.0f; return self; } @@ -32,13 +32,13 @@ static CGFloat screenWidthInPoints; if(_immediateTriggering){ if(self.edges & UIRectEdgeLeft){ - if(startPointX < _edgeTolerancePoints){ + if(startPointX < _EDGE_TOLERANCE){ self.state = UIGestureRecognizerStateEnded; } // NSLog(@"startPointX %f , normalizedGestureDeltaX %f", startPointX, normalizedGestureDistance); } if(self.edges & UIRectEdgeRight){ - if(startPointX > screenWidthInPoints - _edgeTolerancePoints){ + if(startPointX > screenWidthInPoints - _EDGE_TOLERANCE){ self.state = UIGestureRecognizerStateEnded; } // NSLog(@"startPointX %f , normalizedGestureDeltaX %f", startPointX, normalizedGestureDistance); @@ -55,13 +55,13 @@ static CGFloat screenWidthInPoints; CGFloat normalizedGestureDistance = fabs(_endPointX - startPointX)/screenWidthInPoints; if(self.edges & UIRectEdgeLeft){ - if(startPointX < _edgeTolerancePoints && normalizedGestureDistance > _normalizedThresholdDistance){ + if(startPointX < _EDGE_TOLERANCE && normalizedGestureDistance > _normalizedThresholdDistance){ self.state = UIGestureRecognizerStateEnded; } // NSLog(@"startPointX %f , normalizedGestureDeltaX %f", startPointX, normalizedGestureDistance); } if(self.edges & UIRectEdgeRight){ - if((startPointX > (screenWidthInPoints - _edgeTolerancePoints)) && normalizedGestureDistance > _normalizedThresholdDistance){ + if((startPointX > (screenWidthInPoints - _EDGE_TOLERANCE)) && normalizedGestureDistance > _normalizedThresholdDistance){ self.state = UIGestureRecognizerStateEnded; } // NSLog(@"startPointX %f , normalizedGestureDeltaX %f", startPointX, normalizedGestureDistance);