src/video/cocoa/SDL_cocoawindow.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 00:25:44 -0800
changeset 5249 7a963be087ef
parent 5246 58265e606e4e
child 5253 9e70b360f423
permissions -rw-r--r--
Mostly fixed fullscreen mode on Mac OS X, and you can toggle it on and off.

There are still some problems with the ConvertNSRect() calculations when switching video modes, which causes wierd window positioning issues, and the fullscreen window is still minimized on exit.
     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->x = (int)rect.origin.x;
   454         window->y = (int)rect.origin.y;
   455         window->w = (int)rect.size.width;
   456         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: */