Browse Source

Merged default into iOS-improvements

Alex Szpakowski 10 years ago
parent
commit
3071128deb

+ 3 - 0
.hgignore

@@ -8,6 +8,9 @@ Makefile
 sdl-config
 SDL2.spec
 build
+Build
+*xcuserdata*
+*xcworkspacedata*
 
 # for Xcode
 *.orig

+ 12 - 0
Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj

@@ -1274,8 +1274,14 @@
 		FD6526640DE8FCCB002AD96B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				COPY_PHASE_STRIP = NO;
 				IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
+				GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				PRODUCT_NAME = SDL2;
 				SKIP_INSTALL = YES;
 			};
@@ -1284,8 +1290,14 @@
 		FD6526650DE8FCCB002AD96B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				COPY_PHASE_STRIP = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
+				GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				PRODUCT_NAME = SDL2;
 				SKIP_INSTALL = YES;
 			};

+ 4 - 3
include/SDL_hints.h

@@ -261,8 +261,9 @@ extern "C" {
 #define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
     
 /**
- *  \brief  A variable controlling whether an Android built-in accelerometer should be
- *  listed as a joystick device, rather than listing actual joysticks only.
+ *  \brief  A variable controlling whether the Android / iOS built-in
+ *  accelerometer should be listed as a joystick device, rather than listing
+ *  actual joysticks only.
  *
  *  This variable can be set to the following values:
  *    "0"       - List only real joysticks and accept input from them
@@ -345,7 +346,7 @@ extern "C" {
 
 
 /**
- *  \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac)
+ *  \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS)
  */
 #define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
 

+ 10 - 0
include/SDL_system.h

@@ -70,6 +70,16 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *a
 extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
 extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
 
+/* Returns the OpenGL Renderbuffer Object associated with the window's main view.
+   The Renderbuffer must be bound when calling SDL_GL_SwapWindow.
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_iPhoneGetViewRenderbuffer(SDL_Window * window);
+
+/* Returns the OpenGL Framebuffer Object associated with the window's main view.
+   The Framebuffer must be bound when rendering to the screen.
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_iPhoneGetViewFramebuffer(SDL_Window * window);
+
 #endif /* __IPHONEOS__ */
 
 

+ 2 - 3
src/file/cocoa/SDL_rwopsbundlesupport.m

@@ -50,14 +50,13 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
     NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
     if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
         fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
-    }
-    else {
+    } else {
         fp = fopen(file, mode);
     }
 
     return fp;
 }}
 
-#endif /* __MACOSX__ */
+#endif /* __APPLE__ */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 4 - 1
src/filesystem/cocoa/SDL_sysfilesystem.m

@@ -41,6 +41,7 @@ SDL_GetBasePath(void)
     const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
     const char *base = NULL;
     char *retval = NULL;
+
     if (baseType == NULL) {
         baseType = "resource";
     }
@@ -52,6 +53,7 @@ SDL_GetBasePath(void)
         /* this returns the exedir for non-bundled  and the resourceDir for bundled apps */
         base = [[bundle resourcePath] fileSystemRepresentation];
     }
+
     if (base) {
         const size_t len = SDL_strlen(base) + 2;
         retval = (char *) SDL_malloc(len);
@@ -69,9 +71,10 @@ char *
 SDL_GetPrefPath(const char *org, const char *app)
 { @autoreleasepool
 {
-    NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
     char *retval = NULL;
 
+    NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+
     if ([array count] > 0) {  /* we only want the first item in the list. */
         NSString *str = [array objectAtIndex:0];
         const char *base = [str fileSystemRepresentation];

+ 31 - 16
src/joystick/iphoneos/SDL_sysjoystick.m

@@ -23,6 +23,7 @@
 /* This is the iOS implementation of the SDL joystick API */
 
 #include "SDL_joystick.h"
+#include "SDL_hints.h"
 #include "SDL_stdinc.h"
 #include "../SDL_sysjoystick.h"
 #include "../SDL_joystick_c.h"
@@ -32,9 +33,10 @@
 /* needed for SDL_IPHONE_MAX_GFORCE macro */
 #import "SDL_config_iphoneos.h"
 
-const char *accelerometerName = "iOS accelerometer";
+const char *accelerometerName = "iOS Accelerometer";
 
 static CMMotionManager *motionManager = nil;
+static int numjoysticks = 0;
 
 /* Function to scan the system for joysticks.
  * This function should set SDL_numjoysticks to the number of available
@@ -44,12 +46,18 @@ static CMMotionManager *motionManager = nil;
 int
 SDL_SYS_JoystickInit(void)
 {
-    return (1);
+    const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
+    if (!hint || SDL_atoi(hint)) {
+        /* Default behavior, accelerometer as joystick */
+        numjoysticks = 1;
+    }
+
+    return numjoysticks;
 }
 
 int SDL_SYS_NumJoysticks()
 {
-    return 1;
+    return numjoysticks;
 }
 
 void SDL_SYS_JoystickDetect()
@@ -82,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;
 }
@@ -105,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
@@ -153,7 +165,9 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
 void
 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 {
-    [motionManager stopAccelerometerUpdates];
+    @autoreleasepool {
+        [motionManager stopAccelerometerUpdates];
+    }
     joystick->closed = 1;
 }
 
@@ -161,10 +175,11 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 void
 SDL_SYS_JoystickQuit(void)
 {
-    if (motionManager != nil) {
-        [motionManager release];
+    @autoreleasepool {
         motionManager = nil;
     }
+
+    numjoysticks = 0;
 }
 
 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )

+ 19 - 18
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 */

+ 63 - 34
src/video/uikit/SDL_uikitappdelegate.m

@@ -44,7 +44,6 @@ static UIWindow *launch_window;
 int main(int argc, char **argv)
 {
     int i;
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
     /* store arguments */
     forward_argc = argc;
@@ -56,7 +55,9 @@ int main(int argc, char **argv)
     forward_argv[i] = NULL;
 
     /* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
-    UIApplicationMain(argc, argv, NULL, [SDLUIKitDelegate getAppDelegateClassName]);
+    @autoreleasepool {
+        UIApplicationMain(argc, argv, nil, [SDLUIKitDelegate getAppDelegateClassName]);
+    }
 
     /* free the memory we used to hold copies of argc and argv */
     for (i = 0; i < forward_argc; i++) {
@@ -64,7 +65,6 @@ int main(int argc, char **argv)
     }
     free(forward_argv);
 
-    [pool release];
     return exit_status;
 }
 
@@ -75,16 +75,17 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
     [UIApplication sharedApplication].idleTimerDisabled = disable;
 }
 
-@interface SDL_splashviewcontroller : UIViewController {
-    UIImageView *splash;
-    UIImage *splashPortrait;
-    UIImage *splashLandscape;
-}
+@interface SDL_splashviewcontroller : UIViewController
 
 - (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation;
+
 @end
 
-@implementation SDL_splashviewcontroller
+@implementation SDL_splashviewcontroller {
+    UIImageView *splash;
+    UIImage *splashPortrait;
+    UIImage *splashLandscape;
+}
 
 - (id)init
 {
@@ -93,26 +94,20 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
         return nil;
     }
 
-    self->splash = [[UIImageView alloc] init];
-    [self setView:self->splash];
+    splash = [[UIImageView alloc] init];
+    self.view = splash;
 
     CGSize size = [UIScreen mainScreen].bounds.size;
     float height = SDL_max(size.width, size.height);
-    self->splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]];
-    if (!self->splashPortrait) {
-        self->splashPortrait = [UIImage imageNamed:@"Default.png"];
-    }
-    self->splashLandscape = [UIImage imageNamed:@"Default-Landscape.png"];
-    if (!self->splashLandscape && self->splashPortrait) {
-        self->splashLandscape = [[UIImage alloc] initWithCGImage: self->splashPortrait.CGImage
-                                                           scale: 1.0
-                                                     orientation: UIImageOrientationRight];
-    }
-    if (self->splashPortrait) {
-        [self->splashPortrait retain];
+    splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]];
+    if (!splashPortrait) {
+        splashPortrait = [UIImage imageNamed:@"Default.png"];
     }
