Refactor related codes to NativeTouchHandler

This commit is contained in:
True Zhuanjia
2024-05-15 11:35:51 +08:00
parent 82de44df54
commit 208688afe1
6 changed files with 122 additions and 54 deletions
+2
View File
@@ -18,6 +18,8 @@
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSNumber * audioConfig;
@property (nonatomic, retain) NSNumber * onscreenControls;
@property (nonatomic, retain) NSNumber * keyboardToggleFingers;
@property (nonatomic, retain) NSNumber * keyboardToggleTaps;
@property (nonatomic, retain) NSString * uniqueId;
@property (nonatomic) enum {
CODEC_PREF_AUTO,
+3
View File
@@ -85,6 +85,9 @@
self.btMouseSupport = settings.btMouseSupport;
self.absoluteTouchMode = settings.absoluteTouchMode;
self.statsOverlay = settings.statsOverlay;
self.keyboardToggleTaps = @1;
self.keyboardToggleFingers = @4;
#endif
self.uniqueId = settings.uniqueId;
+27
View File
@@ -0,0 +1,27 @@
//
// NativeTouchHandler.h
// Moonlight
//
// Created by ZWM on 2024/5/14.
// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
//
#import "StreamView.h"
NS_ASSUME_NONNULL_BEGIN
@interface NativeTouchHandler : UIResponder
+ (NSMutableDictionary* )initializePointerIdDict;
+ (NSMutableSet* )initializePointerIdSet;
+ (void)populatePointerId:(UITouch*)event;
+ (void)removePointerId:(UITouch*)event;
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)event;
-(id)initWithView:(StreamView*)view;
@end
NS_ASSUME_NONNULL_END
+75
View File
@@ -0,0 +1,75 @@
//
// NativeTouchHandler.m
// Moonlight
//
// Created by ZWM on 2024/5/14.
// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NativeTouchHandler.h"
#include <Limelight.h>
// 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合集,用于快速查找,以防重复.
static NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch.
static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
@implementation NativeTouchHandler {
StreamView* view;
}
- (id)initWithView:(StreamView*)view {
self = [self init];
self->view = view;
return self;
}
+ (NSMutableDictionary* )initializePointerIdDict {
return pointerIdDict = [NSMutableDictionary dictionary];
}
+ (NSMutableSet* )initializePointerIdSet {
return pointerIdSet = [NSMutableSet set];
}
// 随机生成pointerId并填入NSDict和NSSet
// generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
+ (void)populatePointerId:(UITouch*)event{
uint64_t eventAddrValue = (uint64_t)event;
uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
while(true){
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*)event{
uint64_t eventAddrValue = (uint64_t)event;
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*)event{
return [[pointerIdDict objectForKey:@((uint64_t)event)] unsignedIntValue];
}
@end
+13 -52
View File
@@ -11,6 +11,7 @@
#import "DataManager.h"
#import "ControllerSupport.h"
#import "KeyboardSupport.h"
#import "NativeTouchHandler.h"
#import "RelativeTouchHandler.h"
#import "AbsoluteTouchHandler.h"
#import "KeyboardInputField.h"
@@ -23,15 +24,10 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
KeyboardInputField* keyInputField;
BOOL isInputingText;
NSMutableSet* keysDown;
UITapGestureRecognizer* _keyboardToggleTapRecognizer;
uint32_t keyboardToggleFingers;
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
NSInteger lastMouseButtonMask;
@@ -56,8 +52,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
- (void) setupStreamView:(ControllerSupport*)controllerSupport
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
config:(StreamConfiguration*)streamConfig {
pointerIdDict = [NSMutableDictionary dictionary];
pointerIdSet = [NSMutableSet set];
NSMutableDictionary *pointerIdDict = [NativeTouchHandler initializePointerIdDict];
NSMutableSet<NSNumber *> *pointerIdSet = [NativeTouchHandler initializePointerIdSet];
self->interactionDelegate = interactionDelegate;
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
@@ -71,12 +67,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
[keyInputField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[keyInputField setSpellCheckingType:UITextSpellCheckingTypeNo];
[self addSubview:keyInputField];
_keyboardToggleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleKeyboard)];
_keyboardToggleTapRecognizer.numberOfTouchesRequired = 2;
_keyboardToggleTapRecognizer.numberOfTapsRequired = 2;
_keyboardToggleTapRecognizer.delaysTouchesBegan = NO;
_keyboardToggleTapRecognizer.delaysTouchesEnded = NO;
[self addGestureRecognizer:_keyboardToggleTapRecognizer];
keyboardToggleFingers = settings.keyboardToggleFingers.intValue;
//[self addGestureRecognizer:_keyboardToggleTapRecognizer];
#if TARGET_OS_TV
// tvOS requires RelativeTouchHandler to manage Apple Remote input
@@ -291,42 +283,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
return 90 - MIN(90, altitudeDegs);
}
// 随机生成pointerId并填入NSDict和NSSet
// generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
- (void)populatePointerId:(UITouch*)event{
uint64_t eventAddrValue = (uint64_t)event;
uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
while(true){
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*)event{
uint64_t eventAddrValue = (uint64_t)event;
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*)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]]);
LiSendTouchEvent(touchType,[NativeTouchHandler 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]]);
}
@@ -356,7 +317,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
switch (event.phase) {
case UITouchPhaseBegan://开始触摸
type = LI_TOUCH_EVENT_DOWN;
[self populatePointerId:event]; //获取并记录pointerId
[NativeTouchHandler populatePointerId:event]; //获取并记录pointerId
break;
case UITouchPhaseMoved://移动
case UITouchPhaseStationary:
@@ -369,12 +330,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
case UITouchPhaseCancelled://触摸取消
type = LI_TOUCH_EVENT_CANCEL;
[self sendTouchEvent:event touchType:type]; //先发送,再删除
[self removePointerId:event]; //删除pointerId
[NativeTouchHandler removePointerId:event]; //删除pointerId
return;
case UITouchPhaseEnded://触摸结束
type = LI_TOUCH_EVENT_UP;
[self sendTouchEvent:event touchType:type]; //先发送,再删除
[self removePointerId:event]; //删除pointerId
[NativeTouchHandler removePointerId:event]; //删除pointerId
return;
default:
return;
@@ -519,7 +480,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
// is triggered.
[touchHandler touchesBegan:touches withEvent:event];
//if ([[event allTouches] count] == 3) [self toggleKeyboard];
if ([[event allTouches] count] == keyboardToggleFingers) [self toggleKeyboard];
}
}
@@ -24,14 +24,14 @@ static CGFloat EDGE_TOLERANCE_POINTS = 50.0f;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
// [super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
capturedUITouch = touch;
_startPointX = [capturedUITouch locationInView:self.view].x;
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
// [super touchesEnded:touches withEvent:event];
if([touches containsObject:capturedUITouch]){
CGFloat _endPointX = [capturedUITouch locationInView:self.view].x;