Added orientation rotation for iOS.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 28 Mar 2011 23:21:22 -0400
changeset 552009b500e0656d
parent 5519 c425e4e8fc75
child 5521 ef550bdb8c1b
Added orientation rotation for iOS.
src/video/uikit/SDL_uikitopengles.m
src/video/uikit/SDL_uikitopenglview.m
src/video/uikit/SDL_uikitview.h
src/video/uikit/SDL_uikitwindow.h
src/video/uikit/SDL_uikitwindow.m
test/testgles.c
test/testsprite2.c
     1.1 --- a/src/video/uikit/SDL_uikitopengles.m	Mon Mar 28 15:18:01 2011 -0400
     1.2 +++ b/src/video/uikit/SDL_uikitopengles.m	Mon Mar 28 23:21:22 2011 -0400
     1.3 @@ -117,13 +117,15 @@
     1.4                                      majorVersion: _this->gl_config.major_version];
     1.5      
     1.6      data->view = view;
     1.7 -    
     1.8 +    view->viewcontroller = data->viewcontroller;
     1.9 +    if (view->viewcontroller != nil) {
    1.10 +        [view->viewcontroller setView:view];
    1.11 +        [view->viewcontroller retain];
    1.12 +    }
    1.13 +
    1.14      /* add the view to our window */
    1.15      [uiwindow addSubview: view ];
    1.16 -    
    1.17 -    /* Don't worry, the window retained the view */
    1.18 -    [view release];
    1.19 -    
    1.20 +
    1.21      if ( UIKit_GL_MakeCurrent(_this, window, view) < 0 ) {
    1.22          UIKit_GL_DeleteContext(_this, view);
    1.23          return NULL;
    1.24 @@ -140,8 +142,12 @@
    1.25  {
    1.26      /* the delegate has retained the view, this will release him */
    1.27      SDL_uikitopenglview *view = (SDL_uikitopenglview *)context;
    1.28 -    /* this will also delete it */
    1.29 +    if (view->viewcontroller) {
    1.30 +        [view->viewcontroller setView:nil];
    1.31 +        [view->viewcontroller release];
    1.32 +    }
    1.33      [view removeFromSuperview];
    1.34 +    [view release];
    1.35  }
    1.36  
    1.37  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/video/uikit/SDL_uikitopenglview.m	Mon Mar 28 15:18:01 2011 -0400
     2.2 +++ b/src/video/uikit/SDL_uikitopenglview.m	Mon Mar 28 23:21:22 2011 -0400
     2.3 @@ -121,9 +121,12 @@
     2.4          }
     2.5          /* end create buffers */
     2.6  
     2.7 +        // !!! FIXME: use the screen this is on!
     2.8          /* Use the main screen scale (for retina display support) */
     2.9          if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
    2.10              self.contentScaleFactor = [UIScreen mainScreen].scale;
    2.11 +
    2.12 +        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    2.13      }
    2.14      return self;
    2.15  }
     3.1 --- a/src/video/uikit/SDL_uikitview.h	Mon Mar 28 15:18:01 2011 -0400
     3.2 +++ b/src/video/uikit/SDL_uikitview.h	Mon Mar 28 23:21:22 2011 -0400
     3.3 @@ -30,6 +30,16 @@
     3.4  #define MAX_SIMULTANEOUS_TOUCHES 5
     3.5  #endif
     3.6  
     3.7 +@interface SDL_uikitviewcontroller : UIViewController {
     3.8 +@private
     3.9 +    SDL_Window *window;
    3.10 +}
    3.11 +- (id)initWithSDLWindow:(SDL_Window *)_window;
    3.12 +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
    3.13 +- (void)loadView;
    3.14 +- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
    3.15 +@end
    3.16 +
    3.17  /* *INDENT-OFF* */
    3.18  #if SDL_IPHONE_KEYBOARD
    3.19  @interface SDL_uikitview : UIView<UITextFieldDelegate> {
    3.20 @@ -48,7 +58,9 @@
    3.21      UITextField *textField;
    3.22      BOOL keyboardVisible;
    3.23  #endif    
    3.24 -    
    3.25 +
    3.26 +@public
    3.27 +    SDL_uikitviewcontroller *viewcontroller;
    3.28  }
    3.29  - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
    3.30  - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
     4.1 --- a/src/video/uikit/SDL_uikitwindow.h	Mon Mar 28 15:18:01 2011 -0400
     4.2 +++ b/src/video/uikit/SDL_uikitwindow.h	Mon Mar 28 23:21:22 2011 -0400
     4.3 @@ -40,6 +40,7 @@
     4.4  {
     4.5      UIWindow *uiwindow;
     4.6      SDL_uikitopenglview *view;
     4.7 +    SDL_uikitviewcontroller *viewcontroller;
     4.8  };
     4.9  
    4.10  
     5.1 --- a/src/video/uikit/SDL_uikitwindow.m	Mon Mar 28 15:18:01 2011 -0400
     5.2 +++ b/src/video/uikit/SDL_uikitwindow.m	Mon Mar 28 23:21:22 2011 -0400
     5.3 @@ -38,6 +38,58 @@
     5.4  
     5.5  #include <Foundation/Foundation.h>
     5.6  
     5.7 +@implementation SDL_uikitviewcontroller
     5.8 +
     5.9 +- (id)initWithSDLWindow:(SDL_Window *)_window {
    5.10 +    [self init];
    5.11 +    self->window = _window;
    5.12 +    return self;
    5.13 +}
    5.14 +
    5.15 +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient {
    5.16 +    return YES;
    5.17 +}
    5.18 +
    5.19 +- (void)loadView  {
    5.20 +    // do nothing.
    5.21 +}
    5.22 +
    5.23 +// Send a resized event when the orientation changes.
    5.24 +- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    5.25 +    SDL_WindowData *data = self->window->driverdata;
    5.26 +    UIWindow *uiwindow = data->uiwindow;
    5.27 +    CGRect frame = [uiwindow frame];
    5.28 +    const CGSize size = frame.size;
    5.29 +    int w, h;
    5.30 +
    5.31 +    switch (toInterfaceOrientation) {
    5.32 +        case UIInterfaceOrientationPortrait:
    5.33 +        case UIInterfaceOrientationPortraitUpsideDown:
    5.34 +            w = (size.width < size.height) ? size.width : size.height;
    5.35 +            h = (size.width > size.height) ? size.width : size.height;
    5.36 +            break;
    5.37 +
    5.38 +        case UIInterfaceOrientationLandscapeLeft:
    5.39 +        case UIInterfaceOrientationLandscapeRight:
    5.40 +            w = (size.width > size.height) ? size.width : size.height;
    5.41 +            h = (size.width < size.height) ? size.width : size.height;
    5.42 +            break;
    5.43 +
    5.44 +        default:
    5.45 +            SDL_assert(0 && "Unexpected interface orientation!");
    5.46 +            return;
    5.47 +    }
    5.48 +    self->window->w = w;
    5.49 +    self->window->h = h;
    5.50 +    frame.size.width = w;
    5.51 +    frame.size.height = h;
    5.52 +    SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h);
    5.53 +}
    5.54 +
    5.55 +@end
    5.56 +
    5.57 +
    5.58 +
    5.59  static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
    5.60  {
    5.61      SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    5.62 @@ -51,6 +103,7 @@
    5.63          return -1;
    5.64      }
    5.65      data->uiwindow = uiwindow;
    5.66 +    data->viewcontroller = nil;
    5.67      data->view = nil;
    5.68  
    5.69      /* Fill in the SDL window with the window data */
    5.70 @@ -62,9 +115,11 @@
    5.71      }
    5.72      
    5.73      window->driverdata = data;
    5.74 -    
    5.75 +
    5.76 +    // !!! FIXME: should we force this? Shouldn't specifying FULLSCREEN
    5.77 +    // !!! FIXME:  imply BORDERLESS?
    5.78      window->flags |= SDL_WINDOW_FULLSCREEN;        /* window is always fullscreen */
    5.79 -    window->flags |= SDL_WINDOW_SHOWN;            /* only one window on iPod touch, always shown */
    5.80 +    window->flags |= SDL_WINDOW_SHOWN;            /* only one window on iOS, always shown */
    5.81  
    5.82      // SDL_WINDOW_BORDERLESS controls whether status bar is hidden.
    5.83      // This is only set if the window is on the main screen. Other screens
    5.84 @@ -72,6 +127,7 @@
    5.85      if ([UIScreen mainScreen] != uiscreen) {
    5.86          window->flags &= ~SDL_WINDOW_RESIZABLE;  // window is NEVER resizeable
    5.87          window->flags &= ~SDL_WINDOW_INPUT_FOCUS;  // never has input focus
    5.88 +        window->flags |= SDL_WINDOW_BORDERLESS;  // never has a status bar.
    5.89      } else {
    5.90          window->flags |= SDL_WINDOW_INPUT_FOCUS;  // always has input focus
    5.91  
    5.92 @@ -81,21 +137,34 @@
    5.93              [UIApplication sharedApplication].statusBarHidden = NO;
    5.94          }
    5.95  
    5.96 -        // Rotate the view if we have to, but only on the main screen
    5.97 -        //  (presumably, an external display doesn't report orientation).
    5.98          const CGSize uisize = [[uiscreen currentMode] size];
    5.99 -        if ( ((window->w > window->h) && (uisize.width < uisize.height)) ||
   5.100 -             ((window->w < window->h) && (uisize.width > uisize.height)) ) {
   5.101 -            // !!! FIXME: flip orientation.
   5.102 -        }
   5.103 +        const UIDeviceOrientation o = [[UIDevice currentDevice] orientation];
   5.104 +        const BOOL landscape = (o == UIDeviceOrientationLandscapeLeft) ||
   5.105 +                                   (o == UIDeviceOrientationLandscapeRight);
   5.106 +        const BOOL rotate = ( ((window->w > window->h) && (!landscape)) ||
   5.107 +                              ((window->w < window->h) && (landscape)) );
   5.108  
   5.109          if (window->flags & SDL_WINDOW_RESIZABLE) {
   5.110 -            // !!! FIXME: register for orientation change alerts.
   5.111 +            // The View Controller will handle rotating the view when the
   5.112 +            //  device orientation changes. We expose these as resize events.
   5.113 +            SDL_uikitviewcontroller *controller;
   5.114 +            controller = [SDL_uikitviewcontroller alloc];
   5.115 +            data->viewcontroller = [controller initWithSDLWindow:window];
   5.116 +            [data->viewcontroller setTitle:@"SDL App"];  // !!! FIXME: hook up SDL_SetWindowTitle()
   5.117 +            // !!! FIXME: if (rotate), force a "resize" right at the start
   5.118 +        } else {
   5.119 +            // Rotate the view if we have to, but only on the main screen
   5.120 +            //  (presumably, an external display doesn't report orientation).
   5.121 +            if (rotate) {
   5.122 +                #define D2R(x) (M_PI * (x) / 180.0)   // degrees to radians.
   5.123 +                [uiwindow setTransform:CGAffineTransformIdentity];
   5.124 +                [uiwindow setTransform:CGAffineTransformMakeRotation(D2R(90))];
   5.125 +                #undef D2R
   5.126 +            }
   5.127          }
   5.128      }
   5.129  
   5.130      return 0;
   5.131 -    
   5.132  }
   5.133  
   5.134  int
   5.135 @@ -107,7 +176,7 @@
   5.136      // SDL currently puts this window at the start of display's linked list. We rely on this.
   5.137      SDL_assert(_this->windows == window);
   5.138  
   5.139 -    /* We currently only handle a single window per display on iPhone */
   5.140 +    /* We currently only handle a single window per display on iOS */
   5.141      if (window->next != NULL) {
   5.142          SDL_SetError("Only one window allowed per display.");
   5.143          return -1;
   5.144 @@ -172,6 +241,7 @@
   5.145  UIKit_DestroyWindow(_THIS, SDL_Window * window) {
   5.146      SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
   5.147      if (data) {
   5.148 +        [data->viewcontroller release];
   5.149          [data->uiwindow release];
   5.150          SDL_free(data);
   5.151          window->driverdata = NULL;
     6.1 --- a/test/testgles.c	Mon Mar 28 15:18:01 2011 -0400
     6.2 +++ b/test/testgles.c	Mon Mar 28 23:21:22 2011 -0400
     6.3 @@ -140,7 +140,7 @@
     6.4      }
     6.5  
     6.6      /* Set OpenGL parameters */
     6.7 -    state->window_flags |= SDL_WINDOW_OPENGL;
     6.8 +    state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
     6.9      state->gl_red_size = 5;
    6.10      state->gl_green_size = 5;
    6.11      state->gl_blue_size = 5;
     7.1 --- a/test/testsprite2.c	Mon Mar 28 15:18:01 2011 -0400
     7.2 +++ b/test/testsprite2.c	Mon Mar 28 23:21:22 2011 -0400
     7.3 @@ -219,6 +219,9 @@
     7.4      if (!state) {
     7.5          return 1;
     7.6      }
     7.7 +
     7.8 +    state->window_flags |= SDL_WINDOW_RESIZABLE;
     7.9 +
    7.10      for (i = 1; i < argc;) {
    7.11          int consumed;
    7.12