diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard index f9d08de7..dc9db43a 100644 --- a/VoidLink/Base.lproj/iPad.storyboard +++ b/VoidLink/Base.lproj/iPad.storyboard @@ -1380,16 +1380,16 @@ - + - + @@ -1554,6 +1554,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1635,6 +1695,10 @@ + + + + @@ -1657,6 +1721,8 @@ + + @@ -2509,7 +2575,7 @@ - + @@ -2518,13 +2584,13 @@ - + - + - + diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard index 79d9850a..85980073 100644 --- a/VoidLink/Base.lproj/iPhone.storyboard +++ b/VoidLink/Base.lproj/iPhone.storyboard @@ -2192,6 +2192,26 @@ + + + + + + + + + + + + + + @@ -2264,16 +2284,16 @@ - + - + @@ -2367,24 +2387,64 @@ - - + + - + + + + + + + + - + - - + + + + + + + + + + + + + + + + @@ -2468,6 +2528,10 @@ + + + + @@ -2490,6 +2554,8 @@ + + @@ -2549,19 +2615,19 @@ - + - + - + - + diff --git a/VoidLink/Database/DataManager.h b/VoidLink/Database/DataManager.h index 8fd92a8e..ea182d49 100644 --- a/VoidLink/Database/DataManager.h +++ b/VoidLink/Database/DataManager.h @@ -130,6 +130,9 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) { duckOtherApps:(BOOL)duckOtherApps muteInBackground:(BOOL)muteInBackground relativeTouchSlideThreshold:(CGFloat)relativeTouchSlideThreshold + enablePinch:(BOOL)enablePinch + scrollSensitivity:(CGFloat)scrollSensitivity + pinchSensitivity:(CGFloat)pinchSensitivity backgroundSessionTimer:(NSInteger)backgroundSessionTimer; - (NSArray*) getHosts; diff --git a/VoidLink/Database/DataManager.m b/VoidLink/Database/DataManager.m index 54c858cf..a0e2d436 100644 --- a/VoidLink/Database/DataManager.m +++ b/VoidLink/Database/DataManager.m @@ -113,6 +113,9 @@ duckOtherApps:(BOOL)duckOtherApps muteInBackground:(BOOL)muteInBackground relativeTouchSlideThreshold:(CGFloat)relativeTouchSlideThreshold + enablePinch:(BOOL)enablePinch + scrollSensitivity:(CGFloat)scrollSensitivity + pinchSensitivity:(CGFloat)pinchSensitivity backgroundSessionTimer:(NSInteger)backgroundSessionTimer{ [_managedObjectContext performBlockAndWait:^{ @@ -175,7 +178,10 @@ settingsToSave.delayLeftClick = delayLeftClick; settingsToSave.duckOtherApps = duckOtherApps; settingsToSave.muteInBackground = muteInBackground; - settingsToSave.relativeTouchSlideThreshold = [NSNumber numberWithFloat:relativeTouchSlideThreshold];; + settingsToSave.relativeTouchSlideThreshold = [NSNumber numberWithFloat:relativeTouchSlideThreshold]; + settingsToSave.enablePinch = enablePinch; + settingsToSave.scrollSensitivity = [NSNumber numberWithFloat:scrollSensitivity]; + settingsToSave.pinchSensitivity = [NSNumber numberWithFloat:pinchSensitivity]; settingsToSave.rememberFoldState = rememberFoldState; [self saveData]; }]; diff --git a/VoidLink/Database/TemporarySettings.h b/VoidLink/Database/TemporarySettings.h index bd5a800b..44ee605d 100644 --- a/VoidLink/Database/TemporarySettings.h +++ b/VoidLink/Database/TemporarySettings.h @@ -86,7 +86,10 @@ @property (nonatomic) BOOL delayLeftClick; @property (nonatomic) BOOL duckOtherApps; @property (nonatomic) BOOL muteInBackground; +@property (nonatomic) BOOL enablePinch; @property (nonatomic, retain) NSNumber * framePacingMode; +@property (nonatomic, retain) NSNumber * scrollSensitivity; +@property (nonatomic, retain) NSNumber * pinchSensitivity; @property (nonatomic, retain) NSNumber * relativeTouchSlideThreshold; - (id) initFromSettings:(Settings*)settings; diff --git a/VoidLink/Database/TemporarySettings.m b/VoidLink/Database/TemporarySettings.m index 1a0abb55..151792a1 100644 --- a/VoidLink/Database/TemporarySettings.m +++ b/VoidLink/Database/TemporarySettings.m @@ -144,6 +144,9 @@ self.duckOtherApps = settings.duckOtherApps; self.muteInBackground = settings.muteInBackground; self.relativeTouchSlideThreshold = settings.relativeTouchSlideThreshold; + self.enablePinch = settings.enablePinch; + self.scrollSensitivity = settings.scrollSensitivity; + self.pinchSensitivity = settings.pinchSensitivity; #endif return self; diff --git a/VoidLink/Input/TouchPadGestureHandler.swift b/VoidLink/Input/TouchPadGestureHandler.swift index c650aa56..eafa5d38 100644 --- a/VoidLink/Input/TouchPadGestureHandler.swift +++ b/VoidLink/Input/TouchPadGestureHandler.swift @@ -11,6 +11,10 @@ import UIKit @objc class TouchPadGestureHandler: NSObject { @objc public static var ctrlDown:Bool = false + @objc public static var enablePinch:Bool = true + @objc public static var enableHorizontalScroll:Bool = true + @objc public static var scrollSensitivity:CGFloat = 1.0 + @objc public static var pinchSensitivity:CGFloat = 1.0 @objc public static func handleGesture(in view: UIView, with event: UIEvent) { let currentTouches = UITouchUtil.touches(in: view, from: event) guard currentTouches.count == 2 else { return } @@ -28,9 +32,11 @@ import UIKit let midPointDeltaY = UITouchUtil.midPointDeltaY(between: touch1, and: touch2, in: view) let midPointDeltaX = UITouchUtil.midPointDeltaX(between: touch1, and: touch2, in: view) - LiSendHighResScrollEvent(Int16((currentDistance - previousDistance) * 5 + midPointDeltaY * 5)) - LiSendHighResHScrollEvent(Int16(-midPointDeltaX) * 5) + let pinchDelta = enablePinch ? (currentDistance-previousDistance)*5*pinchSensitivity : 0; + LiSendHighResScrollEvent(Int16(pinchDelta + midPointDeltaY*5*scrollSensitivity)) + if enableHorizontalScroll {LiSendHighResHScrollEvent(Int16(-midPointDeltaX*5*scrollSensitivity))} + if !enablePinch {return}; if abs(currentDistance - previousDistance) > abs(midPointDeltaY) { LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["CTRL"]!, CChar(KEY_ACTION_DOWN), 0) ctrlDown = true diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents index 684ac915..74d5d497 100644 --- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents +++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents @@ -36,6 +36,7 @@ + @@ -61,6 +62,7 @@ + @@ -70,6 +72,7 @@ + diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h index b2636b77..707a65d7 100644 --- a/VoidLink/ViewControllers/SettingsViewController.h +++ b/VoidLink/ViewControllers/SettingsViewController.h @@ -193,6 +193,15 @@ @property (strong, nonatomic) IBOutlet UIStackView *relativeTouchSlideThresholdStack; @property (strong, nonatomic) IBOutlet UISlider *relativeTouchSlideThresholdSlider; +@property (strong, nonatomic) IBOutlet UIStackView *pinchGestureStack; +@property (strong, nonatomic) IBOutlet UISwitch *pinchGestureSwitch; + +@property (strong, nonatomic) IBOutlet UIStackView *scrollSensitivityStack; +@property (strong, nonatomic) IBOutlet UISlider *scrollSensitivitySlider; + +@property (strong, nonatomic) IBOutlet UIStackView *pinchSensitivityStack; +@property (strong, nonatomic) IBOutlet UISlider *pinchSensitivitySlider; + @property (strong, nonatomic) IBOutlet UIStackView *testStack; @property (nonatomic, strong) MicHandler *micHandler; diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 2230f5b5..dd6c8dc9 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -714,6 +714,10 @@ BOOL isCustomResolution(int resolutionSelected) { [self addSetting:self.touchModeStack ofId:@"touchModeStack" withInfoTag:YES withDynamicLabel:NO to:touchAndControlSection]; [self addSetting:self.pointerVelocityDividerStack ofId:@"pointerVelocityDividerStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection]; [self addSetting:self.pointerVelocityFactorStack ofId:@"pointerVelocityFactorStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection]; + [self addSetting:self.pinchGestureStack ofId:@"pinchGestureStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection]; + [self addSetting:self.mousePointerVelocityStack ofId:@"mousePointerVelocityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection]; + [self addSetting:self.scrollSensitivityStack ofId:@"scrollSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection]; + [self addSetting:self.pinchSensitivityStack ofId:@"pinchSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection]; [self addSetting:self.mousePointerVelocityStack ofId:@"mousePointerVelocityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection]; // [self addSetting:self.delayLeftClickStack ofId:@"delayLeftClickStack" withInfoTag:YES withDynamicLabel:NO to:touchAndControlSection]; [self addSetting:self.onScreenWidgetStack ofId:@"onScreenWidgetStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection]; @@ -1850,6 +1854,17 @@ BOOL isCustomResolution(int resolutionSelected) { [self.mousePointerVelocityFactorSlider addTarget:self action:@selector(mousePointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved. [self mousePointerVelocityFactorSliderMoved:self.mousePointerVelocityFactorSlider]; + [self.pinchGestureSwitch setOn:self->tempSettings.enablePinch]; + [self.pinchGestureSwitch addTarget:self action:@selector(pinchGestureSwitchFlipped:) forControlEvents:(UIControlEventValueChanged)]; + + [self.scrollSensitivitySlider setValue:self->tempSettings.scrollSensitivity.floatValue animated:NO]; + [self.scrollSensitivitySlider addTarget:self action:@selector(scrollSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; + [self scrollSensitivitySliderMoved:self.scrollSensitivitySlider]; + + [self.pinchSensitivitySlider setValue:self->tempSettings.pinchSensitivity.floatValue animated:NO]; + [self.pinchSensitivitySlider addTarget:self action:@selector(pinchSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; + [self pinchSensitivitySliderMoved:self.pinchSensitivitySlider]; + [self.singleTapSensitivitySlider setValue:self->tempSettings.singleTapSensitivity.doubleValue animated:NO]; [self.singleTapSensitivitySlider addTarget:self action:@selector(singleTapSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; [self singleTapSensitivitySliderMoved:self.singleTapSensitivitySlider]; @@ -2284,6 +2299,14 @@ BOOL isCustomResolution(int resolutionSelected) { [self findDynamicLabelFromStack:_singleTapSensitivityStack].text = [NSString stringWithFormat:@" %.1f ",sender.value]; } +- (void) scrollSensitivitySliderMoved:(UISlider* )sender { + [self findDynamicLabelFromStack:_scrollSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (uint16_t)(sender.value*100)]; +} + +- (void) pinchSensitivitySliderMoved:(UISlider* )sender { + [self findDynamicLabelFromStack:_pinchSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (uint16_t)(sender.value*100)]; +} + - (void) relativeTouchSlideThresholdSliderMoved:(UISlider* )sender { [self findDynamicLabelFromStack:_relativeTouchSlideThresholdStack].text = [NSString stringWithFormat:@" %.1f ",sender.value]; } @@ -2347,6 +2370,14 @@ BOOL isCustomResolution(int resolutionSelected) { [self setHidden:!isNativeTouch forStack:self.pointerVelocityFactorStack]; [self setHidden:!isNativeTouch forStack:self.touchMoveEventIntervalStack]; + [self setHidden:(sender.selectedSegmentIndex!=RelativeTouch + && sender.selectedSegmentIndex!=AbsoluteTouch) forStack:self.pinchGestureStack]; + [self setHidden:(sender.selectedSegmentIndex!=RelativeTouch + && sender.selectedSegmentIndex!=AbsoluteTouch) forStack:self.scrollSensitivityStack]; + [self setHidden:((sender.selectedSegmentIndex!=RelativeTouch + && sender.selectedSegmentIndex!=AbsoluteTouch) + || !_pinchGestureSwitch.isOn) forStack:self.pinchSensitivityStack]; + [self setHidden:sender.selectedSegmentIndex!=RelativeTouch forStack:self.mousePointerVelocityStack]; [self setHidden:sender.selectedSegmentIndex!=RelativeTouch forStack:self.singleTapSensitivityStack]; [self setHidden:sender.selectedSegmentIndex!=RelativeTouch forStack:self.relativeTouchSlideThresholdStack]; @@ -2397,6 +2428,10 @@ BOOL isCustomResolution(int resolutionSelected) { } } +- (void)pinchGestureSwitchFlipped:(UISwitch* )sender{ + [self setHidden:!sender.isOn forStack:_pinchSensitivityStack]; +} + - (void)highlightEmergingStack:(UIStackView* )stack{ [self highlightedBackgroundForView:stack animateWithDuration:0.2]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), @@ -2899,6 +2934,9 @@ BOOL isCustomResolution(int resolutionSelected) { BOOL duckOtherApps = self.duckOtherAppSwitch.isOn; BOOL muteInBackground = self.muteInBackgroundSwitch.isOn; CGFloat relativeTouchSlideThreshold = self.relativeTouchSlideThresholdSlider.value; + BOOL enablePinch = self.pinchGestureSwitch.isOn; + CGFloat scrollSensitivity = self.scrollSensitivitySlider.value; + CGFloat pinchSensitivity = self.pinchSensitivitySlider.value; NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value; [dataMan saveSettingsWithBitrate:_bitrate @@ -2958,6 +2996,9 @@ BOOL isCustomResolution(int resolutionSelected) { duckOtherApps:duckOtherApps muteInBackground:muteInBackground relativeTouchSlideThreshold:relativeTouchSlideThreshold + enablePinch:enablePinch + scrollSensitivity:scrollSensitivity + pinchSensitivity:pinchSensitivity backgroundSessionTimer:backgroundSessionTimer]; } diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index b8a8ebd1..8284f792 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -452,6 +452,10 @@ _streamView.onScreenControls.instanceReceiverDelegate = _motionHandler; [_streamView.onScreenControls sendInstance]; + TouchPadGestureHandler.enablePinch = _settings.enablePinch; + TouchPadGestureHandler.scrollSensitivity = _settings.scrollSensitivity.floatValue; + TouchPadGestureHandler.pinchSensitivity = _settings.pinchSensitivity.floatValue; + NSLog(@"frameview gestures: %d", (uint32_t)[self.view.gestureRecognizers count]); NSLog(@"streamview gestures: %d", (uint32_t)[_streamView.gestureRecognizers count]); } diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings index d8dbad3a..d08ff1af 100644 --- a/VoidLink/mul.lproj/iPad.xcstrings +++ b/VoidLink/mul.lproj/iPad.xcstrings @@ -1969,6 +1969,36 @@ } } }, + "Evh-LH-rdh.text" : { + "comment" : "Class = \"UILabel\"; text = \"Pinch Gesture\"; ObjectID = \"Evh-LH-rdh\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Pinch Gesture" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缩放手势" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放手勢" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放手勢" + } + } + } + }, "FJv-HJ-UYJ.text" : { "comment" : "Class = \"UILabel\"; text = \"Touch Move Event Interval\"; ObjectID = \"FJv-HJ-UYJ\";", "extractionState" : "extracted_with_value", @@ -2419,6 +2449,36 @@ } } }, + "hDf-9O-NGp.text" : { + "comment" : "Class = \"UILabel\"; text = \"Scroll Sensitivity\"; ObjectID = \"hDf-9O-NGp\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Scroll Sensitivity" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "滚动灵敏度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "滾動靈敏度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "滾動靈敏度" + } + } + } + }, "hPX-cJ-dgH.text" : { "comment" : "Class = \"UILabel\"; text = \"Mute in Background\"; ObjectID = \"hPX-cJ-dgH\";", "extractionState" : "extracted_with_value", @@ -4867,6 +4927,36 @@ } } }, + "Zsj-Fa-IgS.text" : { + "comment" : "Class = \"UILabel\"; text = \"Pinch Sensitivity\"; ObjectID = \"Zsj-Fa-IgS\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Pinch Sensitivity" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缩放灵敏度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放靈敏度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放靈敏度" + } + } + } + }, "ZuV-4A-0Zb.text" : { "comment" : "Class = \"UILabel\"; text = \"Size\"; ObjectID = \"ZuV-4A-0Zb\";", "extractionState" : "extracted_with_value", diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings index 3dd97eae..ba83b29e 100644 --- a/VoidLink/mul.lproj/iPhone.xcstrings +++ b/VoidLink/mul.lproj/iPhone.xcstrings @@ -151,6 +151,36 @@ } } }, + "1hc-yp-cbj.text" : { + "comment" : "Class = \"UILabel\"; text = \"Scroll Sensitivity\"; ObjectID = \"1hc-yp-cbj\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Scroll Sensitivity" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "滚动灵敏度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "滾動靈敏度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "滾動靈敏度" + } + } + } + }, "3av-lc-tcF.text" : { "comment" : "Class = \"UILabel\"; text = \"Enable On-Screen Widget & Peripherals\"; ObjectID = \"3av-lc-tcF\";", "extractionState" : "extracted_with_value", @@ -2257,6 +2287,36 @@ } } }, + "HTs-xj-li6.text" : { + "comment" : "Class = \"UILabel\"; text = \"Pinch Sensitivity\"; ObjectID = \"HTs-xj-li6\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Pinch Sensitivity" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缩放灵敏度" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放靈敏度" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放靈敏度" + } + } + } + }, "HvT-Ek-DAx.text" : { "comment" : "Class = \"UILabel\"; text = \"Bitrate\"; ObjectID = \"HvT-Ek-DAx\";", "extractionState" : "extracted_with_value", @@ -3919,6 +3979,36 @@ } } }, + "SSe-4n-pYj.text" : { + "comment" : "Class = \"UILabel\"; text = \"Pinch Gesture\"; ObjectID = \"SSe-4n-pYj\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Pinch Gesture" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "缩放手势" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放手勢" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "縮放手勢" + } + } + } + }, "sUC-Ur-7eI.title" : { "comment" : "Class = \"UIBarButtonItem\"; title = \"Exit\"; ObjectID = \"sUC-Ur-7eI\";", "extractionState" : "extracted_with_value",