Native touch oriented improvements
This commit is contained in:
1 parent
557765f2c0
commit
873269e410
25 files changed
+2254
-283
No files matched your search
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// CustomEdgeSwipeGestureRecognizer.h
|
||||
// Moonlight-ZWM
|
||||
//
|
||||
// Created by ZWM on 2024/4/30.
|
||||
// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef CustomEdgeSwipeGestureRecognizer_h
|
||||
#define CustomEdgeSwipeGestureRecognizer_h
|
||||
// CustomEdgeSwipeGestureRecognizer.h
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CustomEdgeSwipeGestureRecognizer : UIGestureRecognizer
|
||||
|
||||
@property (nonatomic, assign) UIRectEdge edges; // Specify the edge(s) you want to recognize the swipe gesture on
|
||||
@property (nonatomic, assign) CGFloat normalizedThresholdDistance; // Distance from the edge to start recognizing the gesture
|
||||
|
||||
@end
|
||||
#endif /* CustomEdgeSwipeGestureRecognizer_h */
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// CustomEdgeSwipeGestureRecognizer.m
|
||||
// Moonlight-ZWM
|
||||
//
|
||||
// Created by ZWM on 2024/4/30.
|
||||
// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
|
||||
//
|
||||
|
||||
// #import <Foundation/Foundation.h>
|
||||
|
||||
#import "CustomEdgeSwipeGestureRecognizer.h"
|
||||
#import <UIKit/UIGestureRecognizerSubclass.h>
|
||||
|
||||
@implementation CustomEdgeSwipeGestureRecognizer
|
||||
UITouch* capturedUITouch;
|
||||
CGFloat _startPointX;
|
||||
static CGFloat screenWidthInPoints;
|
||||
static CGFloat EDGE_TOLERANCE_POINTS = 50.0f;
|
||||
|
||||
- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action {
|
||||
self = [super initWithTarget:target action:action];
|
||||
screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); // Get the screen's bounds (in points)
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
// [super touchesBegan:touches withEvent:event];
|
||||
UITouch *touch = [touches anyObject];
|
||||
capturedUITouch = touch;
|
||||
_startPointX = [capturedUITouch locationInView:self.view].x;
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
// [super touchesEnded:touches withEvent:event];
|
||||
|
||||
if([touches containsObject:capturedUITouch]){
|
||||
CGFloat _endPointX = [capturedUITouch locationInView:self.view].x;
|
||||
CGFloat normalizedGestureDistance = fabs(_endPointX - _startPointX)/screenWidthInPoints;
|
||||
|
||||
if(self.edges & UIRectEdgeLeft){
|
||||
if(_startPointX < EDGE_TOLERANCE_POINTS && normalizedGestureDistance > _normalizedThresholdDistance){
|
||||
self.state = UIGestureRecognizerStateBegan;
|
||||
self.state = UIGestureRecognizerStateEnded;
|
||||
}
|
||||
// NSLog(@"_startPointX %f , normalizedGestureDeltaX %f", _startPointX, normalizedGestureDistance);
|
||||
}
|
||||
if(self.edges & UIRectEdgeRight){
|
||||
if((_startPointX > (screenWidthInPoints - EDGE_TOLERANCE_POINTS)) && normalizedGestureDistance > _normalizedThresholdDistance){
|
||||
self.state = UIGestureRecognizerStateBegan;
|
||||
self.state = UIGestureRecognizerStateEnded;
|
||||
}
|
||||
// NSLog(@"_startPointX %f , normalizedGestureDeltaX %f", _startPointX, normalizedGestureDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,19 @@
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *btMouseSelector;
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *statsOverlaySelector;
|
||||
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *keyboardToggleFingerNumLabel;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *keyboardToggleFingerNumSlider;
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *liftStreamViewForKeyboardSelector;
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *showKeyboardToolbarSelector;
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *swipeExitScreenEdgeSelector;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *swipeToExitDistanceUILabel;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *swipeToExitDistanceSlider;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *pointerVelocityModeDividerSlider;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *pointerVelocityModeDividerUILabel;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *touchPointerVelocityFactorSlider;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *touchPointerVelocityFactorUILabel;
|
||||
|
||||
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import "TemporarySettings.h"
|
||||
#import "DataManager.h"
|
||||
|
||||
#import <UIKit/UIGestureRecognizerSubclass.h>
|
||||
#import <VideoToolbox/VideoToolbox.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@@ -263,11 +264,60 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
||||
[self updateBitrateText];
|
||||
[self updateResolutionDisplayViewText];
|
||||
|
||||
[self.keyboardToggleFingerNumSlider setValue:(CGFloat)currentSettings.keyboardToggleFingers.intValue animated:YES]; // Load old setting. old setting was converted to uint16_t before saving.
|
||||
if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Tap-Toggle Local Keyboard Disabled"]]; // Initiate label display. Allow higher required finger number to completely disable keyboard toggle
|
||||
else [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Fingers to Tap-Toggle Local Keyboard: %d", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
|
||||
[self.keyboardToggleFingerNumSlider addTarget:self action:@selector(keyboardToggleFingerNumSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self.liftStreamViewForKeyboardSelector setSelectedSegmentIndex:currentSettings.liftStreamViewForKeyboard ? 1 : 0];// Load old setting
|
||||
[self.showKeyboardToolbarSelector setSelectedSegmentIndex:currentSettings.showKeyboardToolbar ? 1 : 0];// Load old setting
|
||||
[self.swipeExitScreenEdgeSelector setSelectedSegmentIndex:[self getSelectorIndexFromScreenEdge:(uint32_t)currentSettings.swipeExitScreenEdge.integerValue]]; // Load old setting
|
||||
[self.swipeToExitDistanceSlider setValue:(CGFloat)currentSettings.swipeToExitDistance.floatValue animated:YES]; // Load old setting.
|
||||
[self.swipeToExitDistanceUILabel setText:[NSString stringWithFormat:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]]; // Initiate label display
|
||||
[self.swipeToExitDistanceSlider addTarget:self action:@selector(swipeToExitDistanceSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
|
||||
[self.pointerVelocityModeDividerSlider setValue:currentSettings.pointerVelocityModeDivider.floatValue * 100 animated:YES]; // Load old setting.
|
||||
[self.pointerVelocityModeDividerUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]]; // Initiate label display
|
||||
[self.pointerVelocityModeDividerSlider addTarget:self action:@selector(pointerVelocityModeDividerSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
|
||||
[self.touchPointerVelocityFactorSlider setValue:currentSettings.touchPointerVelocityFactor.floatValue * 100 animated:YES]; // Load old setting.
|
||||
[self.touchPointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity Factor: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Initiate label display
|
||||
[self.touchPointerVelocityFactorSlider addTarget:self action:@selector(touchPointerVelocityFactorSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
}
|
||||
|
||||
- (void) pointerVelocityModeDividerSliderMoved {
|
||||
[self.pointerVelocityModeDividerUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]];
|
||||
}
|
||||
|
||||
- (void) touchPointerVelocityFactorSliderMoved {
|
||||
[self.touchPointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity Factor: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Initiate label display
|
||||
}
|
||||
|
||||
- (uint32_t) getScreenEdgeFromSelector {
|
||||
switch (self.swipeExitScreenEdgeSelector.selectedSegmentIndex) {
|
||||
case 0: return UIRectEdgeLeft;
|
||||
case 1: return UIRectEdgeRight;
|
||||
case 2: return UIRectEdgeLeft|UIRectEdgeRight;
|
||||
default: return UIRectEdgeLeft;
|
||||
}
|
||||
}
|
||||
|
||||
- (uint32_t) getSelectorIndexFromScreenEdge: (uint32_t)edge {
|
||||
switch (edge) {
|
||||
case UIRectEdgeLeft: return 0;
|
||||
case UIRectEdgeRight: return 1;
|
||||
case UIRectEdgeLeft|UIRectEdgeRight: return 2;
|
||||
default: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
- (void) touchModeChanged {
|
||||
// Disable on-screen controls in absolute touch mode
|
||||
[self.onscreenControlSelector setEnabled:[self.touchModeSelector selectedSegmentIndex] == 0];
|
||||
[self.pointerVelocityModeDividerSlider setEnabled:[self.touchModeSelector selectedSegmentIndex] == 1]; // pointer velocity scaling works only in native touch mode.
|
||||
[self.touchPointerVelocityFactorSlider setEnabled:[self.touchModeSelector selectedSegmentIndex] == 1]; // pointer velocity scaling works only in native touch mode.
|
||||
}
|
||||
|
||||
- (void) updateBitrate {
|
||||
@@ -456,6 +506,15 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[self.resolutionDisplayView addSubview:label2];
|
||||
}
|
||||
|
||||
- (void) keyboardToggleFingerNumSliderMoved{
|
||||
if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Tap-Toggle Local Keyboard Disabled"]];
|
||||
else [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Fingers to Tap-Toggle Local Keyboard: %d", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
|
||||
}
|
||||
|
||||
- (void) swipeToExitDistanceSliderMoved{
|
||||
[self.swipeToExitDistanceUILabel setText:[NSString stringWithFormat:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]];
|
||||
}
|
||||
|
||||
- (void) bitrateSliderMoved {
|
||||
assert(self.bitrateSlider.value < (sizeof(bitrateTable) / sizeof(*bitrateTable)));
|
||||
_bitrate = bitrateTable[(int)self.bitrateSlider.value];
|
||||
@@ -528,6 +587,14 @@ BOOL isCustomResolution(CGSize res) {
|
||||
NSInteger height = [self getChosenStreamHeight];
|
||||
NSInteger width = [self getChosenStreamWidth];
|
||||
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
|
||||
NSInteger keyboardToggleFingers = (uint16_t)self.keyboardToggleFingerNumSlider.value;
|
||||
// NSLog(@"saveSettings keyboardToggleFingers %d", (uint16_t)keyboardToggleFingers);
|
||||
CGFloat swipeToExitDistance = self.swipeToExitDistanceSlider.value;
|
||||
uint32_t swipeExitScreenEdge = [self getScreenEdgeFromSelector];
|
||||
CGFloat pointerVelocityModeDivider = (CGFloat)(uint8_t)self.pointerVelocityModeDividerSlider.value/100;
|
||||
CGFloat touchPointerVelocityFactor =(CGFloat)(uint16_t)self.touchPointerVelocityFactorSlider.value/100;
|
||||
BOOL liftStreamViewForKeyboard = [self.liftStreamViewForKeyboardSelector selectedSegmentIndex] == 1;
|
||||
BOOL showKeyboardToolbar = [self.showKeyboardToolbarSelector selectedSegmentIndex] == 1;
|
||||
BOOL optimizeGames = [self.optimizeSettingsSelector selectedSegmentIndex] == 1;
|
||||
BOOL multiController = [self.multiControllerSelector selectedSegmentIndex] == 1;
|
||||
BOOL swapABXYButtons = [self.swapABXYButtonsSelector selectedSegmentIndex] == 1;
|
||||
@@ -544,6 +611,13 @@ BOOL isCustomResolution(CGSize res) {
|
||||
width:width
|
||||
audioConfig:2 // Stereo
|
||||
onscreenControls:onscreenControls
|
||||
keyboardToggleFingers:keyboardToggleFingers
|
||||
swipeExitScreenEdge:swipeExitScreenEdge
|
||||
swipeToExitDistance:swipeToExitDistance
|
||||
pointerVelocityModeDivider:pointerVelocityModeDivider
|
||||
touchPointerVelocityFactor:touchPointerVelocityFactor
|
||||
liftStreamViewForKeyboard:liftStreamViewForKeyboard
|
||||
showKeyboardToolbar:showKeyboardToolbar
|
||||
optimizeGames:optimizeGames
|
||||
multiController:multiController
|
||||
swapABXYButtons:swapABXYButtons
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <Limelight.h>
|
||||
#import "CustomEdgeSwipeGestureRecognizer.h"
|
||||
|
||||
#if TARGET_OS_TV
|
||||
#import <AVFoundation/AVDisplayCriteria.h>
|
||||
@@ -30,6 +31,8 @@
|
||||
- (id)initWithRefreshRate:(float)arg1 videoDynamicRange:(int)arg2;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation StreamFrameViewController {
|
||||
ControllerSupport *_controllerSupport;
|
||||
StreamManager *_streamMan;
|
||||
@@ -49,7 +52,7 @@
|
||||
CGSize _keyboardSize;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
UIScreenEdgePanGestureRecognizer *_exitSwipeRecognizer;
|
||||
CustomEdgeSwipeGestureRecognizer *_exitSwipeRecognizer;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -83,7 +86,7 @@
|
||||
|
||||
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||||
|
||||
_settings = [[[DataManager alloc] init] getSettings];
|
||||
_settings = [[[DataManager alloc] init] getSettings]; //StreamFrameViewController retrieve the settings here.
|
||||
|
||||
_stageLabel = [[UILabel alloc] init];
|
||||
[_stageLabel setUserInteractionEnabled:NO];
|
||||
@@ -129,12 +132,13 @@
|
||||
[self.view addGestureRecognizer:_playPauseTapGestureRecognizer];
|
||||
|
||||
#else
|
||||
_exitSwipeRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgeSwiped)];
|
||||
_exitSwipeRecognizer.edges = UIRectEdgeLeft;
|
||||
_exitSwipeRecognizer = [[CustomEdgeSwipeGestureRecognizer alloc] initWithTarget:self action:@selector(edgeSwiped)];
|
||||
_exitSwipeRecognizer.edges = _settings.swipeExitScreenEdge.intValue;
|
||||
_exitSwipeRecognizer.normalizedThresholdDistance = _settings.swipeToExitDistance.floatValue;
|
||||
_exitSwipeRecognizer.delaysTouchesBegan = NO;
|
||||
_exitSwipeRecognizer.delaysTouchesEnded = NO;
|
||||
|
||||
[self.view addGestureRecognizer:_exitSwipeRecognizer];
|
||||
|
||||
#endif
|
||||
|
||||
_tipLabel = [[UILabel alloc] init];
|
||||
@@ -143,7 +147,7 @@
|
||||
#if TARGET_OS_TV
|
||||
[_tipLabel setText:@"Tip: Tap the Play/Pause button on the Apple TV Remote to disconnect from your PC"];
|
||||
#else
|
||||
[_tipLabel setText:@"Tip: Swipe from the left edge to disconnect from your PC"];
|
||||
[_tipLabel setText:@"Tip: Swipe from the left edge to the middle of your screen to disconnect from your PC"];
|
||||
#endif
|
||||
|
||||
[_tipLabel sizeToFit];
|
||||
@@ -175,6 +179,7 @@
|
||||
#if 0
|
||||
// FIXME: This doesn't work reliably on iPad for some reason. Showing and hiding the keyboard
|
||||
// several times in a row will not correctly restore the state of the UIScrollView.
|
||||
// I add this notification to the StreamView, works well on ipad mini6.
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(keyboardWillShow:)
|
||||
name: UIKeyboardWillShowNotification
|
||||
@@ -187,25 +192,25 @@
|
||||
#endif
|
||||
|
||||
// Only enable scroll and zoom in absolute touch mode
|
||||
if (_settings.absoluteTouchMode) {
|
||||
_scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
|
||||
#if !TARGET_OS_TV
|
||||
[_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2];
|
||||
#endif
|
||||
[_scrollView setShowsHorizontalScrollIndicator:NO];
|
||||
[_scrollView setShowsVerticalScrollIndicator:NO];
|
||||
[_scrollView setDelegate:self];
|
||||
[_scrollView setMaximumZoomScale:10.0f];
|
||||
|
||||
// Add StreamView inside a UIScrollView for absolute mode
|
||||
[_scrollView addSubview:_streamView];
|
||||
[self.view addSubview:_scrollView];
|
||||
}
|
||||
else {
|
||||
// Add StreamView directly in relative mode
|
||||
[self.view addSubview:_streamView];
|
||||
}
|
||||
|
||||
// if (_settings.absoluteTouchMode) {
|
||||
// _scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
|
||||
//#if !TARGET_OS_TV
|
||||
// [_scrollView.panGestureRecognizer setMinimumNumberOfTouches:2];
|
||||
//#endif
|
||||
// [_scrollView setShowsHorizontalScrollIndicator:NO];
|
||||
// [_scrollView setShowsVerticalScrollIndicator:NO];
|
||||
// [_scrollView setDelegate:self];
|
||||
// [_scrollView setMaximumZoomScale:10.0f];
|
||||
//
|
||||
// // Add StreamView inside a UIScrollView for absolute mode
|
||||
// [_scrollView addSubview:_streamView];
|
||||
// [self.view addSubview:_scrollView];
|
||||
// }
|
||||
// else {
|
||||
// // Add StreamView directly in relative mode
|
||||
// [self.view addSubview:_streamView];
|
||||
// }
|
||||
[self.view addSubview:_streamView];
|
||||
[self.view addSubview:_stageLabel];
|
||||
[self.view addSubview:_spinner];
|
||||
[self.view addSubview:_tipLabel];
|
||||
|
||||
Reference in new issue
Block a user