-    if (self->splashLandscape) {
-        [self->splashLandscape retain];
+    splashLandscape = [UIImage imageNamed:@"Default-Landscape.png"];
+    if (!splashLandscape && splashPortrait) {
+        splashLandscape = [[UIImage alloc] initWithCGImage: splashPortrait.CGImage
+                                                     scale: 1.0
+                                               orientation: UIImageOrientationRight];
     }
 
     [self updateSplashImage:[[UIApplication sharedApplication] statusBarOrientation]];
@@ -147,12 +142,12 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
     UIImage *image;
 
     if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
-        image = self->splashLandscape;
+        image = splashLandscape;
     } else {
-        image = self->splashPortrait;
+        image = splashPortrait;
     }
-    if (image)
-    {
+
+    if (image) {
         splash.image = image;
     }
 }
@@ -165,7 +160,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
 /* convenience method */
 + (id) sharedAppDelegate
 {
-    /* the delegate is set in UIApplicationMain(), which is garaunteed to be called before this method */
+    /* the delegate is set in UIApplicationMain(), which is guaranteed to be called before this method */
     return [[UIApplication sharedApplication] delegate];
 }
 
@@ -191,8 +186,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
 
     /* If we showed a splash image, clean it up */
     if (launch_window) {
-        [launch_window release];
-        launch_window = NULL;
+        launch_window = nil;
     }
 
     /* exit, passing the return status from the user's application */
@@ -205,12 +199,18 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
     /* Keep the launch image up until we set a video mode */
-    launch_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+
+    /* This is disabled temporarily because the splash viewcontroller is
+     * interfering with rotation once a regular window is created: the view's
+     * orientations are incorrect and the status bar rotates without the view.
+     * Additionally, the splash viewcontroller doesn't load the correct launch
+     * images on iOS 7 and modern devices. */
+    /*launch_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 
     UIViewController *splashViewController = [[SDL_splashviewcontroller alloc] init];
     launch_window.rootViewController = splashViewController;
     [launch_window addSubview:splashViewController.view];
-    [launch_window makeKeyAndVisible];
+    [launch_window makeKeyAndVisible];*/
 
     /* Set working directory to resource path */
     [[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]];
@@ -235,6 +235,35 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
     SDL_SendAppEvent(SDL_APP_LOWMEMORY);
 }
 
+- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
+{
+    BOOL isLandscape = UIInterfaceOrientationIsLandscape(application.statusBarOrientation);
+    SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+    if (_this && _this->num_displays > 0) {
+        SDL_DisplayMode *desktopmode = &_this->displays[0].desktop_mode;
+        SDL_DisplayMode *currentmode = &_this->displays[0].current_mode;
+
+        /* The desktop display mode should be kept in sync with the screen
+         * orientation so that updating a window's fullscreen state to
+         * SDL_WINDOW_FULLSCREEN_DESKTOP keeps the window dimensions in the
+         * correct orientation.
+         */
+        if (isLandscape != (desktopmode->w > desktopmode->h)) {
+            int height = desktopmode->w;
+            desktopmode->w = desktopmode->h;
+            desktopmode->h = height;
+        }
+
+        /* Same deal with the current mode + SDL_GetCurrentDisplayMode. */
+        if (isLandscape != (currentmode->w > currentmode->h)) {
+            int height = currentmode->w;
+            currentmode->w = currentmode->h;
+            currentmode->h = height;
+        }
+    }
+}
+
 - (void) applicationWillResignActive:(UIApplication*)application
 {
     SDL_VideoDevice *_this = SDL_GetVideoDevice();

+ 2 - 1
src/video/uikit/SDL_uikitevents.m

@@ -40,8 +40,9 @@ SDL_iPhoneSetEventPump(SDL_bool enabled)
 void
 UIKit_PumpEvents(_THIS)
 {
-    if (!UIKit_EventPumpEnabled)
+    if (!UIKit_EventPumpEnabled) {
         return;
+    }
 
     /* Let the run loop run for a short amount of time: long enough for
        touch events to get processed (which is important to get certain

+ 32 - 34
src/video/uikit/SDL_uikitmessagebox.m

@@ -30,17 +30,16 @@
 
 static SDL_bool s_showingMessageBox = SDL_FALSE;
 
-@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate> {
-@private
-    int *clickedButtonIndex;
-}
+@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate>
 
-- (id)initWithButtonIndex:(int *)_buttonIndex;
+- (id)initWithButtonIndex:(int *)buttonIndex;
 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
 
 @end
 
-@implementation UIKit_UIAlertViewDelegate
+@implementation UIKit_UIAlertViewDelegate {
+    int *clickedButtonIndex;
+}
 
 - (id)initWithButtonIndex:(int *)buttonIndex
 {
@@ -48,12 +47,13 @@ static SDL_bool s_showingMessageBox = SDL_FALSE;
     if (self == nil) {
         return nil;
     }
-    self->clickedButtonIndex = buttonIndex;
+
+    clickedButtonIndex = buttonIndex;
 
     return self;
 }
 
-- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
 {
     *clickedButtonIndex = (int)buttonIndex;
 }
@@ -71,40 +71,38 @@ int
 UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
 {
     int clicked;
+    int i;
+    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
 
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    UIAlertView* alert = [[UIAlertView alloc] init];
-
-    alert.title = [NSString stringWithUTF8String:messageboxdata->title];
-    alert.message = [NSString stringWithUTF8String:messageboxdata->message];
-    alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked];
+    @autoreleasepool {
+        UIAlertView* alert = [[UIAlertView alloc] init];
+        UIKit_UIAlertViewDelegate *delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked];
 
-    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
-    int i;
-    for (i = 0; i < messageboxdata->numbuttons; ++i) {
-        [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]];
-    }
+        alert.title = @(messageboxdata->title);
+        alert.message = @(messageboxdata->message);
+        alert.delegate = delegate;
 
-    /* Set up for showing the alert */
-    clicked = messageboxdata->numbuttons;
+        for (i = 0; i < messageboxdata->numbuttons; ++i) {
+            [alert addButtonWithTitle:@(buttons[i].text)];
+        }
 
-    [alert show];
+        /* Set up for showing the alert */
+        clicked = messageboxdata->numbuttons;
 
-    /* Run the main event loop until the alert has finished */
-    /* Note that this needs to be done on the main thread */
-    s_showingMessageBox = SDL_TRUE;
-    while (clicked == messageboxdata->numbuttons) {
-        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
-    }
-    s_showingMessageBox = SDL_FALSE;
+        [alert show];
 
-    *buttonid = messageboxdata->buttons[clicked].buttonid;
+        /* Run the main event loop until the alert has finished */
+        /* Note that this needs to be done on the main thread */
+        s_showingMessageBox = SDL_TRUE;
+        while (clicked == messageboxdata->numbuttons) {
+            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+        }
+        s_showingMessageBox = SDL_FALSE;
 
-    [alert.delegate release];
-    [alert release];
+        *buttonid = messageboxdata->buttons[clicked].buttonid;
 
-    [pool release];
+        alert.delegate = nil;
+    }
 
     return 0;
 }

+ 11 - 11
src/video/uikit/SDL_uikitmodes.h

@@ -25,17 +25,17 @@
 
 #include "SDL_uikitvideo.h"
 
