From f5c03f80452aea347e74460418aab9369d835024 Mon Sep 17 00:00:00 2001 From: TrueZhuangjia Date: Thu, 12 Sep 2024 15:20:55 +0800 Subject: [PATCH] make on-screen buttons available for absolute touch --- Limelight/Input/StreamView.h | 4 ++- Limelight/Input/StreamView.m | 26 ++++++++++++------- .../ViewControllers/SettingsViewController.m | 17 ++++++------ .../StreamFrameViewController.m | 12 ++++++--- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Limelight/Input/StreamView.h b/Limelight/Input/StreamView.h index 8cdb4bc1..e9dfdd35 100644 --- a/Limelight/Input/StreamView.h +++ b/Limelight/Input/StreamView.h @@ -26,7 +26,9 @@ - (void) setupStreamView:(ControllerSupport*)controllerSupport interactionDelegate:(id)interactionDelegate - config:(StreamConfiguration*)streamConfig; + config:(StreamConfiguration*)streamConfig + streamFrameTopLayerView:(UIView* )topLayerView +; - (void) showOnScreenControls; - (void) setOnScreenControls; - (void) disableOnScreenControls; diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 51a1dcaa..52c0ca35 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -25,6 +25,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; @implementation StreamView { + UIView* streamFrameTopLayerView; TemporarySettings* settings; OnScreenControls* onScreenControls; @@ -65,9 +66,10 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; - (void) setupStreamView:(ControllerSupport*)controllerSupport interactionDelegate:(id)interactionDelegate - config:(StreamConfiguration*)streamConfig { + config:(StreamConfiguration*)streamConfig + streamFrameTopLayerView:(UIView* )topLayerView{ - + self->streamFrameTopLayerView = topLayerView; self->interactionDelegate = interactionDelegate; self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height; @@ -96,8 +98,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; - if(settings.touchMode.intValue == PURE_NATIVE_TOUCH) [self addGestureRecognizer:keyboardToggleRecognizer]; //keep legacy approach in pure native mode - else [self.superview addGestureRecognizer:keyboardToggleRecognizer]; //add to the superview in other modes + if(settings.touchMode.intValue == PURE_NATIVE_TOUCH) [self addGestureRecognizer:keyboardToggleRecognizer]; //keep legacy approach in pure native mode + else [self->streamFrameTopLayerView addGestureRecognizer:keyboardToggleRecognizer]; //add to the superview in other modes #if TARGET_OS_TV @@ -315,10 +317,16 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; #endif } +// we'll enable on screen buttons, and disable on screen controllers for absolute touch - (bool) isOscEnabled{ return (settings.touchMode.intValue == RELATIVE_TOUCH || settings.touchMode.intValue == REGULAR_NATIVE_TOUCH) && settings.onscreenControls.intValue != OnScreenControlsLevelOff; } +// we'll enable on screen buttons, and disable on screen controllers for absolute touch +- (bool) isOnScreenButtonEnabled{ + return (settings.touchMode.intValue == RELATIVE_TOUCH || settings.touchMode.intValue == REGULAR_NATIVE_TOUCH || settings.touchMode.intValue == ABSOLUTE_TOUCH) && settings.onscreenControls.intValue == OnScreenControlsLevelCustom; +} + - (void) reloadOnScreenControlsRealtimeWith:(ControllerSupport*)controllerSupport andConfig:(StreamConfiguration*)streamConfig { [self reloadOnScreenControlsWith:controllerSupport andConfig:streamConfig]; @@ -337,12 +345,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; RelativeTouchHandler* relativeTouchHandler = (RelativeTouchHandler *)touchHandler; onScreenControls.mouseRightClickTapRecognizer = relativeTouchHandler.mouseRightClickTapRecognizer; } */ - [onScreenControls setLevel:(OnScreenControlsLevel)settings.onscreenControls.intValue]; + if([self isOscEnabled]) [onScreenControls setLevel:(OnScreenControlsLevel)settings.onscreenControls.intValue]; } - (void) clearOnScreenKeyboardButtons{ - for (UIView *subview in self.superview.subviews) { + for (UIView *subview in self->streamFrameTopLayerView.subviews) { // 检查子视图是否是特定类型的实例 if ([subview isKindOfClass:[OnScreenButtonView class]]) { // 如果是,就添加到将要被移除的数组中 @@ -358,9 +366,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; // remove all keyboard button views first [self clearOnScreenKeyboardButtons]; - bool customOscEnabled = (settings.touchMode.intValue == RELATIVE_TOUCH || settings.touchMode.intValue == REGULAR_NATIVE_TOUCH) && settings.onscreenControls.intValue == OnScreenControlsLevelCustom; + // bool customOscEnabled = [self isOscEnabled] && settings.onscreenControls.intValue == OnScreenControlsLevelCustom; - if(!customOscEnabled) return; //returns if we're not in custom osc mode + if(![self isOnScreenButtonEnabled]) return; OSCProfilesManager* profilesManager = [OSCProfilesManager sharedManager]; OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile @@ -372,7 +380,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; OnScreenButtonView* buttonView = [[OnScreenButtonView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias]; //reconstruct buttonView buttonView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place // Add the buttonView to the view controller's view - [self.superview addSubview:buttonView]; // add keyboard button to the stream frame view. must add it to the target view before setting location. + [self->streamFrameTopLayerView addSubview:buttonView]; // add keyboard button to the stream frame view. must add it to the target view before setting location. [buttonView setKeyLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y]; } } diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m index 4cc07e54..13aabfc3 100644 --- a/Limelight/ViewControllers/SettingsViewController.m +++ b/Limelight/ViewControllers/SettingsViewController.m @@ -582,8 +582,9 @@ BOOL isCustomResolution(CGSize res) { - - +- (bool) isOnScreenControllerOrButtonEnabled{ + return ([self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == ABSOLUTE_TOUCH) && [self.onscreenControlSelector selectedSegmentIndex] != OnScreenControlsLevelOff; +} @@ -600,8 +601,7 @@ BOOL isCustomResolution(CGSize res) { self.layoutOnScreenControlsVC.modalPresentationStyle = UIModalPresentationFullScreen; } - bool oscEnabled = ([self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH) && [self.onscreenControlSelector selectedSegmentIndex] != OnScreenControlsLevelOff; - bool customOscEnabled = oscEnabled && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; + bool customOscEnabled = [self isOnScreenControllerOrButtonEnabled] && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; // [self widget:self.keyboardToggleFingerNumSlider setEnabled:!customOscEnabled]; if(customOscEnabled && !justEnteredSettingsViewDoNotOpenOscLayoutTool) { // [self.keyboardToggleFingerNumSlider setValue:3.0]; @@ -682,9 +682,8 @@ BOOL isCustomResolution(CGSize res) { - (void) touchModeChanged { // Disable On-Screen Controls & Buttons in non-relative touch mode - bool oscEnabled = ([self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH) && [self.onscreenControlSelector selectedSegmentIndex] != OnScreenControlsLevelOff; - bool oscSelectorEnabled = [self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH; - bool customOscEnabled = oscEnabled && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; + bool oscSelectorEnabled = [self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == ABSOLUTE_TOUCH; + bool customOscEnabled = [self isOnScreenControllerOrButtonEnabled] && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; bool isNativeTouch = [self.touchModeSelector selectedSegmentIndex] == PURE_NATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH; [self.onscreenControlSelector setEnabled:oscSelectorEnabled]; @@ -898,8 +897,8 @@ BOOL isCustomResolution(CGSize res) { } - (void) keyboardToggleFingerNumSliderMoved{ - bool oscEnabled = ([self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH || [self.touchModeSelector selectedSegmentIndex] == REGULAR_NATIVE_TOUCH) && [self.onscreenControlSelector selectedSegmentIndex] != OnScreenControlsLevelOff; - bool customOscEnabled = oscEnabled && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; + // bool oscEnabled = [self isOnScreenControllerOrButtonEnabled]; + bool customOscEnabled = [self isOnScreenControllerOrButtonEnabled] && [self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsLevelCustom; CGFloat sliderValue = self.keyboardToggleFingerNumSlider.value; if(customOscEnabled){ diff --git a/Limelight/ViewControllers/StreamFrameViewController.m b/Limelight/ViewControllers/StreamFrameViewController.m index c950b1c6..ed636bd8 100644 --- a/Limelight/ViewControllers/StreamFrameViewController.m +++ b/Limelight/ViewControllers/StreamFrameViewController.m @@ -62,14 +62,18 @@ #endif } +- (bool)isOscLayoutToolEnabled{ + return (_settings.touchMode.intValue == RELATIVE_TOUCH || _settings.touchMode.intValue == REGULAR_NATIVE_TOUCH || _settings.touchMode.intValue == ABSOLUTE_TOUCH) && _settings.onscreenControls.intValue == OnScreenControlsLevelCustom; +} - (void)configOscLayoutTool{ - if((_settings.touchMode.intValue == RELATIVE_TOUCH || _settings.touchMode.intValue == REGULAR_NATIVE_TOUCH) && _settings.onscreenControls.intValue == OnScreenControlsLevelCustom){ + if([self isOscLayoutToolEnabled]){ _oscLayoutTapRecoginizer = [[CustomTapGestureRecognizer alloc] initWithTarget:self action:@selector(layoutOSC)]; _oscLayoutTapRecoginizer.numberOfTouchesRequired = _settings.oscLayoutToolFingers.intValue; //tap a predefined number of fingers to open osc layout tool _oscLayoutTapRecoginizer.tapDownTimeThreshold = 0.2; _oscLayoutTapRecoginizer.delaysTouchesBegan = NO; _oscLayoutTapRecoginizer.delaysTouchesEnded = NO; + if(_settings.touchMode.intValue == ABSOLUTE_TOUCH) _oscLayoutTapRecoginizer.immediateTriggering = true; // make immediate triggering on for absolute touch mode [self.view addGestureRecognizer:_oscLayoutTapRecoginizer]; // /* sets a reference to the correct 'LayoutOnScreenControlsViewController' depending on whether the user is on an iPhone or iPad */ @@ -112,7 +116,7 @@ [self.view addGestureRecognizer:_slideToCmdToolRecognizer]; } -- (void)configZoomGesture{ +- (void)configZoomGestureAndAddStreamView{ if (_settings.touchMode.intValue == ABSOLUTE_TOUCH) { _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; #if !TARGET_OS_TV @@ -148,12 +152,12 @@ _settings = [[[DataManager alloc] init] getSettings]; //StreamFrameViewController retrieve the settings here. [self configOscLayoutTool]; [self configSwipeGestures]; - [self configZoomGesture]; + [self configZoomGestureAndAddStreamView]; [self->_streamView disableOnScreenControls]; //don't know why but this must be called outside the streamview class, just put it here. execute in streamview class cause hang [self.mainFrameViewcontroller reloadStreamConfig]; // reload streamconfig _controllerSupport = [[ControllerSupport alloc] initWithConfig:self.streamConfig delegate:self]; // reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC - [_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig]; //reinitiate setupStreamView process. + [_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig streamFrameTopLayerView:self.view]; //reinitiate setupStreamView process. [self->_streamView reloadOnScreenControlsRealtimeWith:(ControllerSupport*)_controllerSupport andConfig:(StreamConfiguration*)_streamConfig]; //reload OSC here. [self->_streamView reloadOnScreenKeyboardButtons]; //reload keyboard buttons here. the keyboard button view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering