From caad673f06113c0fdf99b6c53e4801582a6c2081 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 29 Jul 2014 00:36:12 -0300 Subject: [PATCH] Added missing autorelease pool blocks in UIKit backend code. Fixes memory leak issues, especially in SDL_video. --- src/joystick/iphoneos/SDL_sysjoystick.m | 36 +++-- src/power/uikit/SDL_syspower.m | 37 ++--- src/video/uikit/SDL_uikitmodes.m | 88 ++++++----- src/video/uikit/SDL_uikitopengles.m | 194 +++++++++++++----------- src/video/uikit/SDL_uikitview.m | 42 ++--- src/video/uikit/SDL_uikitwindow.m | 194 +++++++++++++----------- 6 files changed, 322 insertions(+), 269 deletions(-) diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index 31b4e84b0..c08dec192 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -90,13 +90,15 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) joystick->nballs = 0; joystick->nbuttons = 0; - if (motionManager == nil) { - motionManager = [[CMMotionManager alloc] init]; - } + @autoreleasepool { + if (motionManager == nil) { + motionManager = [[CMMotionManager alloc] init]; + } - /* Shorter times between updates can significantly increase CPU usage. */ - motionManager.accelerometerUpdateInterval = 0.1; - [motionManager startAccelerometerUpdates]; + /* Shorter times between updates can significantly increase CPU usage. */ + motionManager.accelerometerUpdateInterval = 0.1; + [motionManager startAccelerometerUpdates]; + } return 0; } @@ -113,11 +115,13 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick) const SInt16 maxsint16 = 0x7FFF; CMAcceleration accel; - if (!motionManager.accelerometerActive) { - return; - } + @autoreleasepool { + if (!motionManager.accelerometerActive) { + return; + } - accel = [[motionManager accelerometerData] acceleration]; + accel = motionManager.accelerometerData.acceleration; + } /* Convert accelerometer data from floating point to Sint16, which is what @@ -161,7 +165,9 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - [motionManager stopAccelerometerUpdates]; + @autoreleasepool { + [motionManager stopAccelerometerUpdates]; + } joystick->closed = 1; } @@ -169,9 +175,11 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick) void SDL_SYS_JoystickQuit(void) { - if (motionManager != nil) { - [motionManager release]; - motionManager = nil; + @autoreleasepool { + if (motionManager != nil) { + [motionManager release]; + motionManager = nil; + } } numjoysticks = 0; diff --git a/src/power/uikit/SDL_syspower.m b/src/power/uikit/SDL_syspower.m index 60c42745a..4984b78c4 100644 --- a/src/power/uikit/SDL_syspower.m +++ b/src/power/uikit/SDL_syspower.m @@ -50,24 +50,24 @@ SDL_UIKit_UpdateBatteryMonitoring(void) SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent) { - UIDevice *uidev = [UIDevice currentDevice]; + @autoreleasepool { + UIDevice *uidev = [UIDevice currentDevice]; - if (!SDL_UIKitLastPowerInfoQuery) { - SDL_assert([uidev isBatteryMonitoringEnabled] == NO); - [uidev setBatteryMonitoringEnabled:YES]; - } + if (!SDL_UIKitLastPowerInfoQuery) { + SDL_assert(uidev.isBatteryMonitoringEnabled == NO); + uidev.batteryMonitoringEnabled = YES; + } - /* UIKit_GL_SwapWindow() (etc) will check this and disable the battery - * monitoring if the app hasn't queried it in the last X seconds. - * Apparently monitoring the battery burns battery life. :) - * Apple's docs say not to monitor the battery unless you need it. - */ - SDL_UIKitLastPowerInfoQuery = SDL_GetTicks(); + /* UIKit_GL_SwapWindow() (etc) will check this and disable the battery + * monitoring if the app hasn't queried it in the last X seconds. + * Apparently monitoring the battery burns battery life. :) + * Apple's docs say not to monitor the battery unless you need it. + */ + SDL_UIKitLastPowerInfoQuery = SDL_GetTicks(); - *seconds = -1; /* no API to estimate this in UIKit. */ + *seconds = -1; /* no API to estimate this in UIKit. */ - switch ([uidev batteryState]) - { + switch (uidev.batteryState) { case UIDeviceBatteryStateCharging: *state = SDL_POWERSTATE_CHARGING; break; @@ -84,11 +84,12 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent) default: *state = SDL_POWERSTATE_UNKNOWN; break; - } + } - const float level = [uidev batteryLevel]; - *percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) ); - return SDL_TRUE; /* always the definitive answer on iOS. */ + const float level = uidev.batteryLevel; + *percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) ); + return SDL_TRUE; /* always the definitive answer on iOS. */ + } } #endif /* SDL_POWER_UIKIT */ diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 20a433d55..e17e16ae7 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -159,9 +159,11 @@ UIKit_IsDisplayLandscape(UIScreen *uiscreen) int UIKit_InitModes(_THIS) { - for (UIScreen *uiscreen in [UIScreen screens]) { - if (UIKit_AddDisplay(uiscreen) < 0) { - return -1; + @autoreleasepool { + for (UIScreen *uiscreen in [UIScreen screens]) { + if (UIKit_AddDisplay(uiscreen) < 0) { + return -1; + } } } @@ -173,26 +175,28 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) { SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen); - SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]); - CGFloat scale = data->uiscreen.scale; + @autoreleasepool { + SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen); + SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]); + CGFloat scale = data->uiscreen.scale; - for (UIScreenMode *uimode in [data->uiscreen availableModes]) { - /* The size of a UIScreenMode is in pixels, but we deal exclusively in - * points (except in SDL_GL_GetDrawableSize.) */ - CGSize size = [uimode size]; - int w = (int)(size.width / scale); - int h = (int)(size.height / scale); + for (UIScreenMode *uimode in [data->uiscreen availableModes]) { + /* The size of a UIScreenMode is in pixels, but we deal exclusively in + * points (except in SDL_GL_GetDrawableSize.) */ + CGSize size = [uimode size]; + int w = (int)(size.width / scale); + int h = (int)(size.height / scale); - /* Make sure the width/height are oriented correctly */ - if (isLandscape != (w > h)) { - int tmp = w; - w = h; - h = tmp; + /* Make sure the width/height are oriented correctly */ + if (isLandscape != (w > h)) { + int tmp = w; + w = h; + h = tmp; + } + + /* Add the native screen resolution. */ + UIKit_AddDisplayMode(display, w, h, uimode, addRotation); } - - /* Add the native screen resolution. */ - UIKit_AddDisplayMode(display, w, h, uimode, addRotation); } } @@ -202,16 +206,18 @@ UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata; - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + @autoreleasepool { + [data->uiscreen setCurrentMode:modedata->uiscreenmode]; - if (data->uiscreen == [UIScreen mainScreen]) { - if (mode->w > mode->h) { - if (!UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; - } - } else if (mode->w < mode->h) { - if (UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + if (data->uiscreen == [UIScreen mainScreen]) { + if (mode->w > mode->h) { + if (!UIKit_IsDisplayLandscape(data->uiscreen)) { + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + } + } else if (mode->w < mode->h) { + if (UIKit_IsDisplayLandscape(data->uiscreen)) { + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + } } } } @@ -224,19 +230,21 @@ UIKit_QuitModes(_THIS) { /* Release Objective-C objects, so higher level doesn't free() them. */ int i, j; - for (i = 0; i < _this->num_displays; i++) { - SDL_VideoDisplay *display = &_this->displays[i]; + @autoreleasepool { + for (i = 0; i < _this->num_displays; i++) { + SDL_VideoDisplay *display = &_this->displays[i]; - UIKit_FreeDisplayModeData(&display->desktop_mode); - for (j = 0; j < display->num_display_modes; j++) { - SDL_DisplayMode *mode = &display->display_modes[j]; - UIKit_FreeDisplayModeData(mode); + UIKit_FreeDisplayModeData(&display->desktop_mode); + for (j = 0; j < display->num_display_modes; j++) { + SDL_DisplayMode *mode = &display->display_modes[j]; + UIKit_FreeDisplayModeData(mode); + } + + SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; + [data->uiscreen release]; + SDL_free(data); + display->driverdata = NULL; } - - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - [data->uiscreen release]; - SDL_free(data); - display->driverdata = NULL; } } diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 0b4a684ed..f17c83192 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -52,12 +52,14 @@ UIKit_GL_GetProcAddress(_THIS, const char *proc) int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { - if (context) { - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - [data->view setCurrentContext]; - } - else { - [EAGLContext setCurrentContext: nil]; + @autoreleasepool { + if (context) { + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + [data->view setCurrentContext]; + } + else { + [EAGLContext setCurrentContext: nil]; + } } return 0; @@ -67,11 +69,13 @@ void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (w) { - *w = data->view.backingWidth; - } - if (h) { - *h = data->view.backingHeight; + @autoreleasepool { + if (w) { + *w = data->view.backingWidth; + } + if (h) { + *h = data->view.backingHeight; + } } } @@ -92,106 +96,112 @@ UIKit_GL_LoadLibrary(_THIS, const char *path) void UIKit_GL_SwapWindow(_THIS, SDL_Window * window) { + @autoreleasepool { #if SDL_POWER_UIKIT - /* Check once a frame to see if we should turn off the battery monitor. */ - SDL_UIKit_UpdateBatteryMonitoring(); + /* Check once a frame to see if we should turn off the battery monitor. */ + SDL_UIKit_UpdateBatteryMonitoring(); #endif - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (nil == data->view) { - return; + if (nil == data->view) { + return; + } + [data->view swapBuffers]; + + /* You need to pump events in order for the OS to make changes visible. + We don't pump events here because we don't want iOS application events + (low memory, terminate, etc.) to happen inside low level rendering. + */ } - [data->view swapBuffers]; - - /* You need to pump events in order for the OS to make changes visible. - We don't pump events here because we don't want iOS application events - (low memory, terminate, etc.) to happen inside low level rendering. - */ } SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window) { - SDL_uikitopenglview *view; - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - UIWindow *uiwindow = data->uiwindow; - CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen); - EAGLSharegroup *share_group = nil; - CGFloat scale = 1.0; + @autoreleasepool { + SDL_uikitopenglview *view; + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + UIWindow *uiwindow = data->uiwindow; + CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen); + EAGLSharegroup *share_group = nil; + CGFloat scale = 1.0; - if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { - /* Set the scale to the natural scale factor of the screen - the backing - dimensions of the OpenGL view will match the pixel dimensions of the - screen rather than the dimensions in points. - */ - scale = uiwindow.screen.scale; + if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { + /* Set the scale to the natural scale factor of the screen - the backing + dimensions of the OpenGL view will match the pixel dimensions of the + screen rather than the dimensions in points. + */ + scale = uiwindow.screen.scale; + } + + if (_this->gl_config.share_with_current_context) { + SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); + share_group = [view.context sharegroup]; + } + + /* construct our view, passing in SDL's OpenGL configuration data */ + view = [[SDL_uikitopenglview alloc] initWithFrame: frame + scale: scale + retainBacking: _this->gl_config.retained_backing + rBits: _this->gl_config.red_size + gBits: _this->gl_config.green_size + bBits: _this->gl_config.blue_size + aBits: _this->gl_config.alpha_size + depthBits: _this->gl_config.depth_size + stencilBits: _this->gl_config.stencil_size + sRGB: _this->gl_config.framebuffer_srgb_capable + majorVersion: _this->gl_config.major_version + shareGroup: share_group]; + if (!view) { + return NULL; + } + + data->view = view; + view->viewcontroller = data->viewcontroller; + if (view->viewcontroller != nil) { + [view->viewcontroller setView:view]; + [view->viewcontroller retain]; + } + [uiwindow addSubview: view]; + + /* The view controller needs to be the root in order to control rotation on iOS 6.0 */ + if (uiwindow.rootViewController == nil) { + uiwindow.rootViewController = view->viewcontroller; + } + + if (UIKit_GL_MakeCurrent(_this, window, view) < 0) { + UIKit_GL_DeleteContext(_this, view); + return NULL; + } + + /* Make this window the current mouse focus for touch input */ + if (uiwindow.screen == [UIScreen mainScreen]) { + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + } + + return view; } - - if (_this->gl_config.share_with_current_context) { - SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); - share_group = [view.context sharegroup]; - } - - /* construct our view, passing in SDL's OpenGL configuration data */ - view = [[SDL_uikitopenglview alloc] initWithFrame: frame - scale: scale - retainBacking: _this->gl_config.retained_backing - rBits: _this->gl_config.red_size - gBits: _this->gl_config.green_size - bBits: _this->gl_config.blue_size - aBits: _this->gl_config.alpha_size - depthBits: _this->gl_config.depth_size - stencilBits: _this->gl_config.stencil_size - sRGB: _this->gl_config.framebuffer_srgb_capable - majorVersion: _this->gl_config.major_version - shareGroup: share_group]; - if (!view) { - return NULL; - } - - data->view = view; - view->viewcontroller = data->viewcontroller; - if (view->viewcontroller != nil) { - [view->viewcontroller setView:view]; - [view->viewcontroller retain]; - } - [uiwindow addSubview: view]; - - /* The view controller needs to be the root in order to control rotation on iOS 6.0 */ - if (uiwindow.rootViewController == nil) { - uiwindow.rootViewController = view->viewcontroller; - } - - if (UIKit_GL_MakeCurrent(_this, window, view) < 0) { - UIKit_GL_DeleteContext(_this, view); - return NULL; - } - - /* Make this window the current mouse focus for touch input */ - if (uiwindow.screen == [UIScreen mainScreen]) { - SDL_SetMouseFocus(window); - SDL_SetKeyboardFocus(window); - } - - return view; } void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { - /* the delegate has retained the view, this will release him */ - SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; - if (view->viewcontroller) { - UIWindow *uiwindow = (UIWindow *)view.superview; - if (uiwindow.rootViewController == view->viewcontroller) { - uiwindow.rootViewController = nil; + @autoreleasepool { + /* the delegate has retained the view, this will release him */ + SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; + if (view->viewcontroller) { + UIWindow *uiwindow = (UIWindow *)view.superview; + if (uiwindow.rootViewController == view->viewcontroller) { + uiwindow.rootViewController = nil; + } + [view->viewcontroller setView:nil]; + [view->viewcontroller release]; } - [view->viewcontroller setView:nil]; - [view->viewcontroller release]; + [view removeFromSuperview]; + [view release]; } - [view removeFromSuperview]; - [view release]; } #endif /* SDL_VIDEO_DRIVER_UIKIT */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 620ea2864..7267650ac 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -318,28 +318,34 @@ SDL_bool UIKit_HasScreenKeyboardSupport(_THIS) void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) { - SDL_uikitview *view = getWindowView(window); - if (view != nil) { - [view showKeyboard]; + @autoreleasepool { + SDL_uikitview *view = getWindowView(window); + if (view != nil) { + [view showKeyboard]; + } } } void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) { - SDL_uikitview *view = getWindowView(window); - if (view != nil) { - [view hideKeyboard]; + @autoreleasepool { + SDL_uikitview *view = getWindowView(window); + if (view != nil) { + [view hideKeyboard]; + } } } SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) { - SDL_uikitview *view = getWindowView(window); - if (view == nil) { - return 0; - } + @autoreleasepool { + SDL_uikitview *view = getWindowView(window); + if (view == nil) { + return 0; + } - return view.isKeyboardVisible; + return view.isKeyboardVisible; + } } @@ -423,13 +429,15 @@ UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) SDL_InvalidParamError("rect"); return; } - - SDL_uikitview *view = getWindowView(SDL_GetFocusWindow()); - if (view == nil) { - return ; - } - view.textInputRect = *rect; + @autoreleasepool { + SDL_uikitview *view = getWindowView(SDL_GetFocusWindow()); + if (view == nil) { + return; + } + + view.textInputRect = *rect; + } } diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 7e3fac621..aed4a31fd 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -132,84 +132,86 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, int UIKit_CreateWindow(_THIS, SDL_Window *window) { - SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - const BOOL external = ([UIScreen mainScreen] != data->uiscreen); - const CGSize origsize = [[data->uiscreen currentMode] size]; + @autoreleasepool { + SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); + SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; + const BOOL external = ([UIScreen mainScreen] != data->uiscreen); + const CGSize origsize = [[data->uiscreen currentMode] size]; - /* SDL currently puts this window at the start of display's linked list. We rely on this. */ - SDL_assert(_this->windows == window); + /* SDL currently puts this window at the start of display's linked list. We rely on this. */ + SDL_assert(_this->windows == window); - /* We currently only handle a single window per display on iOS */ - if (window->next != NULL) { - return SDL_SetError("Only one window allowed per display."); - } - - /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the - * user, so it's in standby), try to force the display to a resolution - * that most closely matches the desired window size. - */ - if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) { - if (display->num_display_modes == 0) { - _this->GetDisplayModes(_this, display); + /* We currently only handle a single window per display on iOS */ + if (window->next != NULL) { + return SDL_SetError("Only one window allowed per display."); } - int i; - const SDL_DisplayMode *bestmode = NULL; - for (i = display->num_display_modes; i >= 0; i--) { - const SDL_DisplayMode *mode = &display->display_modes[i]; - if ((mode->w >= window->w) && (mode->h >= window->h)) - bestmode = mode; - } - - if (bestmode) { - SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata; - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; - - /* desktop_mode doesn't change here (the higher level will - * use it to set all the screens back to their defaults - * upon window destruction, SDL_Quit(), etc. - */ - display->current_mode = *bestmode; - } - } - - if (data->uiscreen == [UIScreen mainScreen]) { - if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { - [UIApplication sharedApplication].statusBarHidden = YES; - } else { - [UIApplication sharedApplication].statusBarHidden = NO; - } - } - - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - if (window->w > window->h) { - if (!UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the + * user, so it's in standby), try to force the display to a resolution + * that most closely matches the desired window size. + */ + if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) { + if (display->num_display_modes == 0) { + _this->GetDisplayModes(_this, display); } - } else if (window->w < window->h) { - if (UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + + int i; + const SDL_DisplayMode *bestmode = NULL; + for (i = display->num_display_modes; i >= 0; i--) { + const SDL_DisplayMode *mode = &display->display_modes[i]; + if ((mode->w >= window->w) && (mode->h >= window->h)) + bestmode = mode; + } + + if (bestmode) { + SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata; + [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + + /* desktop_mode doesn't change here (the higher level will + * use it to set all the screens back to their defaults + * upon window destruction, SDL_Quit(), etc. + */ + display->current_mode = *bestmode; } } - } - /* ignore the size user requested, and make a fullscreen window */ - /* !!! FIXME: can we have a smaller view? */ - SDL_uikitwindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data->uiscreen.bounds]; + if (data->uiscreen == [UIScreen mainScreen]) { + if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { + [UIApplication sharedApplication].statusBarHidden = YES; + } else { + [UIApplication sharedApplication].statusBarHidden = NO; + } + } - /* put the window on an external display if appropriate. This implicitly - * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the - * main display, where we land by default, as that would eat the - * status bar real estate. - */ - if (external) { - [uiwindow setScreen:data->uiscreen]; - } + if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + if (window->w > window->h) { + if (!UIKit_IsDisplayLandscape(data->uiscreen)) { + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + } + } else if (window->w < window->h) { + if (UIKit_IsDisplayLandscape(data->uiscreen)) { + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + } + } + } - if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { - [uiwindow release]; - return -1; + /* ignore the size user requested, and make a fullscreen window */ + /* !!! FIXME: can we have a smaller view? */ + SDL_uikitwindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data->uiscreen.bounds]; + + /* put the window on an external display if appropriate. This implicitly + * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the + * main display, where we land by default, as that would eat the + * status bar real estate. + */ + if (external) { + [uiwindow setScreen:data->uiscreen]; + } + + if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { + [uiwindow release]; + return -1; + } } return 1; @@ -218,17 +220,21 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) void UIKit_ShowWindow(_THIS, SDL_Window * window) { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + @autoreleasepool { + UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; - [uiwindow makeKeyAndVisible]; + [uiwindow makeKeyAndVisible]; + } } void UIKit_HideWindow(_THIS, SDL_Window * window) { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + @autoreleasepool { + UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; - uiwindow.hidden = YES; + uiwindow.hidden = YES; + } } void @@ -286,13 +292,17 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) { - UIKit_UpdateWindowBorder(_this, window); + @autoreleasepool { + UIKit_UpdateWindowBorder(_this, window); + } } void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { - UIKit_UpdateWindowBorder(_this, window); + @autoreleasepool { + UIKit_UpdateWindowBorder(_this, window); + } } void @@ -300,27 +310,32 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (data) { - [data->viewcontroller release]; - [data->uiwindow release]; - SDL_free(data); + @autoreleasepool { + if (data) { + [data->viewcontroller release]; + [data->uiwindow release]; + SDL_free(data); + } } + window->driverdata = NULL; } SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + @autoreleasepool { + UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; - if (info->version.major <= SDL_MAJOR_VERSION) { - info->subsystem = SDL_SYSWM_UIKIT; - info->info.uikit.window = uiwindow; - return SDL_TRUE; - } else { - SDL_SetError("Application not compiled with SDL %d.%d\n", - SDL_MAJOR_VERSION, SDL_MINOR_VERSION); - return SDL_FALSE; + if (info->version.major <= SDL_MAJOR_VERSION) { + info->subsystem = SDL_SYSWM_UIKIT; + info->info.uikit.window = uiwindow; + return SDL_TRUE; + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return SDL_FALSE; + } } } @@ -333,7 +348,10 @@ SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callbac return SDL_SetError("Invalid window or view not set"); } - [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + @autoreleasepool { + [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + } + return 0; }