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