feat: functional button "AbsTchDrag"

This commit is contained in:
TrueZhuanjia committed 2025-11-05 11:51:29 +08:00
1 parent 1ad8f51b7a
commit a23a5491ae
7 files changed
+99 -27

No files matched your search

+2
View File
@@ -11,8 +11,10 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface AbsoluteTouchHandler : UIResponder @interface AbsoluteTouchHandler : UIResponder
@property (assign,nonatomic) int mouseButtonForCursorMove;
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings; - (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings;
- (void)pauseLeftButtonDrag;
@end @end
+54 -23
View File
@@ -34,6 +34,8 @@
UITouch* lastTouchUp; UITouch* lastTouchUp;
CGPoint lastTouchUpLocation; CGPoint lastTouchUpLocation;
UITouch* capturedTouch;
CGPoint touchBeganLocation; CGPoint touchBeganLocation;
CGPoint movingTouchLocation; CGPoint movingTouchLocation;
@@ -47,6 +49,7 @@
CGFloat _edgeTolerance; CGFloat _edgeTolerance;
bool _delayMouseLeftClick; bool _delayMouseLeftClick;
bool dragButtonDown;
bool rightButtonClicked; bool rightButtonClicked;
} }
@@ -55,8 +58,10 @@
self = [self init]; self = [self init];
self->streamView = view; self->streamView = view;
_delayMouseLeftClick = settings.delayLeftClick; // _delayMouseLeftClick = settings.delayLeftClick;
_delayMouseLeftClick = true; // deprecate legacy absolute touch
dragButtonDown = false;
leftClickTimeThreshold = 0.15; leftClickTimeThreshold = 0.15;
// upper screen check // upper screen check
@@ -65,13 +70,18 @@
screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - _edgeTolerance; screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - _edgeTolerance;
self->touchPointSpawnedAtUpperScreenEdge = false; self->touchPointSpawnedAtUpperScreenEdge = false;
_mouseButtonForCursorMove = BUTTON_LEFT;
return self; return self;
} }
- (void)onLongPressStart:(NSTimer*)timer { - (void)onLongPressStart:(NSTimer*)timer {
// Raise the left click and start a right click // Raise the left click and start a right click
if([self touchDidntMoveOnScreen:movingTouchLocation]){ if([self touchDidntMoveOnScreen:movingTouchLocation]){
if(_delayMouseLeftClick) LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); if(_delayMouseLeftClick){
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
if(_mouseButtonForCursorMove!=BUTTON_LEFT) LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, _mouseButtonForCursorMove);
}
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT); LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
dispatch_time_t delayShort = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)); dispatch_time_t delayShort = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC));
dispatch_after(delayShort, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_after(delayShort, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -93,24 +103,28 @@
touchPointSpawnedAtUpperScreenEdge = false; // reset this flag immediately if we get a touch event passing the check above, this fixes irresponsive touch after closing the command tool menu. touchPointSpawnedAtUpperScreenEdge = false; // reset this flag immediately if we get a touch event passing the check above, this fixes irresponsive touch after closing the command tool menu.
// Ignore touch down events with more than one finger // Ignore touch down events with more than one finger
/*
if ([[event allTouches] count] > 1) { if ([[event allTouches] count] > 1) {
return; return;
} }*/
UITouch* touch = [touches anyObject]; capturedTouch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:streamView]; CGPoint touchLocation = [capturedTouch locationInView:streamView];
touchBeganTimeStamp = touch.timestamp; touchBeganTimeStamp = capturedTouch.timestamp;
// Don't reposition for finger down events within the deadzone. This makes double-clicking easier. // Don't reposition for finger down events within the deadzone. This makes double-clicking easier.
if (touch.timestamp - lastTouchUp.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY || if (capturedTouch.timestamp - lastTouchUp.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY ||
sqrt(pow((touchLocation.x / streamView.bounds.size.width) - (lastTouchUpLocation.x / streamView.bounds.size.width), 2) + sqrt(pow((touchLocation.x / streamView.bounds.size.width) - (lastTouchUpLocation.x / streamView.bounds.size.width), 2) +
pow((touchLocation.y / streamView.bounds.size.height) - (lastTouchUpLocation.y / streamView.bounds.size.height), 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) { pow((touchLocation.y / streamView.bounds.size.height) - (lastTouchUpLocation.y / streamView.bounds.size.height), 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) {
[streamView updateCursorLocation:touchLocation isMouse:NO]; [streamView updateCursorLocation:touchLocation isMouse:NO];
} }
// Press the left button down // Press the left button down
if(!_delayMouseLeftClick) LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); if(!_delayMouseLeftClick){
// _delayMouseLeftClick will always be true.
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); //deprecated
}
// Start the long press timer // Start the long press timer
longPressTimer = [NSTimer scheduledTimerWithTimeInterval:LONG_PRESS_ACTIVATION_DELAY longPressTimer = [NSTimer scheduledTimerWithTimeInterval:LONG_PRESS_ACTIVATION_DELAY
@@ -119,23 +133,35 @@
userInfo:nil userInfo:nil
repeats:NO]; repeats:NO];
lastTouchDown = touch; lastTouchDown = capturedTouch;
lastTouchDownLocation = touchLocation; lastTouchDownLocation = touchLocation;
movingTouchLocation = touchLocation; movingTouchLocation = touchLocation;
touchBeganLocation = touchLocation; touchBeganLocation = touchLocation;
} }
- (void)pauseLeftButtonDrag{
if(dragButtonDown){
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC));
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, self->_mouseButtonForCursorMove);
});
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC. if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
// Ignore touch move events with more than one finger // Ignore touch move events with more than one finger
/*
if ([[event allTouches] count] > 1) { if ([[event allTouches] count] > 1) {
return; return;
} }*/
UITouch* touch = [touches anyObject]; if(![touches containsObject:capturedTouch]) return;
movingTouchLocation = [touch locationInView:streamView];
movingTouchLocation = [capturedTouch locationInView:streamView];
if (sqrt(pow((movingTouchLocation.x / streamView.bounds.size.width) - (lastTouchDownLocation.x / streamView.bounds.size.width), 2) + if (sqrt(pow((movingTouchLocation.x / streamView.bounds.size.width) - (lastTouchDownLocation.x / streamView.bounds.size.width), 2) +
pow((movingTouchLocation.y / streamView.bounds.size.height) - (lastTouchDownLocation.y / streamView.bounds.size.height), 2)) > LONG_PRESS_ACTIVATION_DELTA) { pow((movingTouchLocation.y / streamView.bounds.size.height) - (lastTouchDownLocation.y / streamView.bounds.size.height), 2)) > LONG_PRESS_ACTIVATION_DELTA) {
@@ -143,11 +169,13 @@
[longPressTimer invalidate]; [longPressTimer invalidate];
longPressTimer = nil; longPressTimer = nil;
if(_delayMouseLeftClick && (CACurrentMediaTime()-touchBeganTimeStamp>leftClickTimeThreshold)) LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT); if(_delayMouseLeftClick && (CACurrentMediaTime()-touchBeganTimeStamp>leftClickTimeThreshold) && !dragButtonDown){
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, _mouseButtonForCursorMove);
dragButtonDown = true;
}
} }
if(!rightButtonClicked) [streamView updateCursorLocation:[[touches anyObject] locationInView:streamView] isMouse:NO]; if(!rightButtonClicked) [streamView updateCursorLocation:movingTouchLocation isMouse:NO];
} }
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -155,36 +183,39 @@
if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC. if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
// Only fire this logic if all touches have ended // Only fire this logic if all touches have ended
if ([[event allTouches] count] == [touches count]) { if ([touches containsObject:capturedTouch]) {
// Cancel the long press timer // Cancel the long press timer
[longPressTimer invalidate]; [longPressTimer invalidate];
longPressTimer = nil; longPressTimer = nil;
// Remember this last touch for touch-down deadzoning // Remember this last touch for touch-down deadzoning
UITouch* touch = [touches anyObject]; CGPoint touchEndLocation = [capturedTouch locationInView:streamView];
CGPoint touchLocation = [touch locationInView:streamView];
if(_delayMouseLeftClick){ if(_delayMouseLeftClick){
if(CACurrentMediaTime()-touchBeganTimeStamp<leftClickTimeThreshold) { if(CACurrentMediaTime()-touchBeganTimeStamp<leftClickTimeThreshold) {
if(CACurrentMediaTime()-lastTouchUp.timestamp<0.15 if(CACurrentMediaTime()-lastTouchUp.timestamp<0.15
&& ![self isAdjacentPoints:touchLocation from:lastTouchUpLocation tolerance:30]) [streamView updateCursorLocation:touchLocation isMouse:NO]; && ![self isAdjacentPoints:touchEndLocation from:lastTouchUpLocation tolerance:30]) [streamView updateCursorLocation:touchEndLocation isMouse:NO];
if([self touchDidntMoveOnScreen:touchLocation] && !rightButtonClicked) [self sendShortMouseLeftButtonClickEvent]; if([self touchDidntMoveOnScreen:touchEndLocation] && !rightButtonClicked) [self sendShortMouseLeftButtonClickEvent];
} }
else if(!rightButtonClicked){ else if(!rightButtonClicked){
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
if(_mouseButtonForCursorMove!=BUTTON_LEFT) LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, _mouseButtonForCursorMove);
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
} }
} }
else{ else{ // deprecated
/*
// Left button up on finger up // Left button up on finger up
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
// Raise right button too in case we triggered a long press gesture // Raise right button too in case we triggered a long press gesture
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT); */
} }
lastTouchUp = [touches anyObject]; lastTouchUp = [touches anyObject];
lastTouchUpLocation = [lastTouchUp locationInView:streamView]; lastTouchUpLocation = [lastTouchUp locationInView:streamView];
dragButtonDown = false;
} }
} }
+1 -1
View File
@@ -122,7 +122,7 @@ import UIKit
@objc public static let nonVectorStickPads: [String] = ["LSPAD", "RSPAD"] @objc public static let nonVectorStickPads: [String] = ["LSPAD", "RSPAD"]
@objc public static let verticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"] @objc public static let verticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"]
@objc public static let bidirectionalVerticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"] @objc public static let bidirectionalVerticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"]
@objc public static let functionalButtonCmds: [String] = ["SETTINGS", "TOOLBOX", "WIDGETTOOL", "WIDGETPROFILES", "PROFILES", "SOFTKEYBOARD"] @objc public static let functionalButtonCmds: [String] = ["SETTINGS", "TOOLBOX", "WIDGETTOOL", "WIDGETPROFILES", "PROFILES", "SOFTKEYBOARD", "ABSTCHDRAG"]
@objc public static let motionControlButtonCmds: [String] = ["GYRO","GYROPAUSE","ACCEL","MOTION"] @objc public static let motionControlButtonCmds: [String] = ["GYRO","GYROPAUSE","ACCEL","MOTION"]
// @objc public static let specialGameWidgets: [String] = ["YSRSV", "YSLT", "YSRT", "YSRB", "YSB", "YSRT2", "YSRB2", "YSB2", "YSEM", "YSML", "YSMR", "YSWASD"] // @objc public static let specialGameWidgets: [String] = ["YSRSV", "YSLT", "YSRT", "YSRB", "YSB", "YSRT2", "YSRB2", "YSB2", "YSEM", "YSML", "YSMR", "YSWASD"]
+19 -1
View File
@@ -33,6 +33,7 @@ import UIKit
func openWidgetLayoutTool() func openWidgetLayoutTool()
func switchWidgetProfile() func switchWidgetProfile()
func bringUpSoftKeyboard() func bringUpSoftKeyboard()
func alterAbsTouchDragWith(mouseButton:Int32)
} }
@objc enum WidgetTypeEnum: UInt8 { @objc enum WidgetTypeEnum: UInt8 {
@@ -1142,6 +1143,9 @@ import UIKit
} }
private func handleButtonDown() { private func handleButtonDown() {
if !OnScreenWidgetView.editMode, !self.functionalButtonString.isEmpty {self.handleFunctionalButtonDown()}
if !OnScreenWidgetView.editMode {self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} if !OnScreenWidgetView.editMode {self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)}
if !OnScreenWidgetView.editMode, !self.motionControlButtonString.isEmpty {self.handleMotionControlButtonDown()} if !OnScreenWidgetView.editMode, !self.motionControlButtonString.isEmpty {self.handleMotionControlButtonDown()}
@@ -1351,7 +1355,7 @@ import UIKit
if CommandManager.keyboardButtonMappings.keys.contains(comboString) { if CommandManager.keyboardButtonMappings.keys.contains(comboString) {
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_DOWN), 0) LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_DOWN), 0)
} }
if CommandManager.mouseButtonMappings.keys.contains(comboString) { if CommandManager.mouseButtonMappings.keys.contains(comboString), self.functionalButtonString != "ABSTCHDRAG" {
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), Int32(CommandManager.mouseButtonMappings[comboString]!)) LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), Int32(CommandManager.mouseButtonMappings[comboString]!))
} }
if comboString != comboStrings.last { if comboString != comboStrings.last {
@@ -1865,6 +1869,17 @@ import UIKit
} }
} }
private func handleFunctionalButtonDown(){
switch self.functionalButtonString {
case "ABSTCHDRAG":
let mouseButton = CommandManager.mouseButtonMappings[Set(self.comboButtonStrings).intersection(CommandManager.mouseButtonMappings.keys).first ?? "MLEFT"] ?? BUTTON_LEFT
print("mouseButton \(mouseButton)");
self.functionalButtonDelegate?.alterAbsTouchDragWith(mouseButton:mouseButton)
default:
break
}
}
private func handleFunctionalButtonUp(){ private func handleFunctionalButtonUp(){
let longPressed = CACurrentMediaTime() - self.touchTapTimeStamp > 0.3 let longPressed = CACurrentMediaTime() - self.touchTapTimeStamp > 0.3
if longPressed, buttonMode == ButtonMode.movable.rawValue {return} if longPressed, buttonMode == ButtonMode.movable.rawValue {return}
@@ -1879,6 +1894,9 @@ import UIKit
self.functionalButtonDelegate?.switchWidgetProfile() self.functionalButtonDelegate?.switchWidgetProfile()
case "SOFTKEYBOARD": case "SOFTKEYBOARD":
self.functionalButtonDelegate?.bringUpSoftKeyboard() self.functionalButtonDelegate?.bringUpSoftKeyboard()
case "ABSTCHDRAG":
// self.functionalButtonDelegate?.alterAbsTouchDragWith(mouseButton:CommandManager.mouseButtonMappings[self.comboButtonStrings.first ?? "MLEFT"] ?? BUTTON_LEFT)
self.functionalButtonDelegate?.alterAbsTouchDragWith(mouseButton:BUTTON_LEFT)
default: default:
break break
} }
+4 -1
View File
@@ -44,6 +44,7 @@
config:(StreamConfiguration*)streamConfig config:(StreamConfiguration*)streamConfig
streamFrameTopLayerView:(UIView* )topLayerView streamFrameTopLayerView:(UIView* )topLayerView
; ;
- (void) showOnScreenControls; - (void) showOnScreenControls;
- (void) setOnScreenControls; - (void) setOnScreenControls;
- (void) disableOnScreenControls; - (void) disableOnScreenControls;
@@ -61,11 +62,13 @@
- (OnScreenControlsLevel) getCurrentOscState; - (OnScreenControlsLevel) getCurrentOscState;
-(void)readyToBringUpSoftKeyboardByToolbox; - (void)readyToBringUpSoftKeyboardByToolbox;
- (void)keyboardWillShow:(NSNotification *)notification; - (void)keyboardWillShow:(NSNotification *)notification;
- (void)keyboardWillHide; - (void)keyboardWillHide;
- (void)liftMetalVideoViewIfNeeded:(CGFloat)liftHeight; - (void)liftMetalVideoViewIfNeeded:(CGFloat)liftHeight;
- (void)alterAbsTouchDragWith:(int32_t)mouseButton;
#if !TARGET_OS_TV #if !TARGET_OS_TV
- (void) updateCursorLocation:(CGPoint)location isMouse:(BOOL)isMouse; - (void) updateCursorLocation:(CGPoint)location isMouse:(BOOL)isMouse;
#endif #endif
+9
View File
@@ -1381,6 +1381,15 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
LiSendScrollEvent(deltaZ); LiSendScrollEvent(deltaZ);
} }
- (void)alterAbsTouchDragWith:(int32_t)mouseButton{
if([touchHandler isKindOfClass:[AbsoluteTouchHandler class]]){
AbsoluteTouchHandler* handler = (AbsoluteTouchHandler* )touchHandler;
handler.mouseButtonForCursorMove = mouseButton;
[handler pauseLeftButtonDrag];
}
else return;
}
#if !TARGET_OS_TV #if !TARGET_OS_TV
- (BOOL)isMultipleTouchEnabled { - (BOOL)isMultipleTouchEnabled {
@@ -19,7 +19,6 @@
#import "DataManager.h" #import "DataManager.h"
#import "PaddedLabel.h" #import "PaddedLabel.h"
#import "ImGuiRenderer.h" #import "ImGuiRenderer.h"
#import "RelativeTouchHandler.h"
#import "MetalVideoRenderer.h" #import "MetalVideoRenderer.h"
#import "CustomEdgeSlideGestureRecognizer.h" #import "CustomEdgeSlideGestureRecognizer.h"
#import "CustomTapGestureRecognizer.h" #import "CustomTapGestureRecognizer.h"
@@ -310,6 +309,11 @@
} }
- (void)handleAbsTouchPanGesture:(UIPanGestureRecognizer* )gesture{
NSLog(@"handleAbsTouchPanGesture %f", CACurrentMediaTime());
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
}
- (void)configZoomGestureAndAddStreamView{ - (void)configZoomGestureAndAddStreamView{
if (_settings.touchMode.intValue == AbsoluteTouch) { if (_settings.touchMode.intValue == AbsoluteTouch) {
if(!_scrollView) _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; if(!_scrollView) _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
@@ -317,6 +321,7 @@
[_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2]; [_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2];
[_scrollView.panGestureRecognizer setMaximumNumberOfTouches:2]; // reduce competing with keyboardToggleRecognizer in StreamView. [_scrollView.panGestureRecognizer setMaximumNumberOfTouches:2]; // reduce competing with keyboardToggleRecognizer in StreamView.
#endif #endif
[_scrollView.panGestureRecognizer addTarget:self action:@selector(handleAbsTouchPanGesture:)];
[_scrollView setShowsHorizontalScrollIndicator:NO]; [_scrollView setShowsHorizontalScrollIndicator:NO];
[_scrollView setShowsVerticalScrollIndicator:NO]; [_scrollView setShowsVerticalScrollIndicator:NO];
[_scrollView setDelegate:self]; [_scrollView setDelegate:self];
@@ -775,6 +780,10 @@
[self.pipController startPictureInPicture]; [self.pipController startPictureInPicture];
} }
- (void)alterAbsTouchDragWithMouseButton:(int32_t)mouseButton{
[_streamView alterAbsTouchDragWith:mouseButton];
}
- (void)oscLayoutClosed{ - (void)oscLayoutClosed{
// Handle the callback // Handle the callback
_streamView.widgetToolOpened = false; _streamView.widgetToolOpened = false;