src/video/cocoa/SDL_cocoawindow.m
author Jjgod Jiang <gzjjgod@gmail.com>
Fri, 21 Jan 2011 00:25:08 +0100
changeset 5059 00d1fef487c5
parent 5057 bdff53ed6c8b
child 5061 9e9940eae455
permissions -rw-r--r--
Fix double mouse motion in OS X

Simply ignore the event handler for Windowed mode in fullscreen.
     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];
   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];
   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 int
   402 SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
   403 {
   404     NSAutoreleasePool *pool;
   405     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   406     SDL_VideoDisplay *display = window->display;
   407     SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
   408     SDL_WindowData *data;
   409 
   410     /* Allocate the window data */
   411     data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
   412     if (!data) {
   413         SDL_OutOfMemory();
   414         return -1;
   415     }
   416     data->window = window;
   417     data->nswindow = nswindow;
   418     data->created = created;
   419     data->display = displaydata->display;
   420     data->videodata = videodata;
   421 
   422     pool = [[NSAutoreleasePool alloc] init];
   423 
   424     /* Create an event listener for the window */
   425     data->listener = [[Cocoa_WindowListener alloc] init];
   426     [data->listener listen:data];
   427 
   428     /* Fill in the SDL window with the window data */
   429     {
   430         SDL_Rect bounds;
   431         NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
   432         NSView *contentView = [[SDLView alloc] initWithFrame: rect
   433                                                     listener: data->listener];
   434 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
   435         [contentView setAcceptsTouchEvents:YES];
   436 #endif
   437         [nswindow setContentView: contentView];
   438         [contentView release];
   439 
   440         ConvertNSRect(&rect);
   441         Cocoa_GetDisplayBounds(_this, display, &bounds);
   442         window->x = (int)rect.origin.x - bounds.x;
   443         window->y = (int)rect.origin.y - bounds.y;
   444         window->w = (int)rect.size.width;
   445         window->h = (int)rect.size.height;
   446     }
   447     if ([nswindow isVisible]) {
   448         window->flags |= SDL_WINDOW_SHOWN;
   449     } else {
   450         window->flags &= ~SDL_WINDOW_SHOWN;
   451     }
   452     {
   453         unsigned int style = [nswindow styleMask];
   454 
   455         if ((style & ~NSResizableWindowMask) == NSBorderlessWindowMask) {
   456             window->flags |= SDL_WINDOW_BORDERLESS;
   457         } else {
   458             window->flags &= ~SDL_WINDOW_BORDERLESS;
   459         }
   460         if (style & NSResizableWindowMask) {
   461             window->flags |= SDL_WINDOW_RESIZABLE;
   462         } else {
   463             window->flags &= ~SDL_WINDOW_RESIZABLE;
   464         }
   465     }
   466     if ([nswindow isZoomed]) {
   467         window->flags |= SDL_WINDOW_MAXIMIZED;
   468     } else {
   469         window->flags &= ~SDL_WINDOW_MAXIMIZED;
   470     }
   471     if ([nswindow isMiniaturized]) {
   472         window->flags |= SDL_WINDOW_MINIMIZED;
   473     } else {
   474         window->flags &= ~SDL_WINDOW_MINIMIZED;
   475     }
   476     if ([nswindow isKeyWindow]) {
   477         window->flags |= SDL_WINDOW_INPUT_FOCUS;
   478         SDL_SetKeyboardFocus(data->window);
   479 
   480         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   481             /* FIXME */
   482         }
   483     }
   484 
   485     /* All done! */
   486     [pool release];
   487     window->driverdata = data;
   488     return 0;
   489 }
   490 
   491 int
   492 Cocoa_CreateWindow(_THIS, SDL_Window * window)
   493 {
   494     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   495     NSWindow *nswindow;
   496     SDL_VideoDisplay *display = window->display;
   497     NSRect rect;
   498     SDL_Rect bounds;
   499     unsigned int style;
   500 
   501     Cocoa_GetDisplayBounds(_this, display, &bounds);
   502     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   503         || window->x == SDL_WINDOWPOS_CENTERED) {
   504         rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
   505     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   506         rect.origin.x = bounds.x;
   507     } else {
   508         rect.origin.x = bounds.x + window->x;
   509     }
   510     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   511         || window->y == SDL_WINDOWPOS_CENTERED) {
   512         rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
   513     } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
   514         rect.origin.y = bounds.y;
   515     } else {
   516         rect.origin.y = bounds.y + window->y;
   517     }
   518     rect.size.width = window->w;
   519     rect.size.height = window->h;
   520     ConvertNSRect(&rect);
   521 
   522     if (window->flags & SDL_WINDOW_BORDERLESS) {
   523         style = NSBorderlessWindowMask;
   524     } else {
   525         style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
   526     }
   527     if (window->flags & SDL_WINDOW_RESIZABLE) {
   528         style |= NSResizableWindowMask;
   529     }
   530 
   531     /* Figure out which screen to place this window */
   532     NSArray *screens = [NSScreen screens];
   533     NSScreen *screen = nil;
   534     NSScreen *candidate;
   535     int i, count = [screens count];
   536     for (i = 0; i < count; ++i) {
   537         candidate = [screens objectAtIndex:i];
   538         NSRect screenRect = [candidate frame];
   539         if (rect.origin.x >= screenRect.origin.x &&
   540             rect.origin.x < screenRect.origin.x + screenRect.size.width &&
   541             rect.origin.y >= screenRect.origin.y &&
   542             rect.origin.y < screenRect.origin.y + screenRect.size.height) {
   543             screen = candidate;
   544             rect.origin.x -= screenRect.origin.x;
   545             rect.origin.y -= screenRect.origin.y;
   546         }
   547     }
   548     nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE screen:screen];
   549 
   550     [pool release];
   551 
   552     if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
   553         [nswindow release];
   554         return -1;
   555     }
   556     return 0;
   557 }
   558 
   559 int
   560 Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   561 {
   562     NSAutoreleasePool *pool;
   563     NSWindow *nswindow = (NSWindow *) data;
   564     NSString *title;
   565 
   566     pool = [[NSAutoreleasePool alloc] init];
   567 
   568     /* Query the title from the existing window */
   569     title = [nswindow title];
   570     if (title) {
   571         window->title = SDL_strdup([title UTF8String]);
   572     }
   573 
   574     [pool release];
   575 
   576     return SetupWindowData(_this, window, nswindow, SDL_FALSE);
   577 }
   578 
   579 void
   580 Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
   581 {
   582     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   583     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   584     NSString *string;
   585 
   586     if(window->title) {
   587         string = [[NSString alloc] initWithUTF8String:window->title];
   588     } else {
   589         string = [[NSString alloc] init];
   590     }
   591     [nswindow setTitle:string];
   592     [string release];
   593 
   594     [pool release];
   595 }
   596 
   597 void
   598 Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
   599 {
   600     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   601     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   602     SDL_VideoDisplay *display = window->display;
   603     NSRect rect;
   604     SDL_Rect bounds;
   605 
   606     Cocoa_GetDisplayBounds(_this, display, &bounds);
   607     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   608         || window->x == SDL_WINDOWPOS_CENTERED) {
   609         rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
   610     } else {
   611         rect.origin.x = bounds.x + window->x;
   612     }
   613     if ((window->flags & SDL_WINDOW_FULLSCREEN)
   614         || window->y == SDL_WINDOWPOS_CENTERED) {
   615         rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
   616     } else {
   617         rect.origin.y = bounds.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_SetWindowGrab(_THIS, SDL_Window * window)
   708 {
   709     if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
   710         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   711         /* FIXME: Grab mouse */
   712     } else {
   713         /* FIXME: Release mouse */
   714     }
   715 }
   716 
   717 void
   718 Cocoa_DestroyWindow(_THIS, SDL_Window * window)
   719 {
   720     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   721     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   722 
   723     if (data) {
   724         [data->listener close];
   725         [data->listener release];
   726         if (data->created) {
   727             [data->nswindow close];
   728         }
   729         SDL_free(data);
   730     }
   731     [pool release];
   732 }
   733 
   734 SDL_bool
   735 Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   736 {
   737     NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
   738 
   739     if (info->version.major <= SDL_MAJOR_VERSION) {
   740         info->subsystem = SDL_SYSWM_COCOA;
   741         info->info.cocoa.window = nswindow;
   742         return SDL_TRUE;
   743     } else {
   744         SDL_SetError("Application not compiled with SDL %d.%d\n",
   745                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   746         return SDL_FALSE;
   747     }
   748 }
   749 
   750 /* vi: set ts=4 sw=4 expandtab: */