Improved pointerId mechanism, 0 probability of repetition.

This commit is contained in:
True Zhuanjia committed 2024-05-12 21:48:57 +08:00
1 parent 4e59c3375e
commit 0fda662370
1 file changed
+66 -45
+66 -45
View File
@@ -14,7 +14,6 @@
#import "RelativeTouchHandler.h" #import "RelativeTouchHandler.h"
#import "AbsoluteTouchHandler.h" #import "AbsoluteTouchHandler.h"
#import "KeyboardInputField.h" #import "KeyboardInputField.h"
#import "zlib.h" //to implement crc32 checksum
static const double X1_MOUSE_SPEED_DIVISOR = 2.5; static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
@@ -27,6 +26,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
float streamAspectRatio; float streamAspectRatio;
// Use a Dictionary to store UITouch object's memory address as key, and pointerId as value,字典存放UITouch对象地址和pointerId映射关系
// pointerId will be generated from electronic noise, by arc4_random, pointerId,由随机噪声生成
// Use a NSSet store pointerId, for quick repeition inquiry, NSSet存放活跃的pointerId合集,用于快速查找,以防重复.
NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch.
NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
// iOS 13.4 mouse support // iOS 13.4 mouse support
NSInteger lastMouseButtonMask; NSInteger lastMouseButtonMask;
float lastMouseX; float lastMouseX;
@@ -50,6 +55,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
- (void) setupStreamView:(ControllerSupport*)controllerSupport - (void) setupStreamView:(ControllerSupport*)controllerSupport
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
config:(StreamConfiguration*)streamConfig { config:(StreamConfiguration*)streamConfig {
pointerIdDict = [NSMutableDictionary dictionary];
pointerIdSet = [NSMutableSet set];
self->interactionDelegate = interactionDelegate; self->interactionDelegate = interactionDelegate;
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height; self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
@@ -240,19 +248,45 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
return 90 - MIN(90, altitudeDegs); return 90 - MIN(90, altitudeDegs);
} }
// convert 64bit pointer to CRC32 checksum // 随机生成pointerId并填入NSDict和NSSet
- (uint32_t)crc32OfUint64:(uint64_t)value { // generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
// uint64_t可以被视为字符数组来计算CRC32 - (void)populatePointerId:(UITouch*)event{
char data[sizeof(value)]; uint64_t eventAddrValue = (uint64_t)event;
memcpy(data, &value, sizeof(value)); uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
uint32_t crc = crc32(0, Z_NULL, 0); while(true){
crc = crc32(crc, (const Bytef *)data, sizeof(value)); if([pointerIdSet containsObject:@(randomPointerId)]) randomPointerId = arc4random_uniform(UINT32_MAX); // in case of new pointerId collides with existing ones, generate again.
return crc; else{ // populate pointerId into NSDict & NSSet.
[pointerIdDict setObject:@(randomPointerId) forKey:@(eventAddrValue)];
[pointerIdSet addObject:@(randomPointerId)];
return;
}
}
} }
- (void)trySendTouchEvent:(UITouch*)event index:(int)index{ // remove pointerId in UITouchPhaseEnded condition
- (void)removePointerId:(UITouch*)event{
uint64_t eventAddrValue = (uint64_t)event;
[pointerIdSet removeObject:[pointerIdDict objectForKey:@(eventAddrValue)]];
[pointerIdDict removeObjectForKey:@(eventAddrValue)];
}
// 从字典中获取UITouch事件对应的pointerId
// call this only when NSDcit & NSSet is up-to-date.
- (uint32_t) retrievePointerIdFromDict:(UITouch*)event{
return [[pointerIdDict objectForKey:@((uint64_t)event)] unsignedIntValue];
}
- (void)sendTouchEvent:(UITouch*)event touchType:(uint8_t)touchType{
CGPoint location = [self adjustCoordinatesForVideoArea:[event locationInView:self]];
CGSize videoSize = [self getVideoAreaSize];
LiSendTouchEvent(touchType,[self retrievePointerIdFromDict:event],location.x / videoSize.width, location.y / videoSize.height,(event.force / event.maximumPossibleForce) / sin(event.altitudeAngle),0.0f, 0.0f,[self getRotationFromAzimuthAngle:[event azimuthAngleInView:self]]);
}
- (void)handleUITouch:(UITouch*)event index:(int)index{
uint8_t type; uint8_t type;
// NSLog(@"trySendTouchEvent %ld,%d",(long)event.phase,(uint32_t)event); // NSLog(@"handleUITouch %ld,%d",(long)event.phase,(uint32_t)event);
//#define LI_TOUCH_EVENT_HOVER 0x00 //#define LI_TOUCH_EVENT_HOVER 0x00
//#define LI_TOUCH_EVENT_DOWN 0x01 //#define LI_TOUCH_EVENT_DOWN 0x01
//#define LI_TOUCH_EVENT_UP 0x02 //#define LI_TOUCH_EVENT_UP 0x02
@@ -276,46 +310,32 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
switch (event.phase) { switch (event.phase) {
case UITouchPhaseBegan://开始触摸 case UITouchPhaseBegan://开始触摸
type = LI_TOUCH_EVENT_DOWN; type = LI_TOUCH_EVENT_DOWN;
[self populatePointerId:event]; //获取并记录pointerId
break; break;
case UITouchPhaseMoved://移动 case UITouchPhaseMoved://移动
case UITouchPhaseStationary: case UITouchPhaseStationary:
type = LI_TOUCH_EVENT_MOVE; type = LI_TOUCH_EVENT_MOVE;
break; break;
case UITouchPhaseEnded://触摸结束
type = LI_TOUCH_EVENT_UP;
break;
case UITouchPhaseCancelled://触摸取消
type = LI_TOUCH_EVENT_CANCEL;
break;
case UITouchPhaseRegionEntered://停留 case UITouchPhaseRegionEntered://停留
case UITouchPhaseRegionMoved://停留 case UITouchPhaseRegionMoved://停留
type = LI_TOUCH_EVENT_HOVER; type = LI_TOUCH_EVENT_HOVER;
break; break;
case UITouchPhaseEnded://触摸结束
type = LI_TOUCH_EVENT_UP;
[self sendTouchEvent:event touchType:type]; //先发送,再删除
[self removePointerId:event]; //删除pointerId
return;
case UITouchPhaseCancelled://触摸取消
type = LI_TOUCH_EVENT_CANCEL;
//[self sendTouchEvent:event touchType:type];
// [pointerIdDict removeAllObjects]; //do not remove object from pointerDict & pointerIdSet here. they'll be removed in UITouchPhaseEnded.
// [pointerIdSet removeAllObjects];
//return;
default: default:
return; return;
} }
// switch (event.phase) {
// case UITouchPhaseBegan: [self sendTouchEvent:event touchType:type];
// type = LI_TOUCH_EVENT_DOWN;
// break;
// case UITouchPhaseMoved:
// type = LI_TOUCH_EVENT_MOVE;
// break;
// case UITouchPhaseEnded:
// type = LI_TOUCH_EVENT_UP;
// break;
// case UITouchPhaseCancelled:
// type = LI_TOUCH_EVENT_CANCEL;
// break;
// default:
// return;
// }
uint32_t pointerId = [self crc32OfUint64:((uint64_t)event)]; // convert pointer event(64bit) to CRC32 checksum as touch pointer ID.
// There's no pointerId like Android in definition of iOS touch event "UITouch", we use pointer to UITouch to generate touch pointer ID.
// Since touch pointer ID is defined to be uint32_t, I implement CRC32 checksum to the 64bit address, which avoids touch pointer ID repetition.
CGPoint location = [self adjustCoordinatesForVideoArea:[event locationInView:self]];
CGSize videoSize = [self getVideoAreaSize];
LiSendTouchEvent(type,pointerId,location.x / videoSize.width, location.y / videoSize.height,(event.force / event.maximumPossibleForce) / sin(event.altitudeAngle),0.0f, 0.0f,[self getRotationFromAzimuthAngle:[event azimuthAngleInView:self]]);
} }
@@ -425,7 +445,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
// } // }
// TemporarySettings* settings = [[[DataManager alloc] init] getSettings]; // TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
// if (settings.absoluteTouchMode) { // if (settings.absoluteTouchMode) {
// [self trySendTouchEvent:arr1[i] index:i]; // [self handleUITouch:arr1[i] index:i];
// return; // return;
// } // }
// } // }
@@ -437,7 +457,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
} }
TemporarySettings* settings = [[[DataManager alloc] init] getSettings]; TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
if (settings.absoluteTouchMode) { if (settings.absoluteTouchMode) {
[self trySendTouchEvent:touch index:0]; [self handleUITouch:touch index:0];
// return; // return;
} }
} }
@@ -620,8 +641,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
} }
TemporarySettings* settings = [[[DataManager alloc] init] getSettings]; TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
if (settings.absoluteTouchMode) { if (settings.absoluteTouchMode) {
[self trySendTouchEvent:touch index:0]; [self handleUITouch:touch index:0];
// return; // return;
} }
} }
@@ -713,7 +734,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
} }
TemporarySettings* settings = [[[DataManager alloc] init] getSettings]; TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
if (settings.absoluteTouchMode) { if (settings.absoluteTouchMode) {
[self trySendTouchEvent:touch index:0]; [self handleUITouch:touch index:0];
// return; // return;
} }
} }
@@ -738,7 +759,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
} }
TemporarySettings* settings = [[[DataManager alloc] init] getSettings]; TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
if (settings.absoluteTouchMode) { if (settings.absoluteTouchMode) {
[self trySendTouchEvent:touch index:0]; [self handleUITouch:touch index:0];
// return; // return;
} }
} }