Refactor related codes to NativeTouchHandler
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user