From d5834d0f8447571dac606022da354d74aaba4fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Oct 2025 21:11:39 +0100 Subject: [PATCH] Move a lot more stuff into PPSSPPBaseViewController --- ios/ViewController.h | 5 +- ios/ViewController.mm | 155 +----------------------------- ios/ViewControllerCommon.h | 3 +- ios/ViewControllerCommon.mm | 175 ++++++++++++++++++++++++++++++++++ ios/ViewControllerMetal.h | 4 +- ios/ViewControllerMetal.mm | 184 +----------------------------------- 6 files changed, 181 insertions(+), 345 deletions(-) diff --git a/ios/ViewController.h b/ios/ViewController.h index 90816dceb6..0b97209924 100644 --- a/ios/ViewController.h +++ b/ios/ViewController.h @@ -9,10 +9,7 @@ #import "ViewControllerCommon.h" -@interface PPSSPPViewControllerGL : PPSSPPBaseViewController - +@interface PPSSPPViewControllerGL : PPSSPPBaseViewController // Public-ish control similar to GLKViewController @property (nonatomic, assign) NSInteger preferredFramesPerSecond; // default 60 diff --git a/ios/ViewController.mm b/ios/ViewController.mm index aff72aaf74..d6db80a5b7 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -98,7 +98,6 @@ PPSSPPBaseViewController *sharedViewController; @interface PPSSPPViewControllerGL () { ICadeTracker g_iCadeTracker; - TouchTracker g_touchTracker; IOSGLESContext *graphicsContext; @@ -119,10 +118,7 @@ PPSSPPBaseViewController *sharedViewController; @end -@implementation PPSSPPViewControllerGL { - UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer; -} - +@implementation PPSSPPViewControllerGL {} -(id) init { self = [super init]; @@ -149,35 +145,6 @@ PPSSPPBaseViewController *sharedViewController; } } -- (void)appSwitchModeChanged -{ - [self setNeedsUpdateOfHomeIndicatorAutoHidden]; -} - -- (void)shareText:(NSString *)text { - NSArray *items = @[text]; - UIActivityViewController * viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self presentViewController:viewController animated:YES completion:nil]; - }); -} - -extern float g_safeInsetLeft; -extern float g_safeInsetRight; -extern float g_safeInsetTop; -extern float g_safeInsetBottom; - -- (void)viewSafeAreaInsetsDidChange { - if (@available(iOS 11.0, *)) { - [super viewSafeAreaInsetsDidChange]; - // we use 0.0f instead of safeAreaInsets.bottom because the bottom overlay isn't disturbing (for now) - g_safeInsetLeft = self.view.safeAreaInsets.left; - g_safeInsetRight = self.view.safeAreaInsets.right; - g_safeInsetTop = self.view.safeAreaInsets.top; - g_safeInsetBottom = 0.0f; - } -} - // The actual rendering is NOT on this thread, this is the emu thread // that runs game logic. void GLRenderLoop(IOSGLESContext *graphicsContext) { @@ -235,23 +202,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { _assert_(!g_renderLoopThread.joinable()); } -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - INFO_LOG(Log::G3D, "viewDidAppear"); - [self hideKeyboard]; - [self updateGesture]; - - // This needs to be called really late during startup, unfortunately. -#if PPSSPP_PLATFORM(IOS_APP_STORE) - [IAPManager sharedIAPManager]; // Kick off the IAPManager early. - NSLog(@"Metal viewDidAppear. updating icon"); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [[IAPManager sharedIAPManager] updateIcon:false]; - [self hideKeyboard]; - }); -#endif // IOS_APP_STORE -} - - (void)viewDidLoad { [super viewDidLoad]; @@ -484,26 +434,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { return UIInterfaceOrientationMaskAll; } -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Began(touches, self.view); -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Moved(touches, self.view); -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Ended(touches, self.view); -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Cancelled(touches, self.view); -} - - (void)bindDefaultFBO { [(GLKView*)self.glView bindDrawable]; @@ -539,46 +469,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { } } -// Enables tapping for edge area. --(UIRectEdge)preferredScreenEdgesDeferringSystemGestures -{ - if (GetUIState() == UISTATE_INGAME) { - // In-game, we need all the control we can get. Though, we could possibly - // allow the top edge? - INFO_LOG(Log::System, "Defer system gestures on all edges"); - return UIRectEdgeAll; - } else { - INFO_LOG(Log::System, "Allow system gestures on the bottom"); - // Allow task switching gestures to take precedence, without causing - // scroll events in the UI. Otherwise, we get "ghost" scrolls when switching tasks. - return UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeRight; - } -} - -- (void)uiStateChanged -{ - [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; - [self hideKeyboard]; - [self updateGesture]; -} - -- (void)updateGesture { - INFO_LOG(Log::System, "Updating swipe gesture."); - - if (mBackGestureRecognizer) { - INFO_LOG(Log::System, "Removing swipe gesture."); - [[self view] removeGestureRecognizer:mBackGestureRecognizer]; - mBackGestureRecognizer = nil; - } - - if (GetUIState() != UISTATE_INGAME) { - INFO_LOG(Log::System, "Adding swipe gesture."); - mBackGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:) ]; - [mBackGestureRecognizer setEdges:UIRectEdgeLeft]; - [[self view] addGestureRecognizer:mBackGestureRecognizer]; - } -} - - (UIView *)getView { return [self view]; } @@ -608,49 +498,6 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) { #endif -// The below is inspired by https://stackoverflow.com/questions/7253477/how-to-display-the-iphone-ipad-keyboard-over-a-full-screen-opengl-es-app -// It's a bit limited but good enough. - --(void) deleteBackward { - KeyInput input{}; - input.deviceId = DEVICE_ID_KEYBOARD; - input.flags = KEY_DOWN | KEY_UP; - input.keyCode = NKCODE_DEL; - NativeKey(input); - INFO_LOG(Log::System, "Backspace"); -} - --(void) insertText:(NSString *)text -{ - std::string str([text UTF8String]); - INFO_LOG(Log::System, "Chars: %s", str.c_str()); - SendKeyboardChars(str); -} - --(BOOL) canBecomeFirstResponder -{ - return true; -} - --(BOOL) hasText -{ - return true; -} - --(void) showKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - INFO_LOG(Log::System, "becomeFirstResponder"); - [self becomeFirstResponder]; - }); -} - --(void) hideKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - INFO_LOG(Log::System, "resignFirstResponder"); - [self resignFirstResponder]; - }); -} - - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; diff --git a/ios/ViewControllerCommon.h b/ios/ViewControllerCommon.h index 1e222b81dd..da9460d49a 100644 --- a/ios/ViewControllerCommon.h +++ b/ios/ViewControllerCommon.h @@ -7,7 +7,8 @@ @interface PPSSPPBaseViewController : UIViewController< UIImagePickerControllerDelegate, UINavigationControllerDelegate, - CameraFrameDelegate, LocationHandlerDelegate> + CameraFrameDelegate, LocationHandlerDelegate, UIKeyInput, + UIGestureRecognizerDelegate> - (void)hideKeyboard; - (void)showKeyboard; diff --git a/ios/ViewControllerCommon.mm b/ios/ViewControllerCommon.mm index 99a544f66e..5f503d3850 100644 --- a/ios/ViewControllerCommon.mm +++ b/ios/ViewControllerCommon.mm @@ -1,19 +1,80 @@ #import "ios/CameraHelper.h" #import "ios/ViewControllerCommon.h" +#import "ios/Controls.h" +#import "ios/IAPManager.h" #include "Common/System/Request.h" +#include "Common/Input/InputState.h" +#include "Common/System/NativeApp.h" +#include "Common/Log.h" #include "Core/HLE/sceUsbCam.h" #include "Core/HLE/sceUsbGps.h" +#include "Core/System.h" +#include "Core/Config.h" @interface PPSSPPBaseViewController () { int imageRequestId; NSString *imageFilename; CameraHelper *cameraHelper; LocationHelper *locationHelper; + TouchTracker g_touchTracker; } @end @implementation PPSSPPBaseViewController { + UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + INFO_LOG(Log::G3D, "viewDidAppear"); + [self hideKeyboard]; + [self updateGesture]; + + // This needs to be called really late during startup, unfortunately. +#if PPSSPP_PLATFORM(IOS_APP_STORE) + [IAPManager sharedIAPManager]; // Kick off the IAPManager early. + NSLog(@"Metal viewDidAppear. updating icon"); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[IAPManager sharedIAPManager] updateIcon:false]; + [self hideKeyboard]; + }); +#endif // IOS_APP_STORE +} + +// Enables tapping for edge area. +-(UIRectEdge)preferredScreenEdgesDeferringSystemGestures { + if (GetUIState() == UISTATE_INGAME) { + // In-game, we need all the control we can get. Though, we could possibly + // allow the top edge? + INFO_LOG(Log::System, "Defer system gestures on all edges"); + return UIRectEdgeAll; + } else { + INFO_LOG(Log::System, "Allow system gestures on the bottom"); + // Allow task switching gestures to take precedence, without causing + // scroll events in the UI. Otherwise, we get "ghost" scrolls when switching tasks. + return UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeRight; + } +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + g_touchTracker.Began(touches, self.view); +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + g_touchTracker.Moved(touches, self.view); +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + g_touchTracker.Ended(touches, self.view); +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + g_touchTracker.Cancelled(touches, self.view); } - (void)pickPhoto:(NSString *)saveFilename requestId:(int)requestId { @@ -57,6 +118,40 @@ [self hideKeyboard]; } +- (void)handleSwipeFrom:(UIScreenEdgePanGestureRecognizer *)recognizer { + if (recognizer.state == UIGestureRecognizerStateEnded) { + KeyInput key; + key.flags = KEY_DOWN | KEY_UP; + key.keyCode = NKCODE_BACK; + key.deviceId = DEVICE_ID_TOUCH; + NativeKey(key); + INFO_LOG(Log::System, "Detected back swipe"); + } +} + +- (void)updateGesture { + INFO_LOG(Log::System, "Updating swipe gesture."); + + if (mBackGestureRecognizer) { + INFO_LOG(Log::System, "Removing swipe gesture."); + [[self view] removeGestureRecognizer:mBackGestureRecognizer]; + mBackGestureRecognizer = nil; + } + + if (GetUIState() != UISTATE_INGAME) { + INFO_LOG(Log::System, "Adding swipe gesture."); + mBackGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:) ]; + [mBackGestureRecognizer setEdges:UIRectEdgeLeft]; + [[self view] addGestureRecognizer:mBackGestureRecognizer]; + } +} + +- (void)uiStateChanged { + [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; + [self hideKeyboard]; + [self updateGesture]; +} + - (void)startVideo:(int)width height:(int)height { [cameraHelper startVideo:width h:height]; } @@ -96,4 +191,84 @@ [locationHelper setDelegate:self]; } +extern float g_safeInsetLeft; +extern float g_safeInsetRight; +extern float g_safeInsetTop; +extern float g_safeInsetBottom; + +static float BoostInset(float inset) { + if (inset > 0.0f) { + // If there's some inset, add a few pixels extra. Really needed on iPhone 12, at least. + inset += 4.0f; + } + return inset; +} + +- (void)viewSafeAreaInsetsDidChange { + if (@available(iOS 11.0, *)) { + [super viewSafeAreaInsetsDidChange]; + // we use 0.0f instead of safeAreaInsets.bottom because the bottom overlay isn't disturbing (for now) + g_safeInsetLeft = BoostInset(self.view.safeAreaInsets.left); + g_safeInsetRight = BoostInset(self.view.safeAreaInsets.right); + g_safeInsetTop = BoostInset(self.view.safeAreaInsets.top); + + // TODO: In portrait mode, should probably use safeAreaInsets.bottom. + // However, in landscape mode, it's not really needed. + // g_safeInsetBottom = BoostInset(self.view.safeAreaInsets.bottom); + g_safeInsetBottom = 0.0f; + } +} + +- (void)shareText:(NSString *)text { + NSArray *items = @[text]; + UIActivityViewController * viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self presentViewController:viewController animated:YES completion:nil]; + }); +} + +- (void)appSwitchModeChanged { + [self setNeedsUpdateOfHomeIndicatorAutoHidden]; +} + +// The below is inspired by https://stackoverflow.com/questions/7253477/how-to-display-the-iphone-ipad-keyboard-over-a-full-screen-opengl-es-app +// It's a bit limited but good enough. + +- (void)deleteBackward { + KeyInput input{}; + input.deviceId = DEVICE_ID_KEYBOARD; + input.flags = KEY_DOWN | KEY_UP; + input.keyCode = NKCODE_DEL; + NativeKey(input); + INFO_LOG(Log::System, "Backspace"); +} + +- (void)insertText:(NSString *)text { + std::string str([text UTF8String]); + INFO_LOG(Log::System, "Chars: %s", str.c_str()); + SendKeyboardChars(str); +} + +- (BOOL)hasText { + return true; +} + +- (void)showKeyboard { + dispatch_async(dispatch_get_main_queue(), ^{ + INFO_LOG(Log::System, "becomeFirstResponder"); + [self becomeFirstResponder]; + }); +} + +- (void)hideKeyboard { + dispatch_async(dispatch_get_main_queue(), ^{ + INFO_LOG(Log::System, "resignFirstResponder"); + [self resignFirstResponder]; + }); +} + +- (BOOL)canBecomeFirstResponder { + return YES; +} + @end diff --git a/ios/ViewControllerMetal.h b/ios/ViewControllerMetal.h index 34c921bc9f..d4fcb7bf6f 100644 --- a/ios/ViewControllerMetal.h +++ b/ios/ViewControllerMetal.h @@ -6,9 +6,7 @@ #import "ViewControllerCommon.h" #import "iCade/iCadeReaderView.h" -@interface PPSSPPViewControllerMetal : PPSSPPBaseViewController< - iCadeEventDelegate, - UIGestureRecognizerDelegate, UIKeyInput> +@interface PPSSPPViewControllerMetal : PPSSPPBaseViewController @end /** The Metal-compatibile view. */ diff --git a/ios/ViewControllerMetal.mm b/ios/ViewControllerMetal.mm index 9ab5a9b51f..63ede0e11a 100644 --- a/ios/ViewControllerMetal.mm +++ b/ios/ViewControllerMetal.mm @@ -179,7 +179,6 @@ static std::thread g_renderLoopThread; @interface PPSSPPViewControllerMetal () { ICadeTracker g_iCadeTracker; - TouchTracker g_touchTracker; IOSVulkanContext *graphicsContext; CameraHelper *cameraHelper; @@ -191,9 +190,7 @@ static std::thread g_renderLoopThread; @end // @interface -@implementation PPSSPPViewControllerMetal { - UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer; -} +@implementation PPSSPPViewControllerMetal {} - (id)init { self = [super init]; @@ -436,23 +433,6 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye INFO_LOG(Log::G3D, "viewWillDisappear"); } -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - INFO_LOG(Log::G3D, "viewDidAppear"); - [self hideKeyboard]; - [self updateGesture]; - - // This needs to be called really late during startup, unfortunately. -#if PPSSPP_PLATFORM(IOS_APP_STORE) - [IAPManager sharedIAPManager]; // Kick off the IAPManager early. - NSLog(@"Metal viewDidAppear. updating icon"); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [[IAPManager sharedIAPManager] updateIcon:false]; - [self hideKeyboard]; - }); -#endif // IOS_APP_STORE -} - - (BOOL)prefersHomeIndicatorAutoHidden { if (g_Config.iAppSwitchMode == (int)AppSwitchMode::DOUBLE_SWIPE_INDICATOR) { return NO; @@ -461,112 +441,11 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye } } -- (void)appSwitchModeChanged -{ - [self setNeedsUpdateOfHomeIndicatorAutoHidden]; -} - -- (void)shareText:(NSString *)text { - NSArray *items = @[text]; - UIActivityViewController * viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self presentViewController:viewController animated:YES completion:nil]; - }); -} - -extern float g_safeInsetLeft; -extern float g_safeInsetRight; -extern float g_safeInsetTop; -extern float g_safeInsetBottom; - -static float BoostInset(float inset) { - if (inset > 0.0f) { - // If there's some inset, add a few pixels extra. Really needed on iPhone 12, at least. - inset += 4.0f; - } - return inset; -} - -- (void)viewSafeAreaInsetsDidChange { - if (@available(iOS 11.0, *)) { - [super viewSafeAreaInsetsDidChange]; - // we use 0.0f instead of safeAreaInsets.bottom because the bottom overlay isn't disturbing (for now) - g_safeInsetLeft = BoostInset(self.view.safeAreaInsets.left); - g_safeInsetRight = BoostInset(self.view.safeAreaInsets.right); - g_safeInsetTop = BoostInset(self.view.safeAreaInsets.top); - - // TODO: In portrait mode, should probably use safeAreaInsets.bottom. - // However, in landscape mode, it's not really needed. - // g_safeInsetBottom = BoostInset(self.view.safeAreaInsets.bottom); - g_safeInsetBottom = 0.0f; - } -} - -// Enables tapping for edge area. --(UIRectEdge)preferredScreenEdgesDeferringSystemGestures -{ - if (GetUIState() == UISTATE_INGAME) { - // In-game, we need all the control we can get. Though, we could possibly - // allow the top edge? - INFO_LOG(Log::System, "Defer system gestures on all edges"); - return UIRectEdgeAll; - } else { - INFO_LOG(Log::System, "Allow system gestures on the bottom"); - // Allow task switching gestures to take precedence, without causing - // scroll events in the UI. - return UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeRight; - } -} - -- (void)uiStateChanged -{ - [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; - [self hideKeyboard]; - [self updateGesture]; -} - -- (void)updateGesture { - INFO_LOG(Log::System, "Updating swipe gesture."); - - if (mBackGestureRecognizer) { - INFO_LOG(Log::System, "Removing swipe gesture."); - [[self view] removeGestureRecognizer:mBackGestureRecognizer]; - mBackGestureRecognizer = nil; - } - - if (GetUIState() != UISTATE_INGAME) { - INFO_LOG(Log::System, "Adding swipe gesture."); - mBackGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:) ]; - [mBackGestureRecognizer setEdges:UIRectEdgeLeft]; - [[self view] addGestureRecognizer:mBackGestureRecognizer]; - } -} - - (void)bindDefaultFBO { // Do nothing } -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Began(touches, self.view); -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Moved(touches, self.view); -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Ended(touches, self.view); -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - g_touchTracker.Cancelled(touches, self.view); -} - - (void)buttonDown:(iCadeState)button { g_iCadeTracker.ButtonDown(button); @@ -622,67 +501,6 @@ static float BoostInset(float inset) { } } -- (void)startVideo:(int)width height:(int)height { - [cameraHelper startVideo:width h:height]; -} - -- (void)stopVideo { - [cameraHelper stopVideo]; -} - -- (void)handleSwipeFrom:(UIScreenEdgePanGestureRecognizer *)recognizer -{ - if (recognizer.state == UIGestureRecognizerStateEnded) { - KeyInput key; - key.flags = KEY_DOWN | KEY_UP; - key.keyCode = NKCODE_BACK; - key.deviceId = DEVICE_ID_TOUCH; - NativeKey(key); - INFO_LOG(Log::System, "Detected back swipe"); - } -} -// The below is inspired by https://stackoverflow.com/questions/7253477/how-to-display-the-iphone-ipad-keyboard-over-a-full-screen-opengl-es-app -// It's a bit limited but good enough. - --(void) deleteBackward { - KeyInput input{}; - input.deviceId = DEVICE_ID_KEYBOARD; - input.flags = KEY_DOWN | KEY_UP; - input.keyCode = NKCODE_DEL; - NativeKey(input); - INFO_LOG(Log::System, "Backspace"); -} - --(BOOL) hasText -{ - return YES; -} - --(void) insertText:(NSString *)text -{ - std::string str([text UTF8String]); - INFO_LOG(Log::System, "Chars: %s", str.c_str()); - SendKeyboardChars(str); -} - --(BOOL) canBecomeFirstResponder -{ - return YES; -} - --(void) showKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - NSLog(@"becomeFirstResponder"); - [self becomeFirstResponder]; - }); -} - --(void) hideKeyboard { - dispatch_async(dispatch_get_main_queue(), ^{ - [self resignFirstResponder]; - }); -} - - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];