src/video/cocoa/SDL_cocoawindow.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 12:17:40 -0800
changeset 5253 9e70b360f423
parent 5249 7a963be087ef
child 5261 595814f561f7
permissions -rw-r--r--
Fixed creating the window on Mac OS X.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_syswm.h"
    25 #include "../SDL_sysvideo.h"
    26 #include "../../events/SDL_keyboard_c.h"
    27 #include "../../events/SDL_mouse_c.h"
    28 #include "../../events/SDL_touch_c.h"
    29 #include "../../events/SDL_windowevents_c.h"
    30 #include "SDL_cocoavideo.h"
    31 #include "SDL_cocoashape.h"
    32 #include "SDL_cocoamouse.h"
    33 
    34 static __inline__ void ConvertNSRect(NSRect *r)
    35 {
    36     r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
    37 }
    38 
    39 @implementation Cocoa_WindowListener
    40 
    41 - (void)listen:(SDL_WindowData *)data
    42 {
    43     NSNotificationCenter *center;
    44 
    45     _data = data;
    46 
    47     center = [NSNotificationCenter defaultCenter];
    48 
    49     [_data->nswindow setNextResponder:self];
    50     if ([_data->nswindow delegate] != nil) {
    51         [center addObserver:self selector:@selector(windowDisExpose:) name:NSWindowDidExposeNotification object:_data->nswindow];
    52         [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:_data->nswindow];
    53         [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:_data->nswindow];
    54         [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:_data->nswindow];
    55         [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:_data->nswindow];
    56         [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:_data->nswindow];
    57         [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:_data->nswindow];
    58     } else {
    59         [_data->nswindow setDelegate:self];
    60     }
    61 // FIXME: Why doesn't this work?
    62 //    [center addObserver:self selector:@selector(rightMouseDown:) name:[NSString stringWithCString:"rightMouseDown" encoding:NSUTF8StringEncoding] object:[_data->nswindow contentView]];
    63     [center addObserver:self selector:@selector(windowDidHide:) name:NSApplicationDidHideNotification object:NSApp];
    64     [center addObserver:self selector:@selector(windowDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp];
    65 
    66     [_data->nswindow setAcceptsMouseMovedEvents:YES];
    67 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
    68     [[_data->nswindow contentView] setAcceptsTouchEvents:YES];
    69 #endif
    70 }
    71 
    72 - (void)close
    73 {
    74     NSNotificationCenter *center;
    75 
    76     center = [NSNotificationCenter defaultCenter];
    77 
    78     [_data->nswindow setNextResponder:nil];
    79     if ([_data->nswindow delegate] != self) {
    80         [center removeObserver:self name:NSWindowDidExposeNotification object:_data->nswindow];
    81         [center removeObserver:self name:NSWindowDidMoveNotification object:_data->nswindow];
    82         [center removeObserver:self name:NSWindowDidResizeNotification object:_data->nswindow];
    83         [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:_data->nswindow];
    84         [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:_data->nswindow];
    85         [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:_data->nswindow];
    86         [center removeObserver:self name:NSWindowDidResignKeyNotification object:_data->nswindow];
    87     } else {
    88         [_data->nswindow setDelegate:nil];
    89     }
    90     [center removeObserver:self name:NSApplicationDidHideNotification object:NSApp];
    91     [center removeObserver:self name:NSApplicationDidUnhideNotification object:NSApp];
    92 }
    93 
    94 - (BOOL)windowShouldClose:(id)sender
    95 {
    96     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
    97     return NO;
    98 }
    99 
   100 - (void)windowDidExpose:(NSNotification *)aNotification
   101 {
   102     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
   103 }
   104 
   105 - (void)windowDidMove:(NSNotification *)aNotification
   106 {
   107     int x, y;
   108     NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
   109     ConvertNSRect(&rect);
   110     x = (int)rect.origin.x;
   111     y = (int)rect.origin.y;
   112     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MOVED, x, y);
   113 }
   114 
   115 - (void)windowDidResize:(NSNotification *)aNotification
   116 {
   117     int w, h;
   118     NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
   119     w = (int)rect.size.width;
   120     h = (int)rect.size.height;
   121     if (SDL_IsShapedWindow(_data->window))
   122         Cocoa_ResizeWindowShape(_data->window);
   123     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
   124 }
   125 
   126 - (void)windowDidMiniaturize:(NSNotification *)aNotification
   127 {
   128     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   129 }
   130 
   131 - (void)windowDidDeminiaturize:(NSNotification *)aNotification
   132 {
   133     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
   134 }
   135 
   136 - (void)windowDidBecomeKey:(NSNotification *)aNotification
   137 {
   138     /* We're going to get keyboard events, since we're key. */
   139     SDL_SetKeyboardFocus(_data->window);
   140 
   141     /* Check to see if someone updated the clipboard */
   142     Cocoa_CheckClipboardUpdate(_data->videodata);
   143 }
   144 
   145 - (void)windowDidResignKey:(NSNotification *)aNotification
   146 {
   147     /* Some other window will get mouse events, since we're not key. */
   148     if (SDL_GetMouseFocus() == _data->window) {
   149         SDL_SetMouseFocus(NULL);
   150     }
   151 
   152     /* Some other window will get keyboard events, since we're not key. */
   153     if (SDL_GetKeyboardFocus() == _data->window) {
   154         SDL_SetKeyboardFocus(NULL);
   155     }
   156 }
   157 
   158 - (void)windowDidHide:(NSNotification *)aNotification
   159 {
   160     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   161 }
   162 
   163 - (void)windowDidUnhide:(NSNotification *)aNotification
   164 {
   165     SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   166 }
   167 
   168 - (void)mouseDown:(NSEvent *)theEvent
   169 {
   170     int button;
   171 
   172     switch ([theEvent buttonNumber]) {
   173     case 0:
   174         button = SDL_BUTTON_LEFT;
   175         break;
   176     case 1:
   177         button = SDL_BUTTON_RIGHT;
   178         break;
   179     case 2:
   180         button = SDL_BUTTON_MIDDLE;
   181         break;
   182     default:
   183         button = [theEvent buttonNumber] + 1;
   184         break;
   185     }
   186     SDL_SendMouseButton(_data->window, SDL_PRESSED, button);
   187 }
   188 
   189 - (void)rightMouseDown:(NSEvent *)theEvent
   190 {
   191     [self mouseDown:theEvent];
   192 }
   193 
   194 - (void)otherMouseDown:(NSEvent *)theEvent
   195 {
   196     [self mouseDown:theEvent];
   197 }
   198 
   199 - (void)mouseUp:(NSEvent *)theEvent
   200 {
   201     int button;
   202 
   203     switch ([theEvent buttonNumber]) {
   204     case 0:
   205         button = SDL_BUTTON_LEFT;
   206         break;
   207     case 1:
   208         button = SDL_BUTTON_RIGHT;
   209         break;
   210     case 2:
   211         button = SDL_BUTTON_MIDDLE;
   212         break;
   213     default:
   214         button = [theEvent buttonNumber] + 1;
   215         break;
   216     }
   217     SDL_SendMouseButton(_data->window, SDL_RELEASED, button);
   218 }
   219 
   220 - (void)rightMouseUp:(NSEvent *)theEvent
   221 {
   222     [self mouseUp:theEvent];
   223 }
   224 
   225 - (void)otherMouseUp:(NSEvent *)theEvent
   226 {
   227     [self mouseUp:theEvent];
   228 }
   229 
   230 - (void)mouseMoved:(NSEvent *)theEvent
   231 {
   232     SDL_Window *window = _data->window;
   233     NSPoint point;
   234 
   235     if (window->flags & SDL_WINDOW_FULLSCREEN)
   236         return;
   237 
   238     point = [theEvent locationInWindow];
   239     point.y = window->h - point.y;
   240     if ( point.x < 0 || point.x >= window->w ||
   241          point.y < 0 || point.y >= window->h ) {
   242         if (SDL_GetMouseFocus() == window) {
   243             SDL_SetMouseFocus(NULL);
   244         }
   245     } else {
   246         SDL_SendMouseMotion(window, 0, (int)point.x, (int)point.y);
   247     }
   248 }
   249 
   250 - (void)mouseDragged:(NSEvent *)theEvent
   251 {
   252     [self mouseMoved:theEvent];
   253 }
   254 
   255 - (void)rightMouseDragged:(NSEvent *)theEvent
   256 {
   257     [self mouseMoved:theEvent];
   258 }
   259 
   260 - (void)otherMouseDragged:(NSEvent *)theEvent
   261 {
   262     [self mouseMoved:theEvent];
   263 }
   264 
   265 - (void)scrollWheel:(NSEvent *)theEvent
   266 {
   267     Cocoa_HandleMouseWheel(_data->window, theEvent);
   268 }
   269 
   270 - (void)touchesBeganWithEvent:(NSEvent *) theEvent
   271 {
   272     [self handleTouches:COCOA_TOUCH_DOWN withEvent:theEvent];
   273 }
   274 
   275 - (void)touchesMovedWithEvent:(NSEvent *) theEvent
   276 {
   277     [self handleTouches:COCOA_TOUCH_MOVE withEvent:theEvent];
   278 }
   279 
   280 - (void)touchesEndedWithEvent:(NSEvent *) theEvent
   281 {
   282     [self handleTouches:COCOA_TOUCH_UP withEvent:theEvent];
   283 }
   284 
   285 - (void)touchesCancelledWithEvent:(NSEvent *) theEvent
   286 {
   287     [self handleTouches:COCOA_TOUCH_CANCELLED withEvent:theEvent];
   288 }
   289 
   290 - (void)handleTouches:(cocoaTouchType)type withEvent:(NSEvent *)event
   291 {
   292 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
   293     NSSet *touches = 0;
   294     NSEnumerator *enumerator;
   295     NSTouch *touch;
   296 
   297     switch (type) {
   298         case COCOA_TOUCH_DOWN:
   299             touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
   300             break;
   301         case COCOA_TOUCH_UP:
   302         case COCOA_TOUCH_CANCELLED:
   303             touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil];
   304             break;
   305         case COCOA_TOUCH_MOVE:
   306             touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil];
   307             break;
   308     }
   309 
   310     enumerator = [touches objectEnumerator];
   311     touch = (NSTouch*)[enumerator nextObject];
   312     while (touch) {
   313         SDL_TouchID touchId = (SDL_TouchID)[touch device];
   314         if (!SDL_GetTouch(touchId)) {
   315             SDL_Touch touch;
   316 
   317             touch.id = touchId;
   318             touch.x_min = 0;
   319             touch.x_max = 1;
   320             touch.native_xres = touch.x_max - touch.x_min;
   321             touch.y_min = 0;
   322             touch.y_max = 1;
   323             touch.native_yres = touch.y_max - touch.y_min;
   324             touch.pressure_min = 0;
   325             touch.pressure_max = 1;
   326             touch.native_pressureres = touch.pressure_max - touch.pressure_min;
   327             
   328             if (SDL_AddTouch(&touch, "") < 0) {
   329                 return;
   330             }
   331         } 
   332 
   333         SDL_FingerID fingerId = (SDL_FingerID)[touch identity];
   334         float x = [touch normalizedPosition].x;
   335         float y = [touch normalizedPosition].y;
   336 	/* Make the origin the upper left instead of the lower left */
   337 	y = 1.0f - y;
   338 
   339         switch (type) {
   340         case COCOA_TOUCH_DOWN:
   341             SDL_SendFingerDown(touchId, fingerId, SDL_TRUE, x, y, 1);
   342             break;
   343         case COCOA_TOUCH_UP:
   344         case COCOA_TOUCH_CANCELLED:
   345             SDL_SendFingerDown(touchId, fingerId, SDL_FALSE, x, y, 1);
   346             break;
   347         case COCOA_TOUCH_MOVE:
   348             SDL_SendTouchMotion(touchId, fingerId, SDL_FALSE, x, y, 1);
   349             break;
   350         }
   351         
   352         touch = (NSTouch*)[enumerator nextObject];
   353     }
   354 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 */
   355 }
   356 
   357 @end
   358 
   359 @interface SDLWindow : NSWindow
   360 /* These are needed for borderless/fullscreen windows */
   361 - (BOOL)canBecomeKeyWindow;
   362 - (BOOL)canBecomeMainWindow;
   363 @end
   364 
   365 @implementation SDLWindow
   366 - (BOOL)canBecomeKeyWindow
   367 {
   368     return YES;
   369 }
   370 
   371 - (BOOL)canBecomeMainWindow
   372 {
   373     return YES;
   374 }
   375 @end
   376 
   377 @interface SDLView : NSView {
   378     Cocoa_WindowListener *listener;
   379 }
   380 @end
   381 
   382 @implementation SDLView
   383 
   384 - (id) initWithFrame: (NSRect) rect
   385             listener: (Cocoa_WindowListener *) theListener
   386 {
   387     if (self = [super initWithFrame:rect]) {
   388         listener = theListener;
   389     }
   390 
   391     return self;
   392 }
   393 
   394 - (void)rightMouseDown:(NSEvent *)theEvent
   395 {
   396     [listener mouseDown:theEvent];
   397 }
   398 
   399 @end
   400 
   401 static unsigned int
   402 GetStyleMask(SDL_Window * window)
   403 {
   404     unsigned int style;
   405 
   406     if (window->flags & SDL_WINDOW_BORDERLESS) {
   407         style = NSBorderlessWindowMask;
   408     } else {
   409         style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
   410     }
   411     if (window->flags & SDL_WINDOW_RESIZABLE) {
   412         style |= NSResizableWindowMask;
   413     }
   414     return style;
   415 }
   416 
   417 static int
   418 SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
   419 {
   420     NSAutoreleasePool *pool;
   421     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   422     SDL_WindowData *data;
   423 
   424     /* Allocate the window data */
   425     data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
   426     if (!data) {
   427         SDL_OutOfMemory();
   428         return -1;
   429     }
   430     data->window = window;
   431     data->nswindow = nswindow;
   432     data->created = created;
   433     data->videodata = videodata;
   434 
   435     pool = [[NSAutoreleasePool alloc] init];
   436 
   437     /* Create an event listener for the window */
   438     data->listener = [[Cocoa_WindowListener alloc] init];
   439     [data->listener listen:data];
   440 
   441     /* Fill in the SDL window with the window data */
   442     {
   443         NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
   444         NSView *contentView = [[SDLView alloc] initWithFrame: rect
   445                                                     listener: data->listener];
   446 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
   447         [contentView setAcceptsTouchEvents:YES];
   448 #endif
   449         [nswindow setContentView: contentView];
   450         [contentView release];
   451 
   452         ConvertNSRect(&rect);
   453         window->fullscreen.x = window->windowed.x = window->x = (int)rect.origin.x;
   454         window->fullscreen.y = window->windowed.y = window->y = (int)rect.origin.y;
   455         window->fullscreen.w = window->windowed.w = window->w = (int)rect.size.width;
   456         window->fullscreen.h = window->windowed.h = window->h = (int)rect.size.height;
   457     }
   458     if ([nswindow isVisible]) {
   459         window->flags |= SDL_WINDOW_SHOWN;
   460     } else {
   461         window->flags &= ~SDL_WINDOW_SHOWN;
   462     }
   463     {
   464         unsigned int style = [nswindow styleMask];
   465 
   466         if ((style & ~NSResizableWindowMask) == NSBorderlessWindowMask) {
   467             window->flags |= SDL_WINDOW_BORDERLESS;
   468         } else {
   469             window->flags &= ~SDL_WINDOW_BORDERLESS;
   470         }
   471         if (style & NSResizableWindowMask) {
   472             window->flags |= SDL_WINDOW_RESIZABLE;
   473         } else {
   474             window->flags &= ~SDL_WINDOW_RESIZABLE;
   475         }
   476     }
   477     if ([nswindow isZoomed]) {
   478         window->flags |= SDL_WINDOW_MAXIMIZED;
   479     } else {
   480         window->flags &= ~SDL_WINDOW_MAXIMIZED;
   481     }
   482     if ([nswindow isMiniaturized]) {
   483         window->flags |= SDL_WINDOW_MINIMIZED;
   484     } else {
   485         window->flags &= ~SDL_WINDOW_MINIMIZED;
   486     }
   487     if ([nswindow isKeyWindow]) {
   488         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   489         SDL_SetKeyboardFocus(data->window);
   490 
   491         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   492             /* FIXME */
   493         }
   494     }
   495 
   496     /* All done! */
   497     [pool release];
   498     window->driverdata = data;
   499     return 0;
   500 }
   501 
   502 int
   503 Cocoa_CreateWindow(_THIS, SDL_Window * window)
   504 {
   505     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   506     NSWindow *nswindow;
   507     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   508     NSRect rect;
   509     SDL_Rect bounds;
   510     unsigned int style;
   511 
   512     Cocoa_GetDisplayBounds(_this, display, &bounds);
   513     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
   514         rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
   515     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
   516         rect.origin.x = bounds.x;
   517     } else {
   518         rect.origin.x = window->x;
   519     }
   520     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
   521         rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
   522     } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
   523         rect.origin.y = bounds.y;
   524     } else {
   525         rect.origin.y = window->y;
   526     }
   527     rect.size.width = window->w;
   528     rect.size.height = window->h;
   529     ConvertNSRect(&rect);
   530 
   531     style = GetStyleMask(window);
   532 
   533     /* Figure out which screen to place this window */
   534     NSArray *screens = [NSScreen screens];
   535     NSScreen *screen = nil;
   536     NSScreen *candidate;
   537     int i, count = [screens count];
   538     for (i = 0; i < count; ++i) {
   539         candidate = [screens objectAtIndex:i];
   540         NSRect screenRect = [candidate frame];
   541         if (rect.origin.x >= screenRect.origin.x &&
   542             rect.origin.x < screenRect.origin.x + screenRect.size.width &&
   543             rect.origin.y >= screenRect.origin.y &&
   544             rect.origin.y < screenRect.origin.y + screenRect.size.height) {
   545             screen = candidate;
   546             rect.origin.x -= screenRect.origin.x;
   547             rect.origin.y -= screenRect.origin.y;
   548         }
   549     }
   550     nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE screen:screen];
   551 
   552     [pool release];
   553 
   554     if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
   555         [nswindow release];
   556         return -1;
   557     }
   558     return 0;
   559 }
   560 
   561 int
   562 Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   563 {
   564     NSAutoreleasePool *pool;
   565     NSWindow *nswindow = (NSWindow *) data;
   566     NSString *title;
   567 
   568     pool = [[NSAutoreleasePool alloc] init];
   569 
   570     /* Query the title from the existing window */
   571     title = [nswindow title];
   572     if (title) {
   573         window->title = SDL_strdup([title UTF8String]);
   574     }
   575 
   576     [pool release];
   577 
   578     return SetupWindowData(_this, window, nswindow, SDL_FALSE);
   579 }
   580 
   581 void
   582 Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
   583 {
   584     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   585     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   586     NSString *string;
   587 
   588     if(window->title) {
   589         string = [[NSString alloc] initWithUTF8String:window->title];
   590     } else {
   591         string = [[NSString alloc] init];
   592     }
   593     [nswindow setTitle:string];
   594     [string release];
   595 
   596     [pool release];
   597 }
   598 
   599 void
   600 Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
   601 {
   602     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   603     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   604     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   605     NSRect rect;
   606     SDL_Rect bounds;
   607 
   608     Cocoa_GetDisplayBounds(_this, display, &bounds);
   609     if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
   610         rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
   611     } else {
   612         rect.origin.x = window->x;
   613     }
   614     if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
   615         rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
   616     } else {
   617         rect.origin.y = window->y;
   618     }
   619     rect.size.width = window->w;
   620     rect.size.height = window->h;
   621     ConvertNSRect(&rect);
   622     rect = [nswindow frameRectForContentRect:rect];
   623     [nswindow setFrameOrigin:rect.origin];
   624     [pool release];
   625 }
   626 
   627 void
   628 Cocoa_SetWindowSize(_THIS, SDL_Window * window)
   629 {
   630     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   631     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   632     NSSize size;
   633 
   634     size.width = window->w;
   635     size.height = window->h;
   636     [nswindow setContentSize:size];
   637     [pool release];
   638 }
   639 
   640 void
   641 Cocoa_ShowWindow(_THIS, SDL_Window * window)
   642 {
   643     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   644     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   645 
   646     if (![nswindow isMiniaturized]) {
   647         [nswindow makeKeyAndOrderFront:nil];
   648     }
   649     [pool release];
   650 }
   651 
   652 void
   653 Cocoa_HideWindow(_THIS, SDL_Window * window)
   654 {
   655     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   656     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   657 
   658     [nswindow orderOut:nil];
   659     [pool release];
   660 }
   661 
   662 void
   663 Cocoa_RaiseWindow(_THIS, SDL_Window * window)
   664 {
   665     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   666     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   667 
   668     [nswindow makeKeyAndOrderFront:nil];
   669     [pool release];
   670 }
   671 
   672 void
   673 Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
   674 {
   675     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   676     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   677 
   678     [nswindow zoom:nil];
   679     [pool release];
   680 }
   681 
   682 void
   683 Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
   684 {
   685     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   686     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   687 
   688     [nswindow miniaturize:nil];
   689     [pool release];
   690 }
   691 
   692 void
   693 Cocoa_RestoreWindow(_THIS, SDL_Window * window)
   694 {
   695     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   696     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   697 
   698     if ([nswindow isMiniaturized]) {
   699         [nswindow deminiaturize:nil];
   700     } else if ([nswindow isZoomed]) {
   701         [nswindow zoom:nil];
   702     }
   703     [pool release];
   704 }
   705 
   706 void
   707 Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window)
   708 {
   709     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   710     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   711     NSWindow *nswindow = data->nswindow;
   712     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   713     NSRect rect;
   714     unsigned int style;
   715 
   716     if (FULLSCREEN_VISIBLE(window)) {
   717         SDL_Rect bounds;
   718 
   719         Cocoa_GetDisplayBounds(_this, display, &bounds);
   720         rect.origin.x = bounds.x;
   721         rect.origin.y = bounds.y;
   722         rect.size.width = bounds.w;
   723         rect.size.height = bounds.h;
   724         ConvertNSRect(&rect);
   725 
   726         style = NSBorderlessWindowMask;
   727     } else {
   728         rect.origin.x = window->windowed.x;
   729         rect.origin.y = window->windowed.y;
   730         rect.size.width = window->windowed.w;
   731         rect.size.height = window->windowed.h;
   732         /* FIXME: This calculation is wrong, we're changing the origin */
   733         ConvertNSRect(&rect);
   734 
   735         style = GetStyleMask(window);
   736     }
   737 
   738     [nswindow setStyleMask:style];
   739     [nswindow setContentSize:rect.size];
   740     rect = [nswindow frameRectForContentRect:rect];
   741     [nswindow setFrameOrigin:rect.origin];
   742 
   743 #ifdef FULLSCREEN_TOGGLEABLE
   744     if (FULLSCREEN_VISIBLE(window)) {
   745         /* OpenGL is rendering to the window, so make it visible! */
   746         [nswindow setLevel:CGShieldingWindowLevel()];
   747     } else {
   748         [nswindow setLevel:kCGNormalWindowLevel];
   749     }
   750 #endif
   751     [nswindow makeKeyAndOrderFront:nil];
   752 
   753     [pool release];
   754 }
   755 
   756 void
   757 Cocoa_SetWindowGrab(_THIS, SDL_Window * window)
   758 {
   759     if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
   760         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   761         /* FIXME: Grab mouse */
   762     } else {
   763         /* FIXME: Release mouse */
   764     }
   765 }
   766 
   767 void
   768 Cocoa_DestroyWindow(_THIS, SDL_Window * window)
   769 {
   770     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   771     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   772 
   773     if (data) {
   774         [data->listener close];
   775         [data->listener release];
   776         if (data->created) {
   777             [data->nswindow close];
   778         }
   779         SDL_free(data);
   780     }
   781     [pool release];
   782 }
   783 
   784 SDL_bool
   785 Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   786 {
   787     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   788 
   789     if (info->version.major <= SDL_MAJOR_VERSION) {
   790         info->subsystem = SDL_SYSWM_COCOA;
   791         info->info.cocoa.window = nswindow;
   792         return SDL_TRUE;
   793     } else {
   794         SDL_SetError("Application not compiled with SDL %d.%d\n",
   795                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   796         return SDL_FALSE;
   797     }
   798 }
   799 
   800 /* vi: set ts=4 sw=4 expandtab: */