Refactored the UIKit mode code into a separate file so it's cleaner and more consistent with other backends
authorSam Lantinga <slouken@libsdl.org>
Sat, 29 Sep 2012 17:23:40 -0700
changeset 6518 42948831d16e
parent 6517 4a4031308518
child 6519 fc926eedd78a
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
src/video/SDL_video.c
src/video/uikit/SDL_uikitmodes.h
src/video/uikit/SDL_uikitmodes.m
src/video/uikit/SDL_uikitopengles.m
src/video/uikit/SDL_uikitvideo.h
src/video/uikit/SDL_uikitvideo.m
src/video/uikit/SDL_uikitview.m
src/video/uikit/SDL_uikitviewcontroller.m
src/video/uikit/SDL_uikitwindow.m
--- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj	Sat Sep 29 17:22:32 2012 -0700
+++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj	Sat Sep 29 17:23:40 2012 -0700
@@ -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 = "<group>"; };
 		93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitviewcontroller.m; sourceTree = "<group>"; };
+		AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmodes.h; sourceTree = "<group>"; };
+		AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmodes.m; sourceTree = "<group>"; };
 		AA628AD9159369E3005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
 		AA628ADA159369E3005138DD /* SDL_rotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = "<group>"; };
 		AA7558651595D55500BBD41B /* begin_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = begin_code.h; sourceTree = "<group>"; };
@@ -837,25 +841,27 @@
 		FD689F090E26E5D900F90B21 /* uikit */ = {
 			isa = PBXGroup;
 			children = (
+				FDC656440E560DF800311C8E /* jumphack.c */,
 				FDC656450E560DF800311C8E /* jumphack.h */,
-				FDC656440E560DF800311C8E /* jumphack.c */,
+				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 */,
+				93CB792213FC5E5200BD3E05 /* SDL_uikitviewcontroller.h */,
+				93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.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 */,
 			);
 			path = uikit;
 			sourceTree = "<group>";
@@ -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;
 		};
--- a/src/video/SDL_video.c	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/SDL_video.c	Sat Sep 29 17:23:40 2012 -0700
@@ -623,8 +623,8 @@
             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;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/uikit/SDL_uikitmodes.h	Sat Sep 29 17:23:40 2012 -0700
@@ -0,0 +1,49 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
+
+  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: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/uikit/SDL_uikitmodes.m	Sat Sep 29 17:23:40 2012 -0700
@@ -0,0 +1,282 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
+
+  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: */
--- a/src/video/uikit/SDL_uikitopengles.m	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitopengles.m	Sat Sep 29 17:23:40 2012 -0700
@@ -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"
--- a/src/video/uikit/SDL_uikitvideo.h	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitvideo.h	Sat Sep 29 17:23:40 2012 -0700
@@ -23,23 +23,7 @@
 
 #include <UIKit/UIKit.h>
 
-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 */
 
--- a/src/video/uikit/SDL_uikitvideo.m	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitvideo.m	Sat Sep 29 17:23:40 2012 -0700
@@ -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 @@
 };
 
 
-/*
-!!! 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 */
--- a/src/video/uikit/SDL_uikitview.m	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitview.m	Sat Sep 29 17:23:40 2012 -0700
@@ -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
--- a/src/video/uikit/SDL_uikitviewcontroller.m	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitviewcontroller.m	Sat Sep 29 17:23:40 2012 -0700
@@ -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
--- a/src/video/uikit/SDL_uikitwindow.m	Sat Sep 29 17:22:32 2012 -0700
+++ b/src/video/uikit/SDL_uikitwindow.m	Sat Sep 29 17:23:40 2012 -0700
@@ -33,6 +33,7 @@
 
 #include "SDL_uikitvideo.h"
 #include "SDL_uikitevents.h"
+#include "SDL_uikitmodes.h"
 #include "SDL_uikitwindow.h"
 #import "SDL_uikitappdelegate.h"