diff --git a/Limelight/AppDelegate.m b/Limelight/AppDelegate.m index 15250aba..06759d9d 100644 --- a/Limelight/AppDelegate.m +++ b/Limelight/AppDelegate.m @@ -25,19 +25,24 @@ static NSString* DB_NAME = @"Limelight_iOS.sqlite"; #if !TARGET_OS_TV + +/* // orietation limitatioin test -/*- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { +- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { UIViewController *topController = window.rootViewController; while (topController.presentedViewController) { topController = topController.presentedViewController; } return [topController supportedInterfaceOrientations]; -}*/ - -- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { - return UIInterfaceOrientationMaskAll; } +*/ +/* +- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { + NSLog(@"orientation limit"); + return UIInterfaceOrientationMaskLandscape; +} +*/ - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler { _pcUuidToLoad = (NSString*)[shortcutItem.userInfo objectForKey:@"UUID"]; diff --git a/Limelight/Base.lproj/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard index d486fb69..65615f3f 100644 --- a/Limelight/Base.lproj/iPad.storyboard +++ b/Limelight/Base.lproj/iPad.storyboard @@ -428,6 +428,23 @@ ICAgICAgICAgICAgICA + + + + + + + + + + + @@ -445,7 +462,7 @@ ICAgICAgICAgICAgICA - + @@ -459,7 +476,7 @@ ICAgICAgICAgICAgICA - + @@ -471,6 +488,7 @@ ICAgICAgICAgICAgICA + @@ -833,6 +851,9 @@ ICAgICAgICAgICAgICA + + + diff --git a/Limelight/Base.lproj/iPhone.storyboard b/Limelight/Base.lproj/iPhone.storyboard index 297abaea..49991696 100644 --- a/Limelight/Base.lproj/iPhone.storyboard +++ b/Limelight/Base.lproj/iPhone.storyboard @@ -463,7 +463,7 @@ ICAgICAgICAgICAgIA - + @@ -476,18 +476,36 @@ ICAgICAgICAgICAgIA - + + + + + + + + + + + + + @@ -829,5 +847,8 @@ ICAgICAgICAgICAgIA + + + diff --git a/Limelight/Database/DataManager.h b/Limelight/Database/DataManager.h index 018b3201..74132d3d 100644 --- a/Limelight/Database/DataManager.h +++ b/Limelight/Database/DataManager.h @@ -37,7 +37,8 @@ btMouseSupport:(BOOL)btMouseSupport // absoluteTouchMode:(BOOL)absoluteTouchMode touchMode:(NSInteger)touchMode - statsOverlay:(BOOL)statsOverlay; + statsOverlay:(BOOL)statsOverlay + allowPortrait:(BOOL)allowPortrait; - (NSArray*) getHosts; - (void) updateHost:(TemporaryHost*)host; diff --git a/Limelight/Database/DataManager.m b/Limelight/Database/DataManager.m index 1218e416..722a4fbe 100644 --- a/Limelight/Database/DataManager.m +++ b/Limelight/Database/DataManager.m @@ -76,7 +76,8 @@ btMouseSupport:(BOOL)btMouseSupport // absoluteTouchMode:(BOOL)absoluteTouchMode touchMode:(NSInteger)touchMode - statsOverlay:(BOOL)statsOverlay { + statsOverlay:(BOOL)statsOverlay + allowPortrait:(BOOL)allowPortrait{ [_managedObjectContext performBlockAndWait:^{ Settings* settingsToSave = [self retrieveSettings]; @@ -105,6 +106,7 @@ // settingsToSave.absoluteTouchMode = absoluteTouchMode; settingsToSave.touchMode = [NSNumber numberWithInteger:(uint16_t)touchMode]; settingsToSave.statsOverlay = statsOverlay; + settingsToSave.allowPortrait = allowPortrait; [self saveData]; }]; diff --git a/Limelight/Database/TemporarySettings.h b/Limelight/Database/TemporarySettings.h index 8f3183d8..40da15d3 100644 --- a/Limelight/Database/TemporarySettings.h +++ b/Limelight/Database/TemporarySettings.h @@ -48,6 +48,7 @@ @property (nonatomic) BOOL statsOverlay; @property (nonatomic) BOOL liftStreamViewForKeyboard; @property (nonatomic) BOOL showKeyboardToolbar; +@property (nonatomic) BOOL allowPortrait; - (id) initFromSettings:(Settings*)settings; diff --git a/Limelight/Database/TemporarySettings.m b/Limelight/Database/TemporarySettings.m index b10e5bb8..a60580e3 100644 --- a/Limelight/Database/TemporarySettings.m +++ b/Limelight/Database/TemporarySettings.m @@ -94,6 +94,7 @@ self.touchPointerVelocityFactor = settings.touchPointerVelocityFactor; self.mousePointerVelocityFactor = settings.mousePointerVelocityFactor; self.pointerVelocityModeDivider = settings.pointerVelocityModeDivider; + self.allowPortrait = settings.allowPortrait; #endif self.uniqueId = settings.uniqueId; diff --git a/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents b/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents index 331099cf..a658466d 100644 --- a/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents +++ b/Limelight/Limelight.xcdatamodeld/Moonlight v1.10.xcdatamodel/contents @@ -21,6 +21,7 @@ + diff --git a/Limelight/ViewControllers/MainFrameViewController.h b/Limelight/ViewControllers/MainFrameViewController.h index e921ba1b..e217452c 100644 --- a/Limelight/ViewControllers/MainFrameViewController.h +++ b/Limelight/ViewControllers/MainFrameViewController.h @@ -21,7 +21,6 @@ #if !TARGET_OS_TV @property (weak, nonatomic) IBOutlet UIBarButtonItem *upButton; @property (nonatomic, assign) bool settingsExpandedInStreamView; -@property (nonatomic, assign) bool isInHostView; -(void)simulateSettingsButtonPress; -(void)reloadStreamConfig; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 206300f9..e78c6c17 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -43,7 +43,7 @@ @implementation MainFrameViewController { UILabel* waterMark; - CGFloat recordedScreenWidth; + //CGFloat recordedScreenWidth; CustomEdgeSwipeGestureRecognizer* _exitSwipeRecognizer; NSOperationQueue* _opQueue; TemporaryHost* _selectedHost; @@ -307,7 +307,6 @@ static NSMutableSet* hostList; [self updateTitle]; [self disableUpButton]; - self.isInHostView = true; // setting flag [self reloadScrollHostView]; // host view must be reloaded here [self.collectionView reloadData]; [self.view addSubview:hostScrollView]; @@ -347,7 +346,6 @@ static NSMutableSet* hostList; [self updateTitle]; [self enableUpButton]; [self disableNavigation]; - self.isInHostView = false; #if TARGET_OS_TV // Intercept the menu key to go back to the host page @@ -610,6 +608,7 @@ static NSMutableSet* hostList; } - (void) prepareToStreamApp:(TemporaryApp *)app { + self.revealViewController.isStreaming = true; // tell the revealViewController streaming is started. _streamConfig = [[StreamConfiguration alloc] init]; _streamConfig.host = app.host.activeAddress; _streamConfig.httpsPort = app.host.httpsPort; @@ -893,32 +892,32 @@ static NSMutableSet* hostList; } } -- (UIInterfaceOrientationMask)supportedInterfaceOrientations { - // Return the supported interface orientations based on the current state - NSLog(@"orchange test"); - return UIInterfaceOrientationMaskLandscape; -} - - - (void)handleOrientationChange { double delayInSeconds = 0.7; // Convert the delay into a dispatch_time_t value dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); // Perform some task after the delay - CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); + //CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); dispatch_after(delayTime, dispatch_get_main_queue(), ^{// Code to execute after the delay [self swapResolutionWidthHeightAccordingly]; - if(self.isInHostView) [self reloadScrollHostView]; // here is a flag for judging whether to reload host view after orientation change. - self->recordedScreenWidth = screenWidthInPoints; // kind of obselete, but i keep this in the code. + if([self->_upButton title] == nil) [self reloadScrollHostView]; // title of the _upButton is good flag for judging if we're on the Host selection view + //self->recordedScreenWidth = screenWidthInPoints; // kind of obselete, but i keep this in the code. }); } -- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position { - [self setNeedsUpdateOfSupportedInterfaceOrientations]; +// currently obselete: +- (void) setNeedsUpdateAllowedOrientation{ + if (@available(iOS 16.0, *)) { + [self setNeedsUpdateOfSupportedInterfaceOrientations]; + } else { + // Fallback on earlier versions + } +} - - // If we moved back to the center position, we should save the settings + +- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position { + // If we moved back to the center position, we should save the settings SettingsViewController* settingsViewController = (SettingsViewController*)[revealController rearViewController]; settingsViewController.mainFrameViewController = self; @@ -936,6 +935,7 @@ static NSMutableSet* hostList; if (position == FrontViewPositionLeft) { [settingsViewController saveSettings]; + [self setNeedsUpdateAllowedOrientation]; // handle allow portratit on & off _settingsButton.enabled = YES; // make sure these 2 buttons are enabled after closing setting view. _upButton.enabled = YES; // here is the select new host button } @@ -1024,7 +1024,7 @@ static NSMutableSet* hostList; [self attachWaterMark]; #if !TARGET_OS_TV self.settingsExpandedInStreamView = false; // init this flag - self.isInHostView = true; + self.revealViewController.isStreaming = false; //init this flag for rvlVC // Set the side bar button action. When it's tapped, it'll show the sidebar. [_settingsButton setTarget:self.revealViewController]; @@ -1080,7 +1080,7 @@ static NSMutableSet* hostList; _boxArtCache = [[NSCache alloc] init]; - recordedScreenWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]); + //recordedScreenWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]); hostScrollView = [[ComputerScrollView alloc] init]; [self reloadScrollHostView]; @@ -1100,8 +1100,8 @@ static NSMutableSet* hostList; CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); CGFloat screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]); + // deal with scroll host view reload after device orientation change here: bool isLandscape = screenWidthInPoints > screenHeightInPoints; - NSLog(@"isLandscape1 %d", isLandscape); CGFloat realViewFrameWidth = self.view.frame.size.width > self.view.frame.size.height ? self.view.frame.size.width : self.view.frame.size.height; CGFloat realViewFrameHeight = self.view.frame.size.width < self.view.frame.size.height ? self.view.frame.size.width : self.view.frame.size.height; if(!isLandscape) { @@ -1251,10 +1251,11 @@ static NSMutableSet* hostList; selector:@selector(handleOrientationChange) // //force expand settings view to update resolution table, and all setting includes current fullscreen resolution will be updated. name:UIDeviceOrientationDidChangeNotification object:nil]; - + [[self revealViewController] setPrimaryViewController:self]; - recordedScreenWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]); // Get the screen's bounds (in points), update recorded screen width - self.isInHostView = true; + self.revealViewController.isStreaming = false; // tell the revealViewController streaming is finished + + //recordedScreenWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]); // Get the screen's bounds (in points), update recorded screen width #endif [self.navigationController setNavigationBarHidden:NO animated:YES]; diff --git a/Limelight/ViewControllers/SWRevealViewController.h b/Limelight/ViewControllers/SWRevealViewController.h index 3eea2633..998c21db 100755 --- a/Limelight/ViewControllers/SWRevealViewController.h +++ b/Limelight/ViewControllers/SWRevealViewController.h @@ -311,6 +311,8 @@ typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType) // Delegate @property (nonatomic,weak) id delegate; +@property (nonatomic,assign) bool isStreaming; + @end diff --git a/Limelight/ViewControllers/SWRevealViewController.m b/Limelight/ViewControllers/SWRevealViewController.m index 11af464a..067c86a1 100755 --- a/Limelight/ViewControllers/SWRevealViewController.m +++ b/Limelight/ViewControllers/SWRevealViewController.m @@ -27,6 +27,7 @@ #import #import "SWRevealViewController.h" +#import "DataManager.h" #pragma mark - StatusBar Helper Function @@ -719,6 +720,36 @@ const int FrontViewPositionNone = 0xff; } +- (UIInterfaceOrientationMask)getCurrentOrientation{ + CGFloat screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]); + CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); + //lock the orientation accordingly after streaming is started + if(screenWidthInPoints > screenHeightInPoints) return UIInterfaceOrientationMaskLandscape; + else return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown; +} + + +// tested on iOS17. this method does not call back on iOS14, so runtime orientation limitation not working for iOS14. Probably depends on iOS16 or higher. +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + // Return the supported interface orientations based on the current state + NSLog(@"supportedInterfaceOrientations called back 666"); + //lock the orientation accordingly after streaming is started + DataManager* dataMan = [[DataManager alloc] init]; + Settings *currentSettings = [dataMan retrieveSettings]; + //Handle allow portrait on & off + if(currentSettings.allowPortrait){ + if (self.isStreaming) return [self getCurrentOrientation]; + else return UIInterfaceOrientationMaskAll; + } + else return UIInterfaceOrientationMaskLandscape; +} + + + +- (void)viewDidLoad{ + self.isStreaming = false; //init this flag +} + - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; @@ -1233,7 +1264,7 @@ const int FrontViewPositionNone = 0xff; CGFloat translation = [recognizer translationInView:_contentView].x; CGFloat baseLocation = [_contentView frontLocationForPosition:_panInitialFrontPosition]; - CGFloat xLocation = baseLocation + translation; + CGFloat xLocation = baseLocation + translation; // buggy on portrait mode??/ if ( xLocation < 0 ) { diff --git a/Limelight/ViewControllers/SettingsViewController.h b/Limelight/ViewControllers/SettingsViewController.h index 4c8a94cb..56ff7981 100644 --- a/Limelight/ViewControllers/SettingsViewController.h +++ b/Limelight/ViewControllers/SettingsViewController.h @@ -45,11 +45,13 @@ @property (strong, nonatomic) IBOutlet UILabel *touchPointerVelocityFactorUILabel; @property (strong, nonatomic) IBOutlet UISlider *mousePointerVelocityFactorSlider; @property (strong, nonatomic) IBOutlet UILabel *mousePointerVelocityFactorUILabel; +@property (strong, nonatomic) IBOutlet UISegmentedControl *allowPortraitSelector; @property (strong, nonatomic) IBOutlet UIButton *goBackToStreamViewButton; @property (strong, nonatomic) LayoutOnScreenControlsViewController *layoutOnScreenControlsVC; @property (nonatomic, strong) MainFrameViewController *mainFrameViewController; @property (nonatomic, strong) CustomEdgeSwipeGestureRecognizer *exitSwipeRecognizer; + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m index 29f5e056..3d03f971 100644 --- a/Limelight/ViewControllers/SettingsViewController.m +++ b/Limelight/ViewControllers/SettingsViewController.m @@ -392,6 +392,9 @@ BOOL isCustomResolution(CGSize res) { [self updateBitrateText]; [self updateResolutionDisplayViewText]; + // allow portrait setting + [self.allowPortraitSelector setSelectedSegmentIndex:currentSettings.allowPortrait ? 1 : 0]; + // lift streamview setting [self.liftStreamViewForKeyboardSelector setSelectedSegmentIndex:currentSettings.liftStreamViewForKeyboard ? 1 : 0];// Load old setting @@ -882,6 +885,7 @@ BOOL isCustomResolution(CGSize res) { NSInteger touchMode = [self.touchModeSelector selectedSegmentIndex]; BOOL statsOverlay = [self.statsOverlaySelector selectedSegmentIndex] == 1; BOOL enableHdr = [self.hdrSelector selectedSegmentIndex] == 1; + BOOL allowPortrait = [self.allowPortraitSelector selectedSegmentIndex] == 1; [dataMan saveSettingsWithBitrate:_bitrate framerate:framerate height:height @@ -906,7 +910,8 @@ BOOL isCustomResolution(CGSize res) { btMouseSupport:btMouseSupport // absoluteTouchMode:absoluteTouchMode touchMode:touchMode - statsOverlay:statsOverlay]; + statsOverlay:statsOverlay + allowPortrait:allowPortrait]; } - (void)didReceiveMemoryWarning { diff --git a/Limelight/mul.lproj/iPad.xcstrings b/Limelight/mul.lproj/iPad.xcstrings index 95d3f216..241a7deb 100644 --- a/Limelight/mul.lproj/iPad.xcstrings +++ b/Limelight/mul.lproj/iPad.xcstrings @@ -31,6 +31,66 @@ } } }, + "7Gm-zB-s7s.segmentTitles[0]" : { + "comment" : "Class = \"UISegmentedControl\"; 7Gm-zB-s7s.segmentTitles[0] = \"No\"; ObjectID = \"7Gm-zB-s7s\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + } + } + }, + "7Gm-zB-s7s.segmentTitles[1]" : { + "comment" : "Class = \"UISegmentedControl\"; 7Gm-zB-s7s.segmentTitles[1] = \"Yes\"; ObjectID = \"7Gm-zB-s7s\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Yes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + } + } + }, "7va-uJ-IfD.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; 7va-uJ-IfD.segmentTitles[0] = \"Lowest Latency\"; ObjectID = \"7va-uJ-IfD\";", "extractionState" : "extracted_with_value", @@ -817,6 +877,36 @@ } } }, + "hAo-1k-oYF.text" : { + "comment" : "Class = \"UILabel\"; text = \"Allow Portrait\"; ObjectID = \"hAo-1k-oYF\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Allow Portrait" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + } + } + }, "hm3-EV-h6d.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; hm3-EV-h6d.segmentTitles[0] = \"No\"; ObjectID = \"hm3-EV-h6d\";", "extractionState" : "extracted_with_value", diff --git a/Limelight/mul.lproj/iPhone.xcstrings b/Limelight/mul.lproj/iPhone.xcstrings index 56ed13d2..04978a13 100644 --- a/Limelight/mul.lproj/iPhone.xcstrings +++ b/Limelight/mul.lproj/iPhone.xcstrings @@ -1627,6 +1627,66 @@ } } }, + "R9O-Tw-UD4.segmentTitles[0]" : { + "comment" : "Class = \"UISegmentedControl\"; R9O-Tw-UD4.segmentTitles[0] = \"No\"; ObjectID = \"R9O-Tw-UD4\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭" + } + } + } + }, + "R9O-Tw-UD4.segmentTitles[1]" : { + "comment" : "Class = \"UISegmentedControl\"; R9O-Tw-UD4.segmentTitles[1] = \"Yes\"; ObjectID = \"R9O-Tw-UD4\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Yes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用" + } + } + } + }, "rdz-eg-2oR.segmentTitles[0]" : { "comment" : "Class = \"UISegmentedControl\"; rdz-eg-2oR.segmentTitles[0] = \"No\"; ObjectID = \"rdz-eg-2oR\";", "extractionState" : "extracted_with_value", @@ -2028,6 +2088,36 @@ } } } + }, + "Z9P-TN-kci.text" : { + "comment" : "Class = \"UILabel\"; text = \"Allow Portrait\"; ObjectID = \"Z9P-TN-kci\";", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Allow Portrait" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "允许竖屏" + } + } + } } }, "version" : "1.0"