From ab2a3500337a1437f5553dad85165af5df426dd9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 25 Sep 2015 15:17:20 -0300 Subject: [PATCH] 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. --- src/joystick/iphoneos/SDL_sysjoystick.m | 14 +- src/video/uikit/SDL_uikitmessagebox.m | 164 +++++++++++++++++----- src/video/uikit/SDL_uikitopengles.m | 2 - src/video/uikit/SDL_uikitviewcontroller.h | 2 - src/video/uikit/SDL_uikitviewcontroller.m | 6 - 5 files changed, 140 insertions(+), 48 deletions(-) diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index e9ad049639448..38c0ffe17b5cc 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -181,7 +181,7 @@ #endif /* !SDL_EVENTS_DISABLED */ } -SDL_JoystickDeviceItem * +static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device) { SDL_JoystickDeviceItem *prev = NULL; @@ -374,12 +374,14 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(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 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick) 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 dea8bdc69a2f2..6c980d4722489 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 -@property (nonatomic, assign) int clickedIndex; +@property (nonatomic, assign) int *clickedIndex; @end @@ -40,52 +128,62 @@ @implementation SDLAlertViewDelegate - (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 e9c26e3184455..ef901247fee5f 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -52,8 +52,6 @@ - (void)dealloc @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 17db0b26aff08..e8462b8e22a7a 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 e1667aac81228..112638eb2077b 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -135,12 +135,6 @@ - (BOOL)prefersStatusBarHidden 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 ---- */