-typedef struct
-{
-    UIScreen *uiscreen;
-    CGFloat scale;
-} SDL_DisplayData;
-
-typedef struct
-{
-    UIScreenMode *uiscreenmode;
-    CGFloat scale;
-} SDL_DisplayModeData;
+@interface SDL_DisplayData : NSObject
+
+@property (nonatomic, strong) UIScreen *uiscreen;
+
+@end
+
+@interface SDL_DisplayModeData : NSObject
+
+@property (nonatomic, strong) UIScreenMode *uiscreenmode;
+
+@end
 
 extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
 

+ 86 - 87
src/video/uikit/SDL_uikitmodes.m

@@ -25,27 +25,36 @@
 #include "SDL_assert.h"
 #include "SDL_uikitmodes.h"
 
+@implementation SDL_DisplayData
+
+@synthesize uiscreen;
+
+@end
+
+@implementation SDL_DisplayModeData
+
+@synthesize uiscreenmode;
+
+@end
+
 
 static int
 UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
-    UIScreenMode * uiscreenmode, CGFloat scale)
+    UIScreenMode * uiscreenmode)
 {
-    SDL_DisplayModeData *data = NULL;
+    SDL_DisplayModeData *data = nil;
 
     if (uiscreenmode != nil) {
         /* Allocate the display mode data */
-        data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
+        data = [[SDL_DisplayModeData alloc] init];
         if (!data) {
             return SDL_OutOfMemory();
         }
 
-        data->uiscreenmode = uiscreenmode;
-        [data->uiscreenmode retain];
-
-        data->scale = scale;
+        data.uiscreenmode = uiscreenmode;
     }
 
-    mode->driverdata = data;
+    mode->driverdata = (void *) CFBridgingRetain(data);
 
     return 0;
 }
@@ -54,23 +63,21 @@ static void
 UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
 {
     if (mode->driverdata != NULL) {
-        SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata;
-        [data->uiscreenmode release];
-        SDL_free(data);
+        CFRelease(mode->driverdata);
         mode->driverdata = NULL;
     }
 }
 
 static int
 UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
-    UIScreenMode * uiscreenmode, CGFloat scale)
+    UIScreenMode * uiscreenmode)
 {
     SDL_DisplayMode mode;
     SDL_zero(mode);
 
     mode.format = SDL_PIXELFORMAT_ABGR8888;
     mode.refresh_rate = 0;
-    if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
+    if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
         return -1;
     }
 
@@ -85,16 +92,16 @@ UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
 }
 
 static int
-UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale,
+UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h,
                      UIScreenMode * uiscreenmode, SDL_bool addRotation)
 {
-    if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) {
+    if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode) < 0) {
         return -1;
     }
 
     if (addRotation) {
         /* Add the rotated version */
-        if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) {
+        if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode) < 0) {
             return -1;
         }
     }
@@ -114,24 +121,16 @@ UIKit_AddDisplay(UIScreen *uiscreen)
         size.height = height;
     }
 
-    /* When dealing with UIKit all coordinates are specified in terms of
-     * what Apple refers to as points. [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 = [uiscreen scale];
-
     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.w = (int) size.width;
+    mode.h = (int) size.height;
 
-    UIScreenMode * uiscreenmode = [uiscreen currentMode];
+    UIScreenMode *uiscreenmode = [uiscreen currentMode];
 
-    if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
+    if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
         return -1;
     }
 
@@ -140,19 +139,18 @@ UIKit_AddDisplay(UIScreen *uiscreen)
     display.current_mode = mode;
 
     /* Allocate the display data */
-    SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data));
+    SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
     if (!data) {
         UIKit_FreeDisplayModeData(&display.desktop_mode);
         return SDL_OutOfMemory();
     }
 
-    [uiscreen retain];
-    data->uiscreen = uiscreen;
-    data->scale = scale;
+    data.uiscreen = uiscreen;
 
-    display.driverdata = data;
+    display.driverdata = (void *) CFBridgingRetain(data);
     SDL_AddVideoDisplay(&display);
 
+
     return 0;
 }
 
@@ -170,9 +168,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;
+            }
         }
     }
 
@@ -182,34 +182,29 @@ UIKit_InitModes(_THIS)
 void
 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]);
-
-    for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
-        CGSize size = [uimode size];
-        int w = (int)size.width;
-        int h = (int)size.height;
-
-        /* Make sure the width/height are oriented correctly */
-        if (isLandscape != (w > h)) {
-            int tmp = w;
-            w = h;
-            h = tmp;
-        }
+    @autoreleasepool {
+        SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
+
+        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);
+
+            /* 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, data->scale, uimode, addRotation);
-
-        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, addRotation);
+            /* Add the native screen resolution. */
+            UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
         }
     }
 }
@@ -217,19 +212,21 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
 int
 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];
-
-    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];
+    @autoreleasepool {
+        SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
+        SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
+
+        [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];
+                }
             }
         }
     }
@@ -242,19 +239,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);
+            if (display->driverdata != NULL) {
+                CFRelease(display->driverdata);
+                display->driverdata = NULL;
+            }
         }
-
-        SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
-        [data->uiscreen release];
-        SDL_free(data);
-        display->driverdata = NULL;
     }
 }
 

+ 2 - 0
src/video/uikit/SDL_uikitopengles.h

@@ -25,6 +25,8 @@
 
 extern int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window,
                                 SDL_GLContext context);
+extern void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window,
+                                     int * w, int * h);
 extern void UIKit_GL_SwapWindow(_THIS, SDL_Window * window);
 extern SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window);
 extern void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context);

+ 150 - 90
src/video/uikit/SDL_uikitopengles.m

@@ -49,12 +49,30 @@ UIKit_GL_GetProcAddress(_THIS, const char *proc)
 /*
     note that SDL_GL_Delete context makes it current without passing the window
 */
-int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+int
+UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
 {
-    [EAGLContext setCurrentContext: context];
+    @autoreleasepool {
+        [EAGLContext setCurrentContext:(__bridge EAGLContext *)context];
+    }
     return 0;
 }
 
+void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
+{
+    @autoreleasepool {
+        SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
+
+        if (w) {
+            *w = data.view.backingWidth;
+        }
+        if (h) {
+            *h = data.view.backingHeight;
+        }
+    }
+}
+
+
 int
 UIKit_GL_LoadLibrary(_THIS, const char *path)
 {
@@ -71,117 +89,159 @@ UIKit_GL_LoadLibrary(_THIS, const char *path)
 
 void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
 {
+    @autoreleasepool {
+        SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
+
 #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;
+        if (data.view == nil) {
+            return;
+        }
+        [data.view swapBuffers];
 
-    if (nil == data->view) {
-        return;
+        /* 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_GLContext
+UIKit_GL_CreateContext(_THIS, SDL_Window * window)
 {
-    SDL_uikitopenglview *view;
-    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
-    SDL_DisplayData *displaydata = display->driverdata;
-    SDL_DisplayModeData *displaymodedata = display->current_mode.driverdata;
-    UIWindow *uiwindow = data->uiwindow;
-    EAGLSharegroup *share_group = nil;
-
-    if (_this->gl_config.share_with_current_context) {
-        SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
-        share_group = [view.context sharegroup];
-    }
+    @autoreleasepool {
+        SDL_uikitopenglview *view;
+        SDL_WindowData *data = (__bridge 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;
+        }
 
-    /* construct our view, passing in SDL's OpenGL configuration data */
-    CGRect frame;
-    if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
-        frame = [displaydata->uiscreen bounds];
-    } else {
-        frame = [displaydata->uiscreen applicationFrame];
-    }
-    view = [[SDL_uikitopenglview alloc] initWithFrame: frame
-                                    scale: displaymodedata->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
-                                    majorVersion: _this->gl_config.major_version
-                                    shareGroup: share_group];
-    if (!view) {
-        return NULL;
-    }
+        if (_this->gl_config.share_with_current_context) {
+            EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
+            share_group = context.sharegroup;
+        }
 
-    data->view = view;
-    view->viewcontroller = data->viewcontroller;
-    if (view->viewcontroller != nil) {
-        [view->viewcontroller setView:view];
-        [view->viewcontroller retain];
-    }
-    [uiwindow addSubview: view];
+        /* 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;
+        }
 
-    /* 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;
-    }
+        data.view = view;
+        view.viewcontroller = data.viewcontroller;
+        if (view.viewcontroller != nil) {
+            view.viewcontroller.view = view;
+        }
+        [uiwindow addSubview: view];
 
-    EAGLContext *context = view.context;
-    if (UIKit_GL_MakeCurrent(_this, window, context) < 0) {
-        UIKit_GL_DeleteContext(_this, context);
-        return NULL;
-    }
+        /* 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;
+        }
 
-    /* Make this window the current mouse focus for touch input */
-    if (displaydata->uiscreen == [UIScreen mainScreen]) {
-        SDL_SetMouseFocus(window);
-        SDL_SetKeyboardFocus(window);
-    }
+        EAGLContext *context = view.context;
+        if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
+            UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
+            return NULL;
+        }
 
-    return context;
+        /* Make this window the current mouse focus for touch input */
+        if (uiwindow.screen == [UIScreen mainScreen]) {
+            SDL_SetMouseFocus(window);
+            SDL_SetKeyboardFocus(window);
+        }
+
+        /* We return a +1'd context. The window's driverdata owns the view. */
+        return (SDL_GLContext) CFBridgingRetain(context);
+    }
 }
 
