From c351e27667ed2a1cc368733960f873d0d9d9ab4c Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 14 Jul 2014 16:50:25 -0300 Subject: [PATCH 01/41] Misc. iOS code improvements. - Use @autoreleasepool instead of NSAutoReleasePool. - Code style fixups. --HG-- branch : iOS-improvements --- .hgignore | 3 + include/SDL_syswm.h | 12 +++- src/file/cocoa/SDL_rwopsbundlesupport.m | 27 ++++---- src/filesystem/cocoa/SDL_sysfilesystem.m | 88 ++++++++++++------------ src/video/uikit/SDL_uikitappdelegate.m | 12 ++-- src/video/uikit/SDL_uikitevents.m | 3 +- src/video/uikit/SDL_uikitmessagebox.m | 62 ++++++++--------- src/video/uikit/SDL_uikitview.m | 30 +++----- 8 files changed, 117 insertions(+), 120 deletions(-) diff --git a/.hgignore b/.hgignore index e61b7d96a..a0d89da14 100644 --- a/.hgignore +++ b/.hgignore @@ -8,6 +8,9 @@ Makefile sdl-config SDL2.spec build +Build +*xcuserdata* +*xcworkspacedata* # for Xcode *.orig diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index 715f2c058..c81cd48de 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -208,13 +208,21 @@ struct SDL_SysWMinfo #if defined(SDL_VIDEO_DRIVER_COCOA) struct { - NSWindow *window; /* The Cocoa window */ +#if defined(__OBJC__) && __has_feature(objc_arc) + NSWindow __unsafe_unretained *window; /* The Cocoa window */ +#else + NSWindow *window; /* The Cocoa window */ +#endif } cocoa; #endif #if defined(SDL_VIDEO_DRIVER_UIKIT) struct { - UIWindow *window; /* The UIKit window */ +#if defined(__OBJC__) && __has_feature(objc_arc) + UIWindow __unsafe_unretained *window; /* The UIKit window */ +#else + UIWindow *window; /* The UIKit window */ +#endif } uikit; #endif #if defined(SDL_VIDEO_DRIVER_WAYLAND) diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.m b/src/file/cocoa/SDL_rwopsbundlesupport.m index f6a65a99a..fcab269c9 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.m +++ b/src/file/cocoa/SDL_rwopsbundlesupport.m @@ -41,27 +41,24 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode) return fopen(file, mode); } - NSAutoreleasePool* autorelease_pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + NSFileManager* file_manager = [NSFileManager defaultManager]; + NSString* resource_path = [[NSBundle mainBundle] resourcePath]; + NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)]; - NSFileManager* file_manager = [NSFileManager defaultManager]; - NSString* resource_path = [[NSBundle mainBundle] resourcePath]; - - NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)]; - - 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); + 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 { + fp = fopen(file, mode); + } } - else { - fp = fopen(file, mode); - } - - [autorelease_pool drain]; return fp; } -#endif /* __MACOSX__ */ +#endif /* __APPLE__ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index adcebd68b..d11739eb9 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -36,67 +36,69 @@ char * SDL_GetBasePath(void) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSBundle *bundle = [NSBundle mainBundle]; - const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String]; - const char *base = NULL; char *retval = NULL; - if (baseType == NULL) { - baseType = "resource"; - } - if (SDL_strcasecmp(baseType, "bundle")==0) { - base = [[bundle bundlePath] fileSystemRepresentation]; - } else if (SDL_strcasecmp(baseType, "parent")==0) { - base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation]; - } else { - /* 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); - if (retval == NULL) { - SDL_OutOfMemory(); + + @autoreleasepool { + const char *base = NULL; + NSBundle *bundle = [NSBundle mainBundle]; + const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String]; + if (baseType == NULL) { + baseType = "resource"; + } + if (SDL_strcasecmp(baseType, "bundle")==0) { + base = [[bundle bundlePath] fileSystemRepresentation]; + } else if (SDL_strcasecmp(baseType, "parent")==0) { + base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation]; } else { - SDL_snprintf(retval, len, "%s/", base); + /* 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); + if (retval == NULL) { + SDL_OutOfMemory(); + } else { + SDL_snprintf(retval, len, "%s/", base); + } } } - [pool release]; return retval; } char * SDL_GetPrefPath(const char *org, const char *app) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); char *retval = NULL; - if ([array count] > 0) { /* we only want the first item in the list. */ - NSString *str = [array objectAtIndex:0]; - const char *base = [str fileSystemRepresentation]; - if (base) { - const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; - retval = (char *) SDL_malloc(len); - if (retval == NULL) { - SDL_OutOfMemory(); - } else { - char *ptr; - SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app); - for (ptr = retval+1; *ptr; ptr++) { - if (*ptr == '/') { - *ptr = '\0'; - mkdir(retval, 0700); - *ptr = '/'; + @autoreleasepool { + 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]; + if (base) { + const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; + retval = (char *) SDL_malloc(len); + if (retval == NULL) { + SDL_OutOfMemory(); + } else { + char *ptr; + SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app); + for (ptr = retval+1; *ptr; ptr++) { + if (*ptr == '/') { + *ptr = '\0'; + mkdir(retval, 0700); + *ptr = '/'; + } } + mkdir(retval, 0700); } - mkdir(retval, 0700); } } } - - [pool release]; return retval; } diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index a9924fbca..2d9280782 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/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, NULL, [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; } @@ -151,8 +151,8 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa } else { image = self->splashPortrait; } - if (image) - { + + if (image) { splash.image = image; } } @@ -165,7 +165,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]; } diff --git a/src/video/uikit/SDL_uikitevents.m b/src/video/uikit/SDL_uikitevents.m index 94fba878b..48bb1bd56 100644 --- a/src/video/uikit/SDL_uikitevents.m +++ b/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 diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index c24f3ff8b..78f84e3eb 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -71,41 +71,39 @@ int UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { int clicked; - - 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]; - - const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; int i; - for (i = 0; i < messageboxdata->numbuttons; ++i) { - [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]]; + const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; + + @autoreleasepool { + UIAlertView* alert = [[UIAlertView alloc] init]; + + alert.title = [NSString stringWithUTF8String:messageboxdata->title]; + alert.message = [NSString stringWithUTF8String:messageboxdata->message]; + alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; + + for (i = 0; i < messageboxdata->numbuttons; ++i) { + [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]]; + } + + /* Set up for showing the alert */ + clicked = messageboxdata->numbuttons; + + [alert show]; + + /* 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; + + *buttonid = messageboxdata->buttons[clicked].buttonid; + + [alert.delegate release]; + [alert release]; } - /* Set up for showing the alert */ - clicked = messageboxdata->numbuttons; - - [alert show]; - - /* 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; - - *buttonid = messageboxdata->buttons[clicked].buttonid; - - [alert.delegate release]; - [alert release]; - - [pool release]; - return 0; } diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index c51a3ba71..a7fa3d511 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -35,7 +35,7 @@ #include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" -void _uikit_keyboard_init() ; +void _uikit_keyboard_init(); @implementation SDL_uikitview @@ -66,7 +66,7 @@ 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_Window *window = viewcontroller.window; SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata; @@ -83,18 +83,15 @@ void _uikit_keyboard_init() ; - (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(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(viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); leftFingerDown = touch; } @@ -118,19 +115,15 @@ 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(viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); leftFingerDown = nil; } @@ -149,7 +142,6 @@ void _uikit_keyboard_init() ; } } #endif - touch = (UITouch*)[enumerator nextObject]; } } @@ -165,15 +157,12 @@ 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(viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; @@ -190,7 +179,6 @@ void _uikit_keyboard_init() ; } } #endif - touch = (UITouch*)[enumerator nextObject]; } } From 2ea3b21ca307b981f864b52a34c342dd6c8b9bec Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 14 Jul 2014 22:35:48 -0300 Subject: [PATCH 02/41] Changed the way retina resolutions are handled in iOS. Previously, SDL would always expose display modes and window dimensions in terms of pixels, and would add an extra 'fake' display mode on retina screens which would contain the non-retina resolution. Calling SDL_CreateWindow with the dimensions of that fake display mode would not work. Now, SDL only exposes display modes and window dimensions in terms of points rather than pixels. If the SDL_WINDOW_ALLOW_HIGHDPI flag is passed into SDL_CreateWindow, then any OpenGL contexts created from that window will be sized in pixels rather than points (retrievable with SDL_GL_GetDrawableSize.) Window dimensions and mouse coordinates are still in terms of points rather than pixels even with that flag. This matches the behavior of SDL in OS X more closely, and lets users choose whether to make use of retina displays and lets them handle it properly. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitmodes.h | 2 - src/video/uikit/SDL_uikitmodes.m | 50 ++++++++--------------- src/video/uikit/SDL_uikitopengles.h | 2 + src/video/uikit/SDL_uikitopengles.m | 42 ++++++++++++++----- src/video/uikit/SDL_uikitopenglview.h | 4 ++ src/video/uikit/SDL_uikitopenglview.m | 7 +++- src/video/uikit/SDL_uikitvideo.m | 7 ++-- src/video/uikit/SDL_uikitview.m | 14 +------ src/video/uikit/SDL_uikitviewcontroller.h | 2 +- src/video/uikit/SDL_uikitviewcontroller.m | 12 ++---- src/video/uikit/SDL_uikitwindow.m | 17 ++++---- 11 files changed, 77 insertions(+), 82 deletions(-) diff --git a/src/video/uikit/SDL_uikitmodes.h b/src/video/uikit/SDL_uikitmodes.h index 9f2e9dd34..276685039 100644 --- a/src/video/uikit/SDL_uikitmodes.h +++ b/src/video/uikit/SDL_uikitmodes.h @@ -28,13 +28,11 @@ typedef struct { UIScreen *uiscreen; - CGFloat scale; } SDL_DisplayData; typedef struct { UIScreenMode *uiscreenmode; - CGFloat scale; } SDL_DisplayModeData; extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen); diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 05e33d9c9..20a433d55 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -28,7 +28,7 @@ static int UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode, - UIScreenMode * uiscreenmode, CGFloat scale) + UIScreenMode * uiscreenmode) { SDL_DisplayModeData *data = NULL; @@ -41,8 +41,6 @@ UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode, data->uiscreenmode = uiscreenmode; [data->uiscreenmode retain]; - - data->scale = scale; } mode->driverdata = data; @@ -63,14 +61,14 @@ UIKit_FreeDisplayModeData(SDL_DisplayMode * mode) 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 +83,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 +112,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; } @@ -148,7 +138,6 @@ UIKit_AddDisplay(UIScreen *uiscreen) [uiscreen retain]; data->uiscreen = uiscreen; - data->scale = scale; display.driverdata = data; SDL_AddVideoDisplay(&display); @@ -186,11 +175,14 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) 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; - int h = (int)size.height; + int w = (int)(size.width / scale); + int h = (int)(size.height / scale); /* Make sure the width/height are oriented correctly */ if (isLandscape != (w > h)) { @@ -200,17 +192,7 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) } /* 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); - } + UIKit_AddDisplayMode(display, w, h, uimode, addRotation); } } diff --git a/src/video/uikit/SDL_uikitopengles.h b/src/video/uikit/SDL_uikitopengles.h index 947678cae..f16918935 100644 --- a/src/video/uikit/SDL_uikitopengles.h +++ b/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); diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 42303e3cb..7313df6aa 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -49,7 +49,8 @@ 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) { if (context) { SDL_WindowData *data = (SDL_WindowData *)window->driverdata; @@ -62,6 +63,19 @@ int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) return 0; } +void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) +{ + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + + if (w) { + *w = data->view.backingWidth; + } + if (h) { + *h = data->view.backingHeight; + } +} + + int UIKit_GL_LoadLibrary(_THIS, const char *path) { @@ -96,15 +110,22 @@ void UIKit_GL_SwapWindow(_THIS, SDL_Window * window) */ } -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; + 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; + } if (_this->gl_config.share_with_current_context) { SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); @@ -114,12 +135,12 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window) /* 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]; + frame = [[uiwindow screen] bounds]; } else { - frame = [displaydata->uiscreen applicationFrame]; + frame = [[uiwindow screen] applicationFrame]; } view = [[SDL_uikitopenglview alloc] initWithFrame: frame - scale: displaymodedata->scale + scale: scale retainBacking: _this->gl_config.retained_backing rBits: _this->gl_config.red_size gBits: _this->gl_config.green_size @@ -152,7 +173,7 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window) } /* Make this window the current mouse focus for touch input */ - if (displaydata->uiscreen == [UIScreen mainScreen]) { + if ([uiwindow screen] == [UIScreen mainScreen]) { SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); } @@ -160,7 +181,8 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window) return view; } -void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) +void +UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { /* the delegate has retained the view, this will release him */ SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index eed2e5b70..3eb9b4f44 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -55,6 +55,10 @@ @property (nonatomic, retain, 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; + - (void)swapBuffers; - (void)setCurrentContext; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 144100bf7..91f690563 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -32,6 +32,9 @@ @synthesize context; +@synthesize backingWidth = backingWidth; +@synthesize backingHeight = backingHeight; + + (Class)layerClass { return [CAEAGLLayer class]; @@ -74,7 +77,9 @@ eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil]; + [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, + colorFormat, kEAGLDrawablePropertyColorFormat, + nil]; context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup]; if (!context || ![EAGLContext setCurrentContext:context]) { diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 4893bc163..e4266ea2e 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -93,12 +93,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; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index a7fa3d511..7312307f5 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -65,19 +65,12 @@ void _uikit_keyboard_init(); { CGPoint point = [touch locationInView: self]; - /* Get the display scale and apply that to the input coordinates */ - SDL_Window *window = viewcontroller.window; - SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); - SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata; - if (normalize) { 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; } @@ -360,7 +353,6 @@ void _uikit_keyboard_update() { 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); @@ -382,9 +374,6 @@ void _uikit_keyboard_update() { offsety = -offsety; } - offsetx /= scale; - offsety /= scale; - view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height); } @@ -412,7 +401,6 @@ void _uikit_keyboard_init() { if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) { height = keyboardSize.width; } - height *= [UIScreen mainScreen].scale; _uikit_keyboard_set_height(height); } ]; diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index e8d595d9b..cc14d4c40 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/src/video/uikit/SDL_uikitviewcontroller.h @@ -28,7 +28,7 @@ SDL_Window *window; } -@property (readwrite) SDL_Window *window; +@property (nonatomic, readwrite) SDL_Window *window; - (id)initWithSDLWindow:(SDL_Window *)_window; - (void)loadView; diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 447b80b80..3bedcc4ec 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -56,15 +56,11 @@ - (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; + if (window->flags & SDL_WINDOW_RESIZABLE) { + SDL_WindowData *data = window->driverdata; const CGSize size = data->view.bounds.size; - int w, h; - - w = (int)(size.width * displaymodedata->scale); - h = (int)(size.height * displaymodedata->scale); + int w = (int) size.width; + int h = (int) size.height; SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h); } diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 2b1567778..8c348353c 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -47,7 +47,6 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *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; @@ -72,9 +71,9 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo bounds = [displaydata->uiscreen applicationFrame]; } - /* 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) bounds.size.width; + int height = (int) bounds.size.height; /* Make sure the width/height are oriented correctly */ if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) { @@ -191,8 +190,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* 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]]; + UIWindow *uiwindow = [[UIWindow 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 @@ -243,7 +241,6 @@ void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; - SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata; UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; if (fullscreen) { @@ -259,9 +256,9 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display bounds = [displaydata->uiscreen applicationFrame]; } - /* 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) bounds.size.width; + int height = (int) bounds.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. From 701d88bb5b200f8010f81b1c90c18a880a196db2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 15 Jul 2014 02:01:43 -0300 Subject: [PATCH 03/41] iOS now respects SDL_HINT_ACCELEROMETER_AS_JOYSTICK. --HG-- branch : iOS-improvements --- include/SDL_hints.h | 5 +++-- src/joystick/iphoneos/SDL_sysjoystick.m | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index e0fce669f..1c46515ed 100644 --- a/include/SDL_hints.h +++ b/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 diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index a4027599e..1f37af413 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/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++; + } + + return numjoysticks; } int SDL_SYS_NumJoysticks() { - return 1; + return numjoysticks; } void SDL_SYS_JoystickDetect() @@ -165,6 +173,8 @@ SDL_SYS_JoystickQuit(void) [motionManager release]; motionManager = nil; } + + numjoysticks = 0; } SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index ) From 52f0e36925fbbc94ae223e82bebd0349bf83d0f0 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 15 Jul 2014 02:04:08 -0300 Subject: [PATCH 04/41] Minor fix for if SDL_JoystickInit is called more than once without a matching SDL_JoystickQuit. --HG-- branch : iOS-improvements --- src/joystick/iphoneos/SDL_sysjoystick.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index 1f37af413..31b4e84b0 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -49,7 +49,7 @@ SDL_SYS_JoystickInit(void) const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK); if (!hint || SDL_atoi(hint)) { /* Default behavior, accelerometer as joystick */ - numjoysticks++; + numjoysticks = 1; } return numjoysticks; From d67085b17c577662058fd7460b518fcfff49212c Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 16 Jul 2014 16:12:20 -0300 Subject: [PATCH 05/41] Fixed SDL_SetWindowFullscreen not properly updating the status bar visibility in iOS 7+ --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitwindow.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 8c348353c..78f0c211f 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -241,7 +241,9 @@ void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; + SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; + UIWindow *uiwindow = windowdata->uiwindow; if (fullscreen) { [UIApplication sharedApplication].statusBarHidden = YES; @@ -249,6 +251,12 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display [UIApplication sharedApplication].statusBarHidden = NO; } +#ifdef __IPHONE_7_0 + if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { + [viewcontroller setNeedsStatusBarAppearanceUpdate]; + } +#endif + CGRect bounds; if (fullscreen) { bounds = [displaydata->uiscreen bounds]; From 7781a9702354994566220a02b013d9750f3a94fd Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 16 Jul 2014 20:05:00 -0300 Subject: [PATCH 06/41] The iOS 7 transparent status bar now uses white text rather than black. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopenglview.m | 3 ++- src/video/uikit/SDL_uikitviewcontroller.h | 1 + src/video/uikit/SDL_uikitviewcontroller.m | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 91f690563..80335e79b 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -169,8 +169,9 @@ animationCallback = callback; animationCallbackParam = callbackParam; - if (animationCallback) + if (animationCallback) { [self startAnimation]; + } } - (void)startAnimation diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index cc14d4c40..64cb47e82 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/src/video/uikit/SDL_uikitviewcontroller.h @@ -36,5 +36,6 @@ - (NSUInteger)supportedInterfaceOrientations; - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient; - (BOOL)prefersStatusBarHidden; +- (UIStatusBarStyle)preferredStatusBarStyle; @end diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 3bedcc4ec..433b91b2e 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -124,6 +124,16 @@ } } +- (UIStatusBarStyle)preferredStatusBarStyle +{ +#ifdef __IPHONE_7_0 + return UIStatusBarStyleLightContent; +#else + /* This is only called in iOS 7+, so the return value isn't important. */ + return UIStatusBarStyleBlackTranslucent; +#endif +} + @end #endif /* SDL_VIDEO_DRIVER_UIKIT */ From 540f7a01e34b5029679b629088aa331a3638fca1 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 16 Jul 2014 21:06:15 -0300 Subject: [PATCH 07/41] Fixed SDL_HINT_ORIENTATIONS to properly allow disabling custom orientations if the hint is set with no valid orientations. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitviewcontroller.m | 26 ++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 433b91b2e..52737a348 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -69,13 +69,12 @@ - (NSUInteger)supportedInterfaceOrientations { NSUInteger orientationMask = 0; + const char *orientationsHint = 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: + if (orientationsHint != NULL) { + NSString *orientationsString = [NSString stringWithCString:orientationsHint + encoding:NSUTF8StringEncoding]; + NSArray *orientations = [orientationsString componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@" "]]; if ([orientations containsObject:@"LandscapeLeft"]) { @@ -90,14 +89,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); } } @@ -117,7 +119,7 @@ - (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; @@ -129,7 +131,7 @@ #ifdef __IPHONE_7_0 return UIStatusBarStyleLightContent; #else - /* This is only called in iOS 7+, so the return value isn't important. */ + /* This method is only used in iOS 7+, so the return value here isn't important. */ return UIStatusBarStyleBlackTranslucent; #endif } From cd7a8a2dd4a05f96b99177c2c8440b9c079b7f40 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 17 Jul 2014 18:05:12 -0300 Subject: [PATCH 08/41] Properly send a window resize event in all cases when viewDidLayoutSubviews is triggered. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitviewcontroller.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 52737a348..808280ec1 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -56,14 +56,12 @@ - (void)viewDidLayoutSubviews { - if (window->flags & SDL_WINDOW_RESIZABLE) { - SDL_WindowData *data = window->driverdata; - const CGSize size = data->view.bounds.size; - int w = (int) size.width; - int h = (int) size.height; + SDL_WindowData *data = window->driverdata; + const CGSize size = data->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 @@ -91,7 +89,7 @@ } } - if (orientationMask == 0 && window->flags & SDL_WINDOW_RESIZABLE) { + if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) { orientationMask = UIInterfaceOrientationMaskAll; /* any orientation is okay. */ } From e83e29ce07216f3f633f33c7c8ff54efebca9604 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 17 Jul 2014 22:55:59 -0300 Subject: [PATCH 09/41] Disabled the custom iOS splashscreen code - it interferes with the normal rotation and orientation behaviour of SDL windows. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.m | 10 ++++++++-- src/video/uikit/SDL_uikitviewcontroller.m | 1 + src/video/uikit/SDL_uikitwindow.m | 8 ++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 2d9280782..212d57691 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -205,12 +205,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]]; diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 808280ec1..7fee597eb 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -127,6 +127,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { #ifdef __IPHONE_7_0 + /* We assume most games don't have a bright white background. */ return UIStatusBarStyleLightContent; #else /* This method is only used in iOS 7+, so the return value here isn't important. */ diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 78f0c211f..f25479b75 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -42,8 +42,6 @@ #include - - static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created) { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); @@ -115,9 +113,7 @@ 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 = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window]; [data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */ return 0; @@ -245,7 +241,7 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; UIWindow *uiwindow = windowdata->uiwindow; - if (fullscreen) { + if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; } else { [UIApplication sharedApplication].statusBarHidden = NO; From 7f3ba59f8b093a41436224c2b1948729a1f83f1f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 21 Jul 2014 02:46:53 -0300 Subject: [PATCH 10/41] The default implementation of [view layoutSubviews] actually does something in iOS 6+, so we should call [super layoutSubviews] when overriding it. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopenglview.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 80335e79b..48f5981e6 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -212,6 +212,8 @@ - (void)layoutSubviews { + [super layoutSubviews]; + [EAGLContext setCurrentContext:context]; [self updateFrame]; } From e1d84374a1b1c53c569ad613e16096e9c9cd9b7a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 22 Jul 2014 16:48:35 -0300 Subject: [PATCH 11/41] Fixed SDL_SetWindowFullscreen on iOS to properly update the view's frame. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitwindow.m | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index f25479b75..275579adb 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -240,6 +240,7 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; UIWindow *uiwindow = windowdata->uiwindow; + CGRect bounds; if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; @@ -253,13 +254,17 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display } #endif - CGRect bounds; - if (fullscreen) { + if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { bounds = [displaydata->uiscreen bounds]; } else { bounds = [displaydata->uiscreen applicationFrame]; } + /* Update the view's frame to account for the status bar change. */ + windowdata->view.frame = bounds; + [windowdata->view setNeedsLayout]; + [windowdata->view layoutIfNeeded]; + /* Get frame dimensions */ int width = (int) bounds.size.width; int height = (int) bounds.size.height; @@ -268,21 +273,11 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display 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; - } + window->w = SDL_max(width, height); + window->h = SDL_min(width, height); } else { - if (width > height) { - window->w = height; - window->h = width; - } else { - window->w = width; - window->h = height; - } + window->w = SDL_min(width, height); + window->h = SDL_max(width, height); } } From adff9206e32aed67a33e93f235a443a014a15aec Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 22 Jul 2014 20:06:13 -0300 Subject: [PATCH 12/41] Cleaned up iOS OpenGL ES context creation code and added sRGB context support on iOS 7+ --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopengles.m | 24 ++++---- src/video/uikit/SDL_uikitopenglview.h | 21 ++++--- src/video/uikit/SDL_uikitopenglview.m | 87 +++++++++++++++++---------- 3 files changed, 79 insertions(+), 53 deletions(-) diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 7313df6aa..aeb81e61d 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -132,24 +132,26 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) share_group = [view.context sharegroup]; } - /* construct our view, passing in SDL's OpenGL configuration data */ CGRect frame; if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { frame = [[uiwindow screen] bounds]; } else { frame = [[uiwindow screen] applicationFrame]; } + + /* 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 - majorVersion: _this->gl_config.major_version - shareGroup: share_group]; + 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; } diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 3eb9b4f44..b951ac50e 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -63,16 +63,17 @@ - (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; + 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; - (void)updateFrame; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 48f5981e6..b5c16eab4 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -41,16 +41,17 @@ } - (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; @@ -59,12 +60,29 @@ 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]) { + [self release]; + SDL_SetError("OpenGL ES %d not supported", majorVersion); + return nil; + } + +#ifdef __IPHONE_7_0 + /* sRGB context support was added in iOS 7 */ + BOOL hasiOS7 = [[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending; + if (sRGB && hasiOS7) { + colorFormat = kEAGLColorFormatSRGBA8; + } else +#endif + if (rBits >= 8 && gBits >= 8 && bBits >= 8) { /* if user specifically requests rbg888 or some color format higher than 16bpp */ colorFormat = kEAGLColorFormatRGBA8; } else { @@ -81,23 +99,24 @@ 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; - } - /* 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); - - glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); - [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; + + if (![context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer]) { + [self release]; + SDL_SetError("Failed creating OpenGL ES drawable"); + return nil; + } + + /* Create the Framebuffer Object */ + glGenFramebuffersOES(1, &viewFramebuffer); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); + + /* 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); @@ -124,15 +143,14 @@ } if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - return NO; + [self release]; + 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; } @@ -220,12 +238,17 @@ - (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; } From 689ed320a9963d4573aec29d57d9804bb9a4072a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 23 Jul 2014 01:28:24 -0300 Subject: [PATCH 13/41] Updated the iOS Objective-C code to use NSDictionary/NSArray/NSNumber literals and subscripting, for improved code clarity. This requires at least Xcode 4.5 and the iOS 6 SDK to build, but it doesn't change the minimum supported runtime version (iOS 5.1). Less than 2% of iOS users are running iOS 5, so I hope developers aren't trying to build SDL using an SDK which doesn't support iOS 6/7... --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitmessagebox.m | 6 +++--- src/video/uikit/SDL_uikitopenglview.m | 8 ++++---- src/video/uikit/SDL_uikitvideo.h | 14 -------------- src/video/uikit/SDL_uikitview.h | 6 +++--- src/video/uikit/SDL_uikitview.m | 2 +- src/video/uikit/SDL_uikitviewcontroller.m | 4 +--- 6 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index 78f84e3eb..0fa4bda2e 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -53,7 +53,7 @@ static SDL_bool s_showingMessageBox = SDL_FALSE; return self; } -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { *clickedButtonIndex = (int)buttonIndex; } @@ -77,8 +77,8 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) @autoreleasepool { UIAlertView* alert = [[UIAlertView alloc] init]; - alert.title = [NSString stringWithUTF8String:messageboxdata->title]; - alert.message = [NSString stringWithUTF8String:messageboxdata->message]; + alert.title = @(messageboxdata->title); + alert.message = @(messageboxdata->message); alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; for (i = 0; i < messageboxdata->numbuttons; ++i) { diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index b5c16eab4..1f33f529d 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -94,10 +94,10 @@ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; - eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, - colorFormat, kEAGLDrawablePropertyColorFormat, - nil]; + eaglLayer.drawableProperties = @{ + kEAGLDrawablePropertyRetainedBacking: @(retained), + kEAGLDrawablePropertyColorFormat: colorFormat + }; /* Set the appropriate scale (for retina display support) */ self.contentScaleFactor = scale; diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h index ef6298257..819f93aff 100644 --- a/src/video/uikit/SDL_uikitvideo.h +++ b/src/video/uikit/SDL_uikitvideo.h @@ -25,20 +25,6 @@ #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 */ - #endif /* _SDL_uikitvideo_h */ diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index ce616c07e..8191915b3 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -61,9 +61,9 @@ - (void)showKeyboard; - (void)hideKeyboard; - (void)initializeKeyboard; -@property (readonly) BOOL keyboardVisible; -@property (nonatomic,assign) SDL_Rect textInputRect; -@property (nonatomic,assign) int keyboardHeight; +@property (nonatomic, readonly) 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); diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 7312307f5..0f790169d 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -395,7 +395,7 @@ 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) { diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 7fee597eb..d21723bfe 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -70,9 +70,7 @@ const char *orientationsHint = SDL_GetHint(SDL_HINT_ORIENTATIONS); if (orientationsHint != NULL) { - NSString *orientationsString = [NSString stringWithCString:orientationsHint - encoding:NSUTF8StringEncoding]; - NSArray *orientations = [orientationsString componentsSeparatedByCharactersInSet: + NSArray *orientations = [@(orientationsHint) componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@" "]]; if ([orientations containsObject:@"LandscapeLeft"]) { From d53e8dc61aa926927ac64625d097899fa4a4d097 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 23 Jul 2014 01:33:59 -0300 Subject: [PATCH 14/41] 90% of iOS users on the App Store run at least iOS 7, so it doesn't make sense to support building using an SDK that doesn't support iOS 7. The minimum supported runtime version is still iOS 5.1. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopenglview.m | 7 ++----- src/video/uikit/SDL_uikitviewcontroller.m | 5 ----- src/video/uikit/SDL_uikitwindow.m | 3 +-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 1f33f529d..f388fa31a 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -75,14 +75,11 @@ return nil; } -#ifdef __IPHONE_7_0 - /* sRGB context support was added in iOS 7 */ BOOL hasiOS7 = [[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending; if (sRGB && hasiOS7) { + /* sRGB EAGL drawable support was added in iOS 7 */ colorFormat = kEAGLColorFormatSRGBA8; - } else -#endif - if (rBits >= 8 && gBits >= 8 && bBits >= 8) { + } else if (rBits >= 8 && gBits >= 8 && bBits >= 8) { /* if user specifically requests rbg888 or some color format higher than 16bpp */ colorFormat = kEAGLColorFormatRGBA8; } else { diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index d21723bfe..c7b3d0934 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -124,13 +124,8 @@ - (UIStatusBarStyle)preferredStatusBarStyle { -#ifdef __IPHONE_7_0 /* We assume most games don't have a bright white background. */ return UIStatusBarStyleLightContent; -#else - /* This method is only used in iOS 7+, so the return value here isn't important. */ - return UIStatusBarStyleBlackTranslucent; -#endif } @end diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 275579adb..9d5f0eeff 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -248,11 +248,10 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display [UIApplication sharedApplication].statusBarHidden = NO; } -#ifdef __IPHONE_7_0 + /* iOS 7+ won't update the status bar until we tell it to. */ if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { [viewcontroller setNeedsStatusBarAppearanceUpdate]; } -#endif if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { bounds = [displaydata->uiscreen bounds]; From 6ebdaca6724b2b92d47f69ccbd2e5324480790c6 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 23 Jul 2014 03:05:31 -0300 Subject: [PATCH 15/41] More cleanup of the iOS Objective-C code. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.m | 13 ++++--- src/video/uikit/SDL_uikitmessagebox.m | 12 +++--- src/video/uikit/SDL_uikitopenglview.h | 46 ++++++----------------- src/video/uikit/SDL_uikitopenglview.m | 24 +++++++++--- src/video/uikit/SDL_uikitview.h | 18 ++------- src/video/uikit/SDL_uikitview.m | 33 +++++++++------- src/video/uikit/SDL_uikitviewcontroller.h | 7 +--- src/video/uikit/SDL_uikitwindow.m | 1 - 8 files changed, 69 insertions(+), 85 deletions(-) diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 212d57691..b72a52c2b 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -75,17 +75,18 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa [UIApplication sharedApplication].idleTimerDisabled = disable; } -@interface SDL_splashviewcontroller : UIViewController { +@interface SDL_splashviewcontroller : UIViewController + +- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation; + +@end + +@implementation SDL_splashviewcontroller { UIImageView *splash; UIImage *splashPortrait; UIImage *splashLandscape; } -- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation; -@end - -@implementation SDL_splashviewcontroller - - (id)init { self = [super init]; diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index 0fa4bda2e..4a1d32b7b 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -30,17 +30,16 @@ static SDL_bool s_showingMessageBox = SDL_FALSE; -@interface UIKit_UIAlertViewDelegate : NSObject { -@private - int *clickedButtonIndex; -} +@interface UIKit_UIAlertViewDelegate : NSObject - (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,7 +47,8 @@ static SDL_bool s_showingMessageBox = SDL_FALSE; if (self == nil) { return nil; } - self->clickedButtonIndex = buttonIndex; + + clickedButtonIndex = buttonIndex; return self; } diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index b951ac50e..4f40514cd 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -29,38 +29,7 @@ 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 { - -@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; - -/* The width and height of the drawable in pixels (as opposed to points.) */ -@property (nonatomic, readonly) int backingWidth; -@property (nonatomic, readonly) int backingHeight; - -- (void)swapBuffers; -- (void)setCurrentContext; +@interface SDL_uikitopenglview : SDL_uikitview - (id)initWithFrame:(CGRect)frame scale:(CGFloat)scale @@ -75,11 +44,20 @@ majorVersion:(int)majorVersion shareGroup:(EAGLSharegroup*)shareGroup; +@property (nonatomic, retain, 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; + +- (void)swapBuffers; +- (void)setCurrentContext; + - (void)updateFrame; - (void)setAnimationCallback:(int)interval - callback:(void (*)(void*))callback - callbackParam:(void*)callbackParam; + callback:(void (*)(void*))callback + callbackParam:(void*)callbackParam; - (void)startAnimation; - (void)stopAnimation; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index f388fa31a..40127c055 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -28,12 +28,28 @@ #include "SDL_uikitmessagebox.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 = backingWidth; -@synthesize backingHeight = backingHeight; +@synthesize backingWidth; +@synthesize backingHeight; + (Class)layerClass { @@ -53,8 +69,6 @@ majorVersion:(int)majorVersion shareGroup:(EAGLSharegroup*)shareGroup { - depthBufferFormat = 0; - if ((self = [super initWithFrame:frame])) { const BOOL useStencilBuffer = (stencilBits != 0); const BOOL useDepthBuffer = (depthBits != 0); diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 8191915b3..417a68f41 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -35,23 +35,10 @@ #else @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 - @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,7 +48,8 @@ - (void)showKeyboard; - (void)hideKeyboard; - (void)initializeKeyboard; -@property (nonatomic, readonly) BOOL keyboardVisible; + +@property (nonatomic, readonly, assign, getter=isKeyboardVisible) BOOL keyboardVisible; @property (nonatomic, assign) SDL_Rect textInputRect; @property (nonatomic, assign) int keyboardHeight; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 0f790169d..18a0538d6 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -37,7 +37,19 @@ 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 { @@ -66,7 +78,7 @@ void _uikit_keyboard_init(); CGPoint point = [touch locationInView: self]; if (normalize) { - CGRect bounds = [self bounds]; + CGRect bounds = self.bounds; point.x /= bounds.size.width; point.y /= bounds.size.height; } @@ -122,7 +134,7 @@ void _uikit_keyboard_init(); 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; @@ -160,7 +172,7 @@ void _uikit_keyboard_init(); 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; @@ -180,14 +192,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 @@ -337,7 +344,7 @@ SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) return 0; } - return view.keyboardVisible; + return view.isKeyboardVisible; } diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index 64cb47e82..0ca98eb40 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/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 (nonatomic, readwrite) SDL_Window *window; +@property (nonatomic, assign) SDL_Window *window; - (id)initWithSDLWindow:(SDL_Window *)_window; - (void)loadView; diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 9d5f0eeff..b636ed7da 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -239,7 +239,6 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; - UIWindow *uiwindow = windowdata->uiwindow; CGRect bounds; if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { From e34e3dfd5c5247028bafc2223afb3dbb95760037 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 23 Jul 2014 21:55:42 -0300 Subject: [PATCH 16/41] Fixed SDL_SetWindowFullscreen on iOS for the last time, hopefully. Fixed iOS version checking code. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopengles.m | 12 +++--------- src/video/uikit/SDL_uikitopenglview.m | 4 ++-- src/video/uikit/SDL_uikitvideo.h | 2 ++ src/video/uikit/SDL_uikitvideo.m | 20 ++++++++++++++++++++ src/video/uikit/SDL_uikitwindow.m | 26 ++++++++------------------ 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index aeb81e61d..0b4a684ed 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -116,6 +116,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) SDL_uikitopenglview *view; SDL_WindowData *data = (SDL_WindowData *) window->driverdata; UIWindow *uiwindow = data->uiwindow; + CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen); EAGLSharegroup *share_group = nil; CGFloat scale = 1.0; @@ -124,7 +125,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) dimensions of the OpenGL view will match the pixel dimensions of the screen rather than the dimensions in points. */ - scale = [uiwindow screen].scale; + scale = uiwindow.screen.scale; } if (_this->gl_config.share_with_current_context) { @@ -132,13 +133,6 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) share_group = [view.context sharegroup]; } - CGRect frame; - if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { - frame = [[uiwindow screen] bounds]; - } else { - frame = [[uiwindow screen] applicationFrame]; - } - /* construct our view, passing in SDL's OpenGL configuration data */ view = [[SDL_uikitopenglview alloc] initWithFrame: frame scale: scale @@ -175,7 +169,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) } /* Make this window the current mouse focus for touch input */ - if ([uiwindow screen] == [UIScreen mainScreen]) { + if (uiwindow.screen == [UIScreen mainScreen]) { SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); } diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 40127c055..7daa12f65 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -26,6 +26,7 @@ #include #include "SDL_uikitopenglview.h" #include "SDL_uikitmessagebox.h" +#include "SDL_uikitvideo.h" @implementation SDL_uikitopenglview { @@ -89,8 +90,7 @@ return nil; } - BOOL hasiOS7 = [[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending; - if (sRGB && hasiOS7) { + 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) { diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h index 819f93aff..dec49cd28 100644 --- a/src/video/uikit/SDL_uikitvideo.h +++ b/src/video/uikit/SDL_uikitvideo.h @@ -25,6 +25,8 @@ #include "../SDL_sysvideo.h" +BOOL UIKit_IsSystemVersionAtLeast(NSString *version); +CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen); #endif /* _SDL_uikitvideo_h */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index e4266ea2e..01783b248 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -130,6 +130,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. * diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index b636ed7da..02dafd6d9 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -62,16 +62,11 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo 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 */ - int width = (int) bounds.size.width; - int height = (int) bounds.size.height; + 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)) { @@ -239,7 +234,7 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; - CGRect bounds; + CGRect frame; if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; @@ -252,20 +247,15 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display [viewcontroller setNeedsStatusBarAppearanceUpdate]; } - if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { - bounds = [displaydata->uiscreen bounds]; - } else { - bounds = [displaydata->uiscreen applicationFrame]; - } - /* Update the view's frame to account for the status bar change. */ - windowdata->view.frame = bounds; + frame = UIKit_ComputeViewFrame(window, displaydata->uiscreen); + windowdata->view.frame = frame; [windowdata->view setNeedsLayout]; [windowdata->view layoutIfNeeded]; /* Get frame dimensions */ - int width = (int) bounds.size.width; - int height = (int) bounds.size.height; + 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. From 995d5ef814a45dc4bcea549a6dc9da0bdb27786a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 23 Jul 2014 22:35:14 -0300 Subject: [PATCH 17/41] Integrated Phil Hassey's patch to fix SDL_IsScreenKeyboardShown on iOS (https://bugzilla.libsdl.org/show_bug.cgi?id=2660) --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitview.h | 2 +- src/video/uikit/SDL_uikitview.m | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 417a68f41..0deafdbd7 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -49,7 +49,7 @@ - (void)hideKeyboard; - (void)initializeKeyboard; -@property (nonatomic, readonly, assign, getter=isKeyboardVisible) BOOL keyboardVisible; +@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible; @property (nonatomic, assign) SDL_Rect textInputRect; @property (nonatomic, assign) int keyboardHeight; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 18a0538d6..3a2676e17 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -387,9 +387,10 @@ void _uikit_keyboard_update() { 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(); } From c02063db691ad4fae031680ff682641474d5d982 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 24 Jul 2014 22:35:25 -0300 Subject: [PATCH 18/41] Fixed SDL_SetWindowFullscreen on iOS causing the window's reported dimensions and supported orientations to go out of sync with what they should be, if the device orientation was different from the screen orientation when the function call was made. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.m | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index b72a52c2b..8be3790ff 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -242,6 +242,28 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa SDL_SendAppEvent(SDL_APP_LOWMEMORY); } +- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation +{ + UIInterfaceOrientation orientation = application.statusBarOrientation; + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + + if (_this && _this->num_displays > 0) { + SDL_VideoDisplay *display = &_this->displays[0]; /* Main screen. */ + SDL_DisplayMode *mode = &display->desktop_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 (UIInterfaceOrientationIsLandscape(orientation) != (mode->w > mode->h)) { + int height = mode->w; + mode->w = mode->h; + mode->h = height; + } + } +} + - (void) applicationWillResignActive:(UIApplication*)application { SDL_VideoDevice *_this = SDL_GetVideoDevice(); From 2e0c23e4363cc785ef1bc34512e0371058dc5bed Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 29 Jul 2014 00:05:48 -0300 Subject: [PATCH 19/41] Added support for SDL_SetWindowBordered on iOS. Worked around a bug with rotating the device on iOS 8. --HG-- branch : iOS-improvements --- include/SDL_hints.h | 2 +- src/video/uikit/SDL_uikitappdelegate.m | 21 ++++--- src/video/uikit/SDL_uikitmessagebox.m | 2 +- src/video/uikit/SDL_uikitvideo.m | 3 +- src/video/uikit/SDL_uikitview.m | 17 ++---- src/video/uikit/SDL_uikitviewcontroller.m | 10 +--- src/video/uikit/SDL_uikitwindow.h | 7 ++- src/video/uikit/SDL_uikitwindow.m | 68 ++++++++++++++++------- 8 files changed, 79 insertions(+), 51 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 1c46515ed..92f31cdbc 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -346,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" diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 8be3790ff..ed01b7077 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -244,22 +244,29 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa - (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation { - UIInterfaceOrientation orientation = application.statusBarOrientation; + BOOL isLandscape = UIInterfaceOrientationIsLandscape(application.statusBarOrientation); SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this && _this->num_displays > 0) { - SDL_VideoDisplay *display = &_this->displays[0]; /* Main screen. */ - SDL_DisplayMode *mode = &display->desktop_mode; + 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 (UIInterfaceOrientationIsLandscape(orientation) != (mode->w > mode->h)) { - int height = mode->w; - mode->w = mode->h; - mode->h = height; + 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; } } } diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index 4a1d32b7b..1cb734428 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -32,7 +32,7 @@ static SDL_bool s_showingMessageBox = SDL_FALSE; @interface UIKit_UIAlertViewDelegate : NSObject -- (id)initWithButtonIndex:(int *)_buttonIndex; +- (id)initWithButtonIndex:(int *)buttonIndex; - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; @end diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 01783b248..5d4e81252 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/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; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 3a2676e17..620ea2864 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -51,23 +51,18 @@ void _uikit_keyboard_init(); } -- (void)dealloc -{ - [super dealloc]; -} - - (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; diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index c7b3d0934..9e5b02616 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/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,8 +53,7 @@ - (void)viewDidLayoutSubviews { - SDL_WindowData *data = window->driverdata; - const CGSize size = data->view.bounds.size; + const CGSize size = self.view.bounds.size; int w = (int) size.width; int h = (int) size.height; diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index 494b028f3..f6d67f00a 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -32,6 +32,7 @@ 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,9 +40,13 @@ extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, @class UIWindow; +@interface SDL_uikitwindow : UIWindow + +@end + struct SDL_WindowData { - UIWindow *uiwindow; + SDL_uikitwindow *uiwindow; SDL_uikitopenglview *view; SDL_uikitviewcontroller *viewcontroller; }; diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 02dafd6d9..7e3fac621 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -41,8 +41,23 @@ #include +@implementation SDL_uikitwindow -static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created) +- (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 + + +static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, SDL_bool created) { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; @@ -181,7 +196,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* ignore the size user requested, and make a fullscreen window */ /* !!! FIXME: can we have a smaller view? */ - UIWindow *uiwindow = [[UIWindow alloc] initWithFrame:[data->uiscreen bounds]]; + 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 @@ -198,7 +213,6 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } return 1; - } void @@ -228,47 +242,59 @@ 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_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; CGRect frame; - if (fullscreen || (window->flags & SDL_WINDOW_BORDERLESS)) { - [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; + } - /* iOS 7+ won't update the status bar until we tell it to. */ - if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { - [viewcontroller setNeedsStatusBarAppearanceUpdate]; + /* iOS 7+ won't update the status bar until we tell it to. */ + if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { + [viewcontroller setNeedsStatusBarAppearanceUpdate]; + } } /* Update the view's frame to account for the status bar change. */ - frame = UIKit_ComputeViewFrame(window, displaydata->uiscreen); + 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 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) { - window->w = SDL_max(width, height); - window->h = SDL_min(width, height); + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(width, height), SDL_min(width, height)); } else { - window->w = SDL_min(width, height); - window->h = SDL_max(width, height); + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(width, height), SDL_max(width, height)); } } +void +UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) +{ + UIKit_UpdateWindowBorder(_this, window); +} + +void +UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) +{ + UIKit_UpdateWindowBorder(_this, window); +} + void UIKit_DestroyWindow(_THIS, SDL_Window * window) { From 383f56a9c1bcd862c7c2484290df853e79da7657 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 29 Jul 2014 00:36:12 -0300 Subject: [PATCH 20/41] Added missing autorelease pool blocks in UIKit backend code. Fixes memory leak issues, especially in SDL_video. --HG-- branch : iOS-improvements --- src/joystick/iphoneos/SDL_sysjoystick.m | 36 +++-- src/power/uikit/SDL_syspower.m | 37 ++--- src/video/uikit/SDL_uikitmodes.m | 88 ++++++----- src/video/uikit/SDL_uikitopengles.m | 194 +++++++++++++----------- src/video/uikit/SDL_uikitview.m | 42 ++--- src/video/uikit/SDL_uikitwindow.m | 194 +++++++++++++----------- 6 files changed, 322 insertions(+), 269 deletions(-) diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index 31b4e84b0..c08dec192 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -90,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; } @@ -113,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 @@ -161,7 +165,9 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - [motionManager stopAccelerometerUpdates]; + @autoreleasepool { + [motionManager stopAccelerometerUpdates]; + } joystick->closed = 1; } @@ -169,9 +175,11 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick) void SDL_SYS_JoystickQuit(void) { - if (motionManager != nil) { - [motionManager release]; - motionManager = nil; + @autoreleasepool { + if (motionManager != nil) { + [motionManager release]; + motionManager = nil; + } } numjoysticks = 0; diff --git a/src/power/uikit/SDL_syspower.m b/src/power/uikit/SDL_syspower.m index 60c42745a..4984b78c4 100644 --- a/src/power/uikit/SDL_syspower.m +++ b/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 */ diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 20a433d55..e17e16ae7 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -159,9 +159,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; + } } } @@ -173,26 +175,28 @@ 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]); - CGFloat scale = data->uiscreen.scale; + @autoreleasepool { + 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); + 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; + /* 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, uimode, addRotation); } - - /* Add the native screen resolution. */ - UIKit_AddDisplayMode(display, w, h, uimode, addRotation); } } @@ -202,16 +206,18 @@ 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]; + @autoreleasepool { + [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]; + 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]; + } } } } @@ -224,19 +230,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); + } + + SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; + [data->uiscreen release]; + SDL_free(data); + display->driverdata = NULL; } - - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - [data->uiscreen release]; - SDL_free(data); - display->driverdata = NULL; } } diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 0b4a684ed..f17c83192 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -52,12 +52,14 @@ UIKit_GL_GetProcAddress(_THIS, const char *proc) int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { - if (context) { - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - [data->view setCurrentContext]; - } - else { - [EAGLContext setCurrentContext: nil]; + @autoreleasepool { + if (context) { + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + [data->view setCurrentContext]; + } + else { + [EAGLContext setCurrentContext: nil]; + } } return 0; @@ -67,11 +69,13 @@ void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (w) { - *w = data->view.backingWidth; - } - if (h) { - *h = data->view.backingHeight; + @autoreleasepool { + if (w) { + *w = data->view.backingWidth; + } + if (h) { + *h = data->view.backingHeight; + } } } @@ -92,106 +96,112 @@ UIKit_GL_LoadLibrary(_THIS, const char *path) void UIKit_GL_SwapWindow(_THIS, SDL_Window * window) { + @autoreleasepool { #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; + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (nil == data->view) { - return; + if (nil == data->view) { + return; + } + [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. + */ } - [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_uikitopenglview *view; - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - UIWindow *uiwindow = data->uiwindow; - CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen); - EAGLSharegroup *share_group = nil; - CGFloat scale = 1.0; + @autoreleasepool { + SDL_uikitopenglview *view; + SDL_WindowData *data = (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; + 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; + } + + if (_this->gl_config.share_with_current_context) { + SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); + share_group = [view.context sharegroup]; + } + + /* 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; + } + + data->view = view; + view->viewcontroller = data->viewcontroller; + if (view->viewcontroller != nil) { + [view->viewcontroller setView:view]; + [view->viewcontroller retain]; + } + [uiwindow addSubview: view]; + + /* 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; + } + + if (UIKit_GL_MakeCurrent(_this, window, view) < 0) { + UIKit_GL_DeleteContext(_this, view); + return NULL; + } + + /* Make this window the current mouse focus for touch input */ + if (uiwindow.screen == [UIScreen mainScreen]) { + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + } + + return view; } - - if (_this->gl_config.share_with_current_context) { - SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); - share_group = [view.context sharegroup]; - } - - /* 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; - } - - data->view = view; - view->viewcontroller = data->viewcontroller; - if (view->viewcontroller != nil) { - [view->viewcontroller setView:view]; - [view->viewcontroller retain]; - } - [uiwindow addSubview: view]; - - /* 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; - } - - if (UIKit_GL_MakeCurrent(_this, window, view) < 0) { - UIKit_GL_DeleteContext(_this, view); - return NULL; - } - - /* Make this window the current mouse focus for touch input */ - if (uiwindow.screen == [UIScreen mainScreen]) { - SDL_SetMouseFocus(window); - SDL_SetKeyboardFocus(window); - } - - return view; } void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { - /* the delegate has retained the view, this will release him */ - SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; - if (view->viewcontroller) { - UIWindow *uiwindow = (UIWindow *)view.superview; - if (uiwindow.rootViewController == view->viewcontroller) { - uiwindow.rootViewController = nil; + @autoreleasepool { + /* the delegate has retained the view, this will release him */ + SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; + if (view->viewcontroller) { + UIWindow *uiwindow = (UIWindow *)view.superview; + if (uiwindow.rootViewController == view->viewcontroller) { + uiwindow.rootViewController = nil; + } + [view->viewcontroller setView:nil]; + [view->viewcontroller release]; } - [view->viewcontroller setView:nil]; - [view->viewcontroller release]; + [view removeFromSuperview]; + [view release]; } - [view removeFromSuperview]; - [view release]; } #endif /* SDL_VIDEO_DRIVER_UIKIT */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 620ea2864..7267650ac 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -318,28 +318,34 @@ 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.isKeyboardVisible; + return view.isKeyboardVisible; + } } @@ -423,13 +429,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; + } } diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 7e3fac621..aed4a31fd 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -132,84 +132,86 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, 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]; + @autoreleasepool { + 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); + /* 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); + /* 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 (bestmode) { - SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata; - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; - - /* 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 (data->uiscreen == [UIScreen mainScreen]) { - if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { - [UIApplication sharedApplication].statusBarHidden = YES; - } else { - [UIApplication sharedApplication].statusBarHidden = NO; - } - } - - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - if (window->w > window->h) { - if (!UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + /* 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); } - } else if (window->w < window->h) { - if (UIKit_IsDisplayLandscape(data->uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + + 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 (bestmode) { + SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata; + [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + + /* 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; } } - } - /* 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]; + if (data->uiscreen == [UIScreen mainScreen]) { + if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { + [UIApplication sharedApplication].statusBarHidden = YES; + } else { + [UIApplication sharedApplication].statusBarHidden = NO; + } + } - /* 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 (!(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]; + } + } + } - if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { - [uiwindow release]; - return -1; + /* 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]; + } + + if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { + [uiwindow release]; + return -1; + } } return 1; @@ -218,17 +220,21 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) void UIKit_ShowWindow(_THIS, SDL_Window * window) { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + @autoreleasepool { + UIWindow *uiwindow = ((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 = ((SDL_WindowData *) window->driverdata)->uiwindow; - uiwindow.hidden = YES; + uiwindow.hidden = YES; + } } void @@ -286,13 +292,17 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) { - UIKit_UpdateWindowBorder(_this, window); + @autoreleasepool { + UIKit_UpdateWindowBorder(_this, window); + } } void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { - UIKit_UpdateWindowBorder(_this, window); + @autoreleasepool { + UIKit_UpdateWindowBorder(_this, window); + } } void @@ -300,27 +310,32 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - if (data) { - [data->viewcontroller release]; - [data->uiwindow release]; - SDL_free(data); + @autoreleasepool { + if (data) { + [data->viewcontroller release]; + [data->uiwindow release]; + SDL_free(data); + } } + window->driverdata = NULL; } SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + @autoreleasepool { + UIWindow *uiwindow = ((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; + } } } @@ -333,7 +348,10 @@ SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callbac return SDL_SetError("Invalid window or view not set"); } - [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + @autoreleasepool { + [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + } + return 0; } From 2b71883624dfd98a10c47667f19358405d84df5d Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 6 Aug 2014 00:45:11 -0300 Subject: [PATCH 21/41] Minor code update for less verbosity --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitviewcontroller.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 9e5b02616..0a9fbab4a 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -63,11 +63,10 @@ - (NSUInteger)supportedInterfaceOrientations { NSUInteger orientationMask = 0; - const char *orientationsHint = SDL_GetHint(SDL_HINT_ORIENTATIONS); + const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS); - if (orientationsHint != NULL) { - NSArray *orientations = [@(orientationsHint) componentsSeparatedByCharactersInSet: - [NSCharacterSet characterSetWithCharactersInString:@" "]]; + if (hint != NULL) { + NSArray *orientations = [@(hint) componentsSeparatedByString:@" "]; if ([orientations containsObject:@"LandscapeLeft"]) { orientationMask |= UIInterfaceOrientationMaskLandscapeLeft; From 9e4e1cac691918974b867b61fbf3c587cad0c8f2 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 6 Aug 2014 03:24:16 -0300 Subject: [PATCH 22/41] Updated the iOS backend code to use Objective-C's automatic reference counting (ARC). --HG-- branch : iOS-improvements --- Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj | 12 +++ include/SDL_syswm.h | 8 +- src/file/cocoa/SDL_rwopsbundlesupport.m | 3 +- src/joystick/iphoneos/SDL_sysjoystick.m | 5 +- src/video/uikit/SDL_uikitappdelegate.m | 35 +++----- src/video/uikit/SDL_uikitmessagebox.m | 8 +- src/video/uikit/SDL_uikitmodes.h | 18 ++-- src/video/uikit/SDL_uikitmodes.m | 67 ++++++++------- src/video/uikit/SDL_uikitopengles.m | 53 ++++++------ src/video/uikit/SDL_uikitopenglview.h | 2 +- src/video/uikit/SDL_uikitopenglview.m | 7 +- src/video/uikit/SDL_uikitview.h | 9 +- src/video/uikit/SDL_uikitview.m | 21 ++--- src/video/uikit/SDL_uikitwindow.h | 15 ++-- src/video/uikit/SDL_uikitwindow.m | 94 +++++++++++---------- 15 files changed, 181 insertions(+), 176 deletions(-) diff --git a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj index 44055cae4..747f150bf 100755 --- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj +++ b/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; }; diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index c81cd48de..5359b5dd4 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -209,9 +209,9 @@ struct SDL_SysWMinfo struct { #if defined(__OBJC__) && __has_feature(objc_arc) - NSWindow __unsafe_unretained *window; /* The Cocoa window */ + NSWindow * __unsafe_unretained window; /* The Cocoa window */ #else - NSWindow *window; /* The Cocoa window */ + NSWindow *window; /* The Cocoa window */ #endif } cocoa; #endif @@ -219,9 +219,9 @@ struct SDL_SysWMinfo struct { #if defined(__OBJC__) && __has_feature(objc_arc) - UIWindow __unsafe_unretained *window; /* The UIKit window */ + UIWindow * __unsafe_unretained window; /* The UIKit window */ #else - UIWindow *window; /* The UIKit window */ + UIWindow *window; /* The UIKit window */ #endif } uikit; #endif diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.m b/src/file/cocoa/SDL_rwopsbundlesupport.m index fcab269c9..648aaffa4 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.m +++ b/src/file/cocoa/SDL_rwopsbundlesupport.m @@ -50,8 +50,7 @@ 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); } } diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index c08dec192..65e8ba791 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -176,10 +176,7 @@ void SDL_SYS_JoystickQuit(void) { @autoreleasepool { - if (motionManager != nil) { - [motionManager release]; - motionManager = nil; - } + motionManager = nil; } numjoysticks = 0; diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index ed01b7077..c4a199915 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -56,7 +56,7 @@ int main(int argc, char **argv) /* Give over control to run loop, SDLUIKitDelegate will handle most things from here */ @autoreleasepool { - UIApplicationMain(argc, argv, NULL, [SDLUIKitDelegate getAppDelegateClassName]); + UIApplicationMain(argc, argv, nil, [SDLUIKitDelegate getAppDelegateClassName]); } /* free the memory we used to hold copies of argc and argv */ @@ -94,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"]; + splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]]; + if (!splashPortrait) { + 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]; - } - 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]]; @@ -148,9 +142,9 @@ 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) { @@ -192,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 */ diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index 1cb734428..9a99db170 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -76,13 +76,14 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) @autoreleasepool { UIAlertView* alert = [[UIAlertView alloc] init]; + UIKit_UIAlertViewDelegate *delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; alert.title = @(messageboxdata->title); alert.message = @(messageboxdata->message); - alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; + alert.delegate = delegate; for (i = 0; i < messageboxdata->numbuttons; ++i) { - [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]]; + [alert addButtonWithTitle:@(buttons[i].text)]; } /* Set up for showing the alert */ @@ -100,8 +101,7 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) *buttonid = messageboxdata->buttons[clicked].buttonid; - [alert.delegate release]; - [alert release]; + alert.delegate = nil; } return 0; diff --git a/src/video/uikit/SDL_uikitmodes.h b/src/video/uikit/SDL_uikitmodes.h index 276685039..65c185ff8 100644 --- a/src/video/uikit/SDL_uikitmodes.h +++ b/src/video/uikit/SDL_uikitmodes.h @@ -25,15 +25,17 @@ #include "SDL_uikitvideo.h" -typedef struct -{ - UIScreen *uiscreen; -} SDL_DisplayData; +@interface SDL_DisplayData : NSObject -typedef struct -{ - UIScreenMode *uiscreenmode; -} SDL_DisplayModeData; +@property (nonatomic, strong) UIScreen *uiscreen; + +@end + +@interface SDL_DisplayModeData : NSObject + +@property (nonatomic, strong) UIScreenMode *uiscreenmode; + +@end extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen); diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index e17e16ae7..37792f1af 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -25,25 +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) { - 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.uiscreenmode = uiscreenmode; } - mode->driverdata = data; + mode->driverdata = (void *) CFBridgingRetain(data); return 0; } @@ -52,9 +63,7 @@ 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; } } @@ -130,18 +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.uiscreen = uiscreen; - display.driverdata = data; + display.driverdata = (void *) CFBridgingRetain(data); SDL_AddVideoDisplay(&display); + return 0; } @@ -173,14 +182,14 @@ UIKit_InitModes(_THIS) void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) { - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - @autoreleasepool { - SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen); - SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]); - CGFloat scale = data->uiscreen.scale; + SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata; - for (UIScreenMode *uimode in [data->uiscreen availableModes]) { + 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]; @@ -203,19 +212,19 @@ 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; - @autoreleasepool { - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata; + SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata; - if (data->uiscreen == [UIScreen mainScreen]) { + [data.uiscreen setCurrentMode:modedata.uiscreenmode]; + + if (data.uiscreen == [UIScreen mainScreen]) { if (mode->w > mode->h) { - if (!UIKit_IsDisplayLandscape(data->uiscreen)) { + if (!UIKit_IsDisplayLandscape(data.uiscreen)) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; } } else if (mode->w < mode->h) { - if (UIKit_IsDisplayLandscape(data->uiscreen)) { + if (UIKit_IsDisplayLandscape(data.uiscreen)) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; } } @@ -240,10 +249,10 @@ UIKit_QuitModes(_THIS) UIKit_FreeDisplayModeData(mode); } - SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; - [data->uiscreen release]; - SDL_free(data); - display->driverdata = NULL; + if (display->driverdata != NULL) { + CFRelease(display->driverdata); + display->driverdata = NULL; + } } } } diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index f17c83192..50bb6a3f8 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -54,8 +54,8 @@ UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { @autoreleasepool { if (context) { - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - [data->view setCurrentContext]; + SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + [data.view setCurrentContext]; } else { [EAGLContext setCurrentContext: nil]; @@ -67,14 +67,14 @@ UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - @autoreleasepool { + SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + if (w) { - *w = data->view.backingWidth; + *w = data.view.backingWidth; } if (h) { - *h = data->view.backingHeight; + *h = data.view.backingHeight; } } } @@ -97,17 +97,17 @@ 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(); #endif - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - - if (nil == data->view) { + if (data.view == nil) { return; } - [data->view swapBuffers]; + [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 @@ -121,8 +121,8 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) { @autoreleasepool { SDL_uikitopenglview *view; - SDL_WindowData *data = (SDL_WindowData *) window->driverdata; - UIWindow *uiwindow = data->uiwindow; + 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; @@ -136,7 +136,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) } if (_this->gl_config.share_with_current_context) { - SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); + SDL_uikitopenglview *view = (__bridge SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); share_group = [view.context sharegroup]; } @@ -157,21 +157,20 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) return NULL; } - data->view = view; - view->viewcontroller = data->viewcontroller; - if (view->viewcontroller != nil) { - [view->viewcontroller setView:view]; - [view->viewcontroller retain]; + data.view = view; + view.viewcontroller = data.viewcontroller; + if (view.viewcontroller != nil) { + view.viewcontroller.view = view; } [uiwindow addSubview: view]; /* 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; + uiwindow.rootViewController = view.viewcontroller; } - if (UIKit_GL_MakeCurrent(_this, window, view) < 0) { - UIKit_GL_DeleteContext(_this, view); + if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext)(view)) < 0) { + UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(view)); return NULL; } @@ -181,7 +180,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) SDL_SetKeyboardFocus(window); } - return view; + return (SDL_GLContext) CFBridgingRetain(view); } } @@ -190,17 +189,15 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { @autoreleasepool { /* the delegate has retained the view, this will release him */ - SDL_uikitopenglview *view = (SDL_uikitopenglview *)context; - if (view->viewcontroller) { + SDL_uikitopenglview *view = (SDL_uikitopenglview *)CFBridgingRelease(context); + if (view.viewcontroller) { UIWindow *uiwindow = (UIWindow *)view.superview; - if (uiwindow.rootViewController == view->viewcontroller) { + if (uiwindow.rootViewController == view.viewcontroller) { uiwindow.rootViewController = nil; } - [view->viewcontroller setView:nil]; - [view->viewcontroller release]; + view.viewcontroller.view = nil; } [view removeFromSuperview]; - [view release]; } } diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 4f40514cd..9bb8f0c7f 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -44,7 +44,7 @@ majorVersion:(int)majorVersion shareGroup:(EAGLSharegroup*)shareGroup; -@property (nonatomic, retain, readonly) EAGLContext *context; +@property (nonatomic, strong, readonly) EAGLContext *context; /* The width and height of the drawable in pixels (as opposed to points.) */ @property (nonatomic, readonly) int backingWidth; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 7daa12f65..da724dce7 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -85,7 +85,6 @@ context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup]; if (!context || ![EAGLContext setCurrentContext:context]) { - [self release]; SDL_SetError("OpenGL ES %d not supported", majorVersion); return nil; } @@ -118,7 +117,6 @@ glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); if (![context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer]) { - [self release]; SDL_SetError("Failed creating OpenGL ES drawable"); return nil; } @@ -154,7 +152,6 @@ } if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - [self release]; SDL_SetError("Failed creating OpenGL ES framebuffer"); return nil; } @@ -268,12 +265,10 @@ - (void)dealloc { - [self destroyFramebuffer]; if ([EAGLContext currentContext] == context) { + [self destroyFramebuffer]; [EAGLContext setCurrentContext:nil]; } - [context release]; - [super dealloc]; } @end diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 0deafdbd7..9824e7866 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -31,13 +31,12 @@ #endif #if SDL_IPHONE_KEYBOARD -@interface SDL_uikitview : UIView { +@interface SDL_uikitview : UIView #else -@interface SDL_uikitview : UIView { +@interface SDL_uikitview : UIView #endif -@public - SDL_uikitviewcontroller *viewcontroller; -} + +@property (nonatomic, weak) SDL_uikitviewcontroller *viewcontroller; - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 7267650ac..c7a77de3b 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -51,6 +51,8 @@ void _uikit_keyboard_init(); } +@synthesize viewcontroller; + - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame: frame]) { @@ -88,10 +90,10 @@ void _uikit_keyboard_init(); CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; /* send moved event */ - SDL_SendMouseMotion(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(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; } @@ -123,7 +125,7 @@ void _uikit_keyboard_init(); for (UITouch *touch in touches) { if (touch == leftFingerDown) { /* send mouse up */ - SDL_SendMouseButton(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; } @@ -162,7 +164,7 @@ void _uikit_keyboard_init(); CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; /* send moved event */ - SDL_SendMouseMotion(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]; @@ -212,7 +214,6 @@ void _uikit_keyboard_init(); keyboardVisible = NO; /* add the UITextField (hidden) to our view */ [self addSubview: textField]; - [textField release]; _uikit_keyboard_init(); } @@ -301,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"); @@ -352,11 +353,11 @@ SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) 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; diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index f6d67f00a..17e9e1bb4 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -26,8 +26,6 @@ #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); @@ -44,12 +42,13 @@ extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, @end -struct SDL_WindowData -{ - SDL_uikitwindow *uiwindow; - SDL_uikitopenglview *view; - SDL_uikitviewcontroller *viewcontroller; -}; +@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 */ diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index aed4a31fd..a250ca5c7 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -56,35 +56,41 @@ @end +@implementation SDL_WindowData + +@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_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 frame = UIKit_ComputeViewFrame(window, displaydata->uiscreen); + CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); /* 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; @@ -94,7 +100,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, window->h = height; } - window->driverdata = data; + window->driverdata = (void *) CFBridgingRetain(data); /* only one window on iOS, always shown */ window->flags &= ~SDL_WINDOW_HIDDEN; @@ -103,7 +109,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, * 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 @@ -123,8 +129,8 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, * device orientation changes. This will trigger resize events, if * appropriate. */ - data->viewcontroller = [[SDL_uikitviewcontroller alloc] 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; } @@ -134,9 +140,9 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) { @autoreleasepool { 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_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); @@ -164,8 +170,8 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } if (bestmode) { - SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata; - [data->uiscreen setCurrentMode:modedata->uiscreenmode]; + SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)bestmode->driverdata; + [data.uiscreen setCurrentMode:modedata.uiscreenmode]; /* desktop_mode doesn't change here (the higher level will * use it to set all the screens back to their defaults @@ -175,7 +181,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } } - if (data->uiscreen == [UIScreen mainScreen]) { + if (data.uiscreen == [UIScreen mainScreen]) { if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; } else { @@ -185,11 +191,11 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) if (!(window->flags & SDL_WINDOW_RESIZABLE)) { if (window->w > window->h) { - if (!UIKit_IsDisplayLandscape(data->uiscreen)) { + if (!UIKit_IsDisplayLandscape(data.uiscreen)) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; } } else if (window->w < window->h) { - if (UIKit_IsDisplayLandscape(data->uiscreen)) { + if (UIKit_IsDisplayLandscape(data.uiscreen)) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; } } @@ -197,7 +203,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* 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]; + 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 @@ -205,13 +211,13 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) * status bar real estate. */ if (external) { - [uiwindow setScreen:data->uiscreen]; + [uiwindow setScreen:data.uiscreen]; } if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { - [uiwindow release]; return -1; } + } return 1; @@ -221,7 +227,7 @@ void UIKit_ShowWindow(_THIS, SDL_Window * window) { @autoreleasepool { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; [uiwindow makeKeyAndVisible]; } @@ -231,7 +237,7 @@ void UIKit_HideWindow(_THIS, SDL_Window * window) { @autoreleasepool { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; uiwindow.hidden = YES; } @@ -251,11 +257,11 @@ UIKit_RaiseWindow(_THIS, SDL_Window * window) static void UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) { - SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; - SDL_uikitviewcontroller *viewcontroller = windowdata->viewcontroller; + SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata; + SDL_uikitviewcontroller *viewcontroller = windowdata.viewcontroller; CGRect frame; - if (windowdata->uiwindow.screen == [UIScreen mainScreen]) { + if (windowdata.uiwindow.screen == [UIScreen mainScreen]) { if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; } else { @@ -269,11 +275,11 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) } /* Update the view's frame to account for the status bar change. */ - frame = UIKit_ComputeViewFrame(window, windowdata->uiwindow.screen); + frame = UIKit_ComputeViewFrame(window, windowdata.uiwindow.screen); - windowdata->view.frame = frame; - [windowdata->view setNeedsLayout]; - [windowdata->view layoutIfNeeded]; + windowdata.view.frame = frame; + [windowdata.view setNeedsLayout]; + [windowdata.view layoutIfNeeded]; /* Get frame dimensions */ int width = (int) frame.size.width; @@ -308,13 +314,9 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display void UIKit_DestroyWindow(_THIS, SDL_Window * window) { - SDL_WindowData *data = (SDL_WindowData *)window->driverdata; - @autoreleasepool { - if (data) { - [data->viewcontroller release]; - [data->uiwindow release]; - SDL_free(data); + if (window->driverdata != NULL) { + CFRelease(window->driverdata); } } @@ -325,7 +327,7 @@ SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) { @autoreleasepool { - UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow; + UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; if (info->version.major <= SDL_MAJOR_VERSION) { info->subsystem = SDL_SYSWM_UIKIT; @@ -342,14 +344,14 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam) { - SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL; - - if (!data || !data->view) { - return SDL_SetError("Invalid window or view not set"); - } - @autoreleasepool { - [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + SDL_WindowData *data = window ? (__bridge SDL_WindowData *)window->driverdata : nil; + + if (!data || !data.view) { + return SDL_SetError("Invalid window or view not set"); + } + + [data.view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; } return 0; From 9858389e85cc35e1a122293f0442d9a264229415 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 7 Aug 2014 00:44:16 -0300 Subject: [PATCH 23/41] Fixed opengl context share groups on iOS. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopengles.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 475a38d5a..7d828093d 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -129,8 +129,8 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) } if (_this->gl_config.share_with_current_context) { - SDL_uikitopenglview *view = (__bridge SDL_uikitopenglview *) SDL_GL_GetCurrentContext(); - share_group = [view.context sharegroup]; + EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext(); + share_group = context.sharegroup; } /* construct our view, passing in SDL's OpenGL configuration data */ @@ -174,6 +174,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) SDL_SetKeyboardFocus(window); } + /* We return a +1'd context. The window's driverdata owns the view. */ return (SDL_GLContext) CFBridgingRetain(context); } } @@ -182,8 +183,9 @@ void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { @autoreleasepool { - SDL_Window *window; + /* 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) { From 1e2d5c6bc47b8e5616e69b34cbc24e766421e111 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 8 Aug 2014 15:14:09 -0300 Subject: [PATCH 24/41] Added iOS-specific functions to get the window view's current OpenGL Renderbuffer and Framebuffer objects, so they can be more easily rebound when necessary. --HG-- branch : iOS-improvements --- include/SDL_system.h | 10 ++++++++ src/video/uikit/SDL_uikitopengles.m | 34 +++++++++++++++++++++++++++ src/video/uikit/SDL_uikitopenglview.h | 3 +++ src/video/uikit/SDL_uikitopenglview.m | 10 ++++++++ 4 files changed, 57 insertions(+) diff --git a/include/SDL_system.h b/include/SDL_system.h index 78d5b0d0a..8184e597c 100644 --- a/include/SDL_system.h +++ b/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__ */ diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 7d828093d..378099d8e 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -210,6 +210,40 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) } } +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; + } + } +} + +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 */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 9bb8f0c7f..b232c53fa 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -50,6 +50,9 @@ @property (nonatomic, readonly) int backingWidth; @property (nonatomic, readonly) int backingHeight; +@property (nonatomic, readonly) GLuint drawableRenderbuffer; +@property (nonatomic, readonly) GLuint drawableFramebuffer; + - (void)swapBuffers; - (void)setCurrentContext; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index da724dce7..4b93ab624 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -162,6 +162,16 @@ return self; } +- (GLuint)drawableRenderbuffer +{ + return viewRenderbuffer; +} + +- (GLuint)drawableFramebuffer +{ + return viewFramebuffer; +} + - (void)updateFrame { glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); From 3a9397926822a51b7f9585ff3688558aaf408283 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 14 Sep 2014 17:04:54 -0300 Subject: [PATCH 25/41] Enabling highdpi mode on an iPhone 6 Plus should now create a 1080x1920 OpenGL view, rather than 1242x2208 (414x736@3x.) --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitmodes.m | 17 ++++++++++++----- src/video/uikit/SDL_uikitopengles.m | 15 +++++++++++---- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 37792f1af..26858a825 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -189,12 +189,19 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]); CGFloat scale = data.uiscreen.scale; +#ifdef __IPHONE_8_0 + /* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than + * 1242x2208 (414x736@3x), so we should use the native scale. */ + if ([data.uiscreen respondsToSelector:@selector(nativeScale)]) { + scale = data.uiscreen.nativeScale; + } +#endif + 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); + /* The size of a UIScreenMode is in pixels, but we deal exclusively + * in points (except in SDL_GL_GetDrawableSize.) */ + int w = (int)(uimode.size.width / scale); + int h = (int)(uimode.size.height / scale); /* Make sure the width/height are oriented correctly */ if (isLandscape != (w > h)) { diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 378099d8e..cb9beaa5b 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -121,11 +121,18 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) 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. + /* 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; +#ifdef __IPHONE_8_0 + if ([uiwindow.screen respondsToSelector:@selector(nativeScale)]) { + scale = uiwindow.screen.nativeScale; + } else +#endif + { + scale = uiwindow.screen.scale; + } } if (_this->gl_config.share_with_current_context) { From 65b84b2bec3620410b739f1f2dd9d2900a6e277f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 24 Oct 2014 03:56:34 -0300 Subject: [PATCH 26/41] Completely removed custom splash screen code. iOS 8 introduced yet another official way to do launch images (via a Storyboard), and the custom splash screen code was broken on newer devices and caused bugs for all devices anyway. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.m | 100 ------------------------- 1 file changed, 100 deletions(-) diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index c4a199915..fe308b2e3 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -39,7 +39,6 @@ static int forward_argc; static char **forward_argv; static int exit_status; -static UIWindow *launch_window; int main(int argc, char **argv) { @@ -75,86 +74,6 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa [UIApplication sharedApplication].idleTimerDisabled = disable; } -@interface SDL_splashviewcontroller : UIViewController - -- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation; - -@end - -@implementation SDL_splashviewcontroller { - UIImageView *splash; - UIImage *splashPortrait; - UIImage *splashLandscape; -} - -- (id)init -{ - self = [super init]; - if (self == nil) { - return nil; - } - - splash = [[UIImageView alloc] init]; - self.view = splash; - - CGSize size = [UIScreen mainScreen].bounds.size; - float height = SDL_max(size.width, size.height); - splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]]; - if (!splashPortrait) { - splashPortrait = [UIImage imageNamed:@"Default.png"]; - } - 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]]; - - return self; -} - -- (NSUInteger)supportedInterfaceOrientations -{ - NSUInteger orientationMask = UIInterfaceOrientationMaskAll; - - /* Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation */ - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { - orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown; - } - return orientationMask; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient -{ - NSUInteger orientationMask = [self supportedInterfaceOrientations]; - return (orientationMask & (1 << orient)); -} - -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration -{ - [self updateSplashImage:interfaceOrientation]; -} - -- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation -{ - UIImage *image; - - if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) { - image = splashLandscape; - } else { - image = splashPortrait; - } - - if (image) { - splash.image = image; - } -} - -@end - - @implementation SDLUIKitDelegate /* convenience method */ @@ -184,11 +103,6 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa exit_status = SDL_main(forward_argc, forward_argv); SDL_iPhoneSetEventPump(SDL_FALSE); - /* If we showed a splash image, clean it up */ - if (launch_window) { - launch_window = nil; - } - /* exit, passing the return status from the user's application */ /* We don't actually exit to support applications that do setup in * their main function and then allow the Cocoa event loop to run. @@ -198,20 +112,6 @@ 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 */ - - /* 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];*/ - /* Set working directory to resource path */ [[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]]; From 737873688a9d123cf297bca824c7d279a67ca862 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 24 Oct 2014 04:06:45 -0300 Subject: [PATCH 27/41] Removed the codepath that gets compiled if IPHONE_TOUCH_EFFICIENT_DANGEROUS is not defined. The "dangerous" codepath relies on the fact that UITouch objects are persistent for the entire touch sequence, which is always guaranteed by Apple. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitview.h | 6 ----- src/video/uikit/SDL_uikitview.m | 42 --------------------------------- 2 files changed, 48 deletions(-) diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 9824e7866..f34b1b155 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -24,12 +24,6 @@ #include "SDL_touch.h" -#define IPHONE_TOUCH_EFFICIENT_DANGEROUS - -#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS -#define MAX_SIMULTANEOUS_TOUCHES 5 -#endif - #if SDL_IPHONE_KEYBOARD @interface SDL_uikitview : UIView #else diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index c7a77de3b..b5ba73b98 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -41,9 +41,6 @@ void _uikit_keyboard_init(); SDL_TouchID touchId; UITouch *leftFingerDown; -#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS - UITouch *finger[MAX_SIMULTANEOUS_TOUCHES]; -#endif #if SDL_IPHONE_KEYBOARD UITextField *textField; @@ -99,24 +96,8 @@ void _uikit_keyboard_init(); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; -#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS - /* FIXME: TODO: Using touch as the fingerId is potentially dangerous - * It is also much more efficient than storing the UITouch pointer - * and comparing it to the incoming event. - */ SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), SDL_TRUE, locationInView.x, locationInView.y, 1.0f); -#else - int i; - for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) { - if (finger[i] == NULL) { - finger[i] = touch; - SDL_SendTouch(touchId, i, - SDL_TRUE, locationInView.x, locationInView.y, 1.0f); - break; - } - } -#endif } } @@ -130,20 +111,8 @@ void _uikit_keyboard_init(); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; -#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), SDL_FALSE, locationInView.x, locationInView.y, 1.0f); -#else - int i; - for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) { - if (finger[i] == touch) { - SDL_SendTouch(touchId, i, - SDL_FALSE, locationInView.x, locationInView.y, 1.0f); - finger[i] = NULL; - break; - } - } -#endif } } @@ -168,19 +137,8 @@ void _uikit_keyboard_init(); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; -#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), locationInView.x, locationInView.y, 1.0f); -#else - int i; - for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) { - if (finger[i] == touch) { - SDL_SendTouchMotion(touchId, i, - locationInView.x, locationInView.y, 1.0f); - break; - } - } -#endif } } From 2e708de35079fce8dca04bd808d07662ab6cc161 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 28 Oct 2014 01:34:40 -0300 Subject: [PATCH 28/41] Switched to the core versions of OpenGL ES framebuffer object and renderbuffer functions. Both the extension (OES) and the core versions work, but the core versions are more correct for GLES2+ and they're less verbose. --HG-- branch : iOS-improvements --- Xcode-iOS/Demos/src/fireworks.c | 3 + src/video/uikit/SDL_uikitopenglview.h | 3 +- src/video/uikit/SDL_uikitopenglview.m | 93 ++++++++++++++------------- 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/Xcode-iOS/Demos/src/fireworks.c b/Xcode-iOS/Demos/src/fireworks.c index 6c60dd125..a5beada91 100644 --- a/Xcode-iOS/Demos/src/fireworks.c +++ b/Xcode-iOS/Demos/src/fireworks.c @@ -387,6 +387,9 @@ main(int argc, char *argv[]) SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + /* create main window and renderer */ window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index b232c53fa..6502d03c5 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -21,8 +21,7 @@ #import #import -#import -#import +#import #import "SDL_uikitview.h" /* This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 4b93ab624..3ffd45f40 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -24,6 +24,8 @@ #include #include +#include +#include #include "SDL_uikitopenglview.h" #include "SDL_uikitmessagebox.h" #include "SDL_uikitvideo.h" @@ -89,10 +91,15 @@ 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 (sRGB) { + /* sRGB EAGL drawable support was added in iOS 7. */ + if (UIKit_IsSystemVersionAtLeast(@"7.0")) { + colorFormat = kEAGLColorFormatSRGBA8; + } else { + SDL_SetError("sRGB drawables are not supported."); + return nil; + } + } else if (rBits >= 8 || gBits >= 8 || bBits >= 8) { /* if user specifically requests rbg888 or some color format higher than 16bpp */ colorFormat = kEAGLColorFormatRGBA8; } else { @@ -113,50 +120,50 @@ self.contentScaleFactor = scale; /* Create the color Renderbuffer Object */ - glGenRenderbuffersOES(1, &viewRenderbuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); + glGenRenderbuffers(1, &viewRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); - if (![context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:eaglLayer]) { - SDL_SetError("Failed creating OpenGL ES drawable"); + if (![context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]) { + SDL_SetError("Failed to create OpenGL ES drawable"); return nil; } /* Create the Framebuffer Object */ - glGenFramebuffersOES(1, &viewFramebuffer); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); + glGenFramebuffers(1, &viewFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer); /* attach the color renderbuffer to the FBO */ - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); if ((useDepthBuffer) || (useStencilBuffer)) { if (useStencilBuffer) { /* Apparently you need to pack stencil and depth into one buffer. */ depthBufferFormat = GL_DEPTH24_STENCIL8_OES; } else if (useDepthBuffer) { - /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */ + /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16 */ depthBufferFormat = GL_DEPTH_COMPONENT24_OES; } - glGenRenderbuffersOES(1, &depthRenderbuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); - glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight); + glGenRenderbuffers(1, &depthRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight); if (useDepthBuffer) { - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); } if (useStencilBuffer) { - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); } } - if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { SDL_SetError("Failed creating OpenGL ES framebuffer"); return nil; } - glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); } return self; @@ -174,30 +181,30 @@ - (void)updateFrame { - glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0); - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0); - glDeleteRenderbuffersOES(1, &viewRenderbuffer); + glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); + glDeleteRenderbuffers(1, &viewRenderbuffer); - glGenRenderbuffersOES(1, &viewRenderbuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); - [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); + glGenRenderbuffers(1, &viewRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); + [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); if (depthRenderbuffer != 0) { - glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); - glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight); + glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight); } - glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); } - (void)setAnimationCallback:(int)interval - callback:(void (*)(void*))callback - callbackParam:(void*)callbackParam + callback:(void (*)(void*))callback + callbackParam:(void*)callbackParam { [self stopAnimation]; @@ -236,16 +243,14 @@ [EAGLContext setCurrentContext:context]; } - - (void)swapBuffers { /* viewRenderbuffer should always be bound here. Code that binds something - else is responsible for rebinding viewRenderbuffer, to reduce - duplicate state changes. */ - [context presentRenderbuffer:GL_RENDERBUFFER_OES]; + else is responsible for rebinding viewRenderbuffer, to reduce duplicate + state changes. */ + [context presentRenderbuffer:GL_RENDERBUFFER]; } - - (void)layoutSubviews { [super layoutSubviews]; @@ -257,17 +262,17 @@ - (void)destroyFramebuffer { if (viewFramebuffer != 0) { - glDeleteFramebuffersOES(1, &viewFramebuffer); + glDeleteFramebuffers(1, &viewFramebuffer); viewFramebuffer = 0; } if (viewRenderbuffer != 0) { - glDeleteRenderbuffersOES(1, &viewRenderbuffer); + glDeleteRenderbuffers(1, &viewRenderbuffer); viewRenderbuffer = 0; } if (depthRenderbuffer != 0) { - glDeleteRenderbuffersOES(1, &depthRenderbuffer); + glDeleteRenderbuffers(1, &depthRenderbuffer); depthRenderbuffer = 0; } } From 530dba51e09638bb506d724e346b787e657e3a57 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 20 Nov 2014 17:19:26 -0400 Subject: [PATCH 29/41] Fixed mismatching orientations for the window width and height on iOS when the window is created or the app is brought to the foreground, when SDL_HINT_ORIENTATIONS or SDL_WINDOW_FULLSCREEN is used. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitviewcontroller.m | 41 +--------- src/video/uikit/SDL_uikitwindow.h | 2 + src/video/uikit/SDL_uikitwindow.m | 91 ++++++++++++++++++----- 3 files changed, 77 insertions(+), 57 deletions(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 0a9fbab4a..de5b3008c 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -62,44 +62,7 @@ - (NSUInteger)supportedInterfaceOrientations { - NSUInteger orientationMask = 0; - const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS); - - if (hint != NULL) { - NSArray *orientations = [@(hint) componentsSeparatedByString:@" "]; - - if ([orientations containsObject:@"LandscapeLeft"]) { - orientationMask |= UIInterfaceOrientationMaskLandscapeLeft; - } - if ([orientations containsObject:@"LandscapeRight"]) { - orientationMask |= UIInterfaceOrientationMaskLandscapeRight; - } - if ([orientations containsObject:@"Portrait"]) { - orientationMask |= UIInterfaceOrientationMaskPortrait; - } - if ([orientations containsObject:@"PortraitUpsideDown"]) { - orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown; - } - } - - if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) { - orientationMask = UIInterfaceOrientationMaskAll; /* any orientation is okay. */ - } - - if (orientationMask == 0) { - if (window->w >= window->h) { - orientationMask |= UIInterfaceOrientationMaskLandscape; - } - if (window->h >= window->w) { - orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); - } - } - - /* Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation */ - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { - orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown; - } - return orientationMask; + return UIKit_GetSupportedOrientations(window); } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient @@ -119,7 +82,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - /* We assume most games don't have a bright white background. */ + /* We assume most SDL apps don't have a bright white background. */ return UIStatusBarStyleLightContent; } diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index 17e9e1bb4..c279d0f6f 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -36,6 +36,8 @@ extern void UIKit_DestroyWindow(_THIS, SDL_Window * window); extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo * info); +extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window * window); + @class UIWindow; @interface SDL_uikitwindow : UIWindow diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index a250ca5c7..0c2f12017 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -80,9 +80,6 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, /* Fill in the SDL window with the window data */ { - window->x = 0; - window->y = 0; - CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); /* Get frame dimensions */ @@ -96,6 +93,8 @@ static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, height = temp; } + window->x = 0; + window->y = 0; window->w = width; window->h = height; } @@ -182,21 +181,32 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } if (data.uiscreen == [UIScreen mainScreen]) { - if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { - [UIApplication sharedApplication].statusBarHidden = YES; - } else { - [UIApplication sharedApplication].statusBarHidden = NO; - } - } + NSUInteger orientations = UIKit_GetSupportedOrientations(window); + UIApplication *app = [UIApplication sharedApplication]; - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - if (window->w > window->h) { - if (!UIKit_IsDisplayLandscape(data.uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { + app.statusBarHidden = YES; + } else { + app.statusBarHidden = NO; + } + + /* Make sure the screen is using a supported orientation. We do it + * now so that SetupWindowData assigns the properly oriented width + * and height to the window's w and h variables. + */ + if (UIKit_IsDisplayLandscape(data.uiscreen)) { + if (!(orientations & UIInterfaceOrientationMaskLandscape)) { + [app setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; } - } else if (window->w < window->h) { - if (UIKit_IsDisplayLandscape(data.uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + } else { + if (!(orientations & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown))) { + UIInterfaceOrientation orient = UIInterfaceOrientationLandscapeLeft; + + if (orientations & UIInterfaceOrientationMaskLandscapeRight) { + orient = UIInterfaceOrientationLandscapeRight; + } + + [app setStatusBarOrientation:orient animated:NO]; } } } @@ -228,7 +238,6 @@ UIKit_ShowWindow(_THIS, SDL_Window * window) { @autoreleasepool { UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; - [uiwindow makeKeyAndVisible]; } } @@ -238,7 +247,6 @@ UIKit_HideWindow(_THIS, SDL_Window * window) { @autoreleasepool { UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; - uiwindow.hidden = YES; } } @@ -341,6 +349,53 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) } } +NSUInteger +UIKit_GetSupportedOrientations(SDL_Window * window) +{ + const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS); + NSUInteger orientationMask = 0; + + @autoreleasepool { + if (hint != NULL) { + NSArray *orientations = [@(hint) componentsSeparatedByString:@" "]; + + if ([orientations containsObject:@"LandscapeLeft"]) { + orientationMask |= UIInterfaceOrientationMaskLandscapeLeft; + } + if ([orientations containsObject:@"LandscapeRight"]) { + orientationMask |= UIInterfaceOrientationMaskLandscapeRight; + } + if ([orientations containsObject:@"Portrait"]) { + orientationMask |= UIInterfaceOrientationMaskPortrait; + } + if ([orientations containsObject:@"PortraitUpsideDown"]) { + orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown; + } + } + + if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) { + /* any orientation is okay. */ + orientationMask = UIInterfaceOrientationMaskAll; + } + + if (orientationMask == 0) { + if (window->w >= window->h) { + orientationMask |= UIInterfaceOrientationMaskLandscape; + } + if (window->h >= window->w) { + orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); + } + } + + /* Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation */ + if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { + orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown; + } + } + + return orientationMask; +} + int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam) { From 2f7811a0e74e8b234833c7c7569c5f02903a5818 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 20 Nov 2014 18:45:04 -0400 Subject: [PATCH 30/41] Minor objective-c code style improvements --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.m | 2 +- src/video/uikit/SDL_uikitopengles.m | 26 +++++++++++++------------- src/video/uikit/SDL_uikitopenglview.m | 4 ++-- src/video/uikit/SDL_uikitview.m | 12 ++++++------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index fe308b2e3..6a07d5d14 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -113,7 +113,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* Set working directory to resource path */ - [[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]]; + [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]]; /* register a callback for the idletimer hint */ SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED, diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index cb9beaa5b..82c1e3054 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -141,18 +141,18 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) } /* 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]; + 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; } @@ -162,7 +162,7 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) if (view.viewcontroller != nil) { view.viewcontroller.view = view; } - [uiwindow addSubview: view]; + [uiwindow addSubview:view]; /* The view controller needs to be the root in order to control rotation on iOS 6.0 */ if (uiwindow.rootViewController == nil) { diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 3ffd45f40..5da30c392 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -112,8 +112,8 @@ eaglLayer.opaque = YES; eaglLayer.drawableProperties = @{ - kEAGLDrawablePropertyRetainedBacking: @(retained), - kEAGLDrawablePropertyColorFormat: colorFormat + kEAGLDrawablePropertyRetainedBacking:@(retained), + kEAGLDrawablePropertyColorFormat:colorFormat }; /* Set the appropriate scale (for retina display support) */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index b5ba73b98..2cb07ca5f 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -52,7 +52,7 @@ void _uikit_keyboard_init(); - (id)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame: frame]) { + if (self = [super initWithFrame:frame]) { #if SDL_IPHONE_KEYBOARD [self initializeKeyboard]; #endif @@ -69,7 +69,7 @@ void _uikit_keyboard_init(); - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize { - CGPoint point = [touch locationInView: self]; + CGPoint point = [touch locationInView:self]; if (normalize) { CGRect bounds = self.bounds; @@ -123,7 +123,7 @@ void _uikit_keyboard_init(); at once, or perhaps in other circumstances. Usually (it seems) all active touches are canceled. */ - [self touchesEnded: touches withEvent: event]; + [self touchesEnded:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event @@ -154,7 +154,7 @@ void _uikit_keyboard_init(); /* Set ourselves up as a UITextFieldDelegate */ - (void)initializeKeyboard { - textField = [[UITextField alloc] initWithFrame: CGRectZero]; + textField = [[UITextField alloc] initWithFrame:CGRectZero]; textField.delegate = self; /* placeholder so there is something to delete! */ textField.text = @" "; @@ -171,7 +171,7 @@ void _uikit_keyboard_init(); textField.hidden = YES; keyboardVisible = NO; /* add the UITextField (hidden) to our view */ - [self addSubview: textField]; + [self addSubview:textField]; _uikit_keyboard_init(); } @@ -204,7 +204,7 @@ void _uikit_keyboard_init(); int i; for (i = 0; i < [string length]; i++) { - unichar c = [string characterAtIndex: i]; + unichar c = [string characterAtIndex:i]; Uint16 mod = 0; SDL_Scancode code; From 71b6fe20ae618c537aa314127c2d8a7fc347c16d Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 21 Nov 2014 03:29:57 -0400 Subject: [PATCH 31/41] Added debug labels for the OpenGL ES objects created with SDL_GL_CreateContext on iOS. More misc. code cleanup. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitmodes.m | 1 - src/video/uikit/SDL_uikitopenglview.h | 2 ++ src/video/uikit/SDL_uikitopenglview.m | 25 ++++++++++++++++++++++++- src/video/uikit/SDL_uikitvideo.h | 2 +- src/video/uikit/SDL_uikitvideo.m | 7 +++---- src/video/uikit/SDL_uikitview.m | 16 +++++++++------- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 26858a825..8b9d7c945 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -150,7 +150,6 @@ UIKit_AddDisplay(UIScreen *uiscreen) display.driverdata = (void *) CFBridgingRetain(data); SDL_AddVideoDisplay(&display); - return 0; } diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 6502d03c5..8221988b8 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -57,6 +57,8 @@ - (void)updateFrame; +- (void)setDebugLabels; + - (void)setAnimationCallback:(int)interval callback:(void (*)(void*))callback callbackParam:(void*)callbackParam; diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 5da30c392..f0237cafb 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -93,7 +93,7 @@ if (sRGB) { /* sRGB EAGL drawable support was added in iOS 7. */ - if (UIKit_IsSystemVersionAtLeast(@"7.0")) { + if (UIKit_IsSystemVersionAtLeast(7.0)) { colorFormat = kEAGLColorFormatSRGBA8; } else { SDL_SetError("sRGB drawables are not supported."); @@ -164,6 +164,8 @@ } glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); + + [self setDebugLabels]; } return self; @@ -200,6 +202,27 @@ } glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); + + [self setDebugLabels]; +} + +- (void)setDebugLabels +{ + if (viewFramebuffer != 0) { + glLabelObjectEXT(GL_FRAMEBUFFER, viewFramebuffer, 0, "context FBO"); + } + + if (viewRenderbuffer != 0) { + glLabelObjectEXT(GL_RENDERBUFFER, viewRenderbuffer, 0, "context color buffer"); + } + + if (depthRenderbuffer != 0) { + if (depthBufferFormat == GL_DEPTH24_STENCIL8_OES) { + glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth-stencil buffer"); + } else { + glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth buffer"); + } + } } - (void)setAnimationCallback:(int)interval diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h index dec49cd28..dac80a2b3 100644 --- a/src/video/uikit/SDL_uikitvideo.h +++ b/src/video/uikit/SDL_uikitvideo.h @@ -25,7 +25,7 @@ #include "../SDL_sysvideo.h" -BOOL UIKit_IsSystemVersionAtLeast(NSString *version); +BOOL UIKit_IsSystemVersionAtLeast(double version); CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen); #endif /* _SDL_uikitvideo_h */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 5d4e81252..c2ceb0de7 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -130,16 +130,15 @@ UIKit_VideoQuit(_THIS) } BOOL -UIKit_IsSystemVersionAtLeast(NSString *version) +UIKit_IsSystemVersionAtLeast(double version) { - NSString *sysversion = [UIDevice currentDevice].systemVersion; - return [sysversion compare:version options:NSNumericSearch] != NSOrderedAscending; + return [[UIDevice currentDevice].systemVersion doubleValue] >= version; } CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen) { - BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(@"7.0"); + 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+. */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 2cb07ca5f..7238bafc1 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -193,19 +193,17 @@ void _uikit_keyboard_init(); /* UITextFieldDelegate method. Invoked when user types something. */ - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - if ([string length] == 0) { + NSUInteger len = string.length; + + if (len == 0) { /* it wants to replace text with nothing, ie a delete */ SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE); SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE); - } - else { + } else { /* go through all the characters in the string we've been sent and convert them to key presses */ - int i; - for (i = 0; i < [string length]; i++) { - + for (int i = 0; i < len; i++) { unichar c = [string characterAtIndex:i]; - Uint16 mod = 0; SDL_Scancode code; @@ -224,16 +222,20 @@ void _uikit_keyboard_init(); /* If character uses shift, press shift down */ SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT); } + /* send a keydown and keyup even for the character */ SDL_SendKeyboardKey(SDL_PRESSED, code); SDL_SendKeyboardKey(SDL_RELEASED, code); + if (mod & KMOD_SHIFT) { /* If character uses shift, press shift back up */ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT); } } + SDL_SendKeyboardText([string UTF8String]); } + return NO; /* don't allow the edit! (keep placeholder text there) */ } From c7ca2d918ecf4c42a93e76b9a5dbb8b1b19eaeda Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 21 Nov 2014 10:03:02 -0400 Subject: [PATCH 32/41] The iOS OpenGL ES context's color Renderbuffer Object is no longer completely destroyed and recreated in layoutSubviews. Its storage is now only reallocated when the actual size of the layer changes. The framebuffer object and renderbuffer object binding states are no longer clobbered by the storage reallocation code in layoutSubviews. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopenglview.m | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index f0237cafb..0c2a6b109 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -183,15 +183,11 @@ - (void)updateFrame { - glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(1, &viewRenderbuffer); + GLint prevRenderbuffer = 0; + glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer); - glGenRenderbuffers(1, &viewRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); @@ -201,9 +197,7 @@ glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight); } - glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); - - [self setDebugLabels]; + glBindRenderbuffer(GL_RENDERBUFFER, prevRenderbuffer); } - (void)setDebugLabels @@ -278,8 +272,15 @@ { [super layoutSubviews]; - [EAGLContext setCurrentContext:context]; - [self updateFrame]; + CGSize layersize = self.layer.bounds.size; + int width = (int) (layersize.width * self.layer.contentsScale); + int height = (int) (layersize.height * self.layer.contentsScale); + + /* Update the color and depth buffer storage if the layer size has changed. */ + if (width != backingWidth || height != backingHeight) { + [EAGLContext setCurrentContext:context]; + [self updateFrame]; + } } - (void)destroyFramebuffer From 3f0b28e9cc6d204647d4b1f9b70d42d99578dd7f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Nov 2014 23:23:47 -0400 Subject: [PATCH 33/41] Cleaned up the iOS text input code, fixed the orientation of the view offset when the onscreen keyboard is shown in iOS 8+, and changed UIKit_SetTextInputRect to update the view offset if the keyboard is currently visible. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitview.h | 8 +- src/video/uikit/SDL_uikitview.m | 205 +++++++++++++++++--------------- 2 files changed, 115 insertions(+), 98 deletions(-) diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index f34b1b155..98f07c257 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -40,7 +40,13 @@ #if SDL_IPHONE_KEYBOARD - (void)showKeyboard; - (void)hideKeyboard; -- (void)initializeKeyboard; +- (void)initKeyboard; +- (void)deinitKeyboard; + +- (void)keyboardWillShow:(NSNotification *)notification; +- (void)keyboardWillHide:(NSNotification *)notification; + +- (void)updateKeyboard; @property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible; @property (nonatomic, assign) SDL_Rect textInputRect; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 7238bafc1..ae41de77f 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -35,8 +35,6 @@ #include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" -void _uikit_keyboard_init(); - @implementation SDL_uikitview { SDL_TouchID touchId; @@ -54,7 +52,7 @@ void _uikit_keyboard_init(); { if (self = [super initWithFrame:frame]) { #if SDL_IPHONE_KEYBOARD - [self initializeKeyboard]; + [self initKeyboard]; #endif self.multipleTouchEnabled = YES; @@ -67,6 +65,13 @@ void _uikit_keyboard_init(); } +- (void)dealloc +{ +#if SDL_IPHONE_KEYBOARD + [self deinitKeyboard]; +#endif +} + - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize { CGPoint point = [touch locationInView:self]; @@ -152,7 +157,7 @@ void _uikit_keyboard_init(); @synthesize keyboardVisible; /* Set ourselves up as a UITextFieldDelegate */ -- (void)initializeKeyboard +- (void)initKeyboard { textField = [[UITextField alloc] initWithFrame:CGRectZero]; textField.delegate = self; @@ -172,8 +177,17 @@ void _uikit_keyboard_init(); keyboardVisible = NO; /* add the UITextField (hidden) to our view */ [self addSubview:textField]; - - _uikit_keyboard_init(); + + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; +} + +- (void)deinitKeyboard +{ + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [center removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } /* reveal onscreen virtual keyboard */ @@ -190,6 +204,71 @@ void _uikit_keyboard_init(); [textField resignFirstResponder]; } +- (void)keyboardWillShow:(NSNotification *)notification +{ + CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + int height; + + /* The keyboard rect is in the coordinate space of the screen, but we want + * its height in the view's coordinate space. + */ +#ifdef __IPHONE_8_0 + if ([self respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) { + UIScreen *screen = self.window.screen; + kbrect = [self convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace]; + height = kbrect.size.height; + } else +#endif + { + /* In iOS 7 and below, the screen's coordinate space is never rotated. */ + if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { + height = kbrect.size.width; + } else { + height = kbrect.size.height; + } + } + + [self setKeyboardHeight:height]; +} + + - (void)keyboardWillHide:(NSNotification *)notification +{ + [self setKeyboardHeight:0]; +} + +- (void)updateKeyboard +{ + SDL_Rect textrect = self.textInputRect; + CGAffineTransform t = self.transform; + CGPoint offset = CGPointMake(0.0, 0.0); + + if (self.keyboardHeight) { + int rectbottom = textrect.y + textrect.h; + int kbottom = self.bounds.size.height - self.keyboardHeight; + if (kbottom < rectbottom) { + offset.y = kbottom - rectbottom; + } + } + + /* Put the offset into the this view transform's coordinate space. */ + t.tx = 0.0; + t.ty = 0.0; + offset = CGPointApplyAffineTransform(offset, t); + + t.tx = offset.x; + t.ty = offset.y; + + /* Move the view by applying the updated transform. */ + self.transform = t; +} + +- (void)setKeyboardHeight:(int)height +{ + keyboardVisible = height > 0; + keyboardHeight = height; + [self updateKeyboard]; +} + /* UITextFieldDelegate method. Invoked when user types something. */ - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { @@ -255,7 +334,8 @@ void _uikit_keyboard_init(); /* iPhone keyboard addition functions */ #if SDL_IPHONE_KEYBOARD -static SDL_uikitview * getWindowView(SDL_Window * window) +static SDL_uikitview * +GetWindowView(SDL_Window * window) { if (window == NULL) { SDL_SetError("Window does not exist"); @@ -272,117 +352,46 @@ static SDL_uikitview * getWindowView(SDL_Window * window) return view; } -SDL_bool UIKit_HasScreenKeyboardSupport(_THIS) +SDL_bool +UIKit_HasScreenKeyboardSupport(_THIS) { return SDL_TRUE; } -void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) +void +UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) { @autoreleasepool { - SDL_uikitview *view = getWindowView(window); + SDL_uikitview *view = GetWindowView(window); if (view != nil) { [view showKeyboard]; } } } -void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) +void +UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) { @autoreleasepool { - SDL_uikitview *view = getWindowView(window); + SDL_uikitview *view = GetWindowView(window); if (view != nil) { [view hideKeyboard]; } } } -SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) +SDL_bool +UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) { @autoreleasepool { - SDL_uikitview *view = getWindowView(window); - if (view == nil) { - return 0; + SDL_uikitview *view = GetWindowView(window); + if (view != nil) { + return view.isKeyboardVisible; } - - return view.isKeyboardVisible; + return 0; } } - -void _uikit_keyboard_update() { - SDL_Window *window = SDL_GetFocusWindow(); - if (!window) { return; } - SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; - if (!data) { return; } - SDL_uikitview *view = data.view; - if (!view) { return; } - - SDL_Rect r = view.textInputRect; - int height = view.keyboardHeight; - int offsetx = 0; - int offsety = 0; - if (height) { - int sw,sh; - SDL_GetWindowSize(window,&sw,&sh); - int bottom = (r.y + r.h); - int kbottom = sh - height; - if (kbottom < bottom) { - offsety = kbottom-bottom; - } - } - UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation]; - if (ui_orient == UIInterfaceOrientationLandscapeLeft) { - int tmp = offsetx; offsetx = offsety; offsety = tmp; - } - if (ui_orient == UIInterfaceOrientationLandscapeRight) { - offsety = -offsety; - int tmp = offsetx; offsetx = offsety; offsety = tmp; - } - if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) { - offsety = -offsety; - } - - 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; - } - - view.keyboardVisible = height > 0; - view.keyboardHeight = height; - _uikit_keyboard_update(); -} - -void _uikit_keyboard_init() { - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - NSOperationQueue *queue = [NSOperationQueue mainQueue]; - [center addObserverForName:UIKeyboardWillShowNotification - object:nil - queue:queue - usingBlock:^(NSNotification *notification) { - int height = 0; - 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; - } - _uikit_keyboard_set_height(height); - } - ]; - [center addObserverForName:UIKeyboardDidHideNotification - object:nil - queue:queue - usingBlock:^(NSNotification *notification) { - _uikit_keyboard_set_height(0); - } - ]; -} - void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) { @@ -392,12 +401,14 @@ UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) } @autoreleasepool { - SDL_uikitview *view = getWindowView(SDL_GetFocusWindow()); - if (view == nil) { - return; - } + SDL_uikitview *view = GetWindowView(SDL_GetFocusWindow()); + if (view != nil) { + view.textInputRect = *rect; - view.textInputRect = *rect; + if (view.keyboardVisible) { + [view updateKeyboard]; + } + } } } From 0239a50edbcf44cdb762d92b5bd235e182edf2f4 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Nov 2014 23:29:24 -0400 Subject: [PATCH 34/41] Removed an ugly hack to make windows rotate properly on iOS 8+. Recent commits apparently resolved the issue that made the hack necessary. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitwindow.h | 6 +----- src/video/uikit/SDL_uikitwindow.m | 19 ++----------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index c279d0f6f..fd91b56f8 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -40,13 +40,9 @@ extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window * window); @class UIWindow; -@interface SDL_uikitwindow : UIWindow - -@end - @interface SDL_WindowData : NSObject -@property (nonatomic, strong) SDL_uikitwindow *uiwindow; +@property (nonatomic, strong) UIWindow *uiwindow; @property (nonatomic, strong) SDL_uikitopenglview *view; @property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller; diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 0c2f12017..d1e32b2cb 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -41,21 +41,6 @@ #include -@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 @synthesize uiwindow; @@ -65,7 +50,7 @@ @end -static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, SDL_bool created) +static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created) { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata; @@ -213,7 +198,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* 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]; + UIWindow *uiwindow = [[UIWindow 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 From b79d62e004f5492d6c949367e83805fa0dd53b37 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 27 Nov 2014 20:25:54 -0400 Subject: [PATCH 35/41] Minor Objective-C code tweaks. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitopengles.m | 34 ++++++++++++----------- src/video/uikit/SDL_uikitopenglview.m | 1 - src/video/uikit/SDL_uikitvideo.m | 1 + src/video/uikit/SDL_uikitview.h | 4 +-- src/video/uikit/SDL_uikitview.m | 10 +++---- src/video/uikit/SDL_uikitviewcontroller.m | 6 +--- src/video/uikit/SDL_uikitwindow.h | 1 + src/video/uikit/SDL_uikitwindow.m | 29 +++++++++++-------- 8 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 82c1e3054..a003882f6 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -58,7 +58,8 @@ UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) return 0; } -void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) +void +UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { @autoreleasepool { SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; @@ -157,16 +158,15 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) return NULL; } + view.sdlwindow = window; data.view = view; - view.viewcontroller = data.viewcontroller; - if (view.viewcontroller != nil) { - view.viewcontroller.view = view; - } - [uiwindow addSubview:view]; + data.viewcontroller.view = view; - /* The view controller needs to be the root in order to control rotation on iOS 6.0 */ + /* The view controller needs to be the root in order to control rotation */ if (uiwindow.rootViewController == nil) { - uiwindow.rootViewController = view.viewcontroller; + uiwindow.rootViewController = data.viewcontroller; + } else { + [uiwindow addSubview:view]; } EAGLContext *context = view.context; @@ -199,17 +199,17 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) 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) { + /* the view controller has retained the view */ + if (data.viewcontroller) { UIWindow *uiwindow = (UIWindow *)view.superview; - if (uiwindow.rootViewController == view.viewcontroller) { + if (uiwindow.rootViewController == data.viewcontroller) { uiwindow.rootViewController = nil; } - view.viewcontroller.view = nil; - view.viewcontroller = nil; + data.viewcontroller.view = nil; } - [view removeFromSuperview]; + [view removeFromSuperview]; + view.sdlwindow = NULL; data.view = nil; return; } @@ -217,7 +217,8 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) } } -Uint32 SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) +Uint32 +SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) { if (!window) { SDL_SetError("Invalid window"); @@ -234,7 +235,8 @@ Uint32 SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) } } -Uint32 SDL_iPhoneGetViewFramebuffer(SDL_Window * window) +Uint32 +SDL_iPhoneGetViewFramebuffer(SDL_Window * window) { if (!window) { SDL_SetError("Invalid window"); diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 0c2a6b109..542c7d88b 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -46,7 +46,6 @@ int animationInterval; void (*animationCallback)(void*); void *animationCallbackParam; - } @synthesize context; diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index c2ceb0de7..c3448efc7 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -75,6 +75,7 @@ UIKit_CreateDevice(int devindex) device->SetDisplayMode = UIKit_SetDisplayMode; device->PumpEvents = UIKit_PumpEvents; device->CreateWindow = UIKit_CreateWindow; + device->SetWindowTitle = UIKit_SetWindowTitle; device->ShowWindow = UIKit_ShowWindow; device->HideWindow = UIKit_HideWindow; device->RaiseWindow = UIKit_RaiseWindow; diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 98f07c257..adee330be 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -20,7 +20,7 @@ */ #import -#import "SDL_uikitviewcontroller.h" +#include "../SDL_sysvideo.h" #include "SDL_touch.h" @@ -30,7 +30,7 @@ @interface SDL_uikitview : UIView #endif -@property (nonatomic, weak) SDL_uikitviewcontroller *viewcontroller; +@property (nonatomic, assign) SDL_Window *sdlwindow; - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index ae41de77f..d7679c19e 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -46,7 +46,7 @@ } -@synthesize viewcontroller; +@synthesize sdlwindow; - (id)initWithFrame:(CGRect)frame { @@ -92,10 +92,10 @@ 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(sdlwindow, 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(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); leftFingerDown = touch; } @@ -111,7 +111,7 @@ 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(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); leftFingerDown = nil; } @@ -138,7 +138,7 @@ 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(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index de5b3008c..77cbc0ba5 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -73,11 +73,7 @@ - (BOOL)prefersStatusBarHidden { - if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) { - return YES; - } else { - return NO; - } + return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0; } - (UIStatusBarStyle)preferredStatusBarStyle diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index fd91b56f8..cc7d8839a 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -27,6 +27,7 @@ #import "SDL_uikitviewcontroller.h" extern int UIKit_CreateWindow(_THIS, SDL_Window * window); +extern void UIKit_SetWindowTitle(_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); diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index d1e32b2cb..849c90888 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -55,7 +55,6 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata; - /* Allocate the window data */ SDL_WindowData *data = [[SDL_WindowData alloc] init]; if (!data) { return SDL_OutOfMemory(); @@ -67,7 +66,6 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo { CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); - /* Get frame dimensions */ int width = (int) frame.size.width; int height = (int) frame.size.height; @@ -114,7 +112,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo * appropriate. */ data.viewcontroller = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window]; - data.viewcontroller.title = @"SDL App"; /* !!! FIXME: hook up SDL_SetWindowTitle() */ + data.viewcontroller.title = @""; return 0; } @@ -186,11 +184,9 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } else { if (!(orientations & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown))) { UIInterfaceOrientation orient = UIInterfaceOrientationLandscapeLeft; - if (orientations & UIInterfaceOrientationMaskLandscapeRight) { orient = UIInterfaceOrientationLandscapeRight; } - [app setStatusBarOrientation:orient animated:NO]; } } @@ -212,12 +208,24 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) { return -1; } - } return 1; } +void +UIKit_SetWindowTitle(_THIS, SDL_Window * window) +{ + @autoreleasepool { + SDL_uikitviewcontroller *vc = ((__bridge SDL_WindowData *) window->driverdata).viewcontroller; + if (window->title) { + vc.title = @(window->title); + } else { + vc.title = @""; + } + } +} + void UIKit_ShowWindow(_THIS, SDL_Window * window) { @@ -275,16 +283,16 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) [windowdata.view layoutIfNeeded]; /* Get frame dimensions */ - int width = (int) frame.size.width; - int height = (int) frame.size.height; + int w = (int) frame.size.width; + int h = (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. */ if (window->w >= window->h) { - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(width, height), SDL_min(width, height)); + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(w, h), SDL_min(w, h)); } else { - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(width, height), SDL_max(width, height)); + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(w, h), SDL_max(w, h)); } } @@ -312,7 +320,6 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window) CFRelease(window->driverdata); } } - window->driverdata = NULL; } From 38563c490c4680b8bcd1662207b819d1f3dc57a0 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 1 Dec 2014 07:31:22 -0400 Subject: [PATCH 36/41] Fixed SDL_GetRendererOutputSize on iOS when high-DPI mode is enabled on a Retina device. --HG-- branch : iOS-improvements --- src/render/opengles/SDL_render_gles.c | 9 +++++++++ src/render/opengles2/SDL_render_gles2.c | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index 72cce305a..617bf659f 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -55,6 +55,7 @@ static const float inv255f = 1.0f / 255.0f; static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags); static void GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event); +static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h); static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, @@ -321,6 +322,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) } renderer->WindowEvent = GLES_WindowEvent; + renderer->GetOutputSize = GLES_GetOutputSize; renderer->CreateTexture = GLES_CreateTexture; renderer->UpdateTexture = GLES_UpdateTexture; renderer->LockTexture = GLES_LockTexture; @@ -438,6 +440,13 @@ GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) } } +static int +GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) +{ + SDL_GL_GetDrawableSize(renderer->window, w, h); + return 0; +} + static SDL_INLINE int power_of_2(int input) { diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index fd7f1b379..cf9da6a6d 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -351,6 +351,13 @@ GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) } } +static int +GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) +{ + SDL_GL_GetDrawableSize(renderer->window, w, h); + return 0; +} + static int GLES2_UpdateViewport(SDL_Renderer * renderer) { @@ -2004,6 +2011,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) /* Populate the function pointers for the module */ renderer->WindowEvent = &GLES2_WindowEvent; + renderer->GetOutputSize = &GLES2_GetOutputSize; renderer->CreateTexture = &GLES2_CreateTexture; renderer->UpdateTexture = &GLES2_UpdateTexture; renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV; From b323ac5ca6acc81214c27dc8f605e75e0fcf8cc5 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 15 Jan 2015 01:06:14 -0400 Subject: [PATCH 37/41] Several improvements to the iOS backend: - Added new custom launch screen code. It uses the launch screen nib when available on iOS 8+, the launch images dictionary if the launch screen nib isn't available, and the old standard image names if the launch image dictionary isn't in the plist. The launch screen is now hidden during the first call to SDL_PumpEvents rather than SDL_CreateWindow so apps can have the launch screen still visible if they do time-consuming loading after creating their window. It also fades out in roughly the same way as the system launch screen behavior. It can be disabled by setting the SDL_IPHONE_LAUNCHSCREEN define in SDL_config_iphoneos.h to 0. - A blank UIView is now created and displayed when the window is first created. The old behavior was to defer creating any view until SDL_GL_CreateContext, which prevented rotation, touch events, and other windowing-related things from working until then. This also makes it easier to use SDL_GetWindowWMInfo after creating a window. - Moved the keyboard and animation callback code from SDL's UIView subclasses to its UIViewController subclass, which lets them work properly in all cases when a SDL window is valid, even before SDL_GL_CreateContext is called and after SDL_GL_DeleteContext is called. - SDL_GL_CreateContext, SDL_GL_SwapWindow, SDL_GL_MakeCurrent, and SDL_GL_DeleteContext are more robust. - Fixed some edge cases where SDL windows weren't rotating properly or their reported sizes were out of sync with their actual sizes. - Removed all calls to [UIApplication setStatusBarOrientation:]. It doesn't seem to work as expected in all cases in recent iOS versions. - Some code style cleanup. --HG-- branch : iOS-improvements --- include/SDL_config_iphoneos.h | 3 + premake/Xcode-iOS/SDL_config_premake.h | 3 + src/video/SDL_video.c | 25 +- src/video/uikit/SDL_uikitappdelegate.h | 16 +- src/video/uikit/SDL_uikitappdelegate.m | 261 +++++++++++++-- src/video/uikit/SDL_uikitmessagebox.m | 38 +-- src/video/uikit/SDL_uikitmodes.m | 18 +- src/video/uikit/SDL_uikitopengles.m | 166 ++++------ src/video/uikit/SDL_uikitopenglview.h | 55 ++-- src/video/uikit/SDL_uikitopenglview.m | 119 +++---- src/video/uikit/SDL_uikitview.h | 32 +- src/video/uikit/SDL_uikitview.m | 374 +++++----------------- src/video/uikit/SDL_uikitviewcontroller.h | 42 ++- src/video/uikit/SDL_uikitviewcontroller.m | 339 +++++++++++++++++++- src/video/uikit/SDL_uikitwindow.h | 6 +- src/video/uikit/SDL_uikitwindow.m | 223 ++++++------- 16 files changed, 984 insertions(+), 736 deletions(-) diff --git a/include/SDL_config_iphoneos.h b/include/SDL_config_iphoneos.h index 4e3eb2c92..79da3667b 100644 --- a/include/SDL_config_iphoneos.h +++ b/include/SDL_config_iphoneos.h @@ -145,6 +145,9 @@ /* enable iPhone keyboard support */ #define SDL_IPHONE_KEYBOARD 1 +/* enable iOS extended launch screen */ +#define SDL_IPHONE_LAUNCHSCREEN 1 + /* enable joystick subsystem */ #define SDL_JOYSTICK_DISABLED 0 diff --git a/premake/Xcode-iOS/SDL_config_premake.h b/premake/Xcode-iOS/SDL_config_premake.h index e0a864173..bae64b187 100644 --- a/premake/Xcode-iOS/SDL_config_premake.h +++ b/premake/Xcode-iOS/SDL_config_premake.h @@ -126,6 +126,9 @@ #ifndef SDL_IPHONE_KEYBOARD #define SDL_IPHONE_KEYBOARD 1 #endif +#ifndef SDL_IPHONE_LAUNCHSCREEN +#define SDL_IPHONE_LAUNCHSCREEN 1 +#endif #ifndef SDL_POWER_UIKIT #define SDL_POWER_UIKIT 1 #endif diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 43d674fe0..895643b6b 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1100,22 +1100,22 @@ SDL_RestoreMousePosition(SDL_Window *window) } } -static void +static int SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) { SDL_VideoDisplay *display; SDL_Window *other; - CHECK_WINDOW_MAGIC(window,); + CHECK_WINDOW_MAGIC(window,-1); /* if we are in the process of hiding don't go back to fullscreen */ if ( window->is_hiding && fullscreen ) - return; + return 0; #ifdef __MACOSX__ if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) { window->last_fullscreen_flags = window->flags; - return; + return 0; } #endif @@ -1132,7 +1132,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) /* See if anything needs to be done now */ if ((display->fullscreen_window == window) == fullscreen) { if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) { - return; + return 0; } } @@ -1161,9 +1161,13 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) /* only do the mode change if we want exclusive fullscreen */ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) { - SDL_SetDisplayModeForDisplay(display, &fullscreen_mode); + if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) { + return -1; + } } else { - SDL_SetDisplayModeForDisplay(display, NULL); + if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) { + return -1; + } } if (_this->SetWindowFullscreen) { @@ -1182,7 +1186,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) SDL_RestoreMousePosition(other); window->last_fullscreen_flags = window->flags; - return; + return 0; } } } @@ -1202,6 +1206,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) SDL_RestoreMousePosition(window); window->last_fullscreen_flags = window->flags; + return 0; } #define CREATE_FLAGS \ @@ -1927,9 +1932,7 @@ SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags) window->flags &= ~FULLSCREEN_MASK; window->flags |= flags; - SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)); - - return 0; + return SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)); } static SDL_Surface * diff --git a/src/video/uikit/SDL_uikitappdelegate.h b/src/video/uikit/SDL_uikitappdelegate.h index d5430beb1..cc4494dbb 100644 --- a/src/video/uikit/SDL_uikitappdelegate.h +++ b/src/video/uikit/SDL_uikitappdelegate.h @@ -21,12 +21,22 @@ #import -@interface SDLUIKitDelegate : NSObject { -} +@interface SDLLaunchScreenController : UIViewController -+ (id) sharedAppDelegate; +- (instancetype)init; +- (void)loadView; +- (BOOL)shouldAutorotate; +- (NSUInteger)supportedInterfaceOrientations; + +@end + +@interface SDLUIKitDelegate : NSObject + ++ (id)sharedAppDelegate; + (NSString *)getAppDelegateClassName; +- (void)hideLaunchScreen; + @end /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 6a07d5d14..3306f38e9 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -28,8 +28,10 @@ #include "SDL_system.h" #include "SDL_main.h" -#include "SDL_uikitappdelegate.h" -#include "SDL_uikitmodes.h" +#import "SDL_uikitappdelegate.h" +#import "SDL_uikitmodes.h" +#import "SDL_uikitwindow.h" + #include "../../events/SDL_events_c.h" #ifdef main @@ -74,46 +76,256 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa [UIApplication sharedApplication].idleTimerDisabled = disable; } -@implementation SDLUIKitDelegate +/* Load a launch image using the old UILaunchImageFile-era naming rules. */ +static UIImage * +SDL_LoadLaunchImageNamed(NSString *name, int screenh) +{ + UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation; + UIUserInterfaceIdiom idiom = [UIDevice currentDevice].userInterfaceIdiom; + UIImage *image = nil; + + if (idiom == UIUserInterfaceIdiomPhone && screenh == 568) { + /* The image name for the iPhone 5 uses its height as a suffix. */ + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-568h", name]]; + } else if (idiom == UIUserInterfaceIdiomPad) { + /* iPad apps can launch in any orientation. */ + if (UIInterfaceOrientationIsLandscape(curorient)) { + if (curorient == UIInterfaceOrientationLandscapeLeft) { + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeLeft", name]]; + } else { + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeRight", name]]; + } + if (!image) { + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Landscape", name]]; + } + } else { + if (curorient == UIInterfaceOrientationPortraitUpsideDown) { + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-PortraitUpsideDown", name]]; + } + if (!image) { + image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Portrait", name]]; + } + } + } + + if (!image) { + image = [UIImage imageNamed:name]; + } + + return image; +} + +@implementation SDLLaunchScreenController + +- (instancetype)init +{ + if (!(self = [super initWithNibName:nil bundle:nil])) { + return nil; + } + + NSBundle *bundle = [NSBundle mainBundle]; + NSString *screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"]; + + /* Launch screens were added in iOS 8. Otherwise we use launch images. */ + if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) { + @try { + self.view = [bundle loadNibNamed:screenname owner:self options:nil][0]; + } + @catch (NSException *exception) { + /* iOS displays a blank screen rather than falling back to an image, + * if a launch screen name is specified but it fails to load. */ + return nil; + } + } + + if (!self.view) { + NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"]; + UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation; + NSString *imagename = nil; + UIImage *image = nil; + + int screenw = (int)([UIScreen mainScreen].bounds.size.width + 0.5); + int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5); + + /* We always want portrait-oriented size, to match UILaunchImageSize. */ + if (screenw > screenh) { + int width = screenw; + screenw = screenh; + screenh = width; + } + + /* Xcode 5 introduced a dictionary of launch images in Info.plist. */ + if (launchimages) { + for (NSDictionary *dict in launchimages) { + UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; + NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"]; + NSString *sizestring = dict[@"UILaunchImageSize"]; + NSString *orientstring = dict[@"UILaunchImageOrientation"]; + + /* Ignore this image if the current version is too low. */ + if (minversion && !UIKit_IsSystemVersionAtLeast(minversion.doubleValue)) { + continue; + } + + /* Ignore this image if the size doesn't match. */ + if (sizestring) { + CGSize size = CGSizeFromString(sizestring); + if ((int)(size.width + 0.5) != screenw || (int)(size.height + 0.5) != screenh) { + continue; + } + } + + if (orientstring) { + if ([orientstring isEqualToString:@"PortraitUpsideDown"]) { + orientmask = UIInterfaceOrientationMaskPortraitUpsideDown; + } else if ([orientstring isEqualToString:@"Landscape"]) { + orientmask = UIInterfaceOrientationMaskLandscape; + } else if ([orientstring isEqualToString:@"LandscapeLeft"]) { + orientmask = UIInterfaceOrientationMaskLandscapeLeft; + } else if ([orientstring isEqualToString:@"LandscapeRight"]) { + orientmask = UIInterfaceOrientationMaskLandscapeRight; + } + } + + /* Ignore this image if the orientation doesn't match. */ + if ((orientmask & (1 << curorient)) == 0) { + continue; + } + + imagename = dict[@"UILaunchImageName"]; + } + + if (imagename) { + image = [UIImage imageNamed:imagename]; + } + } else { + imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"]; + + if (imagename) { + image = SDL_LoadLaunchImageNamed(imagename, screenh); + } + + if (!image) { + image = SDL_LoadLaunchImageNamed(@"Default", screenh); + } + } + + if (image) { + self.view = [[UIImageView alloc] initWithImage:image]; + } + } + + return self; +} + +- (void)loadView +{ + /* Do nothing. */ +} + +- (BOOL)shouldAutorotate +{ + return YES; +} + +- (NSUInteger)supportedInterfaceOrientations +{ + return UIInterfaceOrientationMaskAll; +} + +@end + +@implementation SDLUIKitDelegate { + UIWindow *launchWindow; +} /* convenience method */ -+ (id) sharedAppDelegate ++ (id)sharedAppDelegate { - /* the delegate is set in UIApplicationMain(), which is guaranteed to be called before this method */ - return [[UIApplication sharedApplication] delegate]; + /* the delegate is set in UIApplicationMain(), which is guaranteed to be + * called before this method */ + return [UIApplication sharedApplication].delegate; } + (NSString *)getAppDelegateClassName { - /* subclassing notice: when you subclass this appdelegate, make sure to add a category to override - this method and return the actual name of the delegate */ + /* subclassing notice: when you subclass this appdelegate, make sure to add + * a category to override this method and return the actual name of the + * delegate */ return @"SDLUIKitDelegate"; } -- (id)init +- (void)hideLaunchScreen { - self = [super init]; - return self; + UIWindow *window = launchWindow; + + if (!window || window.hidden) { + return; + } + + launchWindow = nil; + + /* Do a nice animated fade-out (roughly matches the real launch behavior.) */ + [UIView animateWithDuration:0.2 animations:^{ + window.alpha = 0.0; + } completion:^(BOOL finished) { + window.hidden = YES; + }]; } - (void)postFinishLaunch { + /* Hide the launch screen the next time the run loop is run. SDL apps will + * have a chance to load resources while the launch screen is still up. */ + [self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0]; + /* run the user's application, passing argc and argv */ SDL_iPhoneSetEventPump(SDL_TRUE); exit_status = SDL_main(forward_argc, forward_argv); SDL_iPhoneSetEventPump(SDL_FALSE); + if (launchWindow) { + launchWindow.hidden = YES; + launchWindow = nil; + } + /* exit, passing the return status from the user's application */ - /* We don't actually exit to support applications that do setup in - * their main function and then allow the Cocoa event loop to run. - */ + /* We don't actually exit to support applications that do setup in their + * main function and then allow the Cocoa event loop to run. */ /* exit(exit_status); */ } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + NSBundle *bundle = [NSBundle mainBundle]; + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + +#if SDL_IPHONE_LAUNCHSCREEN + /* The normal launch screen is displayed until didFinishLaunching returns, + * but SDL_main is called after that happens and there may be a noticeable + * delay between the start of SDL_main and when the first real frame is + * displayed (e.g. if resources are loaded before SDL_GL_SwapWindow is + * called), so we show the launch screen programmatically until the first + * time events are pumped. */ + UIViewController *viewcontroller = [[SDLLaunchScreenController alloc] init]; + + if (viewcontroller.view) { + launchWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + + /* We don't want the launch window immediately hidden when a real SDL + * window is shown - we fade it out ourselves when we're ready. */ + launchWindow.windowLevel = UIWindowLevelNormal + 1.0; + + /* Show the window but don't make it key. Events should always go to + * other windows when possible. */ + launchWindow.hidden = NO; + + launchWindow.rootViewController = viewcontroller; + } +#endif + /* Set working directory to resource path */ - [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]]; + [[NSFileManager defaultManager] changeCurrentDirectoryPath:[bundle resourcePath]]; /* register a callback for the idletimer hint */ SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED, @@ -121,7 +333,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa SDL_SetMainReady(); [self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0]; - + return YES; } @@ -147,8 +359,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa /* 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. - */ + * correct orientation. */ if (isLandscape != (desktopmode->w > desktopmode->h)) { int height = desktopmode->w; desktopmode->w = desktopmode->h; @@ -164,7 +375,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa } } -- (void) applicationWillResignActive:(UIApplication*)application +- (void)applicationWillResignActive:(UIApplication*)application { SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this) { @@ -177,17 +388,17 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND); } -- (void) applicationDidEnterBackground:(UIApplication*)application +- (void)applicationDidEnterBackground:(UIApplication*)application { SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND); } -- (void) applicationWillEnterForeground:(UIApplication*)application +- (void)applicationWillEnterForeground:(UIApplication*)application { SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND); } -- (void) applicationDidBecomeActive:(UIApplication*)application +- (void)applicationDidBecomeActive:(UIApplication*)application { SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND); @@ -203,11 +414,11 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { - NSURL *fileURL = [url filePathURL]; + NSURL *fileURL = url.filePathURL; if (fileURL != nil) { - SDL_SendDropFile([[fileURL path] UTF8String]); + SDL_SendDropFile([fileURL.path UTF8String]); } else { - SDL_SendDropFile([[url absoluteString] UTF8String]); + SDL_SendDropFile([url.absoluteString UTF8String]); } return YES; } diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m index 9a99db170..f540f0c5c 100644 --- a/src/video/uikit/SDL_uikitmessagebox.m +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -30,35 +30,20 @@ static SDL_bool s_showingMessageBox = SDL_FALSE; -@interface UIKit_UIAlertViewDelegate : NSObject +@interface SDLAlertViewDelegate : NSObject -- (id)initWithButtonIndex:(int *)buttonIndex; -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; +@property (nonatomic, assign) int clickedIndex; @end -@implementation UIKit_UIAlertViewDelegate { - int *clickedButtonIndex; -} - -- (id)initWithButtonIndex:(int *)buttonIndex -{ - self = [self init]; - if (self == nil) { - return nil; - } - - clickedButtonIndex = buttonIndex; - - return self; -} +@implementation SDLAlertViewDelegate - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { - *clickedButtonIndex = (int)buttonIndex; + _clickedIndex = (int)buttonIndex; } -@end /* UIKit_UIAlertViewDelegate */ +@end SDL_bool @@ -70,36 +55,35 @@ UIKit_ShowingMessageBox() int UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { - int clicked; int i; const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; @autoreleasepool { - UIAlertView* alert = [[UIAlertView alloc] init]; - UIKit_UIAlertViewDelegate *delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; + UIAlertView *alert = [[UIAlertView alloc] init]; + SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init]; + alert.delegate = delegate; alert.title = @(messageboxdata->title); alert.message = @(messageboxdata->message); - alert.delegate = delegate; for (i = 0; i < messageboxdata->numbuttons; ++i) { [alert addButtonWithTitle:@(buttons[i].text)]; } /* Set up for showing the alert */ - clicked = messageboxdata->numbuttons; + delegate.clickedIndex = messageboxdata->numbuttons; [alert show]; /* 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) { + while (delegate.clickedIndex == messageboxdata->numbuttons) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } s_showingMessageBox = SDL_FALSE; - *buttonid = messageboxdata->buttons[clicked].buttonid; + *buttonid = messageboxdata->buttons[delegate.clickedIndex].buttonid; alert.delegate = nil; } diff --git a/src/video/uikit/SDL_uikitmodes.m b/src/video/uikit/SDL_uikitmodes.m index 8b9d7c945..1fb9a03c7 100644 --- a/src/video/uikit/SDL_uikitmodes.m +++ b/src/video/uikit/SDL_uikitmodes.m @@ -112,7 +112,7 @@ UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, static int UIKit_AddDisplay(UIScreen *uiscreen) { - CGSize size = [uiscreen bounds].size; + CGSize size = uiscreen.bounds.size; /* Make sure the width/height are oriented correctly */ if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) { @@ -128,7 +128,7 @@ UIKit_AddDisplay(UIScreen *uiscreen) mode.w = (int) size.width; mode.h = (int) size.height; - UIScreenMode *uiscreenmode = [uiscreen currentMode]; + UIScreenMode *uiscreenmode = uiscreen.currentMode; if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) { return -1; @@ -157,9 +157,9 @@ SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen) { if (uiscreen == [UIScreen mainScreen]) { - return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]); + return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation); } else { - CGSize size = [uiscreen bounds].size; + CGSize size = uiscreen.bounds.size; return (size.width > size.height); } } @@ -196,7 +196,7 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) } #endif - for (UIScreenMode *uimode in [data.uiscreen availableModes]) { + 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.) */ int w = (int)(uimode.size.width / scale); @@ -209,7 +209,6 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) h = tmp; } - /* Add the native screen resolution. */ UIKit_AddDisplayMode(display, w, h, uimode, addRotation); } } @@ -225,13 +224,16 @@ UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) [data.uiscreen setCurrentMode:modedata.uiscreenmode]; if (data.uiscreen == [UIScreen mainScreen]) { + /* [UIApplication setStatusBarOrientation:] no longer works reliably + * in recent iOS versions, so we can't rotate the screen when setting + * the display mode. */ if (mode->w > mode->h) { if (!UIKit_IsDisplayLandscape(data.uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + return SDL_SetError("Screen orientation does not match display mode size"); } } else if (mode->w < mode->h) { if (UIKit_IsDisplayLandscape(data.uiscreen)) { - [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; + return SDL_SetError("Screen orientation does not match display mode size"); } } } diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index a003882f6..e9178c183 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -23,10 +23,10 @@ #if SDL_VIDEO_DRIVER_UIKIT #include "SDL_uikitopengles.h" -#include "SDL_uikitopenglview.h" -#include "SDL_uikitappdelegate.h" +#import "SDL_uikitopenglview.h" #include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" +#include "SDL_uikitevents.h" #include "../SDL_sysvideo.h" #include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_mouse_c.h" @@ -40,21 +40,29 @@ void * UIKit_GL_GetProcAddress(_THIS, const char *proc) { /* Look through all SO's for the proc symbol. Here's why: - -Looking for the path to the OpenGL Library seems not to work in the iPhone Simulator. - -We don't know that the path won't change in the future. - */ + * -Looking for the path to the OpenGL Library seems not to work in the iOS Simulator. + * -We don't know that the path won't change in the future. */ return dlsym(RTLD_DEFAULT, proc); } /* - note that SDL_GL_Delete context makes it current without passing the window + note that SDL_GL_DeleteContext makes it current without passing the window */ int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { @autoreleasepool { - [EAGLContext setCurrentContext:(__bridge EAGLContext *)context]; + SDLEAGLContext *eaglcontext = (__bridge SDLEAGLContext *) context; + + if (![EAGLContext setCurrentContext:eaglcontext]) { + return SDL_SetError("Could not make EAGL context current"); + } + + if (eaglcontext) { + [eaglcontext.sdlView setSDLWindow:window]; + } } + return 0; } @@ -63,27 +71,26 @@ 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; + UIView *view = data.viewcontroller.view; + if ([view isKindOfClass:[SDL_uikitopenglview class]]) { + SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view; + if (w) { + *w = glview.backingWidth; + } + if (h) { + *h = glview.backingHeight; + } } } } - int UIKit_GL_LoadLibrary(_THIS, const char *path) { - /* - shouldn't be passing a path into this function - why? Because we've already loaded the library - and because the SDK forbids loading an external SO - */ + /* We shouldn't pass a path to this function, since we've already loaded the + * library. */ if (path != NULL) { - return SDL_SetError("iPhone GL Load Library just here for compatibility"); + return SDL_SetError("iOS GL Load Library just here for compatibility"); } return 0; } @@ -91,22 +98,18 @@ UIKit_GL_LoadLibrary(_THIS, const char *path) void UIKit_GL_SwapWindow(_THIS, SDL_Window * window) { @autoreleasepool { - SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + SDLEAGLContext *context = (__bridge SDLEAGLContext *) SDL_GL_GetCurrentContext(); #if SDL_POWER_UIKIT /* Check once a frame to see if we should turn off the battery monitor. */ SDL_UIKit_UpdateBatteryMonitoring(); #endif - if (data.view == nil) { - return; - } - [data.view swapBuffers]; + [context.sdlView 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. - */ + * We don't pump events here because we don't want iOS application events + * (low memory, terminate, etc.) to happen inside low level rendering. */ } } @@ -116,29 +119,27 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) @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; + CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen); + EAGLSharegroup *sharegroup = 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. - */ -#ifdef __IPHONE_8_0 - if ([uiwindow.screen respondsToSelector:@selector(nativeScale)]) { - scale = uiwindow.screen.nativeScale; - } else -#endif - { - scale = uiwindow.screen.scale; - } - } - if (_this->gl_config.share_with_current_context) { EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext(); - share_group = context.sharegroup; + sharegroup = context.sharegroup; + } + + 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. */ +#ifdef __IPHONE_8_0 + if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) { + scale = data.uiwindow.screen.nativeScale; + } else +#endif + { + scale = data.uiwindow.screen.scale; + } } /* construct our view, passing in SDL's OpenGL configuration data */ @@ -153,35 +154,19 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window) stencilBits:_this->gl_config.stencil_size sRGB:_this->gl_config.framebuffer_srgb_capable majorVersion:_this->gl_config.major_version - shareGroup:share_group]; + shareGroup:sharegroup]; if (!view) { return NULL; } - view.sdlwindow = window; - data.view = view; - data.viewcontroller.view = view; - - /* The view controller needs to be the root in order to control rotation */ - if (uiwindow.rootViewController == nil) { - uiwindow.rootViewController = data.viewcontroller; - } else { - [uiwindow addSubview:view]; - } - - EAGLContext *context = view.context; + SDLEAGLContext *context = view.context; if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) { UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context)); return NULL; } - /* 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. */ + /* We return a +1'd context. The window's driverdata owns the view (via + * MakeCurrent.) */ return (SDL_GLContext) CFBridgingRetain(context); } } @@ -191,29 +176,10 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) { @autoreleasepool { /* Transfer ownership the +1'd context to ARC. */ - EAGLContext *eaglcontext = (EAGLContext *) CFBridgingRelease(context); - SDL_Window *window; + SDLEAGLContext *eaglcontext = (SDLEAGLContext *) CFBridgingRelease(context); - /* 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 view controller has retained the view */ - if (data.viewcontroller) { - UIWindow *uiwindow = (UIWindow *)view.superview; - if (uiwindow.rootViewController == data.viewcontroller) { - uiwindow.rootViewController = nil; - } - data.viewcontroller.view = nil; - } - - [view removeFromSuperview]; - view.sdlwindow = NULL; - data.view = nil; - return; - } - } + /* Detach the context's view from its window. */ + [eaglcontext.sdlView setSDLWindow:NULL]; } } @@ -227,12 +193,15 @@ SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) @autoreleasepool { SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; - if (data.view != nil) { - return data.view.drawableRenderbuffer; - } else { - return 0; + UIView *view = data.viewcontroller.view; + if ([view isKindOfClass:[SDL_uikitopenglview class]]) { + SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view; + return glview.drawableRenderbuffer; } } + + SDL_SetError("Window does not have an attached OpenGL view"); + return 0; } Uint32 @@ -245,12 +214,15 @@ SDL_iPhoneGetViewFramebuffer(SDL_Window * window) @autoreleasepool { SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; - if (data.view != nil) { - return data.view.drawableFramebuffer; - } else { - return 0; + UIView *view = data.viewcontroller.view; + if ([view isKindOfClass:[SDL_uikitopenglview class]]) { + SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view; + return glview.drawableFramebuffer; } } + + SDL_SetError("Window does not have an attached OpenGL view"); + return 0; } #endif /* SDL_VIDEO_DRIVER_UIKIT */ diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h index 8221988b8..1dcac28b7 100644 --- a/src/video/uikit/SDL_uikitopenglview.h +++ b/src/video/uikit/SDL_uikitopenglview.h @@ -21,29 +21,35 @@ #import #import -#import +#import + #import "SDL_uikitview.h" -/* - This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. - 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. - */ +#include "SDL_uikitvideo.h" + +@class SDL_uikitopenglview; + +@interface SDLEAGLContext : EAGLContext + +@property (nonatomic, weak) SDL_uikitopenglview *sdlView; + +@end + @interface SDL_uikitopenglview : SDL_uikitview -- (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; +- (instancetype)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; +@property (nonatomic, readonly, strong) SDLEAGLContext *context; /* The width and height of the drawable in pixels (as opposed to points.) */ @property (nonatomic, readonly) int backingWidth; @@ -57,17 +63,6 @@ - (void)updateFrame; -- (void)setDebugLabels; - -- (void)setAnimationCallback:(int)interval - callback:(void (*)(void*))callback - callbackParam:(void*)callbackParam; - -- (void)startAnimation; -- (void)stopAnimation; - -- (void)doLoop:(CADisplayLink*)sender; - @end /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m index 542c7d88b..df848f3d5 100644 --- a/src/video/uikit/SDL_uikitopenglview.m +++ b/src/video/uikit/SDL_uikitopenglview.m @@ -22,34 +22,27 @@ #if SDL_VIDEO_DRIVER_UIKIT -#include #include -#include #include -#include "SDL_uikitopenglview.h" -#include "SDL_uikitmessagebox.h" -#include "SDL_uikitvideo.h" +#import "SDL_uikitopenglview.h" +#include "SDL_uikitwindow.h" +@implementation SDLEAGLContext + +@end @implementation SDL_uikitopenglview { - - /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ + /* The renderbuffer and framebuffer used to render to this layer. */ GLuint viewRenderbuffer, viewFramebuffer; - /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ + /* The depth buffer that is attached to viewFramebuffer, if it exists. */ GLuint depthRenderbuffer; /* format of depthRenderbuffer */ GLenum depthBufferFormat; - - id displayLink; - int animationInterval; - void (*animationCallback)(void*); - void *animationCallbackParam; } @synthesize context; - @synthesize backingWidth; @synthesize backingHeight; @@ -58,38 +51,36 @@ return [CAEAGLLayer class]; } -- (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 +- (instancetype)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 { 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. - */ + * versions, and this allows us to handle future OpenGL ES versions. */ EAGLRenderingAPI api = majorVersion; - context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup]; + context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:shareGroup]; if (!context || ![EAGLContext setCurrentContext:context]) { SDL_SetError("OpenGL ES %d not supported", majorVersion); return nil; } + context.sdlView = self; + if (sRGB) { /* sRGB EAGL drawable support was added in iOS 7. */ if (UIKit_IsSystemVersionAtLeast(7.0)) { @@ -102,11 +93,10 @@ /* if user specifically requests rbg888 or some color format higher than 16bpp */ colorFormat = kEAGLColorFormatRGBA8; } else { - /* default case (faster) */ + /* default case (potentially faster) */ colorFormat = kEAGLColorFormatRGB565; } - /* Get the layer */ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; @@ -142,7 +132,8 @@ /* Apparently you need to pack stencil and depth into one buffer. */ depthBufferFormat = GL_DEPTH24_STENCIL8_OES; } else if (useDepthBuffer) { - /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16 */ + /* iOS only uses 32-bit float (exposed as fixed point 24-bit) + * depth buffers. */ depthBufferFormat = GL_DEPTH_COMPONENT24_OES; } @@ -186,7 +177,7 @@ glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); - [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; + [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer]; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); @@ -218,42 +209,6 @@ } } -- (void)setAnimationCallback:(int)interval - callback:(void (*)(void*))callback - callbackParam:(void*)callbackParam -{ - [self stopAnimation]; - - animationInterval = interval; - animationCallback = callback; - animationCallbackParam = callbackParam; - - if (animationCallback) { - [self startAnimation]; - } -} - -- (void)startAnimation -{ - displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(doLoop:)]; - [displayLink setFrameInterval:animationInterval]; - [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; -} - -- (void)stopAnimation -{ - [displayLink invalidate]; - displayLink = nil; -} - -- (void)doLoop:(CADisplayLink*)sender -{ - /* Don't run the game loop while a messagebox is up */ - if (!UIKit_ShowingMessageBox()) { - animationCallback(animationCallbackParam); - } -} - - (void)setCurrentContext { [EAGLContext setCurrentContext:context]; @@ -262,8 +217,8 @@ - (void)swapBuffers { /* viewRenderbuffer should always be bound here. Code that binds something - else is responsible for rebinding viewRenderbuffer, to reduce duplicate - state changes. */ + * else is responsible for rebinding viewRenderbuffer, to reduce duplicate + * state changes. */ [context presentRenderbuffer:GL_RENDERBUFFER]; } @@ -271,14 +226,21 @@ { [super layoutSubviews]; - CGSize layersize = self.layer.bounds.size; - int width = (int) (layersize.width * self.layer.contentsScale); - int height = (int) (layersize.height * self.layer.contentsScale); + int width = (int) (self.bounds.size.width * self.contentScaleFactor); + int height = (int) (self.bounds.size.height * self.contentScaleFactor); /* Update the color and depth buffer storage if the layer size has changed. */ if (width != backingWidth || height != backingHeight) { - [EAGLContext setCurrentContext:context]; + EAGLContext *prevContext = [EAGLContext currentContext]; + if (prevContext != context) { + [EAGLContext setCurrentContext:context]; + } + [self updateFrame]; + + if (prevContext != context) { + [EAGLContext setCurrentContext:prevContext]; + } } } @@ -300,7 +262,6 @@ } } - - (void)dealloc { if ([EAGLContext currentContext] == context) { diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index adee330be..dda94b32e 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -20,46 +20,22 @@ */ #import + #include "../SDL_sysvideo.h" #include "SDL_touch.h" -#if SDL_IPHONE_KEYBOARD -@interface SDL_uikitview : UIView -#else @interface SDL_uikitview : UIView -#endif -@property (nonatomic, assign) SDL_Window *sdlwindow; +- (instancetype)initWithFrame:(CGRect)frame; + +- (void)setSDLWindow:(SDL_Window *)window; - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -#if SDL_IPHONE_KEYBOARD -- (void)showKeyboard; -- (void)hideKeyboard; -- (void)initKeyboard; -- (void)deinitKeyboard; - -- (void)keyboardWillShow:(NSNotification *)notification; -- (void)keyboardWillHide:(NSNotification *)notification; - -- (void)updateKeyboard; - -@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); -void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window); -SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window); -void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect); - -#endif - @end /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index d7679c19e..8bd1f3198 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -24,36 +24,26 @@ #include "SDL_uikitview.h" -#include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_touch_c.h" +#include "../../events/SDL_events_c.h" -#if SDL_IPHONE_KEYBOARD -#include "keyinfotable.h" -#endif -#include "SDL_uikitappdelegate.h" -#include "SDL_uikitmodes.h" -#include "SDL_uikitwindow.h" +#import "SDL_uikitappdelegate.h" +#import "SDL_uikitmodes.h" +#import "SDL_uikitwindow.h" @implementation SDL_uikitview { + SDL_Window *sdlwindow; SDL_TouchID touchId; - UITouch *leftFingerDown; - -#if SDL_IPHONE_KEYBOARD - UITextField *textField; -#endif - + UITouch * __weak firstFingerDown; } -@synthesize sdlwindow; - -- (id)initWithFrame:(CGRect)frame +- (instancetype)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { -#if SDL_IPHONE_KEYBOARD - [self initKeyboard]; -#endif + if ((self = [super initWithFrame:frame])) { + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.autoresizesSubviews = YES; self.multipleTouchEnabled = YES; @@ -62,14 +52,65 @@ } return self; - } -- (void)dealloc +- (void)setSDLWindow:(SDL_Window *)window { -#if SDL_IPHONE_KEYBOARD - [self deinitKeyboard]; -#endif + SDL_WindowData *data = nil; + + if (window == sdlwindow) { + return; + } + + if (sdlwindow) { + SDL_uikitview *view = nil; + data = (__bridge SDL_WindowData *) sdlwindow->driverdata; + + [data.views removeObject:self]; + + [self removeFromSuperview]; + + /* Restore the next-oldest view in the old window. */ + if (data.views.count > 0) { + view = data.views[data.views.count - 1]; + } + + data.viewcontroller.view = view; + + if (data.uiwindow.rootViewController != data.viewcontroller) { + data.uiwindow.rootViewController = data.viewcontroller; + } else if (view) { + [data.uiwindow addSubview:view]; + } + + [data.uiwindow layoutIfNeeded]; + } + + if (window) { + data = (__bridge SDL_WindowData *) window->driverdata; + + /* Make sure the SDL window has a strong reference to this view. */ + [data.views addObject:self]; + + /* Replace the view controller's old view with this one. */ + [data.viewcontroller.view removeFromSuperview]; + data.viewcontroller.view = self; + + if (data.uiwindow.rootViewController != data.viewcontroller) { + /* The root view controller handles rotation and the status bar. + * Assigning it also adds the controller's view to the window. */ + data.uiwindow.rootViewController = data.viewcontroller; + } else { + [data.uiwindow addSubview:self]; + } + + /* The view's bounds may not be correct until the next event cycle. That + * might happen after the current dimensions are queried, so we force a + * layout now to immediately update the bounds. */ + [data.uiwindow layoutIfNeeded]; + } + + sdlwindow = window; } - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize @@ -88,16 +129,16 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { - if (!leftFingerDown) { + if (!firstFingerDown) { CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; - /* send moved event */ + /* send mouse moved event */ SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); /* send mouse down event */ SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); - leftFingerDown = touch; + firstFingerDown = touch; } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; @@ -109,10 +150,10 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { - if (touch == leftFingerDown) { + if (touch == firstFingerDown) { /* send mouse up */ SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); - leftFingerDown = nil; + firstFingerDown = nil; } CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; @@ -123,18 +164,13 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - /* - this can happen if the user puts more than 5 touches on the screen - at once, or perhaps in other circumstances. Usually (it seems) - all active touches are canceled. - */ [self touchesEnded:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { - if (touch == leftFingerDown) { + if (touch == firstFingerDown) { CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; /* send moved event */ @@ -147,274 +183,8 @@ } } -/* - ---- Keyboard related functionality below this line ---- -*/ -#if SDL_IPHONE_KEYBOARD - -@synthesize textInputRect; -@synthesize keyboardHeight; -@synthesize keyboardVisible; - -/* Set ourselves up as a UITextFieldDelegate */ -- (void)initKeyboard -{ - textField = [[UITextField alloc] initWithFrame:CGRectZero]; - textField.delegate = self; - /* placeholder so there is something to delete! */ - textField.text = @" "; - - /* set UITextInputTrait properties, mostly to defaults */ - textField.autocapitalizationType = UITextAutocapitalizationTypeNone; - textField.autocorrectionType = UITextAutocorrectionTypeNo; - textField.enablesReturnKeyAutomatically = NO; - textField.keyboardAppearance = UIKeyboardAppearanceDefault; - textField.keyboardType = UIKeyboardTypeDefault; - textField.returnKeyType = UIReturnKeyDefault; - textField.secureTextEntry = NO; - - textField.hidden = YES; - keyboardVisible = NO; - /* add the UITextField (hidden) to our view */ - [self addSubview:textField]; - - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; - [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; -} - -- (void)deinitKeyboard -{ - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center removeObserver:self name:UIKeyboardWillShowNotification object:nil]; - [center removeObserver:self name:UIKeyboardWillHideNotification object:nil]; -} - -/* reveal onscreen virtual keyboard */ -- (void)showKeyboard -{ - keyboardVisible = YES; - [textField becomeFirstResponder]; -} - -/* hide onscreen virtual keyboard */ -- (void)hideKeyboard -{ - keyboardVisible = NO; - [textField resignFirstResponder]; -} - -- (void)keyboardWillShow:(NSNotification *)notification -{ - CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue]; - int height; - - /* The keyboard rect is in the coordinate space of the screen, but we want - * its height in the view's coordinate space. - */ -#ifdef __IPHONE_8_0 - if ([self respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) { - UIScreen *screen = self.window.screen; - kbrect = [self convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace]; - height = kbrect.size.height; - } else -#endif - { - /* In iOS 7 and below, the screen's coordinate space is never rotated. */ - if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { - height = kbrect.size.width; - } else { - height = kbrect.size.height; - } - } - - [self setKeyboardHeight:height]; -} - - - (void)keyboardWillHide:(NSNotification *)notification -{ - [self setKeyboardHeight:0]; -} - -- (void)updateKeyboard -{ - SDL_Rect textrect = self.textInputRect; - CGAffineTransform t = self.transform; - CGPoint offset = CGPointMake(0.0, 0.0); - - if (self.keyboardHeight) { - int rectbottom = textrect.y + textrect.h; - int kbottom = self.bounds.size.height - self.keyboardHeight; - if (kbottom < rectbottom) { - offset.y = kbottom - rectbottom; - } - } - - /* Put the offset into the this view transform's coordinate space. */ - t.tx = 0.0; - t.ty = 0.0; - offset = CGPointApplyAffineTransform(offset, t); - - t.tx = offset.x; - t.ty = offset.y; - - /* Move the view by applying the updated transform. */ - self.transform = t; -} - -- (void)setKeyboardHeight:(int)height -{ - keyboardVisible = height > 0; - keyboardHeight = height; - [self updateKeyboard]; -} - -/* UITextFieldDelegate method. Invoked when user types something. */ -- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string -{ - NSUInteger len = string.length; - - if (len == 0) { - /* it wants to replace text with nothing, ie a delete */ - SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE); - SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE); - } else { - /* go through all the characters in the string we've been sent - and convert them to key presses */ - for (int i = 0; i < len; i++) { - unichar c = [string characterAtIndex:i]; - Uint16 mod = 0; - SDL_Scancode code; - - if (c < 127) { - /* figure out the SDL_Scancode and SDL_keymod for this unichar */ - code = unicharToUIKeyInfoTable[c].code; - mod = unicharToUIKeyInfoTable[c].mod; - } - else { - /* we only deal with ASCII right now */ - code = SDL_SCANCODE_UNKNOWN; - mod = 0; - } - - if (mod & KMOD_SHIFT) { - /* If character uses shift, press shift down */ - SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT); - } - - /* send a keydown and keyup even for the character */ - SDL_SendKeyboardKey(SDL_PRESSED, code); - SDL_SendKeyboardKey(SDL_RELEASED, code); - - if (mod & KMOD_SHIFT) { - /* If character uses shift, press shift back up */ - SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT); - } - } - - SDL_SendKeyboardText([string UTF8String]); - } - - return NO; /* don't allow the edit! (keep placeholder text there) */ -} - -/* Terminates the editing session */ -- (BOOL)textFieldShouldReturn:(UITextField*)_textField -{ - SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN); - SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN); - SDL_StopTextInput(); - return YES; -} - -#endif - @end -/* iPhone keyboard addition functions */ -#if SDL_IPHONE_KEYBOARD - -static SDL_uikitview * -GetWindowView(SDL_Window * window) -{ - if (window == NULL) { - SDL_SetError("Window does not exist"); - return 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"); - } - - return view; -} - -SDL_bool -UIKit_HasScreenKeyboardSupport(_THIS) -{ - return SDL_TRUE; -} - -void -UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) -{ - @autoreleasepool { - SDL_uikitview *view = GetWindowView(window); - if (view != nil) { - [view showKeyboard]; - } - } -} - -void -UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) -{ - @autoreleasepool { - SDL_uikitview *view = GetWindowView(window); - if (view != nil) { - [view hideKeyboard]; - } - } -} - -SDL_bool -UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) -{ - @autoreleasepool { - SDL_uikitview *view = GetWindowView(window); - if (view != nil) { - return view.isKeyboardVisible; - } - return 0; - } -} - -void -UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) -{ - if (!rect) { - SDL_InvalidParamError("rect"); - return; - } - - @autoreleasepool { - SDL_uikitview *view = GetWindowView(SDL_GetFocusWindow()); - if (view != nil) { - view.textInputRect = *rect; - - if (view.keyboardVisible) { - [view updateKeyboard]; - } - } - } -} - - -#endif /* SDL_IPHONE_KEYBOARD */ - #endif /* SDL_VIDEO_DRIVER_UIKIT */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index 0ca98eb40..b8cf3dc55 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/src/video/uikit/SDL_uikitviewcontroller.h @@ -23,11 +23,27 @@ #include "../SDL_sysvideo.h" +#include "SDL_touch.h" + +#if SDL_IPHONE_KEYBOARD +@interface SDL_uikitviewcontroller : UIViewController +#else @interface SDL_uikitviewcontroller : UIViewController +#endif @property (nonatomic, assign) SDL_Window *window; -- (id)initWithSDLWindow:(SDL_Window *)_window; +- (instancetype)initWithSDLWindow:(SDL_Window *)_window; + +- (void)setAnimationCallback:(int)interval + callback:(void (*)(void*))callback + callbackParam:(void*)callbackParam; + +- (void)startAnimation; +- (void)stopAnimation; + +- (void)doLoop:(CADisplayLink*)sender; + - (void)loadView; - (void)viewDidLayoutSubviews; - (NSUInteger)supportedInterfaceOrientations; @@ -35,4 +51,28 @@ - (BOOL)prefersStatusBarHidden; - (UIStatusBarStyle)preferredStatusBarStyle; +#if SDL_IPHONE_KEYBOARD +- (void)showKeyboard; +- (void)hideKeyboard; +- (void)initKeyboard; +- (void)deinitKeyboard; + +- (void)keyboardWillShow:(NSNotification *)notification; +- (void)keyboardWillHide:(NSNotification *)notification; + +- (void)updateKeyboard; + +@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible; +@property (nonatomic, assign) SDL_Rect textInputRect; +@property (nonatomic, assign) int keyboardHeight; +#endif + @end + +#if SDL_IPHONE_KEYBOARD +SDL_bool UIKit_HasScreenKeyboardSupport(_THIS); +void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window); +void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window); +SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window); +void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect); +#endif diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 77cbc0ba5..af1f68dc1 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -28,27 +28,87 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_events_c.h" -#include "SDL_uikitviewcontroller.h" +#import "SDL_uikitviewcontroller.h" +#import "SDL_uikitmessagebox.h" #include "SDL_uikitvideo.h" #include "SDL_uikitmodes.h" #include "SDL_uikitwindow.h" +#if SDL_IPHONE_KEYBOARD +#include "keyinfotable.h" +#endif -@implementation SDL_uikitviewcontroller +@implementation SDL_uikitviewcontroller { + CADisplayLink *displayLink; + int animationInterval; + void (*animationCallback)(void*); + void *animationCallbackParam; + +#if SDL_IPHONE_KEYBOARD + UITextField *textField; +#endif +} @synthesize window; -- (id)initWithSDLWindow:(SDL_Window *)_window +- (instancetype)initWithSDLWindow:(SDL_Window *)_window { if (self = [super initWithNibName:nil bundle:nil]) { self.window = _window; + +#if SDL_IPHONE_KEYBOARD + [self initKeyboard]; +#endif } return self; } +- (void)dealloc +{ +#if SDL_IPHONE_KEYBOARD + [self deinitKeyboard]; +#endif +} + +- (void)setAnimationCallback:(int)interval + callback:(void (*)(void*))callback + callbackParam:(void*)callbackParam +{ + [self stopAnimation]; + + animationInterval = interval; + animationCallback = callback; + animationCallbackParam = callbackParam; + + if (animationCallback) { + [self startAnimation]; + } +} + +- (void)startAnimation +{ + displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(doLoop:)]; + [displayLink setFrameInterval:animationInterval]; + [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; +} + +- (void)stopAnimation +{ + [displayLink invalidate]; + displayLink = nil; +} + +- (void)doLoop:(CADisplayLink*)sender +{ + /* Don't run the game loop while a messagebox is up */ + if (!UIKit_ShowingMessageBox()) { + animationCallback(animationCallbackParam); + } +} + - (void)loadView { - /* do nothing. */ + /* Do nothing. */ } - (void)viewDidLayoutSubviews @@ -67,8 +127,7 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient { - NSUInteger orientationMask = [self supportedInterfaceOrientations]; - return (orientationMask & (1 << orient)); + return ([self supportedInterfaceOrientations] & (1 << orient)) != 0; } - (BOOL)prefersStatusBarHidden @@ -82,8 +141,276 @@ return UIStatusBarStyleLightContent; } +/* + ---- Keyboard related functionality below this line ---- + */ +#if SDL_IPHONE_KEYBOARD + +@synthesize textInputRect; +@synthesize keyboardHeight; +@synthesize keyboardVisible; + +/* Set ourselves up as a UITextFieldDelegate */ +- (void)initKeyboard +{ + textField = [[UITextField alloc] initWithFrame:CGRectZero]; + textField.delegate = self; + /* placeholder so there is something to delete! */ + textField.text = @" "; + + /* set UITextInputTrait properties, mostly to defaults */ + textField.autocapitalizationType = UITextAutocapitalizationTypeNone; + textField.autocorrectionType = UITextAutocorrectionTypeNo; + textField.enablesReturnKeyAutomatically = NO; + textField.keyboardAppearance = UIKeyboardAppearanceDefault; + textField.keyboardType = UIKeyboardTypeDefault; + textField.returnKeyType = UIReturnKeyDefault; + textField.secureTextEntry = NO; + + textField.hidden = YES; + keyboardVisible = NO; + + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; +} + +- (void)setView:(UIView *)view +{ + [super setView:view]; + + [view addSubview:textField]; + + if (keyboardVisible) { + [self showKeyboard]; + } +} + +- (void)deinitKeyboard +{ + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [center removeObserver:self name:UIKeyboardWillHideNotification object:nil]; +} + +/* reveal onscreen virtual keyboard */ +- (void)showKeyboard +{ + keyboardVisible = YES; + if (textField.window) { + [textField becomeFirstResponder]; + } +} + +/* hide onscreen virtual keyboard */ +- (void)hideKeyboard +{ + keyboardVisible = NO; + [textField resignFirstResponder]; +} + +- (void)keyboardWillShow:(NSNotification *)notification +{ + CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + UIView *view = self.view; + int height = 0; + + /* The keyboard rect is in the coordinate space of the screen, but we want + * its height in the view's coordinate space. */ +#ifdef __IPHONE_8_0 + if ([view respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) { + UIScreen *screen = view.window.screen; + kbrect = [view convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace]; + height = kbrect.size.height; + } else +#endif + { + /* In iOS 7 and below, the screen's coordinate space is never rotated. */ + if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { + height = kbrect.size.width; + } else { + height = kbrect.size.height; + } + } + + [self setKeyboardHeight:height]; +} + +- (void)keyboardWillHide:(NSNotification *)notification +{ + [self setKeyboardHeight:0]; +} + +- (void)updateKeyboard +{ + SDL_Rect textrect = self.textInputRect; + CGAffineTransform t = self.view.transform; + CGPoint offset = CGPointMake(0.0, 0.0); + + if (self.keyboardHeight) { + int rectbottom = textrect.y + textrect.h; + int kbottom = self.view.bounds.size.height - self.keyboardHeight; + if (kbottom < rectbottom) { + offset.y = kbottom - rectbottom; + } + } + + /* Put the offset into the this view transform's coordinate space. */ + t.tx = 0.0; + t.ty = 0.0; + offset = CGPointApplyAffineTransform(offset, t); + + t.tx = offset.x; + t.ty = offset.y; + + /* Move the view by applying the updated transform. */ + self.view.transform = t; +} + +- (void)setKeyboardHeight:(int)height +{ + keyboardVisible = height > 0; + keyboardHeight = height; + [self updateKeyboard]; +} + +/* UITextFieldDelegate method. Invoked when user types something. */ +- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + NSUInteger len = string.length; + + if (len == 0) { + /* it wants to replace text with nothing, ie a delete */ + SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE); + SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE); + } else { + /* go through all the characters in the string we've been sent and + * convert them to key presses */ + int i; + for (i = 0; i < len; i++) { + unichar c = [string characterAtIndex:i]; + Uint16 mod = 0; + SDL_Scancode code; + + if (c < 127) { + /* figure out the SDL_Scancode and SDL_keymod for this unichar */ + code = unicharToUIKeyInfoTable[c].code; + mod = unicharToUIKeyInfoTable[c].mod; + } else { + /* we only deal with ASCII right now */ + code = SDL_SCANCODE_UNKNOWN; + mod = 0; + } + + if (mod & KMOD_SHIFT) { + /* If character uses shift, press shift down */ + SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT); + } + + /* send a keydown and keyup even for the character */ + SDL_SendKeyboardKey(SDL_PRESSED, code); + SDL_SendKeyboardKey(SDL_RELEASED, code); + + if (mod & KMOD_SHIFT) { + /* If character uses shift, press shift back up */ + SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT); + } + } + + SDL_SendKeyboardText([string UTF8String]); + } + + return NO; /* don't allow the edit! (keep placeholder text there) */ +} + +/* Terminates the editing session */ +- (BOOL)textFieldShouldReturn:(UITextField*)_textField +{ + SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN); + SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN); + SDL_StopTextInput(); + return YES; +} + +#endif + @end +/* iPhone keyboard addition functions */ +#if SDL_IPHONE_KEYBOARD + +static SDL_uikitviewcontroller * +GetWindowViewController(SDL_Window * window) +{ + if (!window || !window->driverdata) { + SDL_SetError("Invalid window"); + return nil; + } + + SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + + return data.viewcontroller; +} + +SDL_bool +UIKit_HasScreenKeyboardSupport(_THIS) +{ + return SDL_TRUE; +} + +void +UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window) +{ + @autoreleasepool { + SDL_uikitviewcontroller *vc = GetWindowViewController(window); + [vc showKeyboard]; + } +} + +void +UIKit_HideScreenKeyboard(_THIS, SDL_Window *window) +{ + @autoreleasepool { + SDL_uikitviewcontroller *vc = GetWindowViewController(window); + [vc hideKeyboard]; + } +} + +SDL_bool +UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window) +{ + @autoreleasepool { + SDL_uikitviewcontroller *vc = GetWindowViewController(window); + if (vc != nil) { + return vc.isKeyboardVisible; + } + return SDL_FALSE; + } +} + +void +UIKit_SetTextInputRect(_THIS, SDL_Rect *rect) +{ + if (!rect) { + SDL_InvalidParamError("rect"); + return; + } + + @autoreleasepool { + SDL_uikitviewcontroller *vc = GetWindowViewController(SDL_GetFocusWindow()); + if (vc != nil) { + vc.textInputRect = *rect; + + if (vc.keyboardVisible) { + [vc updateKeyboard]; + } + } + } +} + + +#endif /* SDL_IPHONE_KEYBOARD */ + #endif /* SDL_VIDEO_DRIVER_UIKIT */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitwindow.h b/src/video/uikit/SDL_uikitwindow.h index cc7d8839a..73203d189 100644 --- a/src/video/uikit/SDL_uikitwindow.h +++ b/src/video/uikit/SDL_uikitwindow.h @@ -23,7 +23,7 @@ #include "../SDL_sysvideo.h" #import "SDL_uikitvideo.h" -#import "SDL_uikitopenglview.h" +#import "SDL_uikitview.h" #import "SDL_uikitviewcontroller.h" extern int UIKit_CreateWindow(_THIS, SDL_Window * window); @@ -44,9 +44,11 @@ extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window * window); @interface SDL_WindowData : NSObject @property (nonatomic, strong) UIWindow *uiwindow; -@property (nonatomic, strong) SDL_uikitopenglview *view; @property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller; +/* Array of SDL_uikitviews owned by this window. */ +@property (nonatomic, copy) NSMutableArray *views; + @end #endif /* _SDL_uikitwindow_h */ diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 849c90888..550b6f91c 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -37,15 +37,41 @@ #include "SDL_uikitwindow.h" #import "SDL_uikitappdelegate.h" -#import "SDL_uikitopenglview.h" +#import "SDL_uikitview.h" #include @implementation SDL_WindowData @synthesize uiwindow; -@synthesize view; @synthesize viewcontroller; +@synthesize views; + +- (instancetype)init +{ + if ((self = [super init])) { + views = [NSMutableArray new]; + } + + return self; +} + +@end + +@interface SDL_uikitwindow : UIWindow + +- (void)layoutSubviews; + +@end + +@implementation SDL_uikitwindow + +- (void)layoutSubviews +{ + /* Workaround to fix window orientation issues in iOS 8+. */ + self.frame = self.screen.bounds; + [super layoutSubviews]; +} @end @@ -54,65 +80,67 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata; + SDL_uikitview *view; + + CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); + int width = (int) frame.size.width; + int height = (int) frame.size.height; SDL_WindowData *data = [[SDL_WindowData alloc] init]; if (!data) { return SDL_OutOfMemory(); } - data.uiwindow = uiwindow; - - /* Fill in the SDL window with the window data */ - { - CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen); - - 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)) { - int temp = width; - width = height; - height = temp; - } - - window->x = 0; - window->y = 0; - window->w = width; - window->h = height; - } - window->driverdata = (void *) CFBridgingRetain(data); + data.uiwindow = uiwindow; + /* only one window on iOS, always shown */ window->flags &= ~SDL_WINDOW_HIDDEN; - /* SDL_WINDOW_BORDERLESS controls whether status bar is hidden. - * 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]) { 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 - if ([UIApplication sharedApplication].statusBarHidden) { - window->flags |= SDL_WINDOW_BORDERLESS; - } else { - window->flags &= ~SDL_WINDOW_BORDERLESS; - } - */ } else { - window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */ + window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizable */ window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */ window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */ } - /* The View Controller will handle rotating the view when the - * device orientation changes. This will trigger resize events, if - * appropriate. - */ + if (displaydata.uiscreen == [UIScreen mainScreen]) { + NSUInteger orients = UIKit_GetSupportedOrientations(window); + BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0; + BOOL supportsPortrait = (orients & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown)) != 0; + + /* Make sure the width/height are oriented correctly */ + if ((width > height && !supportsLandscape) || (height > width && !supportsPortrait)) { + int temp = width; + width = height; + height = temp; + } + } + + window->x = 0; + window->y = 0; + window->w = width; + window->h = height; + + /* The View Controller will handle rotating the view when the device + * orientation changes. This will trigger resize events, if appropriate. */ data.viewcontroller = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window]; - data.viewcontroller.title = @""; + + /* The window will initially contain a generic view so resizes, touch events, + * etc. can be handled without an active OpenGL view/context. */ + view = [[SDL_uikitview alloc] initWithFrame:frame]; + + /* Sets this view as the controller's view, and adds the view to the window + * heirarchy. */ + [view setSDLWindow:window]; + + /* Make this window the current mouse focus for touch input */ + if (displaydata.uiscreen == [UIScreen mainScreen]) { + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + } return 0; } @@ -123,8 +151,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) @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]; + 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); @@ -136,8 +163,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* 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. - */ + * 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); @@ -147,8 +173,9 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) 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)) + if ((mode->w >= window->w) && (mode->h >= window->h)) { bestmode = mode; + } } if (bestmode) { @@ -157,8 +184,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) /* 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. - */ + * upon window destruction, SDL_Quit(), etc. */ display->current_mode = *bestmode; } } @@ -172,36 +198,14 @@ UIKit_CreateWindow(_THIS, SDL_Window *window) } else { app.statusBarHidden = NO; } - - /* Make sure the screen is using a supported orientation. We do it - * now so that SetupWindowData assigns the properly oriented width - * and height to the window's w and h variables. - */ - if (UIKit_IsDisplayLandscape(data.uiscreen)) { - if (!(orientations & UIInterfaceOrientationMaskLandscape)) { - [app setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; - } - } else { - if (!(orientations & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown))) { - UIInterfaceOrientation orient = UIInterfaceOrientationLandscapeLeft; - if (orientations & UIInterfaceOrientationMaskLandscapeRight) { - orient = UIInterfaceOrientationLandscapeRight; - } - [app setStatusBarOrientation:orient animated:NO]; - } - } } /* ignore the size user requested, and make a fullscreen window */ /* !!! FIXME: can we have a smaller view? */ - UIWindow *uiwindow = [[UIWindow alloc] initWithFrame:data.uiscreen.bounds]; + UIWindow *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) { + /* put the window on an external display if appropriate. */ + if (data.uiscreen != [UIScreen mainScreen]) { [uiwindow setScreen:data.uiscreen]; } @@ -217,11 +221,11 @@ void UIKit_SetWindowTitle(_THIS, SDL_Window * window) { @autoreleasepool { - SDL_uikitviewcontroller *vc = ((__bridge SDL_WindowData *) window->driverdata).viewcontroller; + SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; if (window->title) { - vc.title = @(window->title); + data.viewcontroller.title = @(window->title); } else { - vc.title = @""; + data.viewcontroller.title = nil; } } } @@ -230,8 +234,8 @@ void UIKit_ShowWindow(_THIS, SDL_Window * window) { @autoreleasepool { - UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; - [uiwindow makeKeyAndVisible]; + SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; + [data.uiwindow makeKeyAndVisible]; } } @@ -239,8 +243,8 @@ void UIKit_HideWindow(_THIS, SDL_Window * window) { @autoreleasepool { - UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; - uiwindow.hidden = YES; + SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; + data.uiwindow.hidden = YES; } } @@ -248,21 +252,19 @@ void UIKit_RaiseWindow(_THIS, SDL_Window * window) { /* We don't currently offer a concept of "raising" the SDL window, since - * we only allow one per display, in the iOS fashion. + * we only allow one per display, in the iOS fashion. * However, we use this entry point to rebind the context to the view - * during OnWindowRestored processing. - */ + * during OnWindowRestored processing. */ _this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx); } static void UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) { - SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata; - SDL_uikitviewcontroller *viewcontroller = windowdata.viewcontroller; - CGRect frame; + SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; + SDL_uikitviewcontroller *viewcontroller = data.viewcontroller; - if (windowdata.uiwindow.screen == [UIScreen mainScreen]) { + if (data.uiwindow.screen == [UIScreen mainScreen]) { if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) { [UIApplication sharedApplication].statusBarHidden = YES; } else { @@ -276,24 +278,9 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window) } /* 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 w = (int) frame.size.width; - int h = (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. - */ - if (window->w >= window->h) { - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(w, h), SDL_min(w, h)); - } else { - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(w, h), SDL_max(w, h)); - } + viewcontroller.view.frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen); + [viewcontroller.view setNeedsLayout]; + [viewcontroller.view layoutIfNeeded]; } void @@ -317,7 +304,8 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window) { @autoreleasepool { if (window->driverdata != NULL) { - CFRelease(window->driverdata); + SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata); + [data.viewcontroller stopAnimation]; } } window->driverdata = NULL; @@ -327,11 +315,11 @@ SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) { @autoreleasepool { - UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow; + SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; if (info->version.major <= SDL_MAJOR_VERSION) { info->subsystem = SDL_SYSWM_UIKIT; - info->info.uikit.window = uiwindow; + info->info.uikit.window = data.uiwindow; return SDL_TRUE; } else { SDL_SetError("Application not compiled with SDL %d.%d\n", @@ -380,7 +368,7 @@ UIKit_GetSupportedOrientations(SDL_Window * window) } /* Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation */ - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown; } } @@ -391,14 +379,15 @@ UIKit_GetSupportedOrientations(SDL_Window * window) int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam) { + if (!window || !window->driverdata) { + return SDL_SetError("Invalid window"); + } + @autoreleasepool { - SDL_WindowData *data = window ? (__bridge SDL_WindowData *)window->driverdata : nil; - - if (!data || !data.view) { - return SDL_SetError("Invalid window or view not set"); - } - - [data.view setAnimationCallback:interval callback:callback callbackParam:callbackParam]; + SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + [data.viewcontroller setAnimationCallback:interval + callback:callback + callbackParam:callbackParam]; } return 0; From 46ed3de4f7b864eeb044f38b5722ad3fe3096ac8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 24 Jan 2015 23:53:41 -0400 Subject: [PATCH 38/41] Fixed the extended launch screen causing minor visual issues when rotating the screen in some circumstances. --HG-- branch : iOS-improvements --- src/video/uikit/SDL_uikitappdelegate.h | 1 - src/video/uikit/SDL_uikitappdelegate.m | 22 ++++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/video/uikit/SDL_uikitappdelegate.h b/src/video/uikit/SDL_uikitappdelegate.h index cc4494dbb..45dd91e40 100644 --- a/src/video/uikit/SDL_uikitappdelegate.h +++ b/src/video/uikit/SDL_uikitappdelegate.h @@ -25,7 +25,6 @@ - (instancetype)init; - (void)loadView; -- (BOOL)shouldAutorotate; - (NSUInteger)supportedInterfaceOrientations; @end diff --git a/src/video/uikit/SDL_uikitappdelegate.m b/src/video/uikit/SDL_uikitappdelegate.m index 3306f38e9..2ae61827f 100644 --- a/src/video/uikit/SDL_uikitappdelegate.m +++ b/src/video/uikit/SDL_uikitappdelegate.m @@ -115,7 +115,9 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh) return image; } -@implementation SDLLaunchScreenController +@implementation SDLLaunchScreenController { + UIInterfaceOrientationMask supportedOrientations; +} - (instancetype)init { @@ -126,6 +128,9 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh) NSBundle *bundle = [NSBundle mainBundle]; NSString *screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"]; + /* Normally we don't want to rotate from the initial orientation. */ + supportedOrientations = (1 << [UIApplication sharedApplication].statusBarOrientation); + /* Launch screens were added in iOS 8. Otherwise we use launch images. */ if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) { @try { @@ -211,6 +216,12 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh) } if (image) { + if (image.size.width > image.size.height) { + supportedOrientations = UIInterfaceOrientationMaskLandscape; + } else { + supportedOrientations = UIInterfaceOrientationMaskPortrait; + } + self.view = [[UIImageView alloc] initWithImage:image]; } } @@ -223,14 +234,9 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh) /* Do nothing. */ } -- (BOOL)shouldAutorotate -{ - return YES; -} - - (NSUInteger)supportedInterfaceOrientations { - return UIInterfaceOrientationMaskAll; + return supportedOrientations; } @end @@ -333,7 +339,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh) SDL_SetMainReady(); [self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0]; - + return YES; } From f699d4bf09c39722c776b69279b947db89d6a458 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 8 Apr 2015 15:44:07 -0300 Subject: [PATCH 39/41] Generated dynapi prototypes for the new iPhone functions. --HG-- branch : iOS-improvements --- src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index dcc6d4677..0088c00a2 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -592,3 +592,5 @@ #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL #define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL +#define SDL_iPhoneGetViewRenderbuffer SDL_iPhoneGetViewRenderbuffer_REAL +#define SDL_iPhoneGetViewFramebuffer SDL_iPhoneGetViewFramebuffer_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6408e3f89..f0e2f0225 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -624,3 +624,5 @@ SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) +SDL_DYNAPI_PROC(Uint32,SDL_iPhoneGetViewRenderbuffer,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_iPhoneGetViewFramebuffer,(SDL_Window *a),(a),return) From d7781e2eff57aa19c1148e5e669e1e08fd147561 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 8 Apr 2015 15:59:29 -0300 Subject: [PATCH 40/41] Renamed SDL_iPhoneGetViewFramebuffer/Renderbuffer to SDL_iOSGetViewFramebuffer/Renderbuffer. Added #defines for SDL_iOSSetAnimationCallback and SDL_iOSSetEventPump, which point to SDL_iPhoneSetAnimationCallback and SDL_iPhoneSetEventPump. --HG-- branch : iOS-improvements --- include/SDL_system.h | 7 +++++-- src/dynapi/SDL_dynapi_overrides.h | 4 ++-- src/dynapi/SDL_dynapi_procs.h | 6 ++++-- src/video/uikit/SDL_uikitopengles.m | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/SDL_system.h b/include/SDL_system.h index ad610ba47..0c2d34a3d 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -73,7 +73,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *a /* Platform specific functions for iOS */ #if defined(__IPHONEOS__) && __IPHONEOS__ +#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam) extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); + +#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled) extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); /** @@ -81,14 +84,14 @@ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); The Renderbuffer must be bound when calling SDL_GL_SwapWindow. */ -extern DECLSPEC Uint32 SDLCALL SDL_iPhoneGetViewRenderbuffer(SDL_Window * window); +extern DECLSPEC Uint32 SDLCALL SDL_iOSGetViewRenderbuffer(SDL_Window * window); /** \brief 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); +extern DECLSPEC Uint32 SDLCALL SDL_iOSGetViewFramebuffer(SDL_Window * window); #endif /* __IPHONEOS__ */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 0088c00a2..3508280fa 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -592,5 +592,5 @@ #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL #define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL -#define SDL_iPhoneGetViewRenderbuffer SDL_iPhoneGetViewRenderbuffer_REAL -#define SDL_iPhoneGetViewFramebuffer SDL_iPhoneGetViewFramebuffer_REAL +#define SDL_iOSGetViewRenderbuffer SDL_iOSGetViewRenderbuffer_REAL +#define SDL_iOSGetViewFramebuffer SDL_iOSGetViewFramebuffer_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index f0e2f0225..a66c99760 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -624,5 +624,7 @@ SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) -SDL_DYNAPI_PROC(Uint32,SDL_iPhoneGetViewRenderbuffer,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_iPhoneGetViewFramebuffer,(SDL_Window *a),(a),return) +#if defined(__IPHONEOS__) && __IPHONEOS__ +SDL_DYNAPI_PROC(Uint32,SDL_iOSGetViewRenderbuffer,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_iOSGetViewFramebuffer,(SDL_Window *a),(a),return) +#endif diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index e9178c183..66c912293 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -184,7 +184,7 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) } Uint32 -SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) +SDL_iOSGetViewRenderbuffer(SDL_Window * window) { if (!window) { SDL_SetError("Invalid window"); @@ -205,7 +205,7 @@ SDL_iPhoneGetViewRenderbuffer(SDL_Window * window) } Uint32 -SDL_iPhoneGetViewFramebuffer(SDL_Window * window) +SDL_iOSGetViewFramebuffer(SDL_Window * window) { if (!window) { SDL_SetError("Invalid window"); From 58fb5ed78101944f466846e1242969b244e1b660 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 9 Apr 2015 19:28:00 -0300 Subject: [PATCH 41/41] Added framebuffer and colorbuffer members to the uikit portion of the SDL_SysWMinfo struct, removed SDL_iOSGetViewRenderbuffer and SDL_iOSGetViewFramebuffer. --HG-- branch : iOS-improvements --- include/SDL_system.h | 14 ---------- include/SDL_syswm.h | 3 +++ src/dynapi/SDL_dynapi_overrides.h | 2 -- src/dynapi/SDL_dynapi_procs.h | 4 --- src/video/uikit/SDL_uikitopengles.m | 42 ----------------------------- src/video/uikit/SDL_uikitwindow.m | 16 +++++++++++ 6 files changed, 19 insertions(+), 62 deletions(-) diff --git a/include/SDL_system.h b/include/SDL_system.h index 0c2d34a3d..ee9bb4816 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -79,20 +79,6 @@ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, #define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled) extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); -/** - \brief 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_iOSGetViewRenderbuffer(SDL_Window * window); - -/** - \brief 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_iOSGetViewFramebuffer(SDL_Window * window); - #endif /* __IPHONEOS__ */ diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index c26533384..fa1145534 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -98,6 +98,7 @@ typedef struct _NSWindow NSWindow; typedef struct _UIWindow UIWindow; typedef struct _UIViewController UIViewController; #endif +typedef Uint32 GLuint; #endif #if defined(SDL_VIDEO_DRIVER_ANDROID) @@ -228,6 +229,8 @@ struct SDL_SysWMinfo #else UIWindow *window; /* The UIKit window */ #endif + GLuint framebuffer; /* The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */ + GLuint colorbuffer; /* The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */ } uikit; #endif #if defined(SDL_VIDEO_DRIVER_WAYLAND) diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 3508280fa..dcc6d4677 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -592,5 +592,3 @@ #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL #define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL -#define SDL_iOSGetViewRenderbuffer SDL_iOSGetViewRenderbuffer_REAL -#define SDL_iOSGetViewFramebuffer SDL_iOSGetViewFramebuffer_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index a66c99760..6408e3f89 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -624,7 +624,3 @@ SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) -#if defined(__IPHONEOS__) && __IPHONEOS__ -SDL_DYNAPI_PROC(Uint32,SDL_iOSGetViewRenderbuffer,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_iOSGetViewFramebuffer,(SDL_Window *a),(a),return) -#endif diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m index 66c912293..0184cf758 100644 --- a/src/video/uikit/SDL_uikitopengles.m +++ b/src/video/uikit/SDL_uikitopengles.m @@ -183,48 +183,6 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context) } } -Uint32 -SDL_iOSGetViewRenderbuffer(SDL_Window * window) -{ - if (!window) { - SDL_SetError("Invalid window"); - return 0; - } - - @autoreleasepool { - SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; - UIView *view = data.viewcontroller.view; - if ([view isKindOfClass:[SDL_uikitopenglview class]]) { - SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view; - return glview.drawableRenderbuffer; - } - } - - SDL_SetError("Window does not have an attached OpenGL view"); - return 0; -} - -Uint32 -SDL_iOSGetViewFramebuffer(SDL_Window * window) -{ - if (!window) { - SDL_SetError("Invalid window"); - return 0; - } - - @autoreleasepool { - SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; - UIView *view = data.viewcontroller.view; - if ([view isKindOfClass:[SDL_uikitopenglview class]]) { - SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view; - return glview.drawableFramebuffer; - } - } - - SDL_SetError("Window does not have an attached OpenGL view"); - return 0; -} - #endif /* SDL_VIDEO_DRIVER_UIKIT */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index df4c700ba..e65732cf6 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -38,6 +38,7 @@ #import "SDL_uikitappdelegate.h" #import "SDL_uikitview.h" +#import "SDL_uikitopenglview.h" #include @@ -314,8 +315,23 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; if (info->version.major <= SDL_MAJOR_VERSION) { + int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch); + info->subsystem = SDL_SYSWM_UIKIT; info->info.uikit.window = data.uiwindow; + + /* These struct members were added in SDL 2.0.4. */ + if (versionnum >= SDL_VERSIONNUM(2,0,4)) { + if ([data.viewcontroller.view isKindOfClass:[SDL_uikitopenglview class]]) { + SDL_uikitopenglview *glview = (SDL_uikitopenglview *)data.viewcontroller.view; + info->info.uikit.framebuffer = glview.drawableFramebuffer; + info->info.uikit.colorbuffer = glview.drawableRenderbuffer; + } else { + info->info.uikit.framebuffer = 0; + info->info.uikit.colorbuffer = 0; + } + } + return SDL_TRUE; } else { SDL_SetError("Application not compiled with SDL %d.%d\n",