diff --git a/CMakeLists.txt b/CMakeLists.txt index 89ec8303c5..3735f82025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -735,6 +735,8 @@ elseif(IOS) ios/main.mm ios/AppDelegate.mm ios/AppDelegate.h + ios/DisplayManager.h + ios/DisplayManager.mm ios/ViewController.mm ios/ViewController.h ios/iOSCoreAudio.mm diff --git a/ios/AppDelegate.mm b/ios/AppDelegate.mm index 34b90b2bbe..4cbd2ae1fb 100644 --- a/ios/AppDelegate.mm +++ b/ios/AppDelegate.mm @@ -1,4 +1,5 @@ #import "AppDelegate.h" +#import "DisplayManager.h" #import "ViewController.h" #import "base/NativeApp.h" #import "Core/System.h" @@ -72,27 +73,15 @@ } -(BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - - [[NSNotificationCenter defaultCenter] addObserverForName:UIScreenDidConnectNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { - UIScreen* screen = (UIScreen*)notification.object; - self.screen = screen; - - NSLog(@"Display connected: %@", screen.debugDescription); - UIScreenMode* mode = screen.availableModes[screen.availableModes.count - 1]; - [screen setCurrentMode:mode]; - [screen setOverscanCompensation:UIScreenOverscanCompensationNone]; - - self.window = [[UIWindow alloc] initWithFrame:[screen bounds]]; - [self.window setScreen:screen]; - self.viewController = [[ViewController alloc] init]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil]; - - self.window.rootViewController = self.viewController; - [self.window makeKeyAndVisible]; - }]; + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.viewController = [[ViewController alloc] init]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil]; + + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; return YES; } diff --git a/ios/DisplayManager.h b/ios/DisplayManager.h new file mode 100644 index 0000000000..fb46707a19 --- /dev/null +++ b/ios/DisplayManager.h @@ -0,0 +1,24 @@ +// +// DisplayManager.h +// native +// +// Created by xieyi on 2019/6/9. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface DisplayManager : NSObject + +- (void)setupDisplayListener; +- (void)updateResolution:(UIScreen *)screen; + +@property (nonatomic, strong) UIScreen *mainScreen; + +@property (class, readonly, strong) DisplayManager *shared; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/DisplayManager.mm b/ios/DisplayManager.mm new file mode 100644 index 0000000000..5b20d8a252 --- /dev/null +++ b/ios/DisplayManager.mm @@ -0,0 +1,139 @@ +// +// DisplayManager.m +// native +// +// Created by xieyi on 2019/6/9. +// + +#import "DisplayManager.h" +#import "ViewController.h" +#import "AppDelegate.h" +#include "base/display.h" +#include "base/NativeApp.h" +#include "Core/System.h" + +#define IS_IPAD() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) + +@interface DisplayManager () + +@property BOOL listenerActive; +@property (atomic, retain) NSMutableArray *extDisplays; + +- (void)updateScreen:(UIScreen *)screen; + +@end + +@implementation DisplayManager + +- (instancetype)init +{ + self = [super init]; + if (self) { + [self setListenerActive:NO]; + [self setExtDisplays:[[NSMutableArray alloc] init]]; + } + return self; +} + ++ (DisplayManager *)shared { + static DisplayManager *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[DisplayManager alloc] init]; + }); + return sharedInstance; +} + +- (void)setupDisplayListener { + if ([self listenerActive]) { + NSLog(@"setupDisplayListener already called"); + return; + } + NSLog(@"Setting up display manager"); + [self setMainScreen:[UIScreen mainScreen]]; + // Display connected + [[NSNotificationCenter defaultCenter] addObserverForName:UIScreenDidConnectNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + UIScreen *screen = (UIScreen *) notification.object; + NSLog(@"New display connected: %@", [screen debugDescription]); + [[self extDisplays] addObject:screen]; + // Do not switch to second connected display + if ([self mainScreen] != [UIScreen mainScreen]) { + return; + } + [self updateScreen:screen]; + }]; + // Display disconnected + [[NSNotificationCenter defaultCenter] addObserverForName:UIScreenDidDisconnectNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) { + UIScreen *screen = (UIScreen *) notification.object; + NSLog(@"Display disconnected: %@", [screen debugDescription]); + if ([[self extDisplays] containsObject:screen]) { + [[self extDisplays] removeObject:screen]; + } + if ([[self extDisplays] count] > 0) { + UIScreen *newScreen = [[self extDisplays] lastObject]; + [self updateScreen:newScreen]; + } else { + [self updateScreen:[UIScreen mainScreen]]; + } + }]; + [self setListenerActive:YES]; +} + +- (void)updateScreen:(UIScreen *)screen { + [self setMainScreen:screen]; + UIWindow *gameWindow = [(AppDelegate *)[[UIApplication sharedApplication] delegate] window]; + [gameWindow setScreen:screen]; + // Set optimal resolution + // Dispatch later to prevent "no window is preset" error + dispatch_async(dispatch_get_main_queue(), ^{ + if (screen != [UIScreen mainScreen]) { + NSUInteger count = [[screen availableModes] count]; + UIScreenMode* mode = [screen availableModes][count - 1]; + [screen setCurrentMode:mode]; + [screen setOverscanCompensation:UIScreenOverscanCompensationNone]; + } + [self updateResolution:screen]; + }); +} + +- (void)updateResolution:(UIScreen *)screen { + float scale = screen.scale; + + if ([screen respondsToSelector:@selector(nativeScale)]) { + scale = screen.nativeScale; + } + + CGSize size = screen.applicationFrame.size; + + if (size.height > size.width) { + float h = size.height; + size.height = size.width; + size.width = h; + } + + g_dpi = (IS_IPAD() ? 200.0f : 150.0f) * scale; + g_dpi_scale_x = 240.0f / g_dpi; + g_dpi_scale_y = 240.0f / g_dpi; + g_dpi_scale_real_x = g_dpi_scale_x; + g_dpi_scale_real_y = g_dpi_scale_y; + pixel_xres = size.width * scale; + pixel_yres = size.height * scale; + + dp_xres = pixel_xres * g_dpi_scale_x; + dp_yres = pixel_yres * g_dpi_scale_y; + + pixel_in_dps_x = (float)pixel_xres / (float)dp_xres; + pixel_in_dps_y = (float)pixel_yres / (float)dp_yres; + + [[sharedViewController view] setContentScaleFactor:scale]; + + // PSP native resize + PSP_CoreParameter().pixelWidth = pixel_xres; + PSP_CoreParameter().pixelHeight = pixel_yres; + + NativeResized(); + + NSLog(@"Updated display resolution: (%d, %d) @%.1fx", pixel_xres, pixel_yres, scale); +} + +@end diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 8ebae24cdc..457e331a74 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -7,6 +7,7 @@ #import "AppDelegate.h" #import "ViewController.h" +#import "DisplayManager.h" #import "SubtleVolume.h" #import #include @@ -144,6 +145,7 @@ static GraphicsContext *graphicsContext; - (void)viewDidLoad { [super viewDidLoad]; + [[DisplayManager shared] setupDisplayListener]; UIScreen* screen = [(AppDelegate*)[UIApplication sharedApplication].delegate screen]; self.view.frame = [screen bounds]; @@ -163,34 +165,7 @@ static GraphicsContext *graphicsContext; // Might be useful for a speed boot, sacrificing resolution: view.contentScaleFactor = screen.scale; - float scale = screen.scale; - - - if ([screen respondsToSelector:@selector(nativeScale)]) { - scale = screen.nativeScale; - } - - CGSize size = [[UIApplication sharedApplication].delegate window].frame.size; - - if (size.height > size.width) { - float h = size.height; - size.height = size.width; - size.width = h; - } - - g_dpi = (IS_IPAD() ? 200.0f : 150.0f) * scale; - g_dpi_scale_x = 1;//240.0f / g_dpi; - g_dpi_scale_y = 1;//240.0f / g_dpi; - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; - pixel_xres = size.width * scale; - pixel_yres = size.height * scale; - - dp_xres = pixel_xres * g_dpi_scale_x; - dp_yres = pixel_yres * g_dpi_scale_y; - - pixel_in_dps_x = (float)pixel_xres / (float)dp_xres; - pixel_in_dps_y = (float)pixel_yres / (float)dp_yres; + [[DisplayManager shared] updateResolution:[UIScreen mainScreen]]; graphicsContext = new IOSGraphicsContext();