-void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
+void
+UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
 {
-    SDL_Window *window;
-
-    /* Find the view associated with this context */
-    for (window = _this->windows; window; window = window->next) {
-        SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-        SDL_uikitopenglview *view = data->view;
-        if (view.context == context) {
-            /* the delegate has retained the view, this will release him */
-            if (view->viewcontroller) {
-                UIWindow *uiwindow = (UIWindow *)view.superview;
-                if (uiwindow.rootViewController == view->viewcontroller) {
-                    uiwindow.rootViewController = nil;
+    @autoreleasepool {
+        /* Transfer ownership the +1'd context to ARC. */
+        EAGLContext *eaglcontext = (EAGLContext *) CFBridgingRelease(context);
+        SDL_Window *window;
+
+        /* Find the view associated with this context */
+        for (window = _this->windows; window; window = window->next) {
+            SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
+            SDL_uikitopenglview *view = data.view;
+            if (view.context == eaglcontext) {
+                /* the delegate has retained the view, this will release him */
+                if (view.viewcontroller) {
+                    UIWindow *uiwindow = (UIWindow *)view.superview;
+                    if (uiwindow.rootViewController == view.viewcontroller) {
+                        uiwindow.rootViewController = nil;
+                    }
+                    view.viewcontroller.view = nil;
+                    view.viewcontroller = nil;
                 }
-                [view->viewcontroller setView:nil];
-                [view->viewcontroller release];
+                [view removeFromSuperview];
+
+                data.view = nil;
+                return;
             }
-            [view removeFromSuperview];
+        }
+    }
+}
 
-            /* FIXME: This doesn't actually call view dealloc - what is holding a reference to it? */
-            [view release];
-            return;
+Uint32 SDL_iPhoneGetViewRenderbuffer(SDL_Window * window)
+{
+    if (!window) {
+        SDL_SetError("Invalid window");
+        return 0;
+    }
+
+    @autoreleasepool {
+        SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
+        if (data.view != nil) {
+            return data.view.drawableRenderbuffer;
+        } else {
+            return 0;
         }
     }
+}
 
-    /* View not found... delete the context anyway? */
-    [(EAGLContext *)context release];
+Uint32 SDL_iPhoneGetViewFramebuffer(SDL_Window * window)
+{
+    if (!window) {
+        SDL_SetError("Invalid window");
+        return 0;
+    }
+
+    @autoreleasepool {
+        SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
+        if (data.view != nil) {
+            return data.view.drawableFramebuffer;
+        } else {
+            return 0;
+        }
+    }
 }
 
 #endif /* SDL_VIDEO_DRIVER_UIKIT */

+ 24 - 38
src/video/uikit/SDL_uikitopenglview.h

@@ -29,52 +29,38 @@
     The view content is basically an EAGL surface you render your OpenGL scene into.
     Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
  */
-@interface SDL_uikitopenglview : SDL_uikitview {
+@interface SDL_uikitopenglview : SDL_uikitview
 
-@private
-    /* The pixel dimensions of the backbuffer */
-    GLint backingWidth;
-    GLint backingHeight;
-
-    EAGLContext *context;
-
-    /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
-    GLuint viewRenderbuffer, viewFramebuffer;
-
-    /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
-    GLuint depthRenderbuffer;
-
-    /* format of depthRenderbuffer */
-    GLenum depthBufferFormat;
-
-    id displayLink;
-    int animationInterval;
-    void (*animationCallback)(void*);
-    void *animationCallbackParam;
-}
-
-@property (nonatomic, retain, readonly) EAGLContext *context;
+- (id)initWithFrame:(CGRect)frame
+              scale:(CGFloat)scale
+      retainBacking:(BOOL)retained
+              rBits:(int)rBits
+              gBits:(int)gBits
+              bBits:(int)bBits
+              aBits:(int)aBits
+          depthBits:(int)depthBits
+        stencilBits:(int)stencilBits
+               sRGB:(BOOL)sRGB
+       majorVersion:(int)majorVersion
+         shareGroup:(EAGLSharegroup*)shareGroup;
+
+@property (nonatomic, strong, readonly) EAGLContext *context;
+
+/* The width and height of the drawable in pixels (as opposed to points.) */
+@property (nonatomic, readonly) int backingWidth;
+@property (nonatomic, readonly) int backingHeight;
+
+@property (nonatomic, readonly) GLuint drawableRenderbuffer;
+@property (nonatomic, readonly) GLuint drawableFramebuffer;
 
 - (void)swapBuffers;
 - (void)setCurrentContext;
 
-- (id)initWithFrame:(CGRect)frame
-    scale:(CGFloat)scale
-    retainBacking:(BOOL)retained
-    rBits:(int)rBits
-    gBits:(int)gBits
-    bBits:(int)bBits
-    aBits:(int)aBits
-    depthBits:(int)depthBits
-    stencilBits:(int)stencilBits
-    majorVersion:(int)majorVersion
-    shareGroup:(EAGLSharegroup*)shareGroup;
-
 - (void)updateFrame;
 
 - (void)setAnimationCallback:(int)interval
-    callback:(void (*)(void*))callback
-    callbackParam:(void*)callbackParam;
+                    callback:(void (*)(void*))callback
+               callbackParam:(void*)callbackParam;
 
 - (void)startAnimation;
 - (void)stopAnimation;

+ 87 - 40
src/video/uikit/SDL_uikitopenglview.m

@@ -26,42 +26,73 @@
 #include <OpenGLES/EAGLDrawable.h>
 #include "SDL_uikitopenglview.h"
 #include "SDL_uikitmessagebox.h"
+#include "SDL_uikitvideo.h"
 
 
-@implementation SDL_uikitopenglview
+@implementation SDL_uikitopenglview {
+
+    /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
+    GLuint viewRenderbuffer, viewFramebuffer;
+
+    /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
+    GLuint depthRenderbuffer;
+
+    /* format of depthRenderbuffer */
+    GLenum depthBufferFormat;
+
+    id displayLink;
+    int animationInterval;
+    void (*animationCallback)(void*);
+    void *animationCallbackParam;
+
+}
 
 @synthesize context;
 
+@synthesize backingWidth;
+@synthesize backingHeight;
+
 + (Class)layerClass
 {
     return [CAEAGLLayer class];
 }
 
 - (id)initWithFrame:(CGRect)frame
-      scale:(CGFloat)scale
+              scale:(CGFloat)scale
       retainBacking:(BOOL)retained
-      rBits:(int)rBits
-      gBits:(int)gBits
-      bBits:(int)bBits
-      aBits:(int)aBits
-      depthBits:(int)depthBits
-      stencilBits:(int)stencilBits
-      majorVersion:(int)majorVersion
-      shareGroup:(EAGLSharegroup*)shareGroup
+              rBits:(int)rBits
+              gBits:(int)gBits
+              bBits:(int)bBits
+              aBits:(int)aBits
+          depthBits:(int)depthBits
+        stencilBits:(int)stencilBits
+               sRGB:(BOOL)sRGB
+       majorVersion:(int)majorVersion
+         shareGroup:(EAGLSharegroup*)shareGroup
 {
-    depthBufferFormat = 0;
-
     if ((self = [super initWithFrame:frame])) {
         const BOOL useStencilBuffer = (stencilBits != 0);
         const BOOL useDepthBuffer = (depthBits != 0);
         NSString *colorFormat = nil;
 
+        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+        self.autoresizesSubviews = YES;
+
         /* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
            versions, and this allows us to handle future OpenGL ES versions.
          */
         EAGLRenderingAPI api = majorVersion;
 
-        if (rBits == 8 && gBits == 8 && bBits == 8) {
+        context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
+        if (!context || ![EAGLContext setCurrentContext:context]) {
+            SDL_SetError("OpenGL ES %d not supported", majorVersion);
+            return nil;
+        }
+
+        if (sRGB && UIKit_IsSystemVersionAtLeast(@"7.0")) {
+             /* sRGB EAGL drawable support was added in iOS 7 */
+            colorFormat = kEAGLColorFormatSRGBA8;
+        } else if (rBits >= 8 && gBits >= 8 && bBits >= 8) {
             /* if user specifically requests rbg888 or some color format higher than 16bpp */
             colorFormat = kEAGLColorFormatRGBA8;
         } else {
@@ -73,26 +104,28 @@
         CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
 
         eaglLayer.opaque = YES;
-        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
-                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
-
-        context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
-        if (!context || ![EAGLContext setCurrentContext:context]) {
-            [self release];
-            SDL_SetError("OpenGL ES %d not supported", majorVersion);
-            return nil;
-        }
+        eaglLayer.drawableProperties = @{
+            kEAGLDrawablePropertyRetainedBacking: @(retained),
+            kEAGLDrawablePropertyColorFormat: colorFormat
+        };
 
         /* Set the appropriate scale (for retina display support) */
         self.contentScaleFactor = scale;
 
-        /* create the buffers */
-        glGenFramebuffersOES(1, &viewFramebuffer);
+        /* Create the color Renderbuffer Object */
         glGenRenderbuffersOES(1, &viewRenderbuffer);
+        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
 
+        if (![context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer]) {
+            SDL_SetError("Failed creating OpenGL ES drawable");
+            return nil;
+        }
+
+        /* Create the Framebuffer Object */
+        glGenFramebuffersOES(1, &viewFramebuffer);
         glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
-        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
-        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
+
+        /* attach the color renderbuffer to the FBO */
         glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
 
         glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
@@ -119,18 +152,26 @@
         }
 
         if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
-            return NO;
+            SDL_SetError("Failed creating OpenGL ES framebuffer");
+            return nil;
         }
 
         glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
-        /* end create buffers */
-
-        self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
-        self.autoresizesSubviews = YES;
     }
+
     return self;
 }
 
+- (GLuint)drawableRenderbuffer
+{
+    return viewRenderbuffer;
+}
+
+- (GLuint)drawableFramebuffer
+{
+    return viewFramebuffer;
+}
+
 - (void)updateFrame
 {
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
@@ -164,8 +205,9 @@
     animationCallback = callback;
     animationCallbackParam = callbackParam;
 
-    if (animationCallback)
+    if (animationCallback) {
         [self startAnimation];
+    }
 }
 
 - (void)startAnimation
@@ -206,18 +248,25 @@
 
 - (void)layoutSubviews
 {
+    [super layoutSubviews];
+
     [EAGLContext setCurrentContext:context];
     [self updateFrame];
 }
 
 - (void)destroyFramebuffer
 {
-    glDeleteFramebuffersOES(1, &viewFramebuffer);
-    viewFramebuffer = 0;
-    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
-    viewRenderbuffer = 0;
+    if (viewFramebuffer != 0) {
+        glDeleteFramebuffersOES(1, &viewFramebuffer);
+        viewFramebuffer = 0;
+    }
 
-    if (depthRenderbuffer) {
+    if (viewRenderbuffer != 0) {
+        glDeleteRenderbuffersOES(1, &viewRenderbuffer);
+        viewRenderbuffer = 0;
+    }
+
+    if (depthRenderbuffer != 0) {
         glDeleteRenderbuffersOES(1, &depthRenderbuffer);
         depthRenderbuffer = 0;
     }
@@ -226,12 +275,10 @@
 
 - (void)dealloc
 {
-    [self destroyFramebuffer];
     if ([EAGLContext currentContext] == context) {
+        [self destroyFramebuffer];
         [EAGLContext setCurrentContext:nil];
     }
-    [context release];
-    [super dealloc];
 }
 
 @end

+ 2 - 14
src/video/uikit/SDL_uikitvideo.h

@@ -25,20 +25,8 @@
 
 #include "../SDL_sysvideo.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 */
-enum UIInterfaceOrientationMask
-{
-    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
-    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
-    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
-    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
-    UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
-    UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
-    UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
-};
-#endif /* !__IPHONE_6_0 */
-
+BOOL UIKit_IsSystemVersionAtLeast(NSString *version);
+CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
 
 #endif /* _SDL_uikitvideo_h */
 

+ 25 - 5
src/video/uikit/SDL_uikitvideo.m

@@ -78,12 +78,11 @@ UIKit_CreateDevice(int devindex)
     device->ShowWindow = UIKit_ShowWindow;
     device->HideWindow = UIKit_HideWindow;
     device->RaiseWindow = UIKit_RaiseWindow;
+    device->SetWindowBordered = UIKit_SetWindowBordered;
     device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
     device->DestroyWindow = UIKit_DestroyWindow;
     device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
 
-    /* !!! FIXME: implement SetWindowBordered */
-
 #if SDL_IPHONE_KEYBOARD
     device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
     device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
@@ -93,12 +92,13 @@ UIKit_CreateDevice(int devindex)
 #endif
 
     /* OpenGL (ES) functions */
-    device->GL_MakeCurrent        = UIKit_GL_MakeCurrent;
-    device->GL_SwapWindow        = UIKit_GL_SwapWindow;
+    device->GL_MakeCurrent      = UIKit_GL_MakeCurrent;
+    device->GL_GetDrawableSize  = UIKit_GL_GetDrawableSize;
+    device->GL_SwapWindow       = UIKit_GL_SwapWindow;
     device->GL_CreateContext    = UIKit_GL_CreateContext;
     device->GL_DeleteContext    = UIKit_GL_DeleteContext;
     device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
-    device->GL_LoadLibrary        = UIKit_GL_LoadLibrary;
+    device->GL_LoadLibrary      = UIKit_GL_LoadLibrary;
     device->free = UIKit_DeleteDevice;
 
     device->gl_config.accelerated = 1;
@@ -129,6 +129,26 @@ UIKit_VideoQuit(_THIS)
     UIKit_QuitModes(_this);
 }
 
+BOOL
+UIKit_IsSystemVersionAtLeast(NSString *version)
+{
+    NSString *sysversion = [UIDevice currentDevice].systemVersion;
+    return [sysversion compare:version options:NSNumericSearch] != NSOrderedAscending;
+}
+
+CGRect
+UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
+{
+    BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(@"7.0");
+
+    if (hasiOS7 || (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN))) {
+        /* The view should always show behind the status bar in iOS 7+. */
+        return screen.bounds;
+    } else {
+        return screen.applicationFrame;
+    }
+}
+
 /*
  * iOS log support.
  *

+ 7 - 20
src/video/uikit/SDL_uikitview.h

@@ -31,27 +31,13 @@
 #endif
 
 #if SDL_IPHONE_KEYBOARD
-@interface SDL_uikitview : UIView<UITextFieldDelegate> {
+@interface SDL_uikitview : UIView <UITextFieldDelegate>
 #else
-@interface SDL_uikitview : UIView {
+@interface SDL_uikitview : UIView
 #endif
 
-    SDL_TouchID touchId;
-    UITouch *leftFingerDown;
-#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
-    UITouch *finger[MAX_SIMULTANEOUS_TOUCHES];
-#endif
-
-#if SDL_IPHONE_KEYBOARD
-    UITextField *textField;
-    BOOL keyboardVisible;
-    SDL_Rect textInputRect;
-    int keyboardHeight;
-#endif
+@property (nonatomic, weak) SDL_uikitviewcontroller *viewcontroller;
 
-@public
-    SDL_uikitviewcontroller *viewcontroller;
-}
 - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize;
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
@@ -61,9 +47,10 @@
 - (void)showKeyboard;
 - (void)hideKeyboard;
 - (void)initializeKeyboard;
-@property (readonly) BOOL keyboardVisible;
-@property (nonatomic,assign) SDL_Rect textInputRect;
-@property (nonatomic,assign) int keyboardHeight;
+
+@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible;
+@property (nonatomic, assign) SDL_Rect textInputRect;
+@property (nonatomic, assign) int keyboardHeight;
 
 SDL_bool UIKit_HasScreenKeyboardSupport(_THIS);
 void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window);

+ 68 - 80
src/video/uikit/SDL_uikitview.m

@@ -35,27 +35,36 @@
 #include "SDL_uikitmodes.h"
 #include "SDL_uikitwindow.h"
 
-void _uikit_keyboard_init() ;
+void _uikit_keyboard_init();
 
-@implementation SDL_uikitview
+@implementation SDL_uikitview {
+
+    SDL_TouchID touchId;
+    UITouch *leftFingerDown;
+#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
+    UITouch *finger[MAX_SIMULTANEOUS_TOUCHES];
+#endif
+
+#if SDL_IPHONE_KEYBOARD
+    UITextField *textField;
+#endif
 
-- (void)dealloc
-{
-    [super dealloc];
 }
 
+@synthesize viewcontroller;
+
 - (id)initWithFrame:(CGRect)frame
 {
-    self = [super initWithFrame: frame];
-
+    if (self = [super initWithFrame: frame]) {
 #if SDL_IPHONE_KEYBOARD
-    [self initializeKeyboard];
+        [self initializeKeyboard];
 #endif
 
-    self.multipleTouchEnabled = YES;
+        self.multipleTouchEnabled = YES;
 
-    touchId = 1;
-    SDL_AddTouch(touchId, "");
+        touchId = 1;
+        SDL_AddTouch(touchId, "");
+    }
 
     return self;
 
@@ -65,36 +74,26 @@ void _uikit_keyboard_init() ;
 {
     CGPoint point = [touch locationInView: self];
 
-    /* Get the display scale and apply that to the input coordinates */
-    SDL_Window *window = self->viewcontroller.window;
-    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
-    SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
-
     if (normalize) {
-        CGRect bounds = [self bounds];
+        CGRect bounds = self.bounds;
         point.x /= bounds.size.width;
         point.y /= bounds.size.height;
-    } else {
-        point.x *= displaymodedata->scale;
-        point.y *= displaymodedata->scale;
     }
+
     return point;
 }
 
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {
-    NSEnumerator *enumerator = [touches objectEnumerator];
-    UITouch *touch = (UITouch*)[enumerator nextObject];
-
-    while (touch) {
+    for (UITouch *touch in touches) {
         if (!leftFingerDown) {
             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
 
             /* send moved event */
-            SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
+            SDL_SendMouseMotion(self.viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
 
             /* send mouse down event */
-            SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
+            SDL_SendMouseButton(self.viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
 
             leftFingerDown = touch;
         }
@@ -118,25 +117,21 @@ void _uikit_keyboard_init() ;
             }
         }
 #endif
-        touch = (UITouch*)[enumerator nextObject];
     }
 }
 
 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
 {
-    NSEnumerator *enumerator = [touches objectEnumerator];
-    UITouch *touch = (UITouch*)[enumerator nextObject];
-
-    while(touch) {
+    for (UITouch *touch in touches) {
         if (touch == leftFingerDown) {
             /* send mouse up */
-            SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
+            SDL_SendMouseButton(self.viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
             leftFingerDown = nil;
         }
 
         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
-        SDL_SendTouch(touchId, (long)touch,
+        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
                       SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
 #else
         int i;
@@ -149,7 +144,6 @@ void _uikit_keyboard_init() ;
             }
         }
 #endif
-        touch = (UITouch*)[enumerator nextObject];
     }
 }
 
@@ -165,20 +159,17 @@ void _uikit_keyboard_init() ;
 
 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 {
-    NSEnumerator *enumerator = [touches objectEnumerator];
-    UITouch *touch = (UITouch*)[enumerator nextObject];
-
-    while (touch) {
+    for (UITouch *touch in touches) {
         if (touch == leftFingerDown) {
             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
 
             /* send moved event */
-            SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
+            SDL_SendMouseMotion(self.viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
         }
 
         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
 #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
-        SDL_SendTouchMotion(touchId, (long)touch,
+        SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
                             locationInView.x, locationInView.y, 1.0f);
 #else
         int i;
@@ -190,7 +181,6 @@ void _uikit_keyboard_init() ;
             }
         }
 #endif
-        touch = (UITouch*)[enumerator nextObject];
     }
 }
 
@@ -199,14 +189,9 @@ void _uikit_keyboard_init() ;
 */
 #if SDL_IPHONE_KEYBOARD
 
-@synthesize textInputRect = textInputRect;
-@synthesize keyboardHeight = keyboardHeight;
-
-/* Is the iPhone virtual keyboard visible onscreen? */
-- (BOOL)keyboardVisible
-{
-    return keyboardVisible;
-}
+@synthesize textInputRect;
+@synthesize keyboardHeight;
+@synthesize keyboardVisible;
 
 /* Set ourselves up as a UITextFieldDelegate */
 - (void)initializeKeyboard
@@ -229,7 +214,6 @@ void _uikit_keyboard_init() ;
     keyboardVisible = NO;
     /* add the UITextField (hidden) to our view */
     [self addSubview: textField];
-    [textField release];
     
     _uikit_keyboard_init();
 }
@@ -318,8 +302,8 @@ static SDL_uikitview * getWindowView(SDL_Window * window)
         return nil;
     }
 
-    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
-    SDL_uikitview *view = data != NULL ? data->view : nil;
+    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
+    SDL_uikitview *view = data != nil ? data.view : nil;
 
     if (view == nil) {
         SDL_SetError("Window has no view");
@@ -335,44 +319,49 @@ 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.keyboardVisible;
+        return view.isKeyboardVisible;
+    }
 }
 
 
 void _uikit_keyboard_update() {
     SDL_Window *window = SDL_GetFocusWindow();
     if (!window) { return; }
-    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
     if (!data) { return; }
-    SDL_uikitview *view = data->view;
+    SDL_uikitview *view = data.view;
     if (!view) { return; }
-    
+
     SDL_Rect r = view.textInputRect;
     int height = view.keyboardHeight;
     int offsetx = 0;
     int offsety = 0;
-    float scale = [UIScreen mainScreen].scale;
     if (height) {
         int sw,sh;
         SDL_GetWindowSize(window,&sw,&sh);
@@ -394,18 +383,16 @@ void _uikit_keyboard_update() {
         offsety = -offsety;
     }
 
-    offsetx /= scale;
-    offsety /= scale;
-
     view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
 }
 
 void _uikit_keyboard_set_height(int height) {
     SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
     if (view == nil) {
-        return ;
+        return;
     }
-    
+
+    view.keyboardVisible = height > 0;
     view.keyboardHeight = height;
     _uikit_keyboard_update();
 }
@@ -418,13 +405,12 @@ void _uikit_keyboard_init() {
                          queue:queue
                     usingBlock:^(NSNotification *notification) {
                         int height = 0;
-                        CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
+                        CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
                         height = keyboardSize.height;
                         UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
                         if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
                             height = keyboardSize.width;
                         }
-                        height *= [UIScreen mainScreen].scale;
                         _uikit_keyboard_set_height(height);
                     }
      ];
@@ -444,13 +430,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;
+    }
 }
 
 

