src/video/uikit/SDL_uikitwindow.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Oct 2011 05:56:58 -0400
changeset 6044 35448a5ea044
parent 6014 7a8b72b88d86
child 6064 498e0234dfe6
permissions -rw-r--r--
Lots of fixes importing SDL source wholesale into a new iOS project
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #include "SDL_syswm.h"
    26 #include "SDL_video.h"
    27 #include "SDL_mouse.h"
    28 #include "SDL_assert.h"
    29 #include "SDL_hints.h"
    30 #include "../SDL_sysvideo.h"
    31 #include "../SDL_pixels_c.h"
    32 #include "../../events/SDL_events_c.h"
    33 
    34 #include "SDL_uikitvideo.h"
    35 #include "SDL_uikitevents.h"
    36 #include "SDL_uikitwindow.h"
    37 #import "SDL_uikitappdelegate.h"
    38 
    39 #import "SDL_uikitopenglview.h"
    40 
    41 #include <Foundation/Foundation.h>
    42 
    43 
    44 
    45 
    46 static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
    47 {
    48     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    49     UIScreen *uiscreen = (UIScreen *) display->driverdata;
    50     SDL_WindowData *data;
    51 
    52     /* Allocate the window data */
    53     data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
    54     if (!data) {
    55         SDL_OutOfMemory();
    56         return -1;
    57     }
    58     data->uiwindow = uiwindow;
    59     data->viewcontroller = nil;
    60     data->view = nil;
    61 
    62     /* Fill in the SDL window with the window data */
    63     {
    64         window->x = 0;
    65         window->y = 0;
    66         window->w = (int)uiwindow.frame.size.width;
    67         window->h = (int)uiwindow.frame.size.height;
    68     }
    69 
    70     window->driverdata = data;
    71 
    72     // !!! FIXME: should we force this? Shouldn't specifying FULLSCREEN
    73     // !!! FIXME:  imply BORDERLESS?
    74     window->flags |= SDL_WINDOW_FULLSCREEN;        /* window is always fullscreen */
    75     window->flags |= SDL_WINDOW_SHOWN;            /* only one window on iOS, always shown */
    76 
    77     // SDL_WINDOW_BORDERLESS controls whether status bar is hidden.
    78     // This is only set if the window is on the main screen. Other screens
    79     //  just force the window to have the borderless flag.
    80     if ([UIScreen mainScreen] != uiscreen) {
    81         window->flags &= ~SDL_WINDOW_RESIZABLE;  // window is NEVER resizeable
    82         window->flags &= ~SDL_WINDOW_INPUT_FOCUS;  // never has input focus
    83         window->flags |= SDL_WINDOW_BORDERLESS;  // never has a status bar.
    84     } else {
    85         window->flags |= SDL_WINDOW_INPUT_FOCUS;  // always has input focus
    86 
    87         if (window->flags & SDL_WINDOW_BORDERLESS) {
    88             [UIApplication sharedApplication].statusBarHidden = YES;
    89         } else {
    90             [UIApplication sharedApplication].statusBarHidden = NO;
    91         }
    92 
    93         //const UIDeviceOrientation o = [[UIDevice currentDevice] orientation];
    94         //const BOOL landscape = (o == UIDeviceOrientationLandscapeLeft) ||
    95         //                           (o == UIDeviceOrientationLandscapeRight);
    96         //const BOOL rotate = ( ((window->w > window->h) && (!landscape)) ||
    97         //                      ((window->w < window->h) && (landscape)) );
    98 
    99         // The View Controller will handle rotating the view when the
   100         //  device orientation changes. This will trigger resize events, if
   101         //  appropriate.
   102         SDL_uikitviewcontroller *controller;
   103         controller = [SDL_uikitviewcontroller alloc];
   104         data->viewcontroller = [controller initWithSDLWindow:window];
   105         [data->viewcontroller setTitle:@"SDL App"];  // !!! FIXME: hook up SDL_SetWindowTitle()
   106         // !!! FIXME: if (rotate), force a "resize" right at the start
   107     }
   108 
   109     return 0;
   110 }
   111 
   112 int
   113 UIKit_CreateWindow(_THIS, SDL_Window *window)
   114 {
   115     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   116     UIScreen *uiscreen = (UIScreen *) display->driverdata;
   117     const BOOL external = ([UIScreen mainScreen] != uiscreen);
   118 
   119     // SDL currently puts this window at the start of display's linked list. We rely on this.
   120     SDL_assert(_this->windows == window);
   121 
   122     /* We currently only handle a single window per display on iOS */
   123     if (window->next != NULL) {
   124         SDL_SetError("Only one window allowed per display.");
   125         return -1;
   126     }
   127 
   128     // Non-mainscreen windows must be force to borderless, as there's no
   129     //  status bar there, and we want to get the right dimensions later in
   130     //  this function.
   131     if (external) {
   132         window->flags |= SDL_WINDOW_BORDERLESS;
   133     }
   134 
   135     // If monitor has a resolution of 0x0 (hasn't been explicitly set by the
   136     //  user, so it's in standby), try to force the display to a resolution
   137     //  that most closely matches the desired window size.
   138     if (SDL_UIKit_supports_multiple_displays) {
   139         const CGSize origsize = [[uiscreen currentMode] size];
   140         if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
   141             if (display->num_display_modes == 0) {
   142                 _this->GetDisplayModes(_this, display);
   143             }
   144 
   145             int i;
   146             const SDL_DisplayMode *bestmode = NULL;
   147             for (i = display->num_display_modes; i >= 0; i--) {
   148                 const SDL_DisplayMode *mode = &display->display_modes[i];
   149                 if ((mode->w >= window->w) && (mode->h >= window->h))
   150                     bestmode = mode;
   151             }
   152 
   153             if (bestmode) {
   154                 UIScreenMode *uimode = (UIScreenMode *) bestmode->driverdata;
   155                 [uiscreen setCurrentMode:uimode];
   156 
   157                 // desktop_mode doesn't change here (the higher level will
   158                 //  use it to set all the screens back to their defaults
   159                 //  upon window destruction, SDL_Quit(), etc.
   160                 [((UIScreenMode *) display->current_mode.driverdata) release];
   161                 display->current_mode = *bestmode;
   162                 [((UIScreenMode *) display->current_mode.driverdata) retain];
   163             }
   164         }
   165     }
   166 
   167     /* ignore the size user requested, and make a fullscreen window */
   168     // !!! FIXME: can we have a smaller view?
   169     UIWindow *uiwindow = [UIWindow alloc];
   170     if (window->flags & SDL_WINDOW_BORDERLESS)
   171         uiwindow = [uiwindow initWithFrame:[uiscreen bounds]];
   172     else
   173         uiwindow = [uiwindow initWithFrame:[uiscreen applicationFrame]];
   174 
   175     // put the window on an external display if appropriate. This implicitly
   176     //  does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
   177     //  main display, where we land by default, as that would eat the
   178     //  status bar real estate.
   179     if (external) {
   180         [uiwindow setScreen:uiscreen];
   181     }
   182 
   183     if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
   184         [uiwindow release];
   185         return -1;
   186     }
   187 
   188     return 1;
   189 
   190 }
   191 
   192 void
   193 UIKit_DestroyWindow(_THIS, SDL_Window * window)
   194 {
   195     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
   196     if (data) {
   197         [data->viewcontroller release];
   198         [data->uiwindow release];
   199         SDL_free(data);
   200         window->driverdata = NULL;
   201     }
   202 }
   203 
   204 SDL_bool
   205 UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   206 {
   207     UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
   208 
   209     if (info->version.major <= SDL_MAJOR_VERSION) {
   210         info->subsystem = SDL_SYSWM_UIKIT;
   211         info->info.uikit.window = uiwindow;
   212         return SDL_TRUE;
   213     } else {
   214         SDL_SetError("Application not compiled with SDL %d.%d\n",
   215                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   216         return SDL_FALSE;
   217     }
   218 }
   219 
   220 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   221 
   222 /* vi: set ts=4 sw=4 expandtab: */