SDL  2.0
SDL_cocoawindow.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_COCOA
24 
25 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
26 # error SDL for Mac OS X must be built with a 10.7 SDK or above.
27 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1070 */
28 
29 #include "SDL_syswm.h"
30 #include "SDL_timer.h" /* For SDL_GetTicks() */
31 #include "SDL_hints.h"
32 #include "../SDL_sysvideo.h"
33 #include "../../events/SDL_keyboard_c.h"
34 #include "../../events/SDL_mouse_c.h"
35 #include "../../events/SDL_touch_c.h"
36 #include "../../events/SDL_windowevents_c.h"
37 #include "../../events/SDL_dropevents_c.h"
38 #include "SDL_cocoavideo.h"
39 #include "SDL_cocoashape.h"
40 #include "SDL_cocoamouse.h"
41 #include "SDL_cocoaopengl.h"
42 #include "SDL_assert.h"
43 
44 /* #define DEBUG_COCOAWINDOW */
45 
46 #ifdef DEBUG_COCOAWINDOW
47 #define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
48 #else
49 #define DLog(...) do { } while (0)
50 #endif
51 
52 
53 #define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
54 
55 
56 @interface SDLWindow : NSWindow <NSDraggingDestination>
57 /* These are needed for borderless/fullscreen windows */
58 - (BOOL)canBecomeKeyWindow;
59 - (BOOL)canBecomeMainWindow;
60 - (void)sendEvent:(NSEvent *)event;
61 - (void)doCommandBySelector:(SEL)aSelector;
62 
63 /* Handle drag-and-drop of files onto the SDL window. */
64 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
65 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
66 - (BOOL)wantsPeriodicDraggingUpdates;
67 @end
68 
69 @implementation SDLWindow
70 
71 - (BOOL)canBecomeKeyWindow
72 {
73  return YES;
74 }
75 
76 - (BOOL)canBecomeMainWindow
77 {
78  return YES;
79 }
80 
81 - (void)sendEvent:(NSEvent *)event
82 {
83  [super sendEvent:event];
84 
85  if ([event type] != NSLeftMouseUp) {
86  return;
87  }
88 
89  id delegate = [self delegate];
90  if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
91  return;
92  }
93 
94  if ([delegate isMoving]) {
95  [delegate windowDidFinishMoving];
96  }
97 }
98 
99 /* We'll respond to selectors by doing nothing so we don't beep.
100  * The escape key gets converted to a "cancel" selector, etc.
101  */
102 - (void)doCommandBySelector:(SEL)aSelector
103 {
104  /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
105 }
106 
107 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
108 {
109  if (([sender draggingSourceOperationMask] & NSDragOperationGeneric) == NSDragOperationGeneric) {
110  return NSDragOperationGeneric;
111  }
112 
113  return NSDragOperationNone; /* no idea what to do with this, reject it. */
114 }
115 
116 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
117 { @autoreleasepool
118 {
120  NSPasteboard *pasteboard = [sender draggingPasteboard];
121  NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
122  NSString *desiredType = [pasteboard availableTypeFromArray:types];
123  SDL_Window *sdlwindow = nil;
124 
125  if (desiredType == nil) {
126  return NO; /* can't accept anything that's being dropped here. */
127  }
128 
129  NSData *data = [pasteboard dataForType:desiredType];
130  if (data == nil) {
131  return NO;
132  }
133 
134  SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
135  NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
136 
137  for (NSString *path in array) {
138  NSURL *fileURL = [NSURL fileURLWithPath:path];
139  NSNumber *isAlias = nil;
140 
141  [fileURL getResourceValue:&isAlias forKey:NSURLIsAliasFileKey error:nil];
142 
143  /* If the URL is an alias, resolve it. */
144  if ([isAlias boolValue]) {
145  NSURLBookmarkResolutionOptions opts = NSURLBookmarkResolutionWithoutMounting | NSURLBookmarkResolutionWithoutUI;
146  NSData *bookmark = [NSURL bookmarkDataWithContentsOfURL:fileURL error:nil];
147  if (bookmark != nil) {
148  NSURL *resolvedURL = [NSURL URLByResolvingBookmarkData:bookmark
149  options:opts
150  relativeToURL:nil
151  bookmarkDataIsStale:nil
152  error:nil];
153 
154  if (resolvedURL != nil) {
155  fileURL = resolvedURL;
156  }
157  }
158  }
159 
160  /* !!! FIXME: is there a better way to do this? */
161  if (_this) {
162  for (sdlwindow = _this->windows; sdlwindow; sdlwindow = sdlwindow->next) {
163  NSWindow *nswindow = ((SDL_WindowData *) sdlwindow->driverdata)->nswindow;
164  if (nswindow == self) {
165  break;
166  }
167  }
168  }
169 
170  if (!SDL_SendDropFile(sdlwindow, [[fileURL path] UTF8String])) {
171  return NO;
172  }
173  }
174 
175  SDL_SendDropComplete(sdlwindow);
176  return YES;
177 }}
178 
179 - (BOOL)wantsPeriodicDraggingUpdates
180 {
181  return NO;
182 }
183 
184 @end
185 
186 
187 static Uint32 s_moveHack;
188 
189 static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
190 {
191  r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
192 }
193 
194 static void
195 ScheduleContextUpdates(SDL_WindowData *data)
196 {
197  NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
198  NSMutableArray *contexts = data->nscontexts;
199  @synchronized (contexts) {
200  for (SDLOpenGLContext *context in contexts) {
201  if (context == currentContext) {
202  [context update];
203  } else {
204  [context scheduleUpdate];
205  }
206  }
207  }
208 }
209 
210 /* !!! FIXME: this should use a hint callback. */
211 static int
212 GetHintCtrlClickEmulateRightClick()
213 {
215 }
216 
217 static NSUInteger
218 GetWindowStyle(SDL_Window * window)
219 {
220  NSUInteger style = 0;
221 
222  if (window->flags & SDL_WINDOW_FULLSCREEN) {
223  style = NSBorderlessWindowMask;
224  } else {
225  if (window->flags & SDL_WINDOW_BORDERLESS) {
226  style = NSBorderlessWindowMask;
227  } else {
228  style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
229  }
230  if (window->flags & SDL_WINDOW_RESIZABLE) {
231  style |= NSResizableWindowMask;
232  }
233  }
234  return style;
235 }
236 
237 static SDL_bool
238 SetWindowStyle(SDL_Window * window, NSUInteger style)
239 {
240  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
241  NSWindow *nswindow = data->nswindow;
242 
243  /* The view responder chain gets messed with during setStyleMask */
244  if ([[nswindow contentView] nextResponder] == data->listener) {
245  [[nswindow contentView] setNextResponder:nil];
246  }
247 
248  [nswindow setStyleMask:style];
249 
250  /* The view responder chain gets messed with during setStyleMask */
251  if ([[nswindow contentView] nextResponder] != data->listener) {
252  [[nswindow contentView] setNextResponder:data->listener];
253  }
254 
255  return SDL_TRUE;
256 }
257 
258 
259 @implementation Cocoa_WindowListener
260 
261 - (void)listen:(SDL_WindowData *)data
262 {
263  NSNotificationCenter *center;
264  NSWindow *window = data->nswindow;
265  NSView *view = [window contentView];
266 
267  _data = data;
268  observingVisible = YES;
269  wasCtrlLeft = NO;
270  wasVisible = [window isVisible];
271  isFullscreenSpace = NO;
274  isMoving = NO;
275  isDragAreaRunning = NO;
276 
277  center = [NSNotificationCenter defaultCenter];
278 
279  if ([window delegate] != nil) {
280  [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
281  [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
282  [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
283  [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
284  [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
285  [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
286  [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
287  [center addObserver:self selector:@selector(windowDidChangeBackingProperties:) name:NSWindowDidChangeBackingPropertiesNotification object:window];
288  [center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
289  [center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
290  [center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
291  [center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
292  [center addObserver:self selector:@selector(windowDidFailToEnterFullScreen:) name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
293  [center addObserver:self selector:@selector(windowDidFailToExitFullScreen:) name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
294  } else {
295  [window setDelegate:self];
296  }
297 
298  /* Haven't found a delegate / notification that triggers when the window is
299  * ordered out (is not visible any more). You can be ordered out without
300  * minimizing, so DidMiniaturize doesn't work. (e.g. -[NSWindow orderOut:])
301  */
302  [window addObserver:self
303  forKeyPath:@"visible"
304  options:NSKeyValueObservingOptionNew
305  context:NULL];
306 
307  [window setNextResponder:self];
308  [window setAcceptsMouseMovedEvents:YES];
309 
310  [view setNextResponder:self];
311 
312  [view setAcceptsTouchEvents:YES];
313 }
314 
315 - (void)observeValueForKeyPath:(NSString *)keyPath
316  ofObject:(id)object
317  change:(NSDictionary *)change
318  context:(void *)context
319 {
320  if (!observingVisible) {
321  return;
322  }
323 
324  if (object == _data->nswindow && [keyPath isEqualToString:@"visible"]) {
325  int newVisibility = [[change objectForKey:@"new"] intValue];
326  if (newVisibility) {
328  } else {
330  }
331  }
332 }
333 
335 {
336  observingVisible = NO;
337  wasVisible = [_data->nswindow isVisible];
338 }
339 
341 {
342  BOOL isVisible = [_data->nswindow isVisible];
343  observingVisible = YES;
344  if (wasVisible != isVisible) {
345  if (isVisible) {
347  } else {
349  }
350 
351  wasVisible = isVisible;
352  }
353 }
354 
355 -(BOOL) setFullscreenSpace:(BOOL) state
356 {
357  SDL_Window *window = _data->window;
358  NSWindow *nswindow = _data->nswindow;
359  SDL_VideoData *videodata = ((SDL_WindowData *) window->driverdata)->videodata;
360 
361  if (!videodata->allow_spaces) {
362  return NO; /* Spaces are forcibly disabled. */
363  } else if (state && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP)) {
364  return NO; /* we only allow you to make a Space on FULLSCREEN_DESKTOP windows. */
366  return NO; /* we only handle leaving the Space on windows that were previously FULLSCREEN_DESKTOP. */
367  } else if (state == isFullscreenSpace) {
368  return YES; /* already there. */
369  }
370 
372  if (state) {
373  [self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
374  } else {
375  [self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
376  }
377  return YES;
378  }
380 
381  /* you need to be FullScreenPrimary, or toggleFullScreen doesn't work. Unset it again in windowDidExitFullScreen. */
382  [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
383  [nswindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject:nswindow waitUntilDone:NO];
384  return YES;
385 }
386 
387 -(BOOL) isInFullscreenSpace
388 {
389  return isFullscreenSpace;
390 }
391 
393 {
394  return inFullscreenTransition;
395 }
396 
397 -(void) addPendingWindowOperation:(PendingWindowOperation) operation
398 {
399  pendingWindowOperation = operation;
400 }
401 
402 - (void)close
403 {
404  NSNotificationCenter *center;
405  NSWindow *window = _data->nswindow;
406  NSView *view = [window contentView];
407 
408  center = [NSNotificationCenter defaultCenter];
409 
410  if ([window delegate] != self) {
411  [center removeObserver:self name:NSWindowDidExposeNotification object:window];
412  [center removeObserver:self name:NSWindowDidMoveNotification object:window];
413  [center removeObserver:self name:NSWindowDidResizeNotification object:window];
414  [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
415  [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
416  [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
417  [center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
418  [center removeObserver:self name:NSWindowDidChangeBackingPropertiesNotification object:window];
419  [center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
420  [center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
421  [center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
422  [center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
423  [center removeObserver:self name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
424  [center removeObserver:self name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
425  } else {
426  [window setDelegate:nil];
427  }
428 
429  [window removeObserver:self forKeyPath:@"visible"];
430 
431  if ([window nextResponder] == self) {
432  [window setNextResponder:nil];
433  }
434  if ([view nextResponder] == self) {
435  [view setNextResponder:nil];
436  }
437 }
438 
439 - (BOOL)isMoving
440 {
441  return isMoving;
442 }
443 
444 -(void) setPendingMoveX:(int)x Y:(int)y
445 {
448 }
449 
451 {
452  if ([self isMoving]) {
453  isMoving = NO;
454 
455  SDL_Mouse *mouse = SDL_GetMouse();
456  if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
459  }
460  if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data->window) {
462  }
463  }
464 }
465 
466 - (BOOL)windowShouldClose:(id)sender
467 {
469  return NO;
470 }
471 
472 - (void)windowDidExpose:(NSNotification *)aNotification
473 {
475 }
476 
477 - (void)windowWillMove:(NSNotification *)aNotification
478 {
479  if ([_data->nswindow isKindOfClass:[SDLWindow class]]) {
481  isMoving = YES;
482  }
483 }
484 
485 - (void)windowDidMove:(NSNotification *)aNotification
486 {
487  int x, y;
488  SDL_Window *window = _data->window;
489  NSWindow *nswindow = _data->nswindow;
490  BOOL fullscreen = window->flags & FULLSCREEN_MASK;
491  NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
492  ConvertNSRect([nswindow screen], fullscreen, &rect);
493 
494  if (s_moveHack) {
495  SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500);
496 
497  s_moveHack = 0;
498 
499  if (blockMove) {
500  /* Cocoa is adjusting the window in response to a mode change */
501  rect.origin.x = window->x;
502  rect.origin.y = window->y;
503  ConvertNSRect([nswindow screen], fullscreen, &rect);
504  [nswindow setFrameOrigin:rect.origin];
505  return;
506  }
507  }
508 
509  x = (int)rect.origin.x;
510  y = (int)rect.origin.y;
511 
512  ScheduleContextUpdates(_data);
513 
515 }
516 
517 - (void)windowDidResize:(NSNotification *)aNotification
518 {
520  /* We'll take care of this at the end of the transition */
521  return;
522  }
523 
524  SDL_Window *window = _data->window;
525  NSWindow *nswindow = _data->nswindow;
526  int x, y, w, h;
527  NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
528  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
529  x = (int)rect.origin.x;
530  y = (int)rect.origin.y;
531  w = (int)rect.size.width;
532  h = (int)rect.size.height;
533 
534  if (SDL_IsShapedWindow(window)) {
535  Cocoa_ResizeWindowShape(window);
536  }
537 
538  ScheduleContextUpdates(_data);
539 
540  /* The window can move during a resize event, such as when maximizing
541  or resizing from a corner */
544 
545  const BOOL zoomed = [nswindow isZoomed];
546  if (!zoomed) {
548  } else if (zoomed) {
550  }
551 }
552 
553 - (void)windowDidMiniaturize:(NSNotification *)aNotification
554 {
556 }
557 
558 - (void)windowDidDeminiaturize:(NSNotification *)aNotification
559 {
561 }
562 
563 - (void)windowDidBecomeKey:(NSNotification *)aNotification
564 {
565  SDL_Window *window = _data->window;
566  SDL_Mouse *mouse = SDL_GetMouse();
567 
568  /* We're going to get keyboard events, since we're key. */
569  /* This needs to be done before restoring the relative mouse mode. */
570  SDL_SetKeyboardFocus(window);
571 
572  if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMoving]) {
574  }
575 
576  /* If we just gained focus we need the updated mouse position */
577  if (!mouse->relative_mode) {
578  NSPoint point;
579  int x, y;
580 
581  point = [_data->nswindow mouseLocationOutsideOfEventStream];
582  x = (int)point.x;
583  y = (int)(window->h - point.y);
584 
585  if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
586  SDL_SendMouseMotion(window, 0, 0, x, y);
587  }
588  }
589 
590  /* Check to see if someone updated the clipboard */
592 
594  [NSMenu setMenuBarVisible:NO];
595  }
596 
597  const unsigned int newflags = [NSEvent modifierFlags] & NSAlphaShiftKeyMask;
598  _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSAlphaShiftKeyMask) | newflags;
599  SDL_ToggleModState(KMOD_CAPS, newflags != 0);
600 }
601 
602 - (void)windowDidResignKey:(NSNotification *)aNotification
603 {
604  SDL_Mouse *mouse = SDL_GetMouse();
605  if (mouse->relative_mode && !mouse->relative_mode_warp) {
607  }
608 
609  /* Some other window will get mouse events, since we're not key. */
610  if (SDL_GetMouseFocus() == _data->window) {
612  }
613 
614  /* Some other window will get keyboard events, since we're not key. */
615  if (SDL_GetKeyboardFocus() == _data->window) {
617  }
618 
619  if (isFullscreenSpace) {
620  [NSMenu setMenuBarVisible:YES];
621  }
622 }
623 
624 - (void)windowDidChangeBackingProperties:(NSNotification *)aNotification
625 {
626  NSNumber *oldscale = [[aNotification userInfo] objectForKey:NSBackingPropertyOldScaleFactorKey];
627 
629  return;
630  }
631 
632  if ([oldscale doubleValue] != [_data->nswindow backingScaleFactor]) {
633  /* Force a resize event when the backing scale factor changes. */
634  _data->window->w = 0;
635  _data->window->h = 0;
636  [self windowDidResize:aNotification];
637  }
638 }
639 
640 - (void)windowWillEnterFullScreen:(NSNotification *)aNotification
641 {
642  SDL_Window *window = _data->window;
643 
644  SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask));
645 
646  isFullscreenSpace = YES;
648 }
649 
650 - (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
651 {
652  SDL_Window *window = _data->window;
653 
654  if (window->is_destroying) {
655  return;
656  }
657 
658  SetWindowStyle(window, GetWindowStyle(window));
659 
660  isFullscreenSpace = NO;
662 
663  [self windowDidExitFullScreen:nil];
664 }
665 
666 - (void)windowDidEnterFullScreen:(NSNotification *)aNotification
667 {
668  SDL_Window *window = _data->window;
669 
671 
674  [self setFullscreenSpace:NO];
675  } else {
677  [NSMenu setMenuBarVisible:NO];
678  }
679 
681  /* Force the size change event in case it was delivered earlier
682  while the window was still animating into place.
683  */
684  window->w = 0;
685  window->h = 0;
686  [self windowDidResize:aNotification];
687  }
688 }
689 
690 - (void)windowWillExitFullScreen:(NSNotification *)aNotification
691 {
692  SDL_Window *window = _data->window;
693 
694  /* As of OS X 10.11, the window seems to need to be resizable when exiting
695  a Space, in order for it to resize back to its windowed-mode size.
696  */
697  SetWindowStyle(window, GetWindowStyle(window) | NSResizableWindowMask);
698 
699  isFullscreenSpace = NO;
701 }
702 
703 - (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
704 {
705  SDL_Window *window = _data->window;
706 
707  if (window->is_destroying) {
708  return;
709  }
710 
711  SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask));
712 
713  isFullscreenSpace = YES;
715 
716  [self windowDidEnterFullScreen:nil];
717 }
718 
719 - (void)windowDidExitFullScreen:(NSNotification *)aNotification
720 {
721  SDL_Window *window = _data->window;
722  NSWindow *nswindow = _data->nswindow;
723 
725 
726  SetWindowStyle(window, GetWindowStyle(window));
727 
728  [nswindow setLevel:kCGNormalWindowLevel];
729 
732  [self setFullscreenSpace:YES];
735  [nswindow miniaturize:nil];
736  } else {
737  /* Adjust the fullscreen toggle button and readd menu now that we're here. */
738  if (window->flags & SDL_WINDOW_RESIZABLE) {
739  /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
740  [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
741  } else {
742  [nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
743  }
744  [NSMenu setMenuBarVisible:YES];
745 
747  /* Force the size change event in case it was delivered earlier
748  while the window was still animating into place.
749  */
750  window->w = 0;
751  window->h = 0;
752  [self windowDidResize:aNotification];
753 
754  /* FIXME: Why does the window get hidden? */
755  if (window->flags & SDL_WINDOW_SHOWN) {
757  }
758  }
759 }
760 
761 -(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions
762 {
764  return NSApplicationPresentationFullScreen | NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
765  } else {
766  return proposedOptions;
767  }
768 }
769 
770 
771 /* We'll respond to key events by doing nothing so we don't beep.
772  * We could handle key messages here, but we lose some in the NSApp dispatch,
773  * where they get converted to action messages, etc.
774  */
775 - (void)flagsChanged:(NSEvent *)theEvent
776 {
777  /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
778 }
779 - (void)keyDown:(NSEvent *)theEvent
780 {
781  /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
782 }
783 - (void)keyUp:(NSEvent *)theEvent
784 {
785  /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
786 }
787 
788 /* We'll respond to selectors by doing nothing so we don't beep.
789  * The escape key gets converted to a "cancel" selector, etc.
790  */
791 - (void)doCommandBySelector:(SEL)aSelector
792 {
793  /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
794 }
795 
796 - (BOOL)processHitTest:(NSEvent *)theEvent
797 {
798  SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
799 
800  if (_data->window->hit_test) { /* if no hit-test, skip this. */
801  const NSPoint location = [theEvent locationInWindow];
802  const SDL_Point point = { (int) location.x, _data->window->h - (((int) location.y)-1) };
804  if (rc == SDL_HITTEST_DRAGGABLE) {
805  if (!isDragAreaRunning) {
806  isDragAreaRunning = YES;
807  [_data->nswindow setMovableByWindowBackground:YES];
808  }
809  return YES; /* dragging! */
810  }
811  }
812 
813  if (isDragAreaRunning) {
814  isDragAreaRunning = NO;
815  [_data->nswindow setMovableByWindowBackground:NO];
816  return YES; /* was dragging, drop event. */
817  }
818 
819  return NO; /* not a special area, carry on. */
820 }
821 
822 - (void)mouseDown:(NSEvent *)theEvent
823 {
824  int button;
825  int clicks;
826 
827  /* Ignore events that aren't inside the client area (i.e. title bar.) */
828  if ([theEvent window]) {
829  NSRect windowRect = [[[theEvent window] contentView] frame];
830  if (!NSMouseInRect([theEvent locationInWindow], windowRect, NO)) {
831  return;
832  }
833  }
834 
835  if ([self processHitTest:theEvent]) {
837  return; /* dragging, drop event. */
838  }
839 
840  switch ([theEvent buttonNumber]) {
841  case 0:
842  if (([theEvent modifierFlags] & NSControlKeyMask) &&
843  GetHintCtrlClickEmulateRightClick()) {
844  wasCtrlLeft = YES;
845  button = SDL_BUTTON_RIGHT;
846  } else {
847  wasCtrlLeft = NO;
848  button = SDL_BUTTON_LEFT;
849  }
850  break;
851  case 1:
852  button = SDL_BUTTON_RIGHT;
853  break;
854  case 2:
855  button = SDL_BUTTON_MIDDLE;
856  break;
857  default:
858  button = (int) [theEvent buttonNumber] + 1;
859  break;
860  }
861 
862  clicks = (int) [theEvent clickCount];
863  SDL_SendMouseButtonClicks(_data->window, 0, SDL_PRESSED, button, clicks);
864 }
865 
866 - (void)rightMouseDown:(NSEvent *)theEvent
867 {
868  [self mouseDown:theEvent];
869 }
870 
871 - (void)otherMouseDown:(NSEvent *)theEvent
872 {
873  [self mouseDown:theEvent];
874 }
875 
876 - (void)mouseUp:(NSEvent *)theEvent
877 {
878  int button;
879  int clicks;
880 
881  if ([self processHitTest:theEvent]) {
883  return; /* stopped dragging, drop event. */
884  }
885 
886  switch ([theEvent buttonNumber]) {
887  case 0:
888  if (wasCtrlLeft) {
889  button = SDL_BUTTON_RIGHT;
890  wasCtrlLeft = NO;
891  } else {
892  button = SDL_BUTTON_LEFT;
893  }
894  break;
895  case 1:
896  button = SDL_BUTTON_RIGHT;
897  break;
898  case 2:
899  button = SDL_BUTTON_MIDDLE;
900  break;
901  default:
902  button = (int) [theEvent buttonNumber] + 1;
903  break;
904  }
905 
906  clicks = (int) [theEvent clickCount];
907  SDL_SendMouseButtonClicks(_data->window, 0, SDL_RELEASED, button, clicks);
908 }
909 
910 - (void)rightMouseUp:(NSEvent *)theEvent
911 {
912  [self mouseUp:theEvent];
913 }
914 
915 - (void)otherMouseUp:(NSEvent *)theEvent
916 {
917  [self mouseUp:theEvent];
918 }
919 
920 - (void)mouseMoved:(NSEvent *)theEvent
921 {
922  SDL_Mouse *mouse = SDL_GetMouse();
923  SDL_Window *window = _data->window;
924  NSPoint point;
925  int x, y;
926 
927  if ([self processHitTest:theEvent]) {
929  return; /* dragging, drop event. */
930  }
931 
932  if (mouse->relative_mode) {
933  return;
934  }
935 
936  point = [theEvent locationInWindow];
937  x = (int)point.x;
938  y = (int)(window->h - point.y);
939 
940  if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
941  if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
942  if (x < 0) {
943  x = 0;
944  } else if (x >= window->w) {
945  x = window->w - 1;
946  }
947  if (y < 0) {
948  y = 0;
949  } else if (y >= window->h) {
950  y = window->h - 1;
951  }
952 
953 #if !SDL_MAC_NO_SANDBOX
954  CGPoint cgpoint;
955 
956  /* When SDL_MAC_NO_SANDBOX is set, this is handled by
957  * SDL_cocoamousetap.m.
958  */
959 
960  cgpoint.x = window->x + x;
961  cgpoint.y = window->y + y;
962 
963  CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
964  CGAssociateMouseAndMouseCursorPosition(YES);
965 
966  Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
967 #endif
968  }
969  }
970  SDL_SendMouseMotion(window, 0, 0, x, y);
971 }
972 
973 - (void)mouseDragged:(NSEvent *)theEvent
974 {
975  [self mouseMoved:theEvent];
976 }
977 
978 - (void)rightMouseDragged:(NSEvent *)theEvent
979 {
980  [self mouseMoved:theEvent];
981 }
982 
983 - (void)otherMouseDragged:(NSEvent *)theEvent
984 {
985  [self mouseMoved:theEvent];
986 }
987 
988 - (void)scrollWheel:(NSEvent *)theEvent
989 {
990  Cocoa_HandleMouseWheel(_data->window, theEvent);
991 }
992 
993 - (void)touchesBeganWithEvent:(NSEvent *) theEvent
994 {
995  NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
996  int existingTouchCount = 0;
997 
998  for (NSTouch* touch in touches) {
999  if ([touch phase] != NSTouchPhaseBegan) {
1000  existingTouchCount++;
1001  }
1002  }
1003  if (existingTouchCount == 0) {
1004  SDL_TouchID touchID = (SDL_TouchID)(intptr_t)[[touches anyObject] device];
1005  int numFingers = SDL_GetNumTouchFingers(touchID);
1006  DLog("Reset Lost Fingers: %d", numFingers);
1007  for (--numFingers; numFingers >= 0; --numFingers) {
1008  SDL_Finger* finger = SDL_GetTouchFinger(touchID, numFingers);
1009  SDL_SendTouch(touchID, finger->id, SDL_FALSE, 0, 0, 0);
1010  }
1011  }
1012 
1013  DLog("Began Fingers: %lu .. existing: %d", (unsigned long)[touches count], existingTouchCount);
1014  [self handleTouches:NSTouchPhaseBegan withEvent:theEvent];
1015 }
1016 
1017 - (void)touchesMovedWithEvent:(NSEvent *) theEvent
1018 {
1019  [self handleTouches:NSTouchPhaseMoved withEvent:theEvent];
1020 }
1021 
1022 - (void)touchesEndedWithEvent:(NSEvent *) theEvent
1023 {
1024  [self handleTouches:NSTouchPhaseEnded withEvent:theEvent];
1025 }
1026 
1027 - (void)touchesCancelledWithEvent:(NSEvent *) theEvent
1028 {
1029  [self handleTouches:NSTouchPhaseCancelled withEvent:theEvent];
1030 }
1031 
1032 - (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
1033 {
1034  NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
1035 
1036  for (NSTouch *touch in touches) {
1037  const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
1038  if (SDL_AddTouch(touchId, "") < 0) {
1039  return;
1040  }
1041 
1042  const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
1043  float x = [touch normalizedPosition].x;
1044  float y = [touch normalizedPosition].y;
1045  /* Make the origin the upper left instead of the lower left */
1046  y = 1.0f - y;
1047 
1048  switch (phase) {
1049  case NSTouchPhaseBegan:
1050  SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
1051  break;
1052  case NSTouchPhaseEnded:
1053  case NSTouchPhaseCancelled:
1054  SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
1055  break;
1056  case NSTouchPhaseMoved:
1057  SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
1058  break;
1059  default:
1060  break;
1061  }
1062  }
1063 }
1064 
1065 @end
1066 
1067 @interface SDLView : NSView {
1068  SDL_Window *_sdlWindow;
1069 }
1070 
1071 - (void)setSDLWindow:(SDL_Window*)window;
1072 
1073 /* The default implementation doesn't pass rightMouseDown to responder chain */
1074 - (void)rightMouseDown:(NSEvent *)theEvent;
1075 - (BOOL)mouseDownCanMoveWindow;
1076 - (void)drawRect:(NSRect)dirtyRect;
1077 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
1078 @end
1079 
1080 @implementation SDLView
1081 - (void)setSDLWindow:(SDL_Window*)window
1082 {
1083  _sdlWindow = window;
1084 }
1085 
1086 - (void)drawRect:(NSRect)dirtyRect
1087 {
1088  SDL_SendWindowEvent(_sdlWindow, SDL_WINDOWEVENT_EXPOSED, 0, 0);
1089 }
1090 
1091 - (void)rightMouseDown:(NSEvent *)theEvent
1092 {
1093  [[self nextResponder] rightMouseDown:theEvent];
1094 }
1095 
1096 - (BOOL)mouseDownCanMoveWindow
1097 {
1098  /* Always say YES, but this doesn't do anything until we call
1099  -[NSWindow setMovableByWindowBackground:YES], which we ninja-toggle
1100  during mouse events when we're using a drag area. */
1101  return YES;
1102 }
1103 
1104 - (void)resetCursorRects
1105 {
1106  [super resetCursorRects];
1107  SDL_Mouse *mouse = SDL_GetMouse();
1108 
1109  if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
1110  [self addCursorRect:[self bounds]
1111  cursor:mouse->cur_cursor->driverdata];
1112  } else {
1113  [self addCursorRect:[self bounds]
1114  cursor:[NSCursor invisibleCursor]];
1115  }
1116 }
1117 
1118 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
1119 {
1122  } else {
1123  return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", SDL_FALSE);
1124  }
1125 }
1126 @end
1127 
1128 static int
1129 SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
1130 { @autoreleasepool
1131 {
1132  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1133  SDL_WindowData *data;
1134 
1135  /* Allocate the window data */
1136  window->driverdata = data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
1137  if (!data) {
1138  return SDL_OutOfMemory();
1139  }
1140  data->window = window;
1141  data->nswindow = nswindow;
1142  data->created = created;
1143  data->videodata = videodata;
1144  data->nscontexts = [[NSMutableArray alloc] init];
1145 
1146  /* Create an event listener for the window */
1147  data->listener = [[Cocoa_WindowListener alloc] init];
1148 
1149  /* Fill in the SDL window with the window data */
1150  {
1151  NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
1152  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1153  window->x = (int)rect.origin.x;
1154  window->y = (int)rect.origin.y;
1155  window->w = (int)rect.size.width;
1156  window->h = (int)rect.size.height;
1157  }
1158 
1159  /* Set up the listener after we create the view */
1160  [data->listener listen:data];
1161 
1162  if ([nswindow isVisible]) {
1163  window->flags |= SDL_WINDOW_SHOWN;
1164  } else {
1165  window->flags &= ~SDL_WINDOW_SHOWN;
1166  }
1167 
1168  {
1169  unsigned long style = [nswindow styleMask];
1170 
1171  if (style == NSBorderlessWindowMask) {
1172  window->flags |= SDL_WINDOW_BORDERLESS;
1173  } else {
1174  window->flags &= ~SDL_WINDOW_BORDERLESS;
1175  }
1176  if (style & NSResizableWindowMask) {
1177  window->flags |= SDL_WINDOW_RESIZABLE;
1178  } else {
1179  window->flags &= ~SDL_WINDOW_RESIZABLE;
1180  }
1181  }
1182 
1183  /* isZoomed always returns true if the window is not resizable */
1184  if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
1185  window->flags |= SDL_WINDOW_MAXIMIZED;
1186  } else {
1187  window->flags &= ~SDL_WINDOW_MAXIMIZED;
1188  }
1189 
1190  if ([nswindow isMiniaturized]) {
1191  window->flags |= SDL_WINDOW_MINIMIZED;
1192  } else {
1193  window->flags &= ~SDL_WINDOW_MINIMIZED;
1194  }
1195 
1196  if ([nswindow isKeyWindow]) {
1197  window->flags |= SDL_WINDOW_INPUT_FOCUS;
1199  }
1200 
1201  /* Prevents the window's "window device" from being destroyed when it is
1202  * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
1203  */
1204  [nswindow setOneShot:NO];
1205 
1206  /* All done! */
1207  window->driverdata = data;
1208  return 0;
1209 }}
1210 
1211 int
1213 { @autoreleasepool
1214 {
1215  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1216  NSWindow *nswindow;
1217  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1218  NSRect rect;
1219  SDL_Rect bounds;
1220  NSUInteger style;
1221  NSArray *screens = [NSScreen screens];
1222 
1223  Cocoa_GetDisplayBounds(_this, display, &bounds);
1224  rect.origin.x = window->x;
1225  rect.origin.y = window->y;
1226  rect.size.width = window->w;
1227  rect.size.height = window->h;
1228  ConvertNSRect([screens objectAtIndex:0], (window->flags & FULLSCREEN_MASK), &rect);
1229 
1230  style = GetWindowStyle(window);
1231 
1232  /* Figure out which screen to place this window */
1233  NSScreen *screen = nil;
1234  for (NSScreen *candidate in screens) {
1235  NSRect screenRect = [candidate frame];
1236  if (rect.origin.x >= screenRect.origin.x &&
1237  rect.origin.x < screenRect.origin.x + screenRect.size.width &&
1238  rect.origin.y >= screenRect.origin.y &&
1239  rect.origin.y < screenRect.origin.y + screenRect.size.height) {
1240  screen = candidate;
1241  rect.origin.x -= screenRect.origin.x;
1242  rect.origin.y -= screenRect.origin.y;
1243  }
1244  }
1245 
1246  @try {
1247  nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen];
1248  }
1249  @catch (NSException *e) {
1250  return SDL_SetError("%s", [[e reason] UTF8String]);
1251  }
1252  [nswindow setBackgroundColor:[NSColor blackColor]];
1253 
1254  if (videodata->allow_spaces) {
1255  SDL_assert(floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6);
1256  SDL_assert([nswindow respondsToSelector:@selector(toggleFullScreen:)]);
1257  /* we put FULLSCREEN_DESKTOP windows in their own Space, without a toggle button or menubar, later */
1258  if (window->flags & SDL_WINDOW_RESIZABLE) {
1259  /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
1260  [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
1261  }
1262  }
1263 
1264  /* Create a default view for this window */
1265  rect = [nswindow contentRectForFrameRect:[nswindow frame]];
1266  SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
1267  [contentView setSDLWindow:window];
1268 
1269  if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
1270  if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
1271  [contentView setWantsBestResolutionOpenGLSurface:YES];
1272  }
1273  }
1274 
1275  [nswindow setContentView:contentView];
1276  [contentView release];
1277 
1278  /* Allow files and folders to be dragged onto the window by users */
1279  [nswindow registerForDraggedTypes:[NSArray arrayWithObject:(NSString *)kUTTypeFileURL]];
1280 
1281  if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
1282  [nswindow release];
1283  return -1;
1284  }
1285  return 0;
1286 }}
1287 
1288 int
1289 Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
1290 { @autoreleasepool
1291 {
1292  NSWindow *nswindow = (NSWindow *) data;
1293  NSString *title;
1294 
1295  /* Query the title from the existing window */
1296  title = [nswindow title];
1297  if (title) {
1298  window->title = SDL_strdup([title UTF8String]);
1299  }
1300 
1301  return SetupWindowData(_this, window, nswindow, SDL_FALSE);
1302 }}
1303 
1304 void
1306 { @autoreleasepool
1307 {
1308  const char *title = window->title ? window->title : "";
1309  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1310  NSString *string = [[NSString alloc] initWithUTF8String:title];
1311  [nswindow setTitle:string];
1312  [string release];
1313 }}
1314 
1315 void
1317 { @autoreleasepool
1318 {
1319  NSImage *nsimage = Cocoa_CreateImage(icon);
1320 
1321  if (nsimage) {
1322  [NSApp setApplicationIconImage:nsimage];
1323  }
1324 }}
1325 
1326 void
1328 { @autoreleasepool
1329 {
1330  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1331  NSWindow *nswindow = windata->nswindow;
1332  NSRect rect;
1333  Uint32 moveHack;
1334 
1335  rect.origin.x = window->x;
1336  rect.origin.y = window->y;
1337  rect.size.width = window->w;
1338  rect.size.height = window->h;
1339  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1340 
1341  moveHack = s_moveHack;
1342  s_moveHack = 0;
1343  [nswindow setFrameOrigin:rect.origin];
1344  s_moveHack = moveHack;
1345 
1346  ScheduleContextUpdates(windata);
1347 }}
1348 
1349 void
1351 { @autoreleasepool
1352 {
1353  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1354  NSWindow *nswindow = windata->nswindow;
1355  NSRect rect;
1356  Uint32 moveHack;
1357 
1358  /* Cocoa will resize the window from the bottom-left rather than the
1359  * top-left when -[nswindow setContentSize:] is used, so we must set the
1360  * entire frame based on the new size, in order to preserve the position.
1361  */
1362  rect.origin.x = window->x;
1363  rect.origin.y = window->y;
1364  rect.size.width = window->w;
1365  rect.size.height = window->h;
1366  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1367 
1368  moveHack = s_moveHack;
1369  s_moveHack = 0;
1370  [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES];
1371  s_moveHack = moveHack;
1372 
1373  ScheduleContextUpdates(windata);
1374 }}
1375 
1376 void
1378 { @autoreleasepool
1379 {
1380  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1381 
1382  NSSize minSize;
1383  minSize.width = window->min_w;
1384  minSize.height = window->min_h;
1385 
1386  [windata->nswindow setContentMinSize:minSize];
1387 }}
1388 
1389 void
1391 { @autoreleasepool
1392 {
1393  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1394 
1395  NSSize maxSize;
1396  maxSize.width = window->max_w;
1397  maxSize.height = window->max_h;
1398 
1399  [windata->nswindow setContentMaxSize:maxSize];
1400 }}
1401 
1402 void
1404 { @autoreleasepool
1405 {
1406  SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
1407  NSWindow *nswindow = windowData->nswindow;
1408 
1409  if (![nswindow isMiniaturized]) {
1410  [windowData->listener pauseVisibleObservation];
1411  [nswindow makeKeyAndOrderFront:nil];
1412  [windowData->listener resumeVisibleObservation];
1413  }
1414 }}
1415 
1416 void
1418 { @autoreleasepool
1419 {
1420  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1421 
1422  [nswindow orderOut:nil];
1423 }}
1424 
1425 void
1427 { @autoreleasepool
1428 {
1429  SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
1430  NSWindow *nswindow = windowData->nswindow;
1431 
1432  /* makeKeyAndOrderFront: has the side-effect of deminiaturizing and showing
1433  a minimized or hidden window, so check for that before showing it.
1434  */
1435  [windowData->listener pauseVisibleObservation];
1436  if (![nswindow isMiniaturized] && [nswindow isVisible]) {
1437  [NSApp activateIgnoringOtherApps:YES];
1438  [nswindow makeKeyAndOrderFront:nil];
1439  }
1440  [windowData->listener resumeVisibleObservation];
1441 }}
1442 
1443 void
1445 { @autoreleasepool
1446 {
1447  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1448  NSWindow *nswindow = windata->nswindow;
1449 
1450  [nswindow zoom:nil];
1451 
1452  ScheduleContextUpdates(windata);
1453 }}
1454 
1455 void
1457 { @autoreleasepool
1458 {
1459  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1460  NSWindow *nswindow = data->nswindow;
1461 
1462  if ([data->listener isInFullscreenSpaceTransition]) {
1463  [data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
1464  } else {
1465  [nswindow miniaturize:nil];
1466  }
1467 }}
1468 
1469 void
1471 { @autoreleasepool
1472 {
1473  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1474 
1475  if ([nswindow isMiniaturized]) {
1476  [nswindow deminiaturize:nil];
1477  } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
1478  [nswindow zoom:nil];
1479  }
1480 }}
1481 
1482 void
1483 Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
1484 { @autoreleasepool
1485 {
1486  if (SetWindowStyle(window, GetWindowStyle(window))) {
1487  if (bordered) {
1488  Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */
1489  }
1490  }
1491 }}
1492 
1493 void
1494 Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
1495 { @autoreleasepool
1496 {
1497  /* Don't set this if we're in a space!
1498  * The window will get permanently stuck if resizable is false.
1499  * -flibit
1500  */
1501  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1502  Cocoa_WindowListener *listener = data->listener;
1503  if (![listener isInFullscreenSpace]) {
1504  SetWindowStyle(window, GetWindowStyle(window));
1505  }
1506 }}
1507 
1508 void
1509 Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
1510 { @autoreleasepool
1511 {
1512  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1513  NSWindow *nswindow = data->nswindow;
1514  NSRect rect;
1515 
1516  /* The view responder chain gets messed with during setStyleMask */
1517  if ([[nswindow contentView] nextResponder] == data->listener) {
1518  [[nswindow contentView] setNextResponder:nil];
1519  }
1520 
1521  if (fullscreen) {
1522  SDL_Rect bounds;
1523 
1524  Cocoa_GetDisplayBounds(_this, display, &bounds);
1525  rect.origin.x = bounds.x;
1526  rect.origin.y = bounds.y;
1527  rect.size.width = bounds.w;
1528  rect.size.height = bounds.h;
1529  ConvertNSRect([nswindow screen], fullscreen, &rect);
1530 
1531  /* Hack to fix origin on Mac OS X 10.4 */
1532  NSRect screenRect = [[nswindow screen] frame];
1533  if (screenRect.size.height >= 1.0f) {
1534  rect.origin.y += (screenRect.size.height - rect.size.height);
1535  }
1536 
1537  [nswindow setStyleMask:NSBorderlessWindowMask];
1538  } else {
1539  rect.origin.x = window->windowed.x;
1540  rect.origin.y = window->windowed.y;
1541  rect.size.width = window->windowed.w;
1542  rect.size.height = window->windowed.h;
1543  ConvertNSRect([nswindow screen], fullscreen, &rect);
1544 
1545  [nswindow setStyleMask:GetWindowStyle(window)];
1546 
1547  /* Hack to restore window decorations on Mac OS X 10.10 */
1548  NSRect frameRect = [nswindow frame];
1549  [nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
1550  [nswindow setFrame:frameRect display:NO];
1551  }
1552 
1553  /* The view responder chain gets messed with during setStyleMask */
1554  if ([[nswindow contentView] nextResponder] != data->listener) {
1555  [[nswindow contentView] setNextResponder:data->listener];
1556  }
1557 
1558  s_moveHack = 0;
1559  [nswindow setContentSize:rect.size];
1560  [nswindow setFrameOrigin:rect.origin];
1561  s_moveHack = SDL_GetTicks();
1562 
1563  /* When the window style changes the title is cleared */
1564  if (!fullscreen) {
1565  Cocoa_SetWindowTitle(_this, window);
1566  }
1567 
1568  if (SDL_ShouldAllowTopmost() && fullscreen) {
1569  /* OpenGL is rendering to the window, so make it visible! */
1570  [nswindow setLevel:CGShieldingWindowLevel()];
1571  } else {
1572  [nswindow setLevel:kCGNormalWindowLevel];
1573  }
1574 
1575  if ([nswindow isVisible] || fullscreen) {
1576  [data->listener pauseVisibleObservation];
1577  [nswindow makeKeyAndOrderFront:nil];
1578  [data->listener resumeVisibleObservation];
1579  }
1580 
1581  ScheduleContextUpdates(data);
1582 }}
1583 
1584 int
1585 Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
1586 {
1587  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1588  CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
1589  const uint32_t tableSize = 256;
1590  CGGammaValue redTable[tableSize];
1591  CGGammaValue greenTable[tableSize];
1592  CGGammaValue blueTable[tableSize];
1593  uint32_t i;
1594  float inv65535 = 1.0f / 65535.0f;
1595 
1596  /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
1597  for (i = 0; i < 256; i++) {
1598  redTable[i] = ramp[0*256+i] * inv65535;
1599  greenTable[i] = ramp[1*256+i] * inv65535;
1600  blueTable[i] = ramp[2*256+i] * inv65535;
1601  }
1602 
1603  if (CGSetDisplayTransferByTable(display_id, tableSize,
1604  redTable, greenTable, blueTable) != CGDisplayNoErr) {
1605  return SDL_SetError("CGSetDisplayTransferByTable()");
1606  }
1607  return 0;
1608 }
1609 
1610 int
1612 {
1613  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1614  CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
1615  const uint32_t tableSize = 256;
1616  CGGammaValue redTable[tableSize];
1617  CGGammaValue greenTable[tableSize];
1618  CGGammaValue blueTable[tableSize];
1619  uint32_t i, tableCopied;
1620 
1621  if (CGGetDisplayTransferByTable(display_id, tableSize,
1622  redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
1623  return SDL_SetError("CGGetDisplayTransferByTable()");
1624  }
1625 
1626  for (i = 0; i < tableCopied; i++) {
1627  ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
1628  ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
1629  ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
1630  }
1631  return 0;
1632 }
1633 
1634 void
1635 Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
1636 {
1637  /* Move the cursor to the nearest point in the window */
1638  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1639  if (grabbed && data && ![data->listener isMoving]) {
1640  int x, y;
1641  CGPoint cgpoint;
1642 
1643  SDL_GetMouseState(&x, &y);
1644  cgpoint.x = window->x + x;
1645  cgpoint.y = window->y + y;
1646 
1647  Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
1648 
1649  DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
1650  CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
1651  }
1652 
1653  if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
1655  && ![data->listener isInFullscreenSpace]) {
1656  /* OpenGL is rendering to the window, so make it visible! */
1657  /* Doing this in 10.11 while in a Space breaks things (bug #3152) */
1658  [data->nswindow setLevel:CGShieldingWindowLevel()];
1659  } else {
1660  [data->nswindow setLevel:kCGNormalWindowLevel];
1661  }
1662  }
1663 }
1664 
1665 void
1667 { @autoreleasepool
1668 {
1669  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1670 
1671  if (data) {
1672  if ([data->listener isInFullscreenSpace]) {
1673  [NSMenu setMenuBarVisible:YES];
1674  }
1675  [data->listener close];
1676  [data->listener release];
1677  if (data->created) {
1678  [data->nswindow close];
1679  }
1680 
1681  NSArray *contexts = [[data->nscontexts copy] autorelease];
1682  for (SDLOpenGLContext *context in contexts) {
1683  /* Calling setWindow:NULL causes the context to remove itself from the context list. */
1684  [context setWindow:NULL];
1685  }
1686  [data->nscontexts release];
1687 
1688  SDL_free(data);
1689  }
1690  window->driverdata = NULL;
1691 }}
1692 
1693 SDL_bool
1695 {
1696  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1697 
1698  if (info->version.major <= SDL_MAJOR_VERSION) {
1699  info->subsystem = SDL_SYSWM_COCOA;
1700  info->info.cocoa.window = nswindow;
1701  return SDL_TRUE;
1702  } else {
1703  SDL_SetError("Application not compiled with SDL %d.%d\n",
1705  return SDL_FALSE;
1706  }
1707 }
1708 
1709 SDL_bool
1710 Cocoa_IsWindowInFullscreenSpace(SDL_Window * window)
1711 {
1712  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1713 
1714  if ([data->listener isInFullscreenSpace]) {
1715  return SDL_TRUE;
1716  } else {
1717  return SDL_FALSE;
1718  }
1719 }
1720 
1721 SDL_bool
1722 Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
1723 { @autoreleasepool
1724 {
1725  SDL_bool succeeded = SDL_FALSE;
1726  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1727 
1728  if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
1729  const int maxattempts = 3;
1730  int attempt = 0;
1731  while (++attempt <= maxattempts) {
1732  /* Wait for the transition to complete, so application changes
1733  take effect properly (e.g. setting the window size, etc.)
1734  */
1735  const int limit = 10000;
1736  int count = 0;
1737  while ([data->listener isInFullscreenSpaceTransition]) {
1738  if ( ++count == limit ) {
1739  /* Uh oh, transition isn't completing. Should we assert? */
1740  break;
1741  }
1742  SDL_Delay(1);
1743  SDL_PumpEvents();
1744  }
1745  if ([data->listener isInFullscreenSpace] == (state ? YES : NO))
1746  break;
1747  /* Try again, the last attempt was interrupted by user gestures */
1748  if (![data->listener setFullscreenSpace:(state ? YES : NO)])
1749  break; /* ??? */
1750  }
1751  /* Return TRUE to prevent non-space fullscreen logic from running */
1752  succeeded = SDL_TRUE;
1753  }
1754 
1755  return succeeded;
1756 }}
1757 
1758 int
1760 {
1761  return 0; /* just succeed, the real work is done elsewhere. */
1762 }
1763 
1764 int
1765 Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
1766 {
1767  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1768  [data->nswindow setAlphaValue:opacity];
1769  return 0;
1770 }
1771 
1772 #endif /* SDL_VIDEO_DRIVER_COCOA */
1773 
1774 /* vi: set ts=4 sw=4 expandtab: */
SDL_Window * next
Definition: SDL_sysvideo.h:112
int Cocoa_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
GLint limit
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:66
NSMutableArray * nscontexts
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2072
#define SDL_IsShapedWindow
SDL_Texture * button
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
void Cocoa_MinimizeWindow(_THIS, SDL_Window *window)
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
void * hit_test_data
Definition: SDL_sysvideo.h:105
void Cocoa_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
SDL_bool relative_mode_warp
Definition: SDL_mouse_c.h:85
void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window *window)
SDL_Window * focus
Definition: SDL_mouse_c.h:77
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
SDL_Rect rect
Definition: testrelative.c:27
int(* SetRelativeMouseMode)(SDL_bool enabled)
Definition: SDL_mouse_c.h:67
int SDL_SendDropFile(SDL_Window *window, const char *file)
void Cocoa_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
static SDL_Window * window
void Cocoa_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
#define SDL_BUTTON_RIGHT
Definition: SDL_mouse.h:284
#define SDL_GetTouchFinger
The structure that defines a point.
Definition: SDL_rect.h:48
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
#define SDL_GetHint
int SDL_SendMouseButtonClicks(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:407
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:216
SDL_version version
Definition: SDL_syswm.h:195
Uint8 major
Definition: SDL_version.h:53
GLfloat f
SDL_bool is_destroying
Definition: SDL_sysvideo.h:99
#define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK
A variable that determines whether ctrl+click should generate a right-click event on Mac...
Definition: SDL_hints.h:426
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:196
void Cocoa_SetWindowTitle(_THIS, SDL_Window *window)
GLsizei GLenum GLenum * types
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
SDL_Window * window
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
#define SDL_GetKeyboardFocus
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1565
void Cocoa_SetWindowPosition(_THIS, SDL_Window *window)
unsigned int modifierFlags
SDL_Rect windowed
Definition: SDL_sysvideo.h:85
GLsizeiptr size
int SDL_SendDropComplete(SDL_Window *window)
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:278
#define SDL_GetHintBoolean
#define SDL_PumpEvents
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:967
void Cocoa_RestoreWindow(_THIS, SDL_Window *window)
int x
Definition: SDL_rect.h:50
BOOL isInFullscreenSpaceTransition()
void Cocoa_ShowWindow(_THIS, SDL_Window *window)
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
void * SDL_calloc(size_t nmemb, size_t size)
NSImage * Cocoa_CreateImage(SDL_Surface *surface)
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:188
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
Cocoa_WindowListener * listener
#define _THIS
struct SDL_VideoData * videodata
struct _cl_event * event
void SDL_free(void *mem)
int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
void Cocoa_DestroyWindow(_THIS, SDL_Window *window)
GLint location
void Cocoa_RaiseWindow(_THIS, SDL_Window *window)
SDL_bool cursor_shown
Definition: SDL_mouse_c.h:94
SDL_bool relative_mode
Definition: SDL_mouse_c.h:84
SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void Cocoa_CheckClipboardUpdate(struct SDL_VideoData *data)
SDL_WindowData * _data
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:283
PendingWindowOperation
char * title
Definition: SDL_sysvideo.h:75
#define SDL_GetNumTouchFingers
int x
Definition: SDL_rect.h:66
int Cocoa_SetWindowOpacity(_THIS, SDL_Window *window, float opacity)
SDL_Window * windows
Definition: SDL_sysvideo.h:294
int SDL_AddTouch(SDL_TouchID touchID, const char *name)
Definition: SDL_touch.c:130
int w
Definition: SDL_rect.h:67
void Cocoa_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
int(* WarpMouseGlobal)(int x, int y)
Definition: SDL_mouse_c.h:64
NSWindow * nswindow
#define SDL_Delay
GLenum GLenum GLsizei const GLuint GLboolean enabled
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:850
#define SDL_assert(condition)
Definition: SDL_assert.h:167
PendingWindowOperation pendingWindowOperation
Window window
Definition: SDL_syswm.h:216
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3761
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
#define SDL_GetMouseFocus
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:104
unsigned int uint32_t
Uint32 last_fullscreen_flags
Definition: SDL_sysvideo.h:82
#define SDL_SetError
int Cocoa_CreateWindow(_THIS, SDL_Window *window)
int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1058
int h
Definition: SDL_rect.h:67
#define SDL_strdup
The type used to identify a window.
Definition: SDL_sysvideo.h:71
void Cocoa_SetWindowSize(_THIS, SDL_Window *window)
int Cocoa_ResizeWindowShape(SDL_Window *window)
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:151
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:571
union SDL_SysWMinfo::@18 info
GLenum array
SDL_FingerID id
Definition: SDL_touch.h:46
GLsizei const GLchar *const * path
GLubyte GLubyte GLubyte GLubyte w
void Cocoa_HideWindow(_THIS, SDL_Window *window)
int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
void * driverdata
Definition: SDL_sysvideo.h:109
#define FULLSCREEN_MASK
Definition: SDL_video.c:142
void Cocoa_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
#define SDL_PRESSED
Definition: SDL_events.h:50
SDL_Cursor * cur_cursor
Definition: SDL_mouse_c.h:93
Uint32 flags
Definition: SDL_sysvideo.h:81
#define SDL_RELEASED
Definition: SDL_events.h:49
GLuint in
#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
Allow mouse click events when clicking to focus an SDL window.
Definition: SDL_hints.h:255
SDL_Renderer * screen
#define floor
Definition: math_private.h:37
int y
Definition: SDL_rect.h:66
#define SDL_GetMouseState
GLfloat GLfloat GLfloat GLfloat h
void Cocoa_MaximizeWindow(_THIS, SDL_Window *window)
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window *window)