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