+ 3 - 5
src/video/uikit/SDL_uikitviewcontroller.h

@@ -23,12 +23,9 @@
 
 #include "../SDL_sysvideo.h"
 
-@interface SDL_uikitviewcontroller : UIViewController {
-@private
-    SDL_Window *window;
-}
+@interface SDL_uikitviewcontroller : UIViewController
 
-@property (readwrite) SDL_Window *window;
+@property (nonatomic, assign) SDL_Window *window;
 
 - (id)initWithSDLWindow:(SDL_Window *)_window;
 - (void)loadView;
@@ -36,5 +33,6 @@
 - (NSUInteger)supportedInterfaceOrientations;
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
 - (BOOL)prefersStatusBarHidden;
+- (UIStatusBarStyle)preferredStatusBarStyle;
 
 @end

+ 23 - 28
src/video/uikit/SDL_uikitviewcontroller.m

@@ -40,12 +40,9 @@
 
 - (id)initWithSDLWindow:(SDL_Window *)_window
 {
-    self = [self init];
-    if (self == nil) {
-        return nil;
+    if (self = [super initWithNibName:nil bundle:nil]) {
+        self.window = _window;
     }
-    self.window = _window;
-
     return self;
 }
 
@@ -56,31 +53,20 @@
 
 - (void)viewDidLayoutSubviews
 {
-    if (self->window->flags & SDL_WINDOW_RESIZABLE) {
-        SDL_WindowData *data = self->window->driverdata;
-        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(self->window);
-        SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
-        const CGSize size = data->view.bounds.size;
-        int w, h;
-
-        w = (int)(size.width * displaymodedata->scale);
-        h = (int)(size.height * displaymodedata->scale);
+    const CGSize size = self.view.bounds.size;
+    int w = (int) size.width;
+    int h = (int) size.height;
 
-        SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h);
-    }
+    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
 }
 
 - (NSUInteger)supportedInterfaceOrientations
 {
     NSUInteger orientationMask = 0;
+    const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
 
-    const char *orientationsCString;
-    if ((orientationsCString = SDL_GetHint(SDL_HINT_ORIENTATIONS)) != NULL) {
-        BOOL rotate = NO;
-        NSString *orientationsNSString = [NSString stringWithCString:orientationsCString
-                                                            encoding:NSUTF8StringEncoding];
-        NSArray *orientations = [orientationsNSString componentsSeparatedByCharactersInSet:
-                                 [NSCharacterSet characterSetWithCharactersInString:@" "]];
+    if (hint != NULL) {
+        NSArray *orientations = [@(hint) componentsSeparatedByString:@" "];
 
         if ([orientations containsObject:@"LandscapeLeft"]) {
             orientationMask |= UIInterfaceOrientationMaskLandscapeLeft;
@@ -94,14 +80,17 @@
         if ([orientations containsObject:@"PortraitUpsideDown"]) {
             orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown;
         }
+    }
 
-    } else if (self->window->flags & SDL_WINDOW_RESIZABLE) {
+    if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) {
         orientationMask = UIInterfaceOrientationMaskAll;  /* any orientation is okay. */
-    } else {
-        if (self->window->w >= self->window->h) {
+    }
+
+    if (orientationMask == 0) {
+        if (window->w >= window->h) {
             orientationMask |= UIInterfaceOrientationMaskLandscape;
         }
-        if (self->window->h >= self->window->w) {
+        if (window->h >= window->w) {
             orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
         }
     }
@@ -121,13 +110,19 @@
 
 - (BOOL)prefersStatusBarHidden
 {
-    if (self->window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
+    if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
         return YES;
     } else {
         return NO;
     }
 }
 
+- (UIStatusBarStyle)preferredStatusBarStyle
+{
+    /* We assume most games don't have a bright white background. */
+    return UIStatusBarStyleLightContent;
+}
+
 @end
 
 #endif /* SDL_VIDEO_DRIVER_UIKIT */

+ 12 - 8
src/video/uikit/SDL_uikitwindow.h

@@ -26,12 +26,11 @@
 #import "SDL_uikitopenglview.h"
 #import "SDL_uikitviewcontroller.h"
 
-typedef struct SDL_WindowData SDL_WindowData;
-
 extern int UIKit_CreateWindow(_THIS, SDL_Window * window);
 extern void UIKit_ShowWindow(_THIS, SDL_Window * window);
 extern void UIKit_HideWindow(_THIS, SDL_Window * window);
 extern void UIKit_RaiseWindow(_THIS, SDL_Window * window);
+extern void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
 extern void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
 extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
@@ -39,12 +38,17 @@ extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
 
 @class UIWindow;
 
-struct SDL_WindowData
-{
-    UIWindow *uiwindow;
-    SDL_uikitopenglview *view;
-    SDL_uikitviewcontroller *viewcontroller;
-};
+@interface SDL_uikitwindow : UIWindow
+
+@end
+
+@interface SDL_WindowData : NSObject
+
+@property (nonatomic, strong) SDL_uikitwindow *uiwindow;
+@property (nonatomic, strong) SDL_uikitopenglview *view;
+@property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller;
+
+@end
 
 #endif /* _SDL_uikitwindow_h */
 

+ 177 - 147
src/video/uikit/SDL_uikitwindow.m

@@ -41,43 +41,56 @@
 
 #include <Foundation/Foundation.h>
 
+@implementation SDL_uikitwindow
 
+- (void)layoutSubviews
+{
+    [super layoutSubviews];
+
+    /* This seems to be needed on iOS 8, otherwise the window's frame is put in
+     * an unexpected position when the screen or device is rotated.
+     * FIXME: is there a better solution to that problem than this ugly hack?
+     */
+    self.frame = self.screen.bounds;
+}
+
+@end
 
+@implementation SDL_WindowData
 
-static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
+@synthesize uiwindow;
+@synthesize view;
+@synthesize viewcontroller;
+
+@end
+
+
+static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, SDL_bool created)
 {
     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
-    SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
-    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
-    SDL_WindowData *data;
+    SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata;
 
     /* Allocate the window data */
-    data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
+    SDL_WindowData *data = [[SDL_WindowData alloc] init];
     if (!data) {
         return SDL_OutOfMemory();
     }
-    data->uiwindow = uiwindow;
-    data->viewcontroller = nil;
-    data->view = nil;
+
+    data.uiwindow = uiwindow;
 
     /* Fill in the SDL window with the window data */
     {
         window->x = 0;
         window->y = 0;
 
-        CGRect bounds;
-        if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
-            bounds = [displaydata->uiscreen bounds];
-        } else {
-            bounds = [displaydata->uiscreen applicationFrame];
-        }
+        CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen);
 
-        /* Get frame dimensions in pixels */
-        int width = (int)(bounds.size.width * displaymodedata->scale);
-        int height = (int)(bounds.size.height * displaymodedata->scale);
+        /* Get frame dimensions */
+        int width = (int) frame.size.width;
+        int height = (int) frame.size.height;
 
         /* Make sure the width/height are oriented correctly */
-        if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
+        if (UIKit_IsDisplayLandscape(displaydata.uiscreen) != (width > height)) {
             int temp = width;
             width = height;
             height = temp;
@@ -87,7 +100,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
         window->h = height;
     }
 
-    window->driverdata = data;
+    window->driverdata = (void *) CFBridgingRetain(data);
 
     /* only one window on iOS, always shown */
     window->flags &= ~SDL_WINDOW_HIDDEN;
@@ -96,7 +109,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
      * This is only set if the window is on the main screen. Other screens
      *  just force the window to have the borderless flag.
      */
-    if (displaydata->uiscreen == [UIScreen mainScreen]) {
+    if (displaydata.uiscreen == [UIScreen mainScreen]) {
         window->flags |= SDL_WINDOW_INPUT_FOCUS;  /* always has input focus */
 
         /* This was setup earlier for our window, and in iOS 7 is controlled by the view, not the application
@@ -116,10 +129,8 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
      * device orientation changes. This will trigger resize events, if
      * appropriate.
      */
-    SDL_uikitviewcontroller *controller;
-    controller = [SDL_uikitviewcontroller alloc];
-    data->viewcontroller = [controller initWithSDLWindow:window];
-    [data->viewcontroller setTitle:@"SDL App"];  /* !!! FIXME: hook up SDL_SetWindowTitle() */
+    data.viewcontroller = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window];
+    data.viewcontroller.title = @"SDL App";  /* !!! FIXME: hook up SDL_SetWindowTitle() */
 
     return 0;
 }
@@ -127,105 +138,109 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
 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];
-
-    /* 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);
+    @autoreleasepool {
+        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+        SDL_DisplayData *data = (__bridge 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);
+
+        /* 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 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);
+            }
 
-        if (bestmode) {
-            SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
-            [data->uiscreen setCurrentMode:modedata->uiscreenmode];
+            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;
+            }
 
-            /* 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 (bestmode) {
+                SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)bestmode->driverdata;
+                [data.uiscreen setCurrentMode:modedata.uiscreenmode];
 
-    if (data->uiscreen == [UIScreen mainScreen]) {
-        if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
-            [UIApplication sharedApplication].statusBarHidden = YES;
-        } else {
-            [UIApplication sharedApplication].statusBarHidden = NO;
+                /* 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 (!(window->flags & SDL_WINDOW_RESIZABLE)) {
-        if (window->w > window->h) {
-            if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
+        if (data.uiscreen == [UIScreen mainScreen]) {
+            if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
+                [UIApplication sharedApplication].statusBarHidden = YES;
+            } else {
+                [UIApplication sharedApplication].statusBarHidden = NO;
             }
-        } else if (window->w < window->h) {
-            if (UIKit_IsDisplayLandscape(data->uiscreen)) {
-                [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
+        }
+
+        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];
+                }
             }
         }
-    }
 
-    /* ignore the size user requested, and make a fullscreen window */
-    /* !!! FIXME: can we have a smaller view? */
-    UIWindow *uiwindow = [UIWindow alloc];
-    uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
+        /* 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];
+        }
 
-    /* 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) {
+            return -1;
+        }
 
-    if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
-        [uiwindow release];
-        return -1;
     }
 
     return 1;
-
 }
 
 void
 UIKit_ShowWindow(_THIS, SDL_Window * window)
 {
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    @autoreleasepool {
+        UIWindow *uiwindow = ((__bridge 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 = ((__bridge SDL_WindowData *) window->driverdata).uiwindow;
 
-    uiwindow.hidden = YES;
+        uiwindow.hidden = YES;
+    }
 }
 
 void
@@ -239,91 +254,106 @@ UIKit_RaiseWindow(_THIS, SDL_Window * window)
     _this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
 }
 
-void
-UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+static void
+UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
 {
-    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
-    SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata;
+    SDL_uikitviewcontroller *viewcontroller = windowdata.viewcontroller;
+    CGRect frame;
 
-    if (fullscreen) {
-        [UIApplication sharedApplication].statusBarHidden = YES;
-    } else {
-        [UIApplication sharedApplication].statusBarHidden = NO;
-    }
+    if (windowdata.uiwindow.screen == [UIScreen mainScreen]) {
+        if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) {
+            [UIApplication sharedApplication].statusBarHidden = YES;
+        } else {
+            [UIApplication sharedApplication].statusBarHidden = NO;
+        }
 
-    CGRect bounds;
-    if (fullscreen) {
-        bounds = [displaydata->uiscreen bounds];
-    } else {
-        bounds = [displaydata->uiscreen applicationFrame];
+        /* iOS 7+ won't update the status bar until we tell it to. */
+        if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
+            [viewcontroller setNeedsStatusBarAppearanceUpdate];
+        }
     }
 
