From 2fd54417635699c2f8fe329da743cb902edbe6e1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 29 Sep 2012 17:23:40 -0700 Subject: [PATCH] Refactored the UIKit mode code into a separate file so it's cleaner and more consistent with other backends --- Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj | 24 +- src/video/SDL_video.c | 4 +- src/video/uikit/SDL_uikitmodes.h | 49 ++++ src/video/uikit/SDL_uikitmodes.m | 282 ++++++++++++++++++++ src/video/uikit/SDL_uikitopengles.m | 1 + src/video/uikit/SDL_uikitvideo.h | 18 +- src/video/uikit/SDL_uikitvideo.m | 265 +----------------- src/video/uikit/SDL_uikitview.m | 9 +- src/video/uikit/SDL_uikitviewcontroller.m | 4 +- src/video/uikit/SDL_uikitwindow.m | 1 + 10 files changed, 363 insertions(+), 294 deletions(-) create mode 100644 src/video/uikit/SDL_uikitmodes.h create mode 100644 src/video/uikit/SDL_uikitmodes.m diff --git a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj index 311c7b1a0..35b2ba574 100755 --- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj @@ -98,6 +98,8 @@ 56ED04E3118A8EFD00A56AA6 /* SDL_syspower.m in Sources */ = {isa = PBXBuildFile; fileRef = 56ED04E2118A8EFD00A56AA6 /* SDL_syspower.m */; }; 93CB792313FC5E5200BD3E05 /* SDL_uikitviewcontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = 93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */; }; 93CB792613FC5F5300BD3E05 /* SDL_uikitviewcontroller.m in Sources */ = {isa = PBXBuildFile; fileRef = 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */; }; + AA126AD41617C5E7005ABC8F /* SDL_uikitmodes.h in Headers */ = {isa = PBXBuildFile; fileRef = AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */; }; + AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */ = {isa = PBXBuildFile; fileRef = AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */; }; AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AD9159369E3005138DD /* SDL_rotate.c */; }; AA628ADC159369E3005138DD /* SDL_rotate.h in Headers */ = {isa = PBXBuildFile; fileRef = AA628ADA159369E3005138DD /* SDL_rotate.h */; }; AA7558981595D55500BBD41B /* begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7558651595D55500BBD41B /* begin_code.h */; }; @@ -349,6 +351,8 @@ 56ED04E2118A8EFD00A56AA6 /* SDL_syspower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDL_syspower.m; path = ../../src/power/uikit/SDL_syspower.m; sourceTree = SOURCE_ROOT; }; 93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitviewcontroller.h; sourceTree = ""; }; 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitviewcontroller.m; sourceTree = ""; }; + AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmodes.h; sourceTree = ""; }; + AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmodes.m; sourceTree = ""; }; AA628AD9159369E3005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = ""; }; AA628ADA159369E3005138DD /* SDL_rotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = ""; }; AA7558651595D55500BBD41B /* begin_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = begin_code.h; sourceTree = ""; }; @@ -837,25 +841,27 @@ FD689F090E26E5D900F90B21 /* uikit */ = { isa = PBXGroup; children = ( - FDC656450E560DF800311C8E /* jumphack.h */, FDC656440E560DF800311C8E /* jumphack.c */, + FDC656450E560DF800311C8E /* jumphack.h */, + FDC261780E3A3FC8001C4554 /* keyinfotable.h */, + FD689FCD0E26E9D400F90B21 /* SDL_uikitappdelegate.h */, + FD689FCC0E26E9D400F90B21 /* SDL_uikitappdelegate.m */, FD689F0C0E26E5D900F90B21 /* SDL_uikitevents.h */, FD689F0D0E26E5D900F90B21 /* SDL_uikitevents.m */, + AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */, + AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */, FD689F0E0E26E5D900F90B21 /* SDL_uikitopengles.h */, FD689F0F0E26E5D900F90B21 /* SDL_uikitopengles.m */, + FD689F160E26E5D900F90B21 /* SDL_uikitopenglview.h */, + FD689F170E26E5D900F90B21 /* SDL_uikitopenglview.m */, FD689F100E26E5D900F90B21 /* SDL_uikitvideo.h */, FD689F110E26E5D900F90B21 /* SDL_uikitvideo.m */, - FDC261780E3A3FC8001C4554 /* keyinfotable.h */, FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */, FD689F130E26E5D900F90B21 /* SDL_uikitview.m */, - FD689F140E26E5D900F90B21 /* SDL_uikitwindow.h */, - FD689F150E26E5D900F90B21 /* SDL_uikitwindow.m */, - FD689F160E26E5D900F90B21 /* SDL_uikitopenglview.h */, - FD689F170E26E5D900F90B21 /* SDL_uikitopenglview.m */, - FD689FCD0E26E9D400F90B21 /* SDL_uikitappdelegate.h */, - FD689FCC0E26E9D400F90B21 /* SDL_uikitappdelegate.m */, 93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */, 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */, + FD689F140E26E5D900F90B21 /* SDL_uikitwindow.h */, + FD689F150E26E5D900F90B21 /* SDL_uikitwindow.m */, ); path = uikit; sourceTree = ""; @@ -1234,6 +1240,7 @@ AA7558C81595D55500BBD41B /* SDL_version.h in Headers */, AA7558C91595D55500BBD41B /* SDL_video.h in Headers */, AA7558CA1595D55500BBD41B /* SDL.h in Headers */, + AA126AD41617C5E7005ABC8F /* SDL_uikitmodes.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1450,6 +1457,7 @@ 56EA86FB13E9EC2B002E47EB /* SDL_coreaudio.c in Sources */, 93CB792613FC5F5300BD3E05 /* SDL_uikitviewcontroller.m in Sources */, AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */, + AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index da083c920..1fc8db497 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -623,8 +623,8 @@ SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect) SDL_GetDisplayBounds(displayIndex-1, rect); rect->x += rect->w; } - rect->w = display->desktop_mode.w; - rect->h = display->desktop_mode.h; + rect->w = display->current_mode.w; + rect->h = display->current_mode.h; } return 0; } diff --git a/src/video/uikit/SDL_uikitmodes.h b/src/video/uikit/SDL_uikitmodes.h new file mode 100644 index 000000000..f65be0944 --- /dev/null +++ b/src/video/uikit/SDL_uikitmodes.h @@ -0,0 +1,49 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#ifndef _SDL_uikitmodes_h +#define _SDL_uikitmodes_h + +#include "SDL_uikitvideo.h" + +typedef struct +{ + UIScreen *uiscreen; + CGFloat scale; +} SDL_DisplayData; + +typedef struct +{ + UIScreenMode *uiscreenmode; + CGFloat scale; +} SDL_DisplayModeData; + +extern BOOL SDL_UIKit_supports_multiple_displays; + +extern int UIKit_InitModes(_THIS); +extern void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +extern int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +extern void UIKit_QuitModes(_THIS); + +#endif /* _SDL_uikitmodes_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m new file mode 100644 index 000000000..aba5006d1 --- /dev/null +++ b/src/video/uikit/SDL_uikitmodes.m @@ -0,0 +1,282 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +#include "SDL_assert.h" +#include "SDL_uikitmodes.h" + + +BOOL SDL_UIKit_supports_multiple_displays = NO; + + +static int +UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode, + UIScreenMode * uiscreenmode, CGFloat scale) +{ + SDL_DisplayModeData *data = NULL; + + if (uiscreenmode != nil) { + /* Allocate the display mode data */ + data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data)); + if (!data) { + SDL_OutOfMemory(); + return -1; + } + + data->uiscreenmode = uiscreenmode; + [data->uiscreenmode retain]; + + data->scale = scale; + } + + mode->driverdata = data; + + return 0; +} + +static void +UIKit_FreeDisplayModeData(SDL_DisplayMode * mode) +{ + if (!SDL_UIKit_supports_multiple_displays) { + // Not on at least iPhoneOS 3.2 (versions prior to iPad). + SDL_assert(mode->driverdata == NULL); + } else if (mode->driverdata != NULL) { + SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata; + [data->uiscreenmode release]; + SDL_free(data); + mode->driverdata = NULL; + } +} + +static int +UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h, + UIScreenMode * uiscreenmode, CGFloat scale) +{ + SDL_DisplayMode mode; + SDL_zero(mode); + + mode.format = SDL_PIXELFORMAT_ABGR8888; + mode.refresh_rate = 0; + if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { + return -1; + } + + mode.w = w; + mode.h = h; + if (SDL_AddDisplayMode(display, &mode)) { + return 0; + } else { + UIKit_FreeDisplayModeData(&mode); + return -1; + } +} + +static int +UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale, + UIScreenMode * uiscreenmode, BOOL addRotated) +{ + if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) { + return -1; + } + + if (addRotated) { + // Add the rotated version + if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) { + return -1; + } + } + + return 0; +} + +static int +UIKit_AddDisplay(UIScreen *uiscreen) +{ + CGSize size = [uiscreen bounds].size; + + // When dealing with UIKit all coordinates are specified in terms of + // what Apple refers to as points. On earlier devices without the + // so called "Retina" display, there is a one to one mapping between + // points and pixels. In other cases [UIScreen scale] indicates the + // relationship between points and pixels. Since SDL has no notion + // of points, we must compensate in all cases where dealing with such + // units. + CGFloat scale; + if ([UIScreen instancesRespondToSelector:@selector(scale)]) { + scale = [uiscreen scale]; // iOS >= 4.0 + } else { + scale = 1.0f; // iOS < 4.0 + } + + SDL_VideoDisplay display; + SDL_DisplayMode mode; + SDL_zero(mode); + mode.format = SDL_PIXELFORMAT_ABGR8888; + mode.w = (int)(size.width * scale); + mode.h = (int)(size.height * scale); + + UIScreenMode * uiscreenmode = nil; + // UIScreenMode showed up in 3.2 (the iPad and later). We're + // misusing this supports_multiple_displays flag here for that. + if (SDL_UIKit_supports_multiple_displays) { + uiscreenmode = [uiscreen currentMode]; + } + + if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { + return -1; + } + + SDL_zero(display); + display.desktop_mode = mode; + display.current_mode = mode; + + /* Allocate the display data */ + SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data)); + if (!data) { + SDL_OutOfMemory(); + UIKit_FreeDisplayModeData(&display.desktop_mode); + return -1; + } + + [uiscreen retain]; + data->uiscreen = uiscreen; + data->scale = scale; + + display.driverdata = data; + SDL_AddVideoDisplay(&display); + + return 0; +} + + +int +UIKit_InitModes(_THIS) +{ + // this tells us whether we are running on ios >= 3.2 + SDL_UIKit_supports_multiple_displays = [UIScreen instancesRespondToSelector:@selector(currentMode)]; + + // Add the main screen. + if (UIKit_AddDisplay([UIScreen mainScreen]) < 0) { + return -1; + } + + // If this is iPhoneOS < 3.2, all devices are one screen, 320x480 pixels. + // The iPad added both a larger main screen and the ability to use + // external displays. So, add the other displays (screens in UI speak). + if (SDL_UIKit_supports_multiple_displays) { + for (UIScreen *uiscreen in [UIScreen screens]) { + // Only add the other screens + if (uiscreen != [UIScreen mainScreen]) { + if (UIKit_AddDisplay(uiscreen) < 0) { + return -1; + } + } + } + } + + /* We're done! */ + return 0; +} + +void +UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; + + if (SDL_UIKit_supports_multiple_displays) { + // availableModes showed up in 3.2 (the iPad and later). We should only + // land here for at least that version of the OS. + for (UIScreenMode *uimode in [data->uiscreen availableModes]) { + CGSize size = [uimode size]; + int w = (int)size.width; + int h = (int)size.height; + BOOL addRotated = (data->uiscreen == [UIScreen mainScreen]); + + // Add the native screen resolution. + UIKit_AddDisplayMode(display, w, h, data->scale, uimode, addRotated); + + if (data->scale != 1.0f) { + // Add the native screen resolution divided by its scale. + // This is so devices capable of e.g. 640x960 also advertise + // 320x480. + UIKit_AddDisplayMode(display, + (int)(size.width / data->scale), + (int)(size.height / data->scale), + 1.0f, uimode, addRotated); + } + } + } else { + const CGRect rect = [data->uiscreen bounds]; + UIKit_AddDisplayMode(display, + (int)rect.size.width, (int)rect.size.height, + 1.0f, nil, YES); + } +} + +int +UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; + if (!SDL_UIKit_supports_multiple_displays) { + // Not on at least iPhoneOS 3.2 (versions prior to iPad). + SDL_assert(mode->driverdata == NULL); + } else { + SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata; + [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + + if (mode->w > mode->h) { + if (!UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + } else if (mode->w < mode->h) { + if (!UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + } + } + + return 0; +} + +void +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]; + + 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; + } +} + +#endif /* SDL_VIDEO_DRIVER_UIKIT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index a65407b49..d4a2aef9b 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -25,6 +25,7 @@ #include "SDL_uikitopengles.h" #include "SDL_uikitopenglview.h" #include "SDL_uikitappdelegate.h" +#include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" #include "jumphack.h" #include "../SDL_sysvideo.h" diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h index 4f2cea35c..8218af1cf 100644 --- a/src/video/uikit/SDL_uikitvideo.h +++ b/src/video/uikit/SDL_uikitvideo.h @@ -23,23 +23,7 @@ #include -extern BOOL SDL_UIKit_supports_multiple_displays; - -typedef struct SDL_DisplayData SDL_DisplayData; - -struct SDL_DisplayData -{ - UIScreen *uiscreen; - CGFloat scale; -}; - -typedef struct SDL_DisplayModeData SDL_DisplayModeData; - -struct SDL_DisplayModeData -{ - UIScreenMode *uiscreenmode; - CGFloat scale; -}; +#include "../SDL_sysvideo.h" #endif /* _SDL_uikitvideo_h */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 6e95dd715..06b410cd9 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -32,22 +32,16 @@ #include "SDL_uikitvideo.h" #include "SDL_uikitevents.h" +#include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" #include "SDL_uikitopengles.h" -#include "SDL_assert.h" - #define UIKITVID_DRIVER_NAME "uikit" /* Initialization/Query functions */ static int UIKit_VideoInit(_THIS); -static void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display); -static int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, - SDL_DisplayMode * mode); static void UIKit_VideoQuit(_THIS); -BOOL SDL_UIKit_supports_multiple_displays = NO; - /* DUMMY driver bootstrap functions */ static int @@ -118,274 +112,21 @@ static void UIKit_DeleteDevice(SDL_VideoDevice * device) }; -/* -!!! FIXME: - -The main screen should list a AxB mode for portrait orientation, and then - also list BxA for landscape mode. When setting a given resolution, we should - rotate the view's transform appropriately (extra credit if you check the - accelerometer and rotate the display so it's never upside down). - - http://iphonedevelopment.blogspot.com/2008/10/starting-in-landscape-mode-without.html - -*/ - -static int -UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode, - UIScreenMode * uiscreenmode, CGFloat scale) -{ - SDL_DisplayModeData *data = NULL; - - if (uiscreenmode != nil) { - /* Allocate the display mode data */ - data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data)); - if (!data) { - SDL_OutOfMemory(); - return -1; - } - - data->uiscreenmode = uiscreenmode; - [data->uiscreenmode retain]; - - data->scale = scale; - } - - mode->driverdata = data; - - return 0; -} - -static void -UIKit_FreeDisplayModeData(SDL_DisplayMode * mode) -{ - if (!SDL_UIKit_supports_multiple_displays) { - // Not on at least iPhoneOS 3.2 (versions prior to iPad). - SDL_assert(mode->driverdata == NULL); - } else if (mode->driverdata != NULL) { - SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata; - [data->uiscreenmode release]; - SDL_free(data); - mode->driverdata = NULL; - } -} - -static int -UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h, - UIScreenMode * uiscreenmode, CGFloat scale) -{ - SDL_DisplayMode mode; - SDL_zero(mode); - - mode.format = SDL_PIXELFORMAT_ABGR8888; - mode.refresh_rate = 0; - if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { - return -1; - } - - mode.w = w; - mode.h = h; - if (SDL_AddDisplayMode(display, &mode)) { - return 0; - } - - // Failure case; free resources - SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode.driverdata; - - if (data != NULL) { - [data->uiscreenmode release]; - SDL_free(data); - } - - return -1; -} - -static int -UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale, - UIScreenMode * uiscreenmode, BOOL rotated) -{ - if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) { - return -1; - } - - if (rotated) { - // Add the rotated version - if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) { - return -1; - } - } - - return 0; -} - -static void -UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) -{ - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - - if (SDL_UIKit_supports_multiple_displays) { - // availableModes showed up in 3.2 (the iPad and later). We should only - // land here for at least that version of the OS. - for (UIScreenMode *uimode in [data->uiscreen availableModes]) { - BOOL mainscreen = (data->uiscreen == [UIScreen mainScreen]); - CGSize size = [uimode size]; - int w = (int)size.width; - int h = (int)size.height; - - // Add the native screen resolution. - UIKit_AddDisplayMode(display, w, h, data->scale, uimode, mainscreen); - - if (data->scale != 1.0f) { - // Add the native screen resolution divided by its scale. - // This is so devices capable of e.g. 640x960 also advertise - // 320x480. - UIKit_AddDisplayMode(display, - (int)(w / data->scale), (int)(h / data->scale), - 1.0f, uimode, mainscreen); - } - } - } else { - const CGRect rect = [data->uiscreen bounds]; - UIKit_AddDisplayMode(display, - (int)rect.size.width, (int)rect.size.height, - 1.0f, nil, YES); - } -} - - -static int -UIKit_AddDisplay(UIScreen *uiscreen, CGSize size) -{ - // When dealing with UIKit all coordinates are specified in terms of - // what Apple refers to as points. On earlier devices without the - // so called "Retina" display, there is a one to one mapping between - // points and pixels. In other cases [UIScreen scale] indicates the - // relationship between points and pixels. Since SDL has no notion - // of points, we must compensate in all cases where dealing with such - // units. - CGFloat scale; - if ([UIScreen instancesRespondToSelector:@selector(scale)]) { - scale = [uiscreen scale]; // iOS >= 4.0 - } else { - scale = 1.0f; // iOS < 4.0 - } - - SDL_VideoDisplay display; - SDL_DisplayMode mode; - SDL_zero(mode); - mode.format = SDL_PIXELFORMAT_ABGR8888; - mode.w = (int)(size.width * scale); - mode.h = (int)(size.height * scale); - mode.refresh_rate = 0; - - UIScreenMode * uiscreenmode = nil; - // UIScreenMode showed up in 3.2 (the iPad and later). We're - // misusing this supports_multiple_displays flag here for that. - if (SDL_UIKit_supports_multiple_displays) { - uiscreenmode = [uiscreen currentMode]; - } - - if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { - return -1; - } - - SDL_zero(display); - display.desktop_mode = mode; - display.current_mode = mode; - - /* Allocate the display data */ - SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data)); - if (!data) { - SDL_OutOfMemory(); - UIKit_FreeDisplayModeData(&display.desktop_mode); - return -1; - } - - [uiscreen retain]; - data->uiscreen = uiscreen; - data->scale = scale; - - display.driverdata = data; - SDL_AddVideoDisplay(&display); - - return 0; -} - - int UIKit_VideoInit(_THIS) { _this->gl_config.driver_loaded = 1; - // this tells us whether we are running on ios >= 3.2 - SDL_UIKit_supports_multiple_displays = [UIScreen instancesRespondToSelector:@selector(currentMode)]; - - // Add the main screen. - UIScreen *uiscreen = [UIScreen mainScreen]; - CGSize size = [uiscreen bounds].size; - - if (UIKit_AddDisplay(uiscreen, size) < 0) { + if (UIKit_InitModes(_this) < 0) { return -1; } - - // If this is iPhoneOS < 3.2, all devices are one screen, 320x480 pixels. - // The iPad added both a larger main screen and the ability to use - // external displays. So, add the other displays (screens in UI speak). - if (SDL_UIKit_supports_multiple_displays) { - for (UIScreen *uiscreen in [UIScreen screens]) { - // Only add the other screens - if (uiscreen != [UIScreen mainScreen]) { - size = [uiscreen bounds].size; - if (UIKit_AddDisplay(uiscreen, size) < 0) { - return -1; - } - } - } - } - - /* We're done! */ - return 0; -} - -static int -UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) -{ - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - if (!SDL_UIKit_supports_multiple_displays) { - // Not on at least iPhoneOS 3.2 (versions prior to iPad). - SDL_assert(mode->driverdata == NULL); - } else { - SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata; - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; - - if (mode->w > mode->h) { - if (!UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; - } else if (mode->w < mode->h) { - if (!UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; - } - } - return 0; } void UIKit_VideoQuit(_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]; - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - [data->uiscreen release]; - SDL_free(data); - display->driverdata = NULL; - 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_QuitModes(_this); } #endif /* SDL_VIDEO_DRIVER_UIKIT */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 82dde8600..314699487 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -22,16 +22,17 @@ #if SDL_VIDEO_DRIVER_UIKIT -#import "SDL_uikitview.h" +#include "SDL_uikitview.h" #include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_touch_c.h" #if SDL_IPHONE_KEYBOARD -#import "keyinfotable.h" -#import "SDL_uikitappdelegate.h" -#import "SDL_uikitwindow.h" +#include "keyinfotable.h" +#include "SDL_uikitappdelegate.h" +#include "SDL_uikitmodes.h" +#include "SDL_uikitwindow.h" #endif @implementation SDL_uikitview diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index fc51c6ab4..7f49563eb 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -28,9 +28,11 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_events_c.h" -#include "SDL_uikitwindow.h" #include "SDL_uikitviewcontroller.h" #include "SDL_uikitvideo.h" +#include "SDL_uikitmodes.h" +#include "SDL_uikitwindow.h" + #ifndef __IPHONE_6_0 // This enum isn't available in older SDKs, but we use it for our own purposes on iOS 5.1 and for the system on iOS 6.0 diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 9157f8070..a66f915e9 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -33,6 +33,7 @@ #include "SDL_uikitvideo.h" #include "SDL_uikitevents.h" +#include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" #import "SDL_uikitappdelegate.h"