Refactor related codes to NativeTouchHandler
This commit is contained in:
1 parent
82de44df54
commit
208688afe1
6 files changed
+121
-53
No files matched your search
@@ -18,6 +18,8 @@
|
|||||||
@property (nonatomic, retain) NSNumber * width;
|
@property (nonatomic, retain) NSNumber * width;
|
||||||
@property (nonatomic, retain) NSNumber * audioConfig;
|
@property (nonatomic, retain) NSNumber * audioConfig;
|
||||||
@property (nonatomic, retain) NSNumber * onscreenControls;
|
@property (nonatomic, retain) NSNumber * onscreenControls;
|
||||||
|
@property (nonatomic, retain) NSNumber * keyboardToggleFingers;
|
||||||
|
@property (nonatomic, retain) NSNumber * keyboardToggleTaps;
|
||||||
@property (nonatomic, retain) NSString * uniqueId;
|
@property (nonatomic, retain) NSString * uniqueId;
|
||||||
@property (nonatomic) enum {
|
@property (nonatomic) enum {
|
||||||
CODEC_PREF_AUTO,
|
CODEC_PREF_AUTO,
|
||||||
|
|||||||
@@ -85,6 +85,9 @@
|
|||||||
self.btMouseSupport = settings.btMouseSupport;
|
self.btMouseSupport = settings.btMouseSupport;
|
||||||
self.absoluteTouchMode = settings.absoluteTouchMode;
|
self.absoluteTouchMode = settings.absoluteTouchMode;
|
||||||
self.statsOverlay = settings.statsOverlay;
|
self.statsOverlay = settings.statsOverlay;
|
||||||
|
|
||||||
|
self.keyboardToggleTaps = @1;
|
||||||
|
self.keyboardToggleFingers = @4;
|
||||||
#endif
|
#endif
|
||||||
self.uniqueId = settings.uniqueId;
|
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 "DataManager.h"
|
||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "KeyboardSupport.h"
|
#import "KeyboardSupport.h"
|
||||||
|
#import "NativeTouchHandler.h"
|
||||||
#import "RelativeTouchHandler.h"
|
#import "RelativeTouchHandler.h"
|
||||||
#import "AbsoluteTouchHandler.h"
|
#import "AbsoluteTouchHandler.h"
|
||||||
#import "KeyboardInputField.h"
|
#import "KeyboardInputField.h"
|
||||||
@@ -23,15 +24,10 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
KeyboardInputField* keyInputField;
|
KeyboardInputField* keyInputField;
|
||||||
BOOL isInputingText;
|
BOOL isInputingText;
|
||||||
NSMutableSet* keysDown;
|
NSMutableSet* keysDown;
|
||||||
UITapGestureRecognizer* _keyboardToggleTapRecognizer;
|
uint32_t keyboardToggleFingers;
|
||||||
|
|
||||||
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;
|
||||||
@@ -56,8 +52,8 @@ 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];
|
NSMutableDictionary *pointerIdDict = [NativeTouchHandler initializePointerIdDict];
|
||||||
pointerIdSet = [NSMutableSet set];
|
NSMutableSet<NSNumber *> *pointerIdSet = [NativeTouchHandler initializePointerIdSet];
|
||||||
|
|
||||||
self->interactionDelegate = interactionDelegate;
|
self->interactionDelegate = interactionDelegate;
|
||||||
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
|
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 setAutocapitalizationType:UITextAutocapitalizationTypeNone];
|
||||||
[keyInputField setSpellCheckingType:UITextSpellCheckingTypeNo];
|
[keyInputField setSpellCheckingType:UITextSpellCheckingTypeNo];
|
||||||
[self addSubview:keyInputField];
|
[self addSubview:keyInputField];
|
||||||
_keyboardToggleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleKeyboard)];
|
keyboardToggleFingers = settings.keyboardToggleFingers.intValue;
|
||||||
_keyboardToggleTapRecognizer.numberOfTouchesRequired = 2;
|
//[self addGestureRecognizer:_keyboardToggleTapRecognizer];
|
||||||
_keyboardToggleTapRecognizer.numberOfTapsRequired = 2;
|
|
||||||
_keyboardToggleTapRecognizer.delaysTouchesBegan = NO;
|
|
||||||
_keyboardToggleTapRecognizer.delaysTouchesEnded = NO;
|
|
||||||
[self addGestureRecognizer:_keyboardToggleTapRecognizer];
|
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
#if TARGET_OS_TV
|
||||||
// tvOS requires RelativeTouchHandler to manage Apple Remote input
|
// 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);
|
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{
|
- (void)sendTouchEvent:(UITouch*)event touchType:(uint8_t)touchType{
|
||||||
CGPoint location = [self adjustCoordinatesForVideoArea:[event locationInView:self]];
|
CGPoint location = [self adjustCoordinatesForVideoArea:[event locationInView:self]];
|
||||||
CGSize videoSize = [self getVideoAreaSize];
|
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) {
|
switch (event.phase) {
|
||||||
case UITouchPhaseBegan://开始触摸
|
case UITouchPhaseBegan://开始触摸
|
||||||
type = LI_TOUCH_EVENT_DOWN;
|
type = LI_TOUCH_EVENT_DOWN;
|
||||||
[self populatePointerId:event]; //获取并记录pointerId
|
[NativeTouchHandler populatePointerId:event]; //获取并记录pointerId
|
||||||
break;
|
break;
|
||||||
case UITouchPhaseMoved://移动
|
case UITouchPhaseMoved://移动
|
||||||
case UITouchPhaseStationary:
|
case UITouchPhaseStationary:
|
||||||
@@ -369,12 +330,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
case UITouchPhaseCancelled://触摸取消
|
case UITouchPhaseCancelled://触摸取消
|
||||||
type = LI_TOUCH_EVENT_CANCEL;
|
type = LI_TOUCH_EVENT_CANCEL;
|
||||||
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
||||||
[self removePointerId:event]; //删除pointerId
|
[NativeTouchHandler removePointerId:event]; //删除pointerId
|
||||||
return;
|
return;
|
||||||
case UITouchPhaseEnded://触摸结束
|
case UITouchPhaseEnded://触摸结束
|
||||||
type = LI_TOUCH_EVENT_UP;
|
type = LI_TOUCH_EVENT_UP;
|
||||||
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
||||||
[self removePointerId:event]; //删除pointerId
|
[NativeTouchHandler removePointerId:event]; //删除pointerId
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@@ -519,7 +480,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
// is triggered.
|
// is triggered.
|
||||||
[touchHandler touchesBegan:touches withEvent:event];
|
[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 {
|
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||||
[super touchesBegan:touches withEvent:event];
|
// [super touchesBegan:touches withEvent:event];
|
||||||
UITouch *touch = [touches anyObject];
|
UITouch *touch = [touches anyObject];
|
||||||
capturedUITouch = touch;
|
capturedUITouch = touch;
|
||||||
_startPointX = [capturedUITouch locationInView:self.view].x;
|
_startPointX = [capturedUITouch locationInView:self.view].x;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||||
[super touchesEnded:touches withEvent:event];
|
// [super touchesEnded:touches withEvent:event];
|
||||||
|
|
||||||
if([touches containsObject:capturedUITouch]){
|
if([touches containsObject:capturedUITouch]){
|
||||||
CGFloat _endPointX = [capturedUITouch locationInView:self.view].x;
|
CGFloat _endPointX = [capturedUITouch locationInView:self.view].x;
|
||||||
|
|||||||
Reference in new issue
Block a user