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