diff --git a/VoidLink/Input/StreamView.h b/VoidLink/Input/StreamView.h index 78f77415..8a01770b 100644 --- a/VoidLink/Input/StreamView.h +++ b/VoidLink/Input/StreamView.h @@ -42,7 +42,6 @@ @property (assign, nonatomic) bool widgetToolOpened; @property (strong, nonatomic) OnScreenControls* onScreenControls; @property (weak, nonatomic) PencilHandler* pencilHandler; -@property (weak, nonatomic) UIViewController* streamFrameVC; - (void) setupStreamViewWithControllerSupport:(ControllerSupport*)controllerSupport interactionDelegate:(id)interactionDelegate diff --git a/VoidLink/Input/StreamView.m b/VoidLink/Input/StreamView.m index e9752a89..a6ef1027 100644 --- a/VoidLink/Input/StreamView.m +++ b/VoidLink/Input/StreamView.m @@ -29,9 +29,13 @@ #import "StreamFrameViewController.h" -static const double X1_MOUSE_SPEED_DIVISOR = 2.5; +@interface StreamView() +@property (weak, nonatomic) StreamFrameViewController* streamFrameVC; +@end +static const double X1_MOUSE_SPEED_DIVISOR = 2.5; + /* Stream Video has been moved out of this class to _renderView in StreamFrameViewController. */ @@ -663,15 +667,13 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; newProfile.buttonStatesEncoded[i] = newButtonStateEncoded; } } - - StreamFrameViewController* streamFrameVC = (StreamFrameViewController*)_streamFrameVC; - + newProfile.unfoldedExclusiveFolderSequence = OnScreenWidgetView.unfoldedExclusiveFolderSequence; newProfile.postExclusiveUnfoldedSequences = OnScreenWidgetView.postExclusiveUnfoldedSequences; - newProfile.gamepadOverlayEnabled = streamFrameVC.virtualGamepadOverlay != nil; + newProfile.gamepadOverlayEnabled = _streamFrameVC.virtualGamepadOverlay != nil; - newProfile.normalizedStreamViewOffset = CGPointMake(streamFrameVC.streamViewMagnifierContentOffset.x/self.bounds.size.width, streamFrameVC.streamViewMagnifierContentOffset.y/self.bounds.size.height); - newProfile.streamViewScale = streamFrameVC.streamViewMagnifierZoomScale; + newProfile.normalizedStreamViewOffset = CGPointMake(_streamFrameVC.streamViewMagnifierContentOffset.x/self.bounds.size.width, _streamFrameVC.streamViewMagnifierContentOffset.y/self.bounds.size.height); + newProfile.streamViewScale = _streamFrameVC.streamViewMagnifierZoomScale; [oscProfileMan replaceSelectedProfileWith:newProfile overwriteDefault:YES]; } @@ -689,7 +691,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; MotionHandler* motionHandler = [MotionHandler sharedWithProfile:profile]; // get streamFrameVC - if(!self->_streamFrameVC) self->_streamFrameVC = [GenericUtils parentViewControllerForView:self]; + if(!self.streamFrameVC) self.streamFrameVC = (StreamFrameViewController* )[GenericUtils parentViewControllerForView:self]; /* if (@available(iOS 13.0, *)) { @@ -843,7 +845,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; [PencilHandler.shared setupPressureLUTWithProfile:profile]; } - [(StreamFrameViewController* )self->_streamFrameVC restorePersistedStreamViewOffsetAndScaleWithProfile:profile]; + [self.streamFrameVC restorePersistedStreamViewOffsetAndScaleWithProfile:profile]; [self updateTouchHandlerWithProfile:profile]; }); } @@ -1280,7 +1282,36 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; } } +- (BOOL)isOptionVerticalArrowPress:(UIPress *)press { + if (@available(iOS 13.4, tvOS 13.4, *)) { + UIKey *key = press.key; + if (key == nil) { + return NO; + } + + return key.modifierFlags == UIKeyModifierAlternate && + (key.keyCode == UIKeyboardHIDUsageKeyboardUpArrow || + key.keyCode == UIKeyboardHIDUsageKeyboardDownArrow); + } + + return NO; +} + - (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event { + if (@available(iOS 17.0, *)) nil; + else { + BOOL shouldBypassMagnifierInset = NO; + for (UIPress *press in presses) { + if ([self isOptionVerticalArrowPress:press]) { + shouldBypassMagnifierInset = YES; + break; + } + } + if (shouldBypassMagnifierInset) { + _streamFrameVC.scrollView.contentInset = UIEdgeInsetsZero; + } + } + BOOL handled = NO; if (@available(iOS 13.4, tvOS 13.4, *)) { @@ -1301,6 +1332,21 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; } - (void)pressesEnded:(NSSet *)presses withEvent:(UIPressesEvent *)event { + if (@available(iOS 17.0, *)) nil; + else { + BOOL shouldRestoreMagnifierMetrics = NO; + for (UIPress *press in presses) { + if ([self isOptionVerticalArrowPress:press]) { + shouldRestoreMagnifierMetrics = YES; + break; + } + } + if (shouldRestoreMagnifierMetrics) { + [_streamFrameVC updateMagnifierViewportMetrics]; + [_streamFrameVC resetMagnifierStreamViewWithAnimated:NO]; + } + } + BOOL handled = NO; if (@available(iOS 13.4, tvOS 13.4, *)) { diff --git a/VoidLink/ViewControllers/StreamFrameViewController.h b/VoidLink/ViewControllers/StreamFrameViewController.h index 26156b6c..1fe01e8f 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.h +++ b/VoidLink/ViewControllers/StreamFrameViewController.h @@ -42,6 +42,7 @@ @property (nonatomic, strong) MetalViewController *metalViewController; @property (nonatomic, strong) ImGuiRenderer *imguiView; @property (nonatomic, strong) UIView* virtualGamepadOverlay; +@property (nonatomic, strong) UIScrollView* scrollView; @property (nonatomic, assign) CGPoint streamViewMagnifierContentOffset; @property (nonatomic, assign) CGFloat streamViewMagnifierZoomScale; @@ -55,5 +56,6 @@ - (void)toggleGamepadOverlayWithOverlayEnabled:(BOOL)overlayEnabled API_AVAILABLE(ios(13.0)); - (void)loadAbstractGamepadOverlayIfNeeded API_AVAILABLE(ios(13.0)); - (void)restorePersistedStreamViewOffsetAndScaleWithProfile:(OSCProfile* )profile; +- (void)updateMagnifierViewportMetrics; @end diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 34b7418b..1cae4284 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -61,7 +61,6 @@ UILabel *_tipLabel; UIActivityIndicatorView *_spinner; StreamView *_streamView; - UIScrollView *_scrollView; BOOL _magnifierViewportInteractionActive; BOOL _userIsInteracting; bool viewIsBeingResized; @@ -391,6 +390,9 @@ } BOOL interactionEnabled = _magnifierViewportInteractionActive; + if (@available(iOS 17.0, *)) { + _scrollView.allowsKeyboardScrolling = false; + } _scrollView.scrollEnabled = interactionEnabled; _scrollView.panGestureRecognizer.enabled = interactionEnabled; _scrollView.pinchGestureRecognizer.enabled = interactionEnabled; @@ -441,16 +443,29 @@ [self syncMagnifierStateFromScrollView]; } +- (void)handleScrollPan:(UIPanGestureRecognizer *)gesture { + switch (gesture.state){ + case UIGestureRecognizerStateEnded: + if(_settings.touchMode.intValue == AbsoluteTouch && _scrollView.zoomScale < 1.0) [self resetMagnifierStreamViewWithAnimated:true]; + break; + default: + break; + } +} + - (void)configZoomGestureAndAddStreamView{ BOOL shouldWrapInScrollView = [self shouldWrapStreamViewInScrollView]; if (shouldWrapInScrollView) { if(!_scrollView) _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; + _scrollView.scrollsToTop = false; _scrollView.frame = self.view.bounds; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; #if !TARGET_OS_TV [_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2]; [_scrollView.panGestureRecognizer setMaximumNumberOfTouches:2]; // reduce competing with keyboardToggleRecognizer in StreamView. + [_scrollView.panGestureRecognizer addTarget:self + action:@selector(handleScrollPan:)]; #endif [_scrollView setShowsHorizontalScrollIndicator:NO]; [_scrollView setShowsVerticalScrollIndicator:NO]; @@ -1004,7 +1019,7 @@ } - (void)setMagnifierViewportInteractionEnabled:(BOOL)enabled { - _magnifierViewportInteractionActive = enabled; + _magnifierViewportInteractionActive = enabled || _settings.touchMode.intValue == AbsoluteTouch; [self updateScrollViewInteractionState]; }