Commit ab2a3500337a1437f5553dad85165af5df426dd9

Alex Szpakowski 2015-09-25T15:17:20

iOS: show message boxes using the new UIAlertController APIs when supported, rather than the deprecated UIAlertView. UIAlertController is also supported on tvOS, whereas UIAlertView is not.

diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m
index e9ad049..38c0ffe 100644
--- a/src/joystick/iphoneos/SDL_sysjoystick.m
+++ b/src/joystick/iphoneos/SDL_sysjoystick.m
@@ -181,7 +181,7 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
 #endif /* !SDL_EVENTS_DISABLED */
 }
 
-SDL_JoystickDeviceItem *
+static SDL_JoystickDeviceItem *
 SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
 {
     SDL_JoystickDeviceItem *prev = NULL;
@@ -374,12 +374,14 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
 }
 
 /* Function to determine if this joystick is attached to the system right now */
-SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
+SDL_bool
+SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
 {
     return joystick->hwdata != NULL;
 }
 
-static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
+static void
+SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
 {
     const float maxgforce = SDL_IPHONE_MAX_GFORCE;
     const SInt16 maxsint16 = 0x7FFF;
@@ -579,7 +581,8 @@ SDL_SYS_JoystickQuit(void)
     numjoysticks = 0;
 }
 
-SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
+SDL_JoystickGUID
+SDL_SYS_JoystickGetDeviceGUID( int device_index )
 {
     SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
     SDL_JoystickGUID guid;
@@ -591,7 +594,8 @@ SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
     return guid;
 }
 
-SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
+SDL_JoystickGUID
+SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
 {
     SDL_JoystickGUID guid;
     if (joystick->hwdata) {
diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m
index dea8bdc..6c980d4 100644
--- a/src/video/uikit/SDL_uikitmessagebox.m
+++ b/src/video/uikit/SDL_uikitmessagebox.m
@@ -24,15 +24,103 @@
 
 #include "SDL.h"
 #include "SDL_uikitvideo.h"
-
+#include "SDL_uikitwindow.h"
 
 /* Display a UIKit message box */
 
 static SDL_bool s_showingMessageBox = SDL_FALSE;
 
+SDL_bool
+UIKit_ShowingMessageBox()
+{
+    return s_showingMessageBox;
+}
+
+static void
+UIKit_WaitUntilMessageBoxClosed(const SDL_MessageBoxData *messageboxdata, int *clickedindex)
+{
+    *clickedindex = messageboxdata->numbuttons;
+
+    @autoreleasepool {
+        /* 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 ((*clickedindex) == messageboxdata->numbuttons) {
+            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+        }
+        s_showingMessageBox = SDL_FALSE;
+    }
+}
+
+static BOOL
+UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+#ifdef __IPHONE_8_0
+    int i;
+    int __block clickedindex = messageboxdata->numbuttons;
+    const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
+    UIWindow *window = nil;
+    UIWindow *alertwindow = nil;
+
+    if (![UIAlertController class]) {
+        return NO;
+    }
+
+    UIAlertController *alert;
+    alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
+                                                message:@(messageboxdata->message)
+                                         preferredStyle:UIAlertControllerStyleAlert];
+
+    for (i = 0; i < messageboxdata->numbuttons; i++) {
+        UIAlertAction *action;
+        UIAlertActionStyle style = UIAlertActionStyleDefault;
+
+        if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
+            style = UIAlertActionStyleCancel;
+        }
+
+        action = [UIAlertAction actionWithTitle:@(buttons[i].text)
+                                          style:style
+                                        handler:^(UIAlertAction *action) {
+                                            clickedindex = i;
+                                        }];
+        [alert addAction:action];
+    }
+
+    if (messageboxdata->window) {
+        SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
+        window = data.uiwindow;
+    }
+
+    if (window == nil || window.rootViewController == nil) {
+        alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+        alertwindow.rootViewController = [UIViewController new];
+        alertwindow.windowLevel = UIWindowLevelAlert;
+
+        window = alertwindow;
+
+        [alertwindow makeKeyAndVisible];
+    }
+
+    [window.rootViewController presentViewController:alert animated:YES completion:nil];
+    UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
+
+    if (alertwindow) {
+        alertwindow.hidden = YES;
+    }
+
+    *buttonid = messageboxdata->buttons[clickedindex].buttonid;
+    return YES;
+#else
+    return NO;
+#endif /* __IPHONE_8_0 */
+}
+
+/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
 @interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
 
-@property (nonatomic, assign) int clickedIndex;
+@property (nonatomic, assign) int *clickedIndex;
 
 @end
 
@@ -40,52 +128,62 @@ static SDL_bool s_showingMessageBox = SDL_FALSE;
 
 - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
 {
-    _clickedIndex = (int)buttonIndex;
+    if (_clickedIndex != NULL) {
+        *_clickedIndex = (int) buttonIndex;
+    }
 }
 
 @end
+#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
 
-
-SDL_bool
-UIKit_ShowingMessageBox()
-{
-    return s_showingMessageBox;
-}
-
-int
-UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+static BOOL
+UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
 {
+    /* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
     int i;
+    int clickedindex = messageboxdata->numbuttons;
     const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
+    UIAlertView *alert = [[UIAlertView alloc] init];
+    SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
 
-    @autoreleasepool {
-        UIAlertView *alert = [[UIAlertView alloc] init];
-        SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
+    alert.delegate = delegate;
+    alert.title = @(messageboxdata->title);
+    alert.message = @(messageboxdata->message);
 
-        alert.delegate = delegate;
-        alert.title = @(messageboxdata->title);
-        alert.message = @(messageboxdata->message);
+    for (i = 0; i < messageboxdata->numbuttons; i++) {
+        [alert addButtonWithTitle:@(buttons[i].text)];
+    }
 
-        for (i = 0; i < messageboxdata->numbuttons; ++i) {
-            [alert addButtonWithTitle:@(buttons[i].text)];
-        }
+    delegate.clickedIndex = &clickedindex;
 
-        /* Set up for showing the alert */
-        delegate.clickedIndex = messageboxdata->numbuttons;
+    [alert show];
 
-        [alert show];
+    UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
 
-        /* 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 (delegate.clickedIndex == messageboxdata->numbuttons) {
-            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
-        }
-        s_showingMessageBox = SDL_FALSE;
+    alert.delegate = nil;
 
-        *buttonid = messageboxdata->buttons[delegate.clickedIndex].buttonid;
+    *buttonid = messageboxdata->buttons[clickedindex].buttonid;
+    return YES;
+#else
+    return NO;
+#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
+}
+
+int
+UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+    BOOL success = NO;
+
+    @autoreleasepool {
+        success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
+        if (!success) {
+            success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
+        }
+    }
 
-        alert.delegate = nil;
+    if (!success) {
+        return SDL_SetError("Could not show message box.");
     }
 
     return 0;
diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m
index e9c26e3..ef90124 100644
--- a/src/video/uikit/SDL_uikitopengles.m
+++ b/src/video/uikit/SDL_uikitopengles.m
@@ -52,8 +52,6 @@
 
 @end
 
-static int UIKit_GL_Initialize(_THIS);
-
 void *
 UIKit_GL_GetProcAddress(_THIS, const char *proc)
 {
diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h
index 17db0b2..e8462b8 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.h
+++ b/src/video/uikit/SDL_uikitviewcontroller.h
@@ -47,9 +47,7 @@
 - (void)loadView;
 - (void)viewDidLayoutSubviews;
 - (NSUInteger)supportedInterfaceOrientations;
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
 - (BOOL)prefersStatusBarHidden;
-- (UIStatusBarStyle)preferredStatusBarStyle;
 
 #if SDL_IPHONE_KEYBOARD
 - (void)showKeyboard;
diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m
index e1667aa..112638e 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.m
+++ b/src/video/uikit/SDL_uikitviewcontroller.m
@@ -135,12 +135,6 @@
     return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
 }
 
-- (UIStatusBarStyle)preferredStatusBarStyle
-{
-    /* We assume most SDL apps don't have a bright white background. */
-    return UIStatusBarStyleLightContent;
-}
-
 /*
  ---- Keyboard related functionality below this line ----
  */