-    /* Get frame dimensions in pixels */
-    int width = (int)(bounds.size.width * displaymodedata->scale);
-    int height = (int)(bounds.size.height * displaymodedata->scale);
+    /* Update the view's frame to account for the status bar change. */
+    frame = UIKit_ComputeViewFrame(window, windowdata.uiwindow.screen);
+
+    windowdata.view.frame = frame;
+    [windowdata.view setNeedsLayout];
+    [windowdata.view layoutIfNeeded];
+
+    /* Get frame dimensions */
+    int width  = (int) frame.size.width;
+    int height = (int) frame.size.height;
 
     /* We can pick either width or height here and we'll rotate the
-       screen to match, so we pick the closest to what we wanted.
+     screen to match, so we pick the closest to what we wanted.
      */
     if (window->w >= window->h) {
-        if (width > height) {
-            window->w = width;
-            window->h = height;
-        } else {
-            window->w = height;
-            window->h = width;
-        }
+        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(width, height), SDL_min(width, height));
     } else {
-        if (width > height) {
-            window->w = height;
-            window->h = width;
-        } else {
-            window->w = width;
-            window->h = height;
-        }
+        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(width, height), SDL_max(width, height));
     }
 }
 
 void
-UIKit_DestroyWindow(_THIS, SDL_Window * window)
+UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
 {
-    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+    @autoreleasepool {
+        UIKit_UpdateWindowBorder(_this, window);
+    }
+}
 
-    if (data) {
-        [data->viewcontroller release];
-        [data->uiwindow release];
-        SDL_free(data);
+void
+UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+{
+    @autoreleasepool {
+        UIKit_UpdateWindowBorder(_this, window);
+    }
+}
+
+void
+UIKit_DestroyWindow(_THIS, SDL_Window * window)
+{
+    @autoreleasepool {
+        if (window->driverdata != NULL) {
+            CFRelease(window->driverdata);
+        }
     }
+
     window->driverdata = NULL;
 }
 
 SDL_bool
 UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
 {
-    UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
+    @autoreleasepool {
+        UIWindow *uiwindow = ((__bridge 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;
+        }
     }
 }
 
 int
 SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
 {
-    SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
+    @autoreleasepool {
+        SDL_WindowData *data = window ? (__bridge SDL_WindowData *)window->driverdata : nil;
+
+        if (!data || !data.view) {
+            return SDL_SetError("Invalid window or view not set");
+        }
 
-    if (!data || !data->view) {
-        return SDL_SetError("Invalid window or view not set");
+        [data.view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
     }
 
-    [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
     return 0;
 }