diff --git a/VoidLink/Input/AbsoluteTouchHandler.h b/VoidLink/Input/AbsoluteTouchHandler.h index 2913d561..003fdd25 100644 --- a/VoidLink/Input/AbsoluteTouchHandler.h +++ b/VoidLink/Input/AbsoluteTouchHandler.h @@ -11,8 +11,10 @@ NS_ASSUME_NONNULL_BEGIN @interface AbsoluteTouchHandler : UIResponder +@property (assign,nonatomic) int mouseButtonForCursorMove; - (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings; +- (void)pauseLeftButtonDrag; @end diff --git a/VoidLink/Input/AbsoluteTouchHandler.m b/VoidLink/Input/AbsoluteTouchHandler.m index f2e90cd2..75f1014d 100644 --- a/VoidLink/Input/AbsoluteTouchHandler.m +++ b/VoidLink/Input/AbsoluteTouchHandler.m @@ -34,6 +34,8 @@ UITouch* lastTouchUp; CGPoint lastTouchUpLocation; + UITouch* capturedTouch; + CGPoint touchBeganLocation; CGPoint movingTouchLocation; @@ -47,6 +49,7 @@ CGFloat _edgeTolerance; bool _delayMouseLeftClick; + bool dragButtonDown; bool rightButtonClicked; } @@ -55,8 +58,10 @@ self = [self init]; self->streamView = view; - _delayMouseLeftClick = settings.delayLeftClick; - + // _delayMouseLeftClick = settings.delayLeftClick; + _delayMouseLeftClick = true; // deprecate legacy absolute touch + dragButtonDown = false; + leftClickTimeThreshold = 0.15; // upper screen check @@ -65,13 +70,18 @@ screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - _edgeTolerance; self->touchPointSpawnedAtUpperScreenEdge = false; + _mouseButtonForCursorMove = BUTTON_LEFT; + return self; } - (void)onLongPressStart:(NSTimer*)timer { // Raise the left click and start a right click 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); 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), ^{ @@ -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. // Ignore touch down events with more than one finger + /* if ([[event allTouches] count] > 1) { return; - } + }*/ - UITouch* touch = [touches anyObject]; - CGPoint touchLocation = [touch locationInView:streamView]; + capturedTouch = [touches anyObject]; + 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. - 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) + pow((touchLocation.y / streamView.bounds.size.height) - (lastTouchUpLocation.y / streamView.bounds.size.height), 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) { [streamView updateCursorLocation:touchLocation isMouse:NO]; } // 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 longPressTimer = [NSTimer scheduledTimerWithTimeInterval:LONG_PRESS_ACTIVATION_DELAY @@ -119,23 +133,35 @@ userInfo:nil repeats:NO]; - lastTouchDown = touch; + lastTouchDown = capturedTouch; lastTouchDownLocation = touchLocation; movingTouchLocation = 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 { 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 + /* if ([[event allTouches] count] > 1) { return; - } + }*/ - UITouch* touch = [touches anyObject]; - movingTouchLocation = [touch locationInView:streamView]; + if(![touches containsObject:capturedTouch]) return; + + movingTouchLocation = [capturedTouch locationInView:streamView]; 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) { @@ -143,11 +169,13 @@ [longPressTimer invalidate]; 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 { @@ -155,36 +183,39 @@ 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 - if ([[event allTouches] count] == [touches count]) { + if ([touches containsObject:capturedTouch]) { // Cancel the long press timer [longPressTimer invalidate]; longPressTimer = nil; // Remember this last touch for touch-down deadzoning - UITouch* touch = [touches anyObject]; - CGPoint touchLocation = [touch locationInView:streamView]; + CGPoint touchEndLocation = [capturedTouch locationInView:streamView]; if(_delayMouseLeftClick){ if(CACurrentMediaTime()-touchBeganTimeStamp 0.3 if longPressed, buttonMode == ButtonMode.movable.rawValue {return} @@ -1879,6 +1894,9 @@ import UIKit self.functionalButtonDelegate?.switchWidgetProfile() case "SOFTKEYBOARD": self.functionalButtonDelegate?.bringUpSoftKeyboard() + case "ABSTCHDRAG": + // self.functionalButtonDelegate?.alterAbsTouchDragWith(mouseButton:CommandManager.mouseButtonMappings[self.comboButtonStrings.first ?? "MLEFT"] ?? BUTTON_LEFT) + self.functionalButtonDelegate?.alterAbsTouchDragWith(mouseButton:BUTTON_LEFT) default: break } diff --git a/VoidLink/Input/StreamView.h b/VoidLink/Input/StreamView.h index 5b5a30a2..5162d91c 100644 --- a/VoidLink/Input/StreamView.h +++ b/VoidLink/Input/StreamView.h @@ -44,6 +44,7 @@ config:(StreamConfiguration*)streamConfig streamFrameTopLayerView:(UIView* )topLayerView ; + - (void) showOnScreenControls; - (void) setOnScreenControls; - (void) disableOnScreenControls; @@ -61,11 +62,13 @@ - (OnScreenControlsLevel) getCurrentOscState; --(void)readyToBringUpSoftKeyboardByToolbox; +- (void)readyToBringUpSoftKeyboardByToolbox; - (void)keyboardWillShow:(NSNotification *)notification; - (void)keyboardWillHide; - (void)liftMetalVideoViewIfNeeded:(CGFloat)liftHeight; +- (void)alterAbsTouchDragWith:(int32_t)mouseButton; + #if !TARGET_OS_TV - (void) updateCursorLocation:(CGPoint)location isMouse:(BOOL)isMouse; #endif diff --git a/VoidLink/Input/StreamView.m b/VoidLink/Input/StreamView.m index ab0980c6..818f5825 100644 --- a/VoidLink/Input/StreamView.m +++ b/VoidLink/Input/StreamView.m @@ -1381,6 +1381,15 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; 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 - (BOOL)isMultipleTouchEnabled { diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index bd58f244..3bd87401 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -19,7 +19,6 @@ #import "DataManager.h" #import "PaddedLabel.h" #import "ImGuiRenderer.h" -#import "RelativeTouchHandler.h" #import "MetalVideoRenderer.h" #import "CustomEdgeSlideGestureRecognizer.h" #import "CustomTapGestureRecognizer.h" @@ -310,6 +309,11 @@ } +- (void)handleAbsTouchPanGesture:(UIPanGestureRecognizer* )gesture{ + NSLog(@"handleAbsTouchPanGesture %f", CACurrentMediaTime()); + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT); +} + - (void)configZoomGestureAndAddStreamView{ if (_settings.touchMode.intValue == AbsoluteTouch) { if(!_scrollView) _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; @@ -317,6 +321,7 @@ [_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2]; [_scrollView.panGestureRecognizer setMaximumNumberOfTouches:2]; // reduce competing with keyboardToggleRecognizer in StreamView. #endif + [_scrollView.panGestureRecognizer addTarget:self action:@selector(handleAbsTouchPanGesture:)]; [_scrollView setShowsHorizontalScrollIndicator:NO]; [_scrollView setShowsVerticalScrollIndicator:NO]; [_scrollView setDelegate:self]; @@ -775,6 +780,10 @@ [self.pipController startPictureInPicture]; } +- (void)alterAbsTouchDragWithMouseButton:(int32_t)mouseButton{ + [_streamView alterAbsTouchDragWith:mouseButton]; +} + - (void)oscLayoutClosed{ // Handle the callback _streamView.widgetToolOpened = false;