feat: track point for native touch

This commit is contained in:
True Zhuanjia committed 2026-02-11 22:56:50 +08:00
1 parent 8d54ed9316
commit bb6f2f0c0d
3 files changed
+123 -27

No files matched your search

+61 -14
View File
@@ -15,7 +15,6 @@
#include <Limelight.h> #include <Limelight.h>
@implementation NativeTouchHandler { @implementation NativeTouchHandler {
TemporarySettings* currentSettings;
__weak StreamView* streamView; __weak StreamView* streamView;
bool activateCoordSelector; bool activateCoordSelector;
bool singleTouchDisabled; bool singleTouchDisabled;
@@ -35,6 +34,9 @@
NSMutableSet<NSNumber *> *unassignedPointerIds; NSMutableSet<NSNumber *> *unassignedPointerIds;
NSMutableSet *blacklistedTouches; NSMutableSet *blacklistedTouches;
bool trackPointEnabled;
NSMutableArray<CAShapeLayer *> * trackPointPool; //pre-defined pool of pointerIds.
NSMutableDictionary *pointerObjDict; NSMutableDictionary *pointerObjDict;
CGFloat slideGestureVerticalThreshold; CGFloat slideGestureVerticalThreshold;
@@ -49,16 +51,19 @@
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{ - (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{
self = [super init]; self = [super init];
self->streamView = view; self->streamView = view;
self->currentSettings = settings; self->activateCoordSelector = settings.pointerVelocityModeDivider.floatValue != 1.0;
self->activateCoordSelector = currentSettings.pointerVelocityModeDivider.floatValue != 1.0; self->moveEventIntervalNSec = (int64_t)(settings.touchMoveEventInterval.intValue * 1000);;
self->moveEventIntervalNSec = (int64_t)(currentSettings.touchMoveEventInterval.intValue * 1000);;
self->streamViewBounds = view.bounds; self->streamViewBounds = view.bounds;
self->pointerIdDict = [NSMutableDictionary dictionary]; self->pointerIdDict = [NSMutableDictionary dictionary];
self->pointerIdPool = [NSMutableSet set]; self->pointerIdPool = [NSMutableSet set];
self->trackPointEnabled = settings.touchPointTracking;
self->trackPointPool = [NSMutableArray array];
for (uint8_t i = 0; i <= 10; i++) { //ipadOS supports upto 11 finger touches for (uint8_t i = 0; i <= 10; i++) { //ipadOS supports upto 11 finger touches
[self->pointerIdPool addObject:@(i)]; [self->pointerIdPool addObject:@(i)];
[self->trackPointPool addObject:[GraphicUtils makeTouchTrackpointIn:streamView]];
} }
self->activePointerIds = [NSMutableSet set]; self->activePointerIds = [NSMutableSet set];
self->blacklistedTouches = [NSMutableSet set]; self->blacklistedTouches = [NSMutableSet set];
@@ -219,7 +224,7 @@
} }
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (asyncNativeTouch) dispatch_async(dispatch_get_global_queue(touchDownQos, 0), ^{ dispatch_async(dispatch_get_global_queue(touchDownQos, 0), ^{
for (UITouch* touch in touches){ for (UITouch* touch in touches){
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch // continue to the next loop if current touch is already captured by OSC. works only in regular native touch
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue; if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
@@ -227,16 +232,21 @@
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch]; if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN withEvent:event]; [self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN withEvent:event];
} }
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.position = [touch locationInView:self->streamView];
trackPoint.hidden = false;
}
[CATransaction commit];
}
});
}); });
else{
for (UITouch* touch in touches){
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
[self handleTouchDown:touch]; //generate & populate pointerId
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN withEvent:event];
}
}
} }
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -248,6 +258,19 @@
[[self getPointerObjFromDict:touch] doesNeedResetCoords]; [[self getPointerObjFromDict:touch] doesNeedResetCoords];
} }
}); });
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.position = [touch locationInView:self->streamView];
}
[CATransaction commit];
}
});
} }
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -263,6 +286,19 @@
[self->blacklistedTouches removeObject:@((uintptr_t)touch)]; [self->blacklistedTouches removeObject:@((uintptr_t)touch)];
} }
}); });
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.hidden = true;
}
[CATransaction commit];
}
});
} }
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -302,4 +338,15 @@
singleTouchDisabled = !enabled; singleTouchDisabled = !enabled;
} }
- (void)dealloc{
NSLog(@"dealloc nativeTouchHanlder %f", CACurrentMediaTime());
pointerIdDict = nil;
activePointerIds = nil;
pointerIdPool= nil;
unassignedPointerIds = nil;
blacklistedTouches = nil;
trackPointPool = nil;
pointerObjDict = nil;
}
@end @end
+1
View File
@@ -470,6 +470,7 @@ import SVGKit
self.hasL3R3Indicator = !self.isStickWheel && !self.isDirectionPad && self.widgetType == WidgetTypeEnum.touchPad self.hasL3R3Indicator = !self.isStickWheel && !self.isDirectionPad && self.widgetType == WidgetTypeEnum.touchPad
self.hasTrackPoint = (CommandManager.vectorTouchPads.contains(self.touchPadString) self.hasTrackPoint = (CommandManager.vectorTouchPads.contains(self.touchPadString)
|| self.isStickWheel
|| (self.widgetType == WidgetTypeEnum.button || (self.widgetType == WidgetTypeEnum.button
&& (buttonMode == .slideAndHold || buttonMode == .slideToToggle))) && (buttonMode == .slideAndHold || buttonMode == .slideToToggle)))
} }
+61 -13
View File
@@ -15,7 +15,6 @@
#include <Limelight.h> #include <Limelight.h>
@implementation PureNativeTouchHandler { @implementation PureNativeTouchHandler {
TemporarySettings* currentSettings;
__weak StreamView* streamView; __weak StreamView* streamView;
bool activateCoordSelector; bool activateCoordSelector;
CGFloat pointerVelocityDividerLocationByPoints; CGFloat pointerVelocityDividerLocationByPoints;
@@ -34,6 +33,9 @@
NSMutableSet<NSNumber *> *unassignedPointerIds; NSMutableSet<NSNumber *> *unassignedPointerIds;
NSMutableSet *blacklistedTouches; NSMutableSet *blacklistedTouches;
bool trackPointEnabled;
NSMutableArray<CAShapeLayer *> * trackPointPool;
NSMutableDictionary *pointerObjDict; NSMutableDictionary *pointerObjDict;
CGFloat slideGestureVerticalThreshold; CGFloat slideGestureVerticalThreshold;
@@ -48,16 +50,20 @@
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{ - (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings{
self = [super init]; self = [super init];
self->streamView = view; self->streamView = view;
self->currentSettings = settings;
self->activateCoordSelector = currentSettings.pointerVelocityModeDivider.floatValue != 1.0; self->activateCoordSelector = settings.pointerVelocityModeDivider.floatValue != 1.0;
self->moveEventIntervalNSec = (int64_t)(currentSettings.touchMoveEventInterval.intValue * 1000);; self->moveEventIntervalNSec = (int64_t)(settings.touchMoveEventInterval.intValue * 1000);;
self->streamViewBounds = view.bounds; self->streamViewBounds = view.bounds;
self->pointerIdDict = [NSMutableDictionary dictionary]; self->pointerIdDict = [NSMutableDictionary dictionary];
self->pointerIdPool = [NSMutableSet set]; self->pointerIdPool = [NSMutableSet set];
self->trackPointEnabled = settings.touchPointTracking;
self->trackPointPool = [NSMutableArray array];
for (uint8_t i = 0; i <= 10; i++) { //ipadOS supports upto 11 finger touches for (uint8_t i = 0; i <= 10; i++) { //ipadOS supports upto 11 finger touches
[self->pointerIdPool addObject:@(i)]; [self->pointerIdPool addObject:@(i)];
[self->trackPointPool addObject:[GraphicUtils makeTouchTrackpointIn:streamView]];
} }
self->activePointerIds = [NSMutableSet set]; self->activePointerIds = [NSMutableSet set];
self->blacklistedTouches = [NSMutableSet set]; self->blacklistedTouches = [NSMutableSet set];
@@ -209,22 +215,27 @@
} }
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (asyncNativeTouch) dispatch_async(dispatch_get_global_queue(touchDownQos, 0), ^{ dispatch_async(dispatch_get_global_queue(touchDownQos, 0), ^{
for (UITouch* touch in touches){ for (UITouch* touch in touches){
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch // continue to the next loop if current touch is already captured by OSC. works only in regular native touch
[self handleTouchDown:touch]; //generate & populate pointerId [self handleTouchDown:touch]; //generate & populate pointerId
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch]; if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN]; [self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
} }
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.position = [touch locationInView:self->streamView];
trackPoint.hidden = false;
}
[CATransaction commit];
}
});
}); });
else{
for (UITouch* touch in touches){
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
[self handleTouchDown:touch]; //generate & populate pointerId
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
}
}
} }
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -235,6 +246,19 @@
[[self getPointerObjFromDict:touch] doesNeedResetCoords]; [[self getPointerObjFromDict:touch] doesNeedResetCoords];
} }
}); });
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.position = [touch locationInView:self->streamView];
}
[CATransaction commit];
}
});
} }
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -246,6 +270,19 @@
[self->blacklistedTouches removeObject:@((uintptr_t)touch)]; [self->blacklistedTouches removeObject:@((uintptr_t)touch)];
} }
}); });
dispatch_async(dispatch_get_main_queue(), ^{
if(self->trackPointEnabled){
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (UITouch* touch in touches){
uint8_t pointerId = [self retrievePointerIdFromDict:touch];
CAShapeLayer* trackPoint = self->trackPointPool[pointerId];
trackPoint.hidden = true;
}
[CATransaction commit];
}
});
} }
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -281,5 +318,16 @@
return pointer.useRelativeCoords ? pointer.latestRelativePoint : pointer.latestPoint; return pointer.useRelativeCoords ? pointer.latestRelativePoint : pointer.latestPoint;
} }
- (void)dealloc{
NSLog(@"dealloc purePativeTouchHanlder %f", CACurrentMediaTime());
pointerIdDict = nil;
activePointerIds = nil;
pointerIdPool= nil;
unassignedPointerIds = nil;
blacklistedTouches = nil;
trackPointPool = nil;
pointerObjDict = nil;
}
@end @end