|
@@ -37,89 +37,110 @@
|
|
|
#include "SDL_uikitwindow.h"
|
|
|
#import "SDL_uikitappdelegate.h"
|
|
|
|
|
|
-#import "SDL_uikitopenglview.h"
|
|
|
+#import "SDL_uikitview.h"
|
|
|
|
|
|
#include <Foundation/Foundation.h>
|
|
|
|
|
|
+@implementation SDL_WindowData
|
|
|
|
|
|
+@synthesize uiwindow;
|
|
|
+@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
|
|
|
|
|
|
|
|
|
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;
|
|
|
+ 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;
|
|
|
|
|
|
- /* 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;
|
|
|
-
|
|
|
- /* Fill in the SDL window with the window data */
|
|
|
- {
|
|
|
- window->x = 0;
|
|
|
- window->y = 0;
|
|
|
-
|
|
|
- CGRect bounds;
|
|
|
- if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
|
|
- bounds = [displaydata->uiscreen bounds];
|
|
|
- } else {
|
|
|
- bounds = [displaydata->uiscreen applicationFrame];
|
|
|
- }
|
|
|
|
|
|
- /* Get frame dimensions in pixels */
|
|
|
- int width = (int)(bounds.size.width * displaymodedata->scale);
|
|
|
- int height = (int)(bounds.size.height * displaymodedata->scale);
|
|
|
+ window->driverdata = (void *) CFBridgingRetain(data);
|
|
|
+
|
|
|
+ data.uiwindow = uiwindow;
|
|
|
+
|
|
|
+ /* only one window on iOS, always shown */
|
|
|
+ window->flags &= ~SDL_WINDOW_HIDDEN;
|
|
|
+
|
|
|
+ if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
|
|
+ window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
|
|
|
+ } else {
|
|
|
+ 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. */
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
|
|
|
+ if ((width > height && !supportsLandscape) || (height > width && !supportsPortrait)) {
|
|
|
int temp = width;
|
|
|
width = height;
|
|
|
height = temp;
|
|
|
}
|
|
|
-
|
|
|
- window->w = width;
|
|
|
- window->h = height;
|
|
|
}
|
|
|
|
|
|
- window->driverdata = data;
|
|
|
+ window->x = 0;
|
|
|
+ window->y = 0;
|
|
|
+ window->w = width;
|
|
|
+ window->h = height;
|
|
|
|
|
|
- /* only one window on iOS, always shown */
|
|
|
- window->flags &= ~SDL_WINDOW_HIDDEN;
|
|
|
+ /* 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];
|
|
|
|
|
|
- /* 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 */
|
|
|
+ /* 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];
|
|
|
|
|
|
- /* 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_INPUT_FOCUS; /* never has input focus */
|
|
|
- window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
|
|
|
- }
|
|
|
+ /* Sets this view as the controller's view, and adds the view to the window
|
|
|
+ * heirarchy. */
|
|
|
+ [view setSDLWindow:window];
|
|
|
|
|
|
- /* The View Controller will handle rotating the view when the
|
|
|
- * device orientation changes. This will trigger resize events, if
|
|
|
- * appropriate.
|
|
|
- */
|
|
|
- SDL_uikitviewcontroller *controller;
|
|
|
- controller = [SDL_uikitviewcontroller alloc];
|
|
|
- data->viewcontroller = [controller initWithSDLWindow:window];
|
|
|
- [data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */
|
|
|
+ /* Make this window the current mouse focus for touch input */
|
|
|
+ if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
|
|
+ SDL_SetMouseFocus(window);
|
|
|
+ SDL_SetKeyboardFocus(window);
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -127,173 +148,165 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
|
|
int
|
|
|
UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|
|
{
|
|
|
- SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
|
|
- SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
|
|
- const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
|
|
|
- const CGSize origsize = [[data->uiscreen currentMode] size];
|
|
|
+ @autoreleasepool {
|
|
|
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
|
|
+ SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
|
|
+ const CGSize origsize = data.uiscreen.currentMode.size;
|
|
|
|
|
|
- /* SDL currently puts this window at the start of display's linked list. We rely on this. */
|
|
|
- SDL_assert(_this->windows == window);
|
|
|
-
|
|
|
- /* We currently only handle a single window per display on iOS */
|
|
|
- if (window->next != NULL) {
|
|
|
- return SDL_SetError("Only one window allowed per display.");
|
|
|
- }
|
|
|
+ /* SDL currently puts this window at the start of display's linked list. We rely on this. */
|
|
|
+ SDL_assert(_this->windows == 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.
|
|
|
- */
|
|
|
- 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 monitor has a resolution of 0x0 (hasn't been explicitly set by the
|
|
|
+ * user, so it's in standby), try to force the display to a resolution
|
|
|
+ * that most closely matches the desired window size. */
|
|
|
+ if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
|
|
|
+ if (display->num_display_modes == 0) {
|
|
|
+ _this->GetDisplayModes(_this, display);
|
|
|
+ }
|
|
|
|
|
|
- if (bestmode) {
|
|
|
- SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
|
|
|
- [data->uiscreen setCurrentMode:modedata->uiscreenmode];
|
|
|
+ int i;
|
|
|
+ const SDL_DisplayMode *bestmode = NULL;
|
|
|
+ for (i = display->num_display_modes; i >= 0; i--) {
|
|
|
+ const SDL_DisplayMode *mode = &display->display_modes[i];
|
|
|
+ if ((mode->w >= window->w) && (mode->h >= window->h)) {
|
|
|
+ bestmode = mode;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- /* desktop_mode doesn't change here (the higher level will
|
|
|
- * use it to set all the screens back to their defaults
|
|
|
- * upon window destruction, SDL_Quit(), etc.
|
|
|
- */
|
|
|
- display->current_mode = *bestmode;
|
|
|
- }
|
|
|
- }
|
|
|
+ if (bestmode) {
|
|
|
+ SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)bestmode->driverdata;
|
|
|
+ [data.uiscreen setCurrentMode:modedata.uiscreenmode];
|
|
|
|
|
|
- if (data->uiscreen == [UIScreen mainScreen]) {
|
|
|
- if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
|
|
- [UIApplication sharedApplication].statusBarHidden = YES;
|
|
|
- } else {
|
|
|
- [UIApplication sharedApplication].statusBarHidden = NO;
|
|
|
+ /* desktop_mode doesn't change here (the higher level will
|
|
|
+ * use it to set all the screens back to their defaults
|
|
|
+ * upon window destruction, SDL_Quit(), etc. */
|
|
|
+ display->current_mode = *bestmode;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
|
|
- if (window->w > window->h) {
|
|
|
- if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
|
|
|
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
|
|
|
- }
|
|
|
- } else if (window->w < window->h) {
|
|
|
- if (UIKit_IsDisplayLandscape(data->uiscreen)) {
|
|
|
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
|
|
|
+ if (data.uiscreen == [UIScreen mainScreen]) {
|
|
|
+ NSUInteger orientations = UIKit_GetSupportedOrientations(window);
|
|
|
+ UIApplication *app = [UIApplication sharedApplication];
|
|
|
+
|
|
|
+ if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
|
|
+ app.statusBarHidden = YES;
|
|
|
+ } else {
|
|
|
+ app.statusBarHidden = NO;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- /* ignore the size user requested, and make a fullscreen window */
|
|
|
- /* !!! FIXME: can we have a smaller view? */
|
|
|
- UIWindow *uiwindow = [UIWindow alloc];
|
|
|
- uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
|
|
|
-
|
|
|
- /* 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];
|
|
|
- }
|
|
|
+ /* ignore the size user requested, and make a fullscreen window */
|
|
|
+ /* !!! FIXME: can we have a smaller view? */
|
|
|
+ UIWindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data.uiscreen.bounds];
|
|
|
|
|
|
- if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
|
|
- [uiwindow release];
|
|
|
- return -1;
|
|
|
+ /* put the window on an external display if appropriate. */
|
|
|
+ if (data.uiscreen != [UIScreen mainScreen]) {
|
|
|
+ [uiwindow setScreen:data.uiscreen];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
+}
|
|
|
|
|
|
+void
|
|
|
+UIKit_SetWindowTitle(_THIS, SDL_Window * window)
|
|
|
+{
|
|
|
+ @autoreleasepool {
|
|
|
+ SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
|
|
+ if (window->title) {
|
|
|
+ data.viewcontroller.title = @(window->title);
|
|
|
+ } else {
|
|
|
+ data.viewcontroller.title = nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|
|
|
UIKit_ShowWindow(_THIS, SDL_Window * window)
|
|
|
{
|
|
|
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
|
|
-
|
|
|
- [uiwindow makeKeyAndVisible];
|
|
|
+ @autoreleasepool {
|
|
|
+ SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
|
|
+ [data.uiwindow makeKeyAndVisible];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|
|
|
UIKit_HideWindow(_THIS, SDL_Window * window)
|
|
|
{
|
|
|
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
|
|
-
|
|
|
- uiwindow.hidden = YES;
|
|
|
+ @autoreleasepool {
|
|
|
+ SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
|
|
+ data.uiwindow.hidden = YES;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
-UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
|
|
+static void
|
|
|
+UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
|
|
|
{
|
|
|
- SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
|
|
- SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
|
|
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
|
|
+ SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
|
|
+ SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
|
|
|
|
|
|
- if (fullscreen) {
|
|
|
- [UIApplication sharedApplication].statusBarHidden = YES;
|
|
|
- } else {
|
|
|
- [UIApplication sharedApplication].statusBarHidden = NO;
|
|
|
+ if (data.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];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- CGRect bounds;
|
|
|
- if (fullscreen) {
|
|
|
- bounds = [displaydata->uiscreen bounds];
|
|
|
- } else {
|
|
|
- bounds = [displaydata->uiscreen applicationFrame];
|
|
|
+ /* Update the view's frame to account for the status bar change. */
|
|
|
+ viewcontroller.view.frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
|
|
+ [viewcontroller.view setNeedsLayout];
|
|
|
+ [viewcontroller.view layoutIfNeeded];
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
|
|
+{
|
|
|
+ @autoreleasepool {
|
|
|
+ UIKit_UpdateWindowBorder(_this, window);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /* Get frame dimensions in pixels */
|
|
|
- int width = (int)(bounds.size.width * displaymodedata->scale);
|
|
|
- int height = (int)(bounds.size.height * displaymodedata->scale);
|
|
|
-
|
|
|
- /* 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) {
|
|
|
- if (width > height) {
|
|
|
- window->w = width;
|
|
|
- window->h = height;
|
|
|
- } else {
|
|
|
- window->w = height;
|
|
|
- window->h = width;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (width > height) {
|
|
|
- window->w = height;
|
|
|
- window->h = width;
|
|
|
- } else {
|
|
|
- window->w = width;
|
|
|
- window->h = height;
|
|
|
- }
|
|
|
+void
|
|
|
+UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
|
|
+{
|
|
|
+ @autoreleasepool {
|
|
|
+ UIKit_UpdateWindowBorder(_this, window);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void
|
|
|
UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
|
|
{
|
|
|
- SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
|
|
-
|
|
|
- if (data) {
|
|
|
- [data->viewcontroller release];
|
|
|
- [data->uiwindow release];
|
|
|
- SDL_free(data);
|
|
|
+ @autoreleasepool {
|
|
|
+ if (window->driverdata != NULL) {
|
|
|
+ SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
|
|
+ [data.viewcontroller stopAnimation];
|
|
|
+ }
|
|
|
}
|
|
|
window->driverdata = NULL;
|
|
|
}
|
|
@@ -301,29 +314,82 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
|
|
SDL_bool
|
|
|
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|
|
{
|
|
|
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
|
|
+ @autoreleasepool {
|
|
|
+ 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;
|
|
|
- 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 = data.uiwindow;
|
|
|
+ return SDL_TRUE;
|
|
|
+ } else {
|
|
|
+ SDL_SetError("Application not compiled with SDL %d.%d\n",
|
|
|
+ SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
|
|
+ return SDL_FALSE;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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)
|
|
|
{
|
|
|
- SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
|
|
|
+ if (!window || !window->driverdata) {
|
|
|
+ return SDL_SetError("Invalid window");
|
|
|
+ }
|
|
|
|
|
|
- if (!data || !data->view) {
|
|
|
- return SDL_SetError("Invalid window or view not set");
|
|
|
+ @autoreleasepool {
|
|
|
+ SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
|
|
+ [data.viewcontroller setAnimationCallback:interval
|
|
|
+ callback:callback
|
|
|
+ callbackParam:callbackParam];
|
|
|
}
|
|
|
|
|
|
- [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
|
|
|
return 0;
|
|
|
}
|
|
|
|