refactor: adopt UIScene lifecycle
feat: add initial support for pip feat: add setting toggle for pip fix: let os handle invokation of pip which is more reliable fix: UIScene compatibility with airplay fix: black screen on external display when on app view and streaming fix: incorrect window size when launched directly on external display fix: wrong resolution shown in settings when in stream session Enable gamemode flag for iOS18+ Explicitly enters pip mode when in background
This commit is contained in:
1 parent
51e915b598
commit
b5ce7a8ff7
24 files changed
+480
-144
No files matched your search
@@ -0,0 +1,91 @@
|
||||
#import "SceneDelegate.h"
|
||||
#import "StreamFrameViewController.h"
|
||||
|
||||
@implementation SceneDelegate
|
||||
|
||||
static UIView *_sharedStreamVideoRenderView = nil;
|
||||
static UIWindow *_externalSceneWindow = nil;
|
||||
|
||||
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
|
||||
if (![scene isKindOfClass:[UIWindowScene class]]) {
|
||||
return;
|
||||
}
|
||||
UIWindowScene *windowScene = (UIWindowScene *)scene;
|
||||
if ([session.role isEqualToString:UIWindowSceneSessionRoleApplication]) {
|
||||
self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
|
||||
NSString *storyboardName;
|
||||
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
|
||||
storyboardName = @"iPad";
|
||||
} else {
|
||||
storyboardName = @"iPhone";
|
||||
}
|
||||
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
|
||||
UIViewController *initialViewController = [storyboard instantiateInitialViewController];
|
||||
self.window.rootViewController = initialViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
Log(LOG_I, @"SceneDelegate: Main app scene connected.");
|
||||
|
||||
} else if ([session.role isEqualToString:UIWindowSceneSessionRoleExternalDisplay]) {
|
||||
Log(LOG_I, @"SceneDelegate: External display scene connecting for screen: %@", ((UIWindowScene *)scene).screen.description);
|
||||
UIWindowScene *windowScene = (UIWindowScene *)scene;
|
||||
_externalSceneWindow = [[UIWindow alloc] initWithWindowScene:windowScene];
|
||||
UIViewController *externalVC = [[UIViewController alloc] init];
|
||||
externalVC.view.backgroundColor = [UIColor blackColor]; // Set a default background
|
||||
_externalSceneWindow.rootViewController = externalVC;
|
||||
|
||||
if (_sharedStreamVideoRenderView) {
|
||||
_sharedStreamVideoRenderView.frame = _externalSceneWindow.bounds;
|
||||
[_externalSceneWindow.rootViewController.view addSubview:_sharedStreamVideoRenderView];
|
||||
Log(LOG_I, @"SceneDelegate: External display scene connected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Method for StreamFrameViewController to provide its render view
|
||||
+ (void)setExternalDisplayRenderView:(UIView *)renderView {
|
||||
_sharedStreamVideoRenderView = renderView;
|
||||
if (_externalSceneWindow && _externalSceneWindow.rootViewController && _sharedStreamVideoRenderView) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Ensure it's removed from any previous parent (should have been done by StreamFrameVC)
|
||||
[_sharedStreamVideoRenderView removeFromSuperview];
|
||||
_sharedStreamVideoRenderView.frame = _externalSceneWindow.bounds; // Set frame for external window
|
||||
[_externalSceneWindow.rootViewController.view addSubview:_sharedStreamVideoRenderView];
|
||||
_externalSceneWindow.hidden = NO;
|
||||
Log(LOG_I, @"SceneDelegate: Added render view to external window's root view.");
|
||||
});
|
||||
} else {
|
||||
Log(LOG_E, @"SceneDelegate: External display window or root view controller not available.");
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)clearExternalDisplayRenderView {
|
||||
if (_sharedStreamVideoRenderView) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_sharedStreamVideoRenderView removeFromSuperview];
|
||||
Log(LOG_I, @"SceneDelegate: Removed render view from external display.");
|
||||
});
|
||||
}
|
||||
_sharedStreamVideoRenderView = nil;
|
||||
}
|
||||
|
||||
- (void)sceneDidDisconnect:(UIScene *)scene {
|
||||
Log(LOG_I, @"SceneDelegate: Scene disconnected: %@, role: %@", scene.title, scene.session.role);
|
||||
|
||||
if ([scene.session.role isEqualToString:UIWindowSceneSessionRoleExternalDisplay]) {
|
||||
if ([scene isKindOfClass:[UIWindowScene class]]) {
|
||||
UIWindowScene *windowScene = (UIWindowScene *)scene;
|
||||
if (_externalSceneWindow == windowScene.windows.firstObject) { // Compare with the window from the disconnecting scene
|
||||
[SceneDelegate clearExternalDisplayRenderView]; // Clears the shared view
|
||||
_externalSceneWindow = nil;
|
||||
Log(LOG_I, @"SceneDelegate: External display scene fully disconnected and cleaned up.");
|
||||
} else {
|
||||
Log(LOG_W, @"SceneDelegate: Disconnecting scene is not the one holding our _externalSceneWindow.");
|
||||
}
|
||||
} else {
|
||||
Log(LOG_W, @"SceneDelegate: Disconnecting scene is not a UIWindowScene.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user