diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index a1d30e7..9c7df6c 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -28,6 +28,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; NSInteger lastMouseButtonMask; float lastMouseX; float lastMouseY; + CGPoint lastScrollTranslation; // Citrix X1 mouse support X1Mouse* x1mouse; @@ -91,11 +92,17 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; if (@available(iOS 13.4, *)) { [self addInteraction:[[UIPointerInteraction alloc] initWithDelegate:self]]; - UIPanGestureRecognizer *mouseWheelRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mouseWheelMoved:)]; - mouseWheelRecognizer.maximumNumberOfTouches = 0; - mouseWheelRecognizer.allowedScrollTypesMask = UIScrollTypeMaskAll; - mouseWheelRecognizer.allowedTouchTypes = @[@(UITouchTypeIndirectPointer)]; - [self addGestureRecognizer:mouseWheelRecognizer]; + UIPanGestureRecognizer *discreteMouseWheelRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mouseWheelMovedDiscrete:)]; + discreteMouseWheelRecognizer.maximumNumberOfTouches = 0; + discreteMouseWheelRecognizer.allowedScrollTypesMask = UIScrollTypeMaskDiscrete; + discreteMouseWheelRecognizer.allowedTouchTypes = @[@(UITouchTypeIndirectPointer)]; + [self addGestureRecognizer:discreteMouseWheelRecognizer]; + + UIPanGestureRecognizer *continuousMouseWheelRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mouseWheelMovedContinuous:)]; + continuousMouseWheelRecognizer.maximumNumberOfTouches = 0; + continuousMouseWheelRecognizer.allowedScrollTypesMask = UIScrollTypeMaskContinuous; + continuousMouseWheelRecognizer.allowedTouchTypes = @[@(UITouchTypeIndirectPointer)]; + [self addGestureRecognizer:continuousMouseWheelRecognizer]; } #endif @@ -448,24 +455,48 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; return [UIPointerStyle hiddenPointerStyle]; } -- (void)mouseWheelMoved:(UIPanGestureRecognizer *)gesture { +- (void)mouseWheelMovedContinuous:(UIPanGestureRecognizer *)gesture { switch (gesture.state) { case UIGestureRecognizerStateBegan: case UIGestureRecognizerStateChanged: case UIGestureRecognizerStateEnded: break; - + default: // Ignore recognition failure and other states return; } - - CGPoint velocity = [gesture velocityInView:self]; - if ((short)velocity.y != 0) { - LiSendHighResScrollEvent((short)velocity.y); + + short velocityY = [gesture velocityInView:self].y; + if (velocityY != 0) { + LiSendHighResScrollEvent(velocityY); } } +- (void)mouseWheelMovedDiscrete:(UIPanGestureRecognizer *)gesture { + switch (gesture.state) { + case UIGestureRecognizerStateBegan: + case UIGestureRecognizerStateChanged: + break; + + case UIGestureRecognizerStateEnded: + default: + // Ignore recognition failure and other states + lastScrollTranslation = CGPointMake(0, 0); + return; + } + + // Using velocityInView is 0 for discrete scroll events + // when scrolling very slowly, but translationInView does work. + CGPoint currentScrollTranslation = [gesture translationInView:self]; + short translationDeltaY = currentScrollTranslation.y - lastScrollTranslation.y; + if (translationDeltaY != 0) { + LiSendScrollEvent(translationDeltaY > 0 ? 1 : -1); + } + + lastScrollTranslation = currentScrollTranslation; +} + #endif - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {