NativeTouchHandler improvement, general coding improvements.
This commit is contained in:
1 parent
ee4eb35fe3
commit
f09c7be18d
5 files changed
+65
-76
No files matched your search
@@ -15,8 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@interface NativeTouchHandler : UIResponder
|
@interface NativeTouchHandler : UIResponder
|
||||||
|
|
||||||
- (id)initWith:(StreamView*)view and:(TemporarySettings*)settings;
|
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -15,39 +15,80 @@
|
|||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@implementation NativeTouchHandler {
|
@implementation NativeTouchHandler {
|
||||||
StreamView* streamView;
|
StreamView* streamView;
|
||||||
TemporarySettings* currentSettings;
|
TemporarySettings* currentSettings;
|
||||||
bool activateCoordSelector;
|
bool activateCoordSelector;
|
||||||
|
// 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,
|
||||||
|
NSMutableDictionary *pointerIdDict; //pointerId Dict for active touches.
|
||||||
|
NSMutableSet<NSNumber *> *activePointerIds; //pointerId Set for active touches.
|
||||||
|
NSMutableSet<NSNumber *> *pointerIdPool; //pre-defined pool of pointerIds.
|
||||||
|
NSMutableSet<NSNumber *> *unassignedPointerIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (id)initWith:(StreamView*)view and:(TemporarySettings*)settings{
|
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{
|
||||||
self = [self init];
|
self = [super init];
|
||||||
self->streamView = view;
|
self->streamView = view;
|
||||||
self->currentSettings = settings;
|
self->currentSettings = settings;
|
||||||
self->activateCoordSelector = currentSettings.pointerVelocityModeDivider.floatValue != 1.0;
|
self->activateCoordSelector = currentSettings.pointerVelocityModeDivider.floatValue != 1.0;
|
||||||
|
|
||||||
|
pointerIdDict = [NSMutableDictionary dictionary];
|
||||||
|
pointerIdPool = [NSMutableSet set];
|
||||||
|
for (uint8_t i = 0; i < 10; i++) { //ipadOS supports upto 11 finger touches
|
||||||
|
[pointerIdPool addObject:@(i)];
|
||||||
|
}
|
||||||
|
activePointerIds = [NSMutableSet set];
|
||||||
|
|
||||||
[NativeTouchPointer setPointerVelocityDivider:settings.pointerVelocityModeDivider.floatValue];
|
[NativeTouchPointer setPointerVelocityDivider:settings.pointerVelocityModeDivider.floatValue];
|
||||||
[NativeTouchPointer setPointerVelocityFactor:settings.touchPointerVelocityFactor.floatValue];
|
[NativeTouchPointer setPointerVelocityFactor:settings.touchPointerVelocityFactor.floatValue];
|
||||||
[NativeTouchPointer initContextWith:streamView];
|
[NativeTouchPointer initContextWithView:streamView];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// generate & populate pointerId into NSDict & NSSet, called in touchesBegan
|
||||||
|
- (void)populatePointerId:(UITouch*)touch{
|
||||||
|
uintptr_t memAddrValue = (uintptr_t)touch;
|
||||||
|
unassignedPointerIds = [pointerIdPool mutableCopy]; //reset unassignedPointerIds
|
||||||
|
[unassignedPointerIds minusSet:activePointerIds];
|
||||||
|
uint8_t pointerId = [[unassignedPointerIds anyObject] intValue];
|
||||||
|
[pointerIdDict setObject:@(pointerId) forKey:@(memAddrValue)];
|
||||||
|
[activePointerIds addObject:@(pointerId)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove pointerId in touchesEnded or touchesCancelled
|
||||||
|
- (void)removePointerId:(UITouch*)touch{
|
||||||
|
uintptr_t memAddrValue = (uintptr_t)touch;
|
||||||
|
NSNumber* pointerIdObj = [pointerIdDict objectForKey:@(memAddrValue)];
|
||||||
|
if(pointerIdObj != nil){
|
||||||
|
[activePointerIds removeObject:pointerIdObj];
|
||||||
|
[pointerIdDict removeObjectForKey:@(memAddrValue)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从字典中获取UITouch事件对应的pointerId
|
||||||
|
// called in method of sendTouchEvent
|
||||||
|
- (uint32_t) retrievePointerIdFromDict:(UITouch*)touch{
|
||||||
|
return [[pointerIdDict objectForKey:@((uintptr_t)touch)] unsignedIntValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType{
|
- (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType{
|
||||||
CGPoint targetCoords;
|
CGPoint targetCoords;
|
||||||
if(activateCoordSelector && touch.phase == UITouchPhaseMoved) targetCoords = [NativeTouchPointer selectCoordsFor:touch]; // coordinates of touch pointer replaced to relative ones here.
|
if(activateCoordSelector && touch.phase == UITouchPhaseMoved) targetCoords = [NativeTouchPointer selectCoordsFor:touch]; // coordinates of touch pointer replaced to relative ones here.
|
||||||
else targetCoords = [touch locationInView:streamView];
|
else targetCoords = [touch locationInView:streamView];
|
||||||
CGPoint location = [streamView adjustCoordinatesForVideoArea:targetCoords];
|
CGPoint location = [streamView adjustCoordinatesForVideoArea:targetCoords];
|
||||||
CGSize videoSize = [streamView getVideoAreaSize];
|
CGSize videoSize = [streamView getVideoAreaSize];
|
||||||
LiSendTouchEvent(touchType,[NativeTouchPointer retrievePointerIdFromDict:touch],location.x / videoSize.width, location.y / videoSize.height,(touch.force / touch.maximumPossibleForce) / sin(touch.altitudeAngle),0.0f, 0.0f,[streamView getRotationFromAzimuthAngle:[touch azimuthAngleInView:streamView]]);
|
LiSendTouchEvent(touchType,[self retrievePointerIdFromDict:touch],location.x / videoSize.width, location.y / videoSize.height,(touch.force / touch.maximumPossibleForce) / sin(touch.altitudeAngle),0.0f, 0.0f,[streamView getRotationFromAzimuthAngle:[touch azimuthAngleInView:streamView]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
for (UITouch* touch in touches){
|
for (UITouch* touch in touches){
|
||||||
[NativeTouchPointer populatePointerId:touch]; //generate & populate pointerId
|
[self populatePointerId:touch]; //generate & populate pointerId
|
||||||
if(activateCoordSelector) [NativeTouchPointer populatePointerObjIntoDict:touch];
|
if(activateCoordSelector) [NativeTouchPointer populatePointerObjIntoDict:touch];
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
||||||
}
|
}
|
||||||
@@ -66,18 +107,14 @@
|
|||||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
for (UITouch* touch in touches){
|
for (UITouch* touch in touches){
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
||||||
[NativeTouchPointer removePointerId:touch]; //then remove pointerId
|
[self removePointerId:touch]; //then remove pointerId
|
||||||
if(activateCoordSelector) [NativeTouchPointer removePointerObjFromDict:touch];
|
if(activateCoordSelector) [NativeTouchPointer removePointerObjFromDict:touch];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
for (UITouch* touch in touches){
|
[self touchesEnded:touches withEvent:event];
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
|
||||||
[NativeTouchPointer removePointerId:touch]; //then remove pointerId
|
|
||||||
if(activateCoordSelector) [NativeTouchPointer removePointerObjFromDict:touch];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@interface NativeTouchPointer : NSObject
|
@interface NativeTouchPointer : NSObject
|
||||||
|
|
||||||
+ (void)initContextWith:(StreamView *)view;
|
+ (void)initContextWithView:(StreamView *)view;
|
||||||
+ (void)populatePointerId:(UITouch*)touch;
|
|
||||||
+ (void)removePointerId:(UITouch*)touch;
|
|
||||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)touch;
|
|
||||||
+ (void)setPointerVelocityDivider:(CGFloat)dividerLocation;
|
+ (void)setPointerVelocityDivider:(CGFloat)dividerLocation;
|
||||||
+ (void)setPointerVelocityFactor:(CGFloat)velocityFactor;
|
+ (void)setPointerVelocityFactor:(CGFloat)velocityFactor;
|
||||||
+ (void)populatePointerObjIntoDict:(UITouch*)touch;
|
+ (void)populatePointerObjIntoDict:(UITouch*)touch;
|
||||||
@@ -24,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
+ (CGPoint)selectCoordsFor:(UITouch *)touch;
|
+ (CGPoint)selectCoordsFor:(UITouch *)touch;
|
||||||
|
|
||||||
|
|
||||||
- (instancetype)initWith:(UITouch *)touch;
|
- (instancetype)initWithTouch:(UITouch *)touch;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,7 @@
|
|||||||
// pointer instance with coordinate manipulation.
|
// pointer instance with coordinate manipulation.
|
||||||
|
|
||||||
|
|
||||||
// Use a Dictionary to store UITouch object's memory address as key, and pointerId as value,字典存放UITouch对象地址和pointerId映射关系
|
static NSMutableDictionary *pointerObjDict;
|
||||||
// pointerId will be generated from electronic noise, by arc4_random, pointerId,由随机噪声生成
|
|
||||||
// Use a NSSet store pointerId, for quick repeition inquiry, NSSet存放活跃的pointerId合集,用于快速查找,以防重复.
|
|
||||||
static NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch.
|
|
||||||
static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
|
|
||||||
static NSMutableDictionary *pointerDict;
|
|
||||||
|
|
||||||
static CGFloat pointerVelocityFactor;
|
static CGFloat pointerVelocityFactor;
|
||||||
static CGFloat pointerVelocityDivider;
|
static CGFloat pointerVelocityDivider;
|
||||||
@@ -34,8 +29,6 @@ StreamView *streamView;
|
|||||||
CGPoint previousPoint;
|
CGPoint previousPoint;
|
||||||
CGPoint latestRelativePoint;
|
CGPoint latestRelativePoint;
|
||||||
CGPoint previousRelativePoint;
|
CGPoint previousRelativePoint;
|
||||||
// CGFloat velocityX;
|
|
||||||
// CGFloat velocityY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)setPointerVelocityDivider:(CGFloat)dividerLocation{
|
+ (void)setPointerVelocityDivider:(CGFloat)dividerLocation{
|
||||||
@@ -47,8 +40,8 @@ StreamView *streamView;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (instancetype)initWith:(UITouch *)touch{
|
- (instancetype)initWithTouch:(UITouch *)touch{
|
||||||
self = [self init];
|
self = [super init];
|
||||||
self->initialPoint = [touch locationInView:streamView];
|
self->initialPoint = [touch locationInView:streamView];
|
||||||
self->latestPoint = self->initialPoint;
|
self->latestPoint = self->initialPoint;
|
||||||
self->latestRelativePoint = self->initialPoint;
|
self->latestRelativePoint = self->initialPoint;
|
||||||
@@ -58,43 +51,39 @@ StreamView *streamView;
|
|||||||
- (void)updatePointerCoords:(UITouch *)touch{
|
- (void)updatePointerCoords:(UITouch *)touch{
|
||||||
previousPoint = latestPoint;
|
previousPoint = latestPoint;
|
||||||
latestPoint = [touch locationInView:streamView];
|
latestPoint = [touch locationInView:streamView];
|
||||||
// velocityX = latestPoint.x - previousPoint.x;
|
|
||||||
// velocityY = latestPoint.y - previousPoint.y;
|
|
||||||
previousRelativePoint = latestRelativePoint;
|
previousRelativePoint = latestRelativePoint;
|
||||||
latestRelativePoint.x = previousRelativePoint.x + pointerVelocityFactor * (latestPoint.x - previousPoint.x);
|
latestRelativePoint.x = previousRelativePoint.x + pointerVelocityFactor * (latestPoint.x - previousPoint.x);
|
||||||
latestRelativePoint.y = previousRelativePoint.y + pointerVelocityFactor * (latestPoint.y - previousPoint.y);
|
latestRelativePoint.y = previousRelativePoint.y + pointerVelocityFactor * (latestPoint.y - previousPoint.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)initContextWith:(StreamView *)view{
|
+ (void)initContextWithView:(StreamView *)view{
|
||||||
streamView = view;
|
streamView = view;
|
||||||
pointerIdDict = [NSMutableDictionary dictionary];
|
pointerObjDict = [NSMutableDictionary dictionary];
|
||||||
pointerIdSet = [NSMutableSet set];
|
|
||||||
pointerDict = [NSMutableDictionary dictionary];
|
|
||||||
pointerVelocityDividerLocationByPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]) * pointerVelocityDivider;
|
pointerVelocityDividerLocationByPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]) * pointerVelocityDivider;
|
||||||
NSLog(@"pointerVelocityDivider: %.2f", pointerVelocityDivider);
|
NSLog(@"pointerVelocityDivider: %.2f", pointerVelocityDivider);
|
||||||
NSLog(@"pointerVelocityDividerLocationByPoints: %.2f", pointerVelocityDividerLocationByPoints);
|
NSLog(@"pointerVelocityDividerLocationByPoints: %.2f", pointerVelocityDividerLocationByPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)populatePointerObjIntoDict:(UITouch*)touch{
|
+ (void)populatePointerObjIntoDict:(UITouch*)touch{
|
||||||
[pointerDict setObject:[[NativeTouchPointer alloc] initWith:touch] forKey:@((uint64_t)touch)];
|
[pointerObjDict setObject:[[NativeTouchPointer alloc] initWithTouch:touch] forKey:@((uintptr_t)touch)];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)removePointerObjFromDict:(UITouch*)touch{
|
+ (void)removePointerObjFromDict:(UITouch*)touch{
|
||||||
uint64_t eventAddrValue = (uint64_t)touch;
|
uintptr_t memAddrValue = (uintptr_t)touch;
|
||||||
NativeTouchPointer* pointer = [pointerDict objectForKey:@(eventAddrValue)];
|
NativeTouchPointer* pointer = [pointerObjDict objectForKey:@(memAddrValue)];
|
||||||
if(pointer != nil){
|
if(pointer != nil){
|
||||||
[pointerDict removeObjectForKey:@(eventAddrValue)];
|
[pointerObjDict removeObjectForKey:@(memAddrValue)];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)updatePointerObjInDict:(UITouch *)touch{
|
+ (void)updatePointerObjInDict:(UITouch *)touch{
|
||||||
[[pointerDict objectForKey:@((uint64_t)touch)] updatePointerCoords:touch];
|
[[pointerObjDict objectForKey:@((uintptr_t)touch)] updatePointerCoords:touch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+ (CGPoint)selectCoordsFor:(UITouch *)touch{
|
+ (CGPoint)selectCoordsFor:(UITouch *)touch{
|
||||||
NativeTouchPointer *pointer = [pointerDict objectForKey:@((uint64_t)touch)];
|
NativeTouchPointer *pointer = [pointerObjDict objectForKey:@((uintptr_t)touch)];
|
||||||
if((pointer -> initialPoint).x > pointerVelocityDividerLocationByPoints){ //if first contact coords locates on the right side of divider.
|
if((pointer -> initialPoint).x > pointerVelocityDividerLocationByPoints){ //if first contact coords locates on the right side of divider.
|
||||||
return pointer->latestRelativePoint;
|
return pointer->latestRelativePoint;
|
||||||
}
|
}
|
||||||
@@ -103,39 +92,5 @@ StreamView *streamView;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 随机生成pointerId并填入NSDict和NSSet
|
|
||||||
// generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
|
|
||||||
+ (void)populatePointerId:(UITouch*)touch{
|
|
||||||
uint64_t eventAddrValue = (uint64_t)touch;
|
|
||||||
uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
|
|
||||||
for(;;){
|
|
||||||
if([pointerIdSet containsObject:@(randomPointerId)]) randomPointerId = arc4random_uniform(UINT32_MAX); // in case of new pointerId collides with existing ones, generate again.
|
|
||||||
else{ // populate pointerId into NSDict & NSSet.
|
|
||||||
[pointerIdDict setObject:@(randomPointerId) forKey:@(eventAddrValue)];
|
|
||||||
[pointerIdSet addObject:@(randomPointerId)];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// remove pointerId in UITouchPhaseEnded condition
|
|
||||||
+ (void)removePointerId:(UITouch*)touch{
|
|
||||||
uint64_t eventAddrValue = (uint64_t)touch;
|
|
||||||
NSNumber* pointerIdObj = [pointerIdDict objectForKey:@(eventAddrValue)];
|
|
||||||
if(pointerIdObj != nil){
|
|
||||||
[pointerIdSet removeObject:pointerIdObj];
|
|
||||||
[pointerIdDict removeObjectForKey:@(eventAddrValue)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从字典中获取UITouch事件对应的pointerId
|
|
||||||
// call this only when NSDcit & NSSet is up-to-date.
|
|
||||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)touch{
|
|
||||||
return [[pointerIdDict objectForKey:@((uint64_t)touch)] unsignedIntValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -98,7 +98,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
switch (settings.touchMode.intValue) {
|
switch (settings.touchMode.intValue) {
|
||||||
case NATIVE_TOUCH_MODE:
|
case NATIVE_TOUCH_MODE:
|
||||||
self->touchHandler = [[NativeTouchHandler alloc] initWith:self and:settings];break;
|
self->touchHandler = [[NativeTouchHandler alloc] initWithView:self andSettings:settings];break;
|
||||||
case RELATIVE_TOUCH_MODE:
|
case RELATIVE_TOUCH_MODE:
|
||||||
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
||||||
keyboardToggleRecognizer.immediateTriggering = true; //triggers signal in touchesBegan callback stage
|
keyboardToggleRecognizer.immediateTriggering = true; //triggers signal in touchesBegan callback stage
|
||||||
|
|||||||
Reference in new issue
Block a user