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();
486  if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
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 @end
1147 
1148 @implementation SDLView
1149 - (void)setSDLWindow:(SDL_Window*)window
1150 {
1151  _sdlWindow = window;
1152 }
1153 
1154 - (void)drawRect:(NSRect)dirtyRect
1155 {
1156  /* Force the graphics context to clear to black so we don't get a flash of
1157  white until the app is ready to draw. In practice on modern macOS, this
1158  only gets called for window creation and other extraordinary events. */
1159  [[NSColor blackColor] setFill];
1160  NSRectFill(dirtyRect);
1161  SDL_SendWindowEvent(_sdlWindow, SDL_WINDOWEVENT_EXPOSED, 0, 0);
1162 }
1163 
1164 - (void)rightMouseDown:(NSEvent *)theEvent
1165 {
1166  [[self nextResponder] rightMouseDown:theEvent];
1167 }
1168 
1169 - (BOOL)mouseDownCanMoveWindow
1170 {
1171  /* Always say YES, but this doesn't do anything until we call
1172  -[NSWindow setMovableByWindowBackground:YES], which we ninja-toggle
1173  during mouse events when we're using a drag area. */
1174  return YES;
1175 }
1176 
1177 - (void)resetCursorRects
1178 {
1179  [super resetCursorRects];
1180  SDL_Mouse *mouse = SDL_GetMouse();
1181 
1182  if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
1183  [self addCursorRect:[self bounds]
1184  cursor:mouse->cur_cursor->driverdata];
1185  } else {
1186  [self addCursorRect:[self bounds]
1187  cursor:[NSCursor invisibleCursor]];
1188  }
1189 }
1190 
1191 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
1192 {
1195  } else {
1196  return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", SDL_FALSE);
1197  }
1198 }
1199 @end
1200 
1201 static int
1202 SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
1203 { @autoreleasepool
1204 {
1205  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1206  SDL_WindowData *data;
1207 
1208  /* Allocate the window data */
1209  window->driverdata = data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
1210  if (!data) {
1211  return SDL_OutOfMemory();
1212  }
1213  data->window = window;
1214  data->nswindow = nswindow;
1215  data->created = created;
1216  data->videodata = videodata;
1217  data->nscontexts = [[NSMutableArray alloc] init];
1218 
1219  /* Create an event listener for the window */
1220  data->listener = [[Cocoa_WindowListener alloc] init];
1221 
1222  /* Fill in the SDL window with the window data */
1223  {
1224  NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
1225  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1226  window->x = (int)rect.origin.x;
1227  window->y = (int)rect.origin.y;
1228  window->w = (int)rect.size.width;
1229  window->h = (int)rect.size.height;
1230  }
1231 
1232  /* Set up the listener after we create the view */
1233  [data->listener listen:data];
1234 
1235  if ([nswindow isVisible]) {
1236  window->flags |= SDL_WINDOW_SHOWN;
1237  } else {
1238  window->flags &= ~SDL_WINDOW_SHOWN;
1239  }
1240 
1241  {
1242  unsigned long style = [nswindow styleMask];
1243 
1244  if (style == NSWindowStyleMaskBorderless) {
1245  window->flags |= SDL_WINDOW_BORDERLESS;
1246  } else {
1247  window->flags &= ~SDL_WINDOW_BORDERLESS;
1248  }
1249  if (style & NSWindowStyleMaskResizable) {
1250  window->flags |= SDL_WINDOW_RESIZABLE;
1251  } else {
1252  window->flags &= ~SDL_WINDOW_RESIZABLE;
1253  }
1254  }
1255 
1256  /* isZoomed always returns true if the window is not resizable */
1257  if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
1258  window->flags |= SDL_WINDOW_MAXIMIZED;
1259  } else {
1260  window->flags &= ~SDL_WINDOW_MAXIMIZED;
1261  }
1262 
1263  if ([nswindow isMiniaturized]) {
1264  window->flags |= SDL_WINDOW_MINIMIZED;
1265  } else {
1266  window->flags &= ~SDL_WINDOW_MINIMIZED;
1267  }
1268 
1269  if ([nswindow isKeyWindow]) {
1270  window->flags |= SDL_WINDOW_INPUT_FOCUS;
1272  }
1273 
1274  /* Prevents the window's "window device" from being destroyed when it is
1275  * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
1276  */
1277  [nswindow setOneShot:NO];
1278 
1279  /* All done! */
1280  window->driverdata = data;
1281  return 0;
1282 }}
1283 
1284 int
1286 { @autoreleasepool
1287 {
1288  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
1289  NSWindow *nswindow;
1290  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1291  NSRect rect;
1292  SDL_Rect bounds;
1293  NSUInteger style;
1294  NSArray *screens = [NSScreen screens];
1295 
1296  Cocoa_GetDisplayBounds(_this, display, &bounds);
1297  rect.origin.x = window->x;
1298  rect.origin.y = window->y;
1299  rect.size.width = window->w;
1300  rect.size.height = window->h;
1301  ConvertNSRect([screens objectAtIndex:0], (window->flags & FULLSCREEN_MASK), &rect);
1302 
1303  style = GetWindowStyle(window);
1304 
1305  /* Figure out which screen to place this window */
1306  NSScreen *screen = nil;
1307  for (NSScreen *candidate in screens) {
1308  NSRect screenRect = [candidate frame];
1309  if (rect.origin.x >= screenRect.origin.x &&
1310  rect.origin.x < screenRect.origin.x + screenRect.size.width &&
1311  rect.origin.y >= screenRect.origin.y &&
1312  rect.origin.y < screenRect.origin.y + screenRect.size.height) {
1313  screen = candidate;
1314  rect.origin.x -= screenRect.origin.x;
1315  rect.origin.y -= screenRect.origin.y;
1316  }
1317  }
1318 
1319  @try {
1320  nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen];
1321  }
1322  @catch (NSException *e) {
1323  return SDL_SetError("%s", [[e reason] UTF8String]);
1324  }
1325 
1326  if (videodata->allow_spaces) {
1327  SDL_assert(floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6);
1328  SDL_assert([nswindow respondsToSelector:@selector(toggleFullScreen:)]);
1329  /* we put FULLSCREEN_DESKTOP windows in their own Space, without a toggle button or menubar, later */
1330  if (window->flags & SDL_WINDOW_RESIZABLE) {
1331  /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
1332  [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
1333  }
1334  }
1335 
1336  /* Create a default view for this window */
1337  rect = [nswindow contentRectForFrameRect:[nswindow frame]];
1338  SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
1339  [contentView setSDLWindow:window];
1340 
1341  if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
1342  if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
1343  [contentView setWantsBestResolutionOpenGLSurface:YES];
1344  }
1345  }
1346 #if SDL_VIDEO_OPENGL_ES2
1347 #if SDL_VIDEO_OPENGL_EGL
1348  if ((window->flags & SDL_WINDOW_OPENGL) &&
1350  [contentView setWantsLayer:TRUE];
1351  }
1352 #endif /* SDL_VIDEO_OPENGL_EGL */
1353 #endif /* SDL_VIDEO_OPENGL_ES2 */
1354  [nswindow setContentView:contentView];
1355  [contentView release];
1356 
1357  /* Allow files and folders to be dragged onto the window by users */
1358  [nswindow registerForDraggedTypes:[NSArray arrayWithObject:(NSString *)kUTTypeFileURL]];
1359 
1360  if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
1361  [nswindow release];
1362  return -1;
1363  }
1364 
1365  if (!(window->flags & SDL_WINDOW_OPENGL)) {
1366  return 0;
1367  }
1368 
1369  /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
1370 #if SDL_VIDEO_OPENGL_ES2
1372 #if SDL_VIDEO_OPENGL_EGL
1373  if (Cocoa_GLES_SetupWindow(_this, window) < 0) {
1374  Cocoa_DestroyWindow(_this, window);
1375  return -1;
1376  }
1377  return 0;
1378 #else
1379  return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
1380 #endif /* SDL_VIDEO_OPENGL_EGL */
1381  }
1382 #endif /* SDL_VIDEO_OPENGL_ES2 */
1383  return 0;
1384 }}
1385 
1386 int
1387 Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
1388 { @autoreleasepool
1389 {
1390  NSWindow *nswindow = (NSWindow *) data;
1391  NSString *title;
1392 
1393  /* Query the title from the existing window */
1394  title = [nswindow title];
1395  if (title) {
1396  window->title = SDL_strdup([title UTF8String]);
1397  }
1398 
1399  return SetupWindowData(_this, window, nswindow, SDL_FALSE);
1400 }}
1401 
1402 void
1404 { @autoreleasepool
1405 {
1406  const char *title = window->title ? window->title : "";
1407  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1408  NSString *string = [[NSString alloc] initWithUTF8String:title];
1409  [nswindow setTitle:string];
1410  [string release];
1411 }}
1412 
1413 void
1415 { @autoreleasepool
1416 {
1417  NSImage *nsimage = Cocoa_CreateImage(icon);
1418 
1419  if (nsimage) {
1420  [NSApp setApplicationIconImage:nsimage];
1421  }
1422 }}
1423 
1424 void
1426 { @autoreleasepool
1427 {
1428  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1429  NSWindow *nswindow = windata->nswindow;
1430  NSRect rect;
1431  Uint32 moveHack;
1432 
1433  rect.origin.x = window->x;
1434  rect.origin.y = window->y;
1435  rect.size.width = window->w;
1436  rect.size.height = window->h;
1437  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1438 
1439  moveHack = s_moveHack;
1440  s_moveHack = 0;
1441  [nswindow setFrameOrigin:rect.origin];
1442  s_moveHack = moveHack;
1443 
1444  ScheduleContextUpdates(windata);
1445 }}
1446 
1447 void
1449 { @autoreleasepool
1450 {
1451  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1452  NSWindow *nswindow = windata->nswindow;
1453  NSRect rect;
1454  Uint32 moveHack;
1455 
1456  /* Cocoa will resize the window from the bottom-left rather than the
1457  * top-left when -[nswindow setContentSize:] is used, so we must set the
1458  * entire frame based on the new size, in order to preserve the position.
1459  */
1460  rect.origin.x = window->x;
1461  rect.origin.y = window->y;
1462  rect.size.width = window->w;
1463  rect.size.height = window->h;
1464  ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
1465 
1466  moveHack = s_moveHack;
1467  s_moveHack = 0;
1468  [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES];
1469  s_moveHack = moveHack;
1470 
1471  ScheduleContextUpdates(windata);
1472 }}
1473 
1474 void
1476 { @autoreleasepool
1477 {
1478  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1479 
1480  NSSize minSize;
1481  minSize.width = window->min_w;
1482  minSize.height = window->min_h;
1483 
1484  [windata->nswindow setContentMinSize:minSize];
1485 }}
1486 
1487 void
1489 { @autoreleasepool
1490 {
1491  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1492 
1493  NSSize maxSize;
1494  maxSize.width = window->max_w;
1495  maxSize.height = window->max_h;
1496 
1497  [windata->nswindow setContentMaxSize:maxSize];
1498 }}
1499 
1500 void
1502 { @autoreleasepool
1503 {
1504  SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
1505  NSWindow *nswindow = windowData->nswindow;
1506 
1507  if (![nswindow isMiniaturized]) {
1508  [windowData->listener pauseVisibleObservation];
1509  [nswindow makeKeyAndOrderFront:nil];
1510  [windowData->listener resumeVisibleObservation];
1511  }
1512 }}
1513 
1514 void
1516 { @autoreleasepool
1517 {
1518  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1519 
1520  [nswindow orderOut:nil];
1521 }}
1522 
1523 void
1525 { @autoreleasepool
1526 {
1527  SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
1528  NSWindow *nswindow = windowData->nswindow;
1529 
1530  /* makeKeyAndOrderFront: has the side-effect of deminiaturizing and showing
1531  a minimized or hidden window, so check for that before showing it.
1532  */
1533  [windowData->listener pauseVisibleObservation];
1534  if (![nswindow isMiniaturized] && [nswindow isVisible]) {
1535  [NSApp activateIgnoringOtherApps:YES];
1536  [nswindow makeKeyAndOrderFront:nil];
1537  }
1538  [windowData->listener resumeVisibleObservation];
1539 }}
1540 
1541 void
1543 { @autoreleasepool
1544 {
1545  SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
1546  NSWindow *nswindow = windata->nswindow;
1547 
1548  [nswindow zoom:nil];
1549 
1550  ScheduleContextUpdates(windata);
1551 }}
1552 
1553 void
1555 { @autoreleasepool
1556 {
1557  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1558  NSWindow *nswindow = data->nswindow;
1559 
1560  if ([data->listener isInFullscreenSpaceTransition]) {
1561  [data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
1562  } else {
1563  [nswindow miniaturize:nil];
1564  }
1565 }}
1566 
1567 void
1569 { @autoreleasepool
1570 {
1571  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1572 
1573  if ([nswindow isMiniaturized]) {
1574  [nswindow deminiaturize:nil];
1575  } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
1576  [nswindow zoom:nil];
1577  }
1578 }}
1579 
1580 void
1581 Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
1582 { @autoreleasepool
1583 {
1584  if (SetWindowStyle(window, GetWindowStyle(window))) {
1585  if (bordered) {
1586  Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */
1587  }
1588  }
1589 }}
1590 
1591 void
1592 Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
1593 { @autoreleasepool
1594 {
1595  /* Don't set this if we're in a space!
1596  * The window will get permanently stuck if resizable is false.
1597  * -flibit
1598  */
1599  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1600  Cocoa_WindowListener *listener = data->listener;
1601  if (![listener isInFullscreenSpace]) {
1602  SetWindowStyle(window, GetWindowStyle(window));
1603  }
1604 }}
1605 
1606 void
1607 Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
1608 { @autoreleasepool
1609 {
1610  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1611  NSWindow *nswindow = data->nswindow;
1612  NSRect rect;
1613 
1614  /* The view responder chain gets messed with during setStyleMask */
1615  if ([[nswindow contentView] nextResponder] == data->listener) {
1616  [[nswindow contentView] setNextResponder:nil];
1617  }
1618 
1619  if (fullscreen) {
1620  SDL_Rect bounds;
1621 
1622  Cocoa_GetDisplayBounds(_this, display, &bounds);
1623  rect.origin.x = bounds.x;
1624  rect.origin.y = bounds.y;
1625  rect.size.width = bounds.w;
1626  rect.size.height = bounds.h;
1627  ConvertNSRect([nswindow screen], fullscreen, &rect);
1628 
1629  /* Hack to fix origin on Mac OS X 10.4 */
1630  NSRect screenRect = [[nswindow screen] frame];
1631  if (screenRect.size.height >= 1.0f) {
1632  rect.origin.y += (screenRect.size.height - rect.size.height);
1633  }
1634 
1635  [nswindow setStyleMask:NSWindowStyleMaskBorderless];
1636  } else {
1637  rect.origin.x = window->windowed.x;
1638  rect.origin.y = window->windowed.y;
1639  rect.size.width = window->windowed.w;
1640  rect.size.height = window->windowed.h;
1641  ConvertNSRect([nswindow screen], fullscreen, &rect);
1642 
1643  [nswindow setStyleMask:GetWindowStyle(window)];
1644 
1645  /* Hack to restore window decorations on Mac OS X 10.10 */
1646  NSRect frameRect = [nswindow frame];
1647  [nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
1648  [nswindow setFrame:frameRect display:NO];
1649  }
1650 
1651  /* The view responder chain gets messed with during setStyleMask */
1652  if ([[nswindow contentView] nextResponder] != data->listener) {
1653  [[nswindow contentView] setNextResponder:data->listener];
1654  }
1655 
1656  s_moveHack = 0;
1657  [nswindow setContentSize:rect.size];
1658  [nswindow setFrameOrigin:rect.origin];
1659  s_moveHack = SDL_GetTicks();
1660 
1661  /* When the window style changes the title is cleared */
1662  if (!fullscreen) {
1663  Cocoa_SetWindowTitle(_this, window);
1664  }
1665 
1666  if (SDL_ShouldAllowTopmost() && fullscreen) {
1667  /* OpenGL is rendering to the window, so make it visible! */
1668  [nswindow setLevel:CGShieldingWindowLevel()];
1669  } else {
1670  [nswindow setLevel:kCGNormalWindowLevel];
1671  }
1672 
1673  if ([nswindow isVisible] || fullscreen) {
1674  [data->listener pauseVisibleObservation];
1675  [nswindow makeKeyAndOrderFront:nil];
1676  [data->listener resumeVisibleObservation];
1677  }
1678 
1679  ScheduleContextUpdates(data);
1680 }}
1681 
1682 int
1683 Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
1684 {
1685  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1686  CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
1687  const uint32_t tableSize = 256;
1688  CGGammaValue redTable[tableSize];
1689  CGGammaValue greenTable[tableSize];
1690  CGGammaValue blueTable[tableSize];
1691  uint32_t i;
1692  float inv65535 = 1.0f / 65535.0f;
1693 
1694  /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
1695  for (i = 0; i < 256; i++) {
1696  redTable[i] = ramp[0*256+i] * inv65535;
1697  greenTable[i] = ramp[1*256+i] * inv65535;
1698  blueTable[i] = ramp[2*256+i] * inv65535;
1699  }
1700 
1701  if (CGSetDisplayTransferByTable(display_id, tableSize,
1702  redTable, greenTable, blueTable) != CGDisplayNoErr) {
1703  return SDL_SetError("CGSetDisplayTransferByTable()");
1704  }
1705  return 0;
1706 }
1707 
1708 int
1710 {
1711  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
1712  CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
1713  const uint32_t tableSize = 256;
1714  CGGammaValue redTable[tableSize];
1715  CGGammaValue greenTable[tableSize];
1716  CGGammaValue blueTable[tableSize];
1717  uint32_t i, tableCopied;
1718 
1719  if (CGGetDisplayTransferByTable(display_id, tableSize,
1720  redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
1721  return SDL_SetError("CGGetDisplayTransferByTable()");
1722  }
1723 
1724  for (i = 0; i < tableCopied; i++) {
1725  ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
1726  ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
1727  ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
1728  }
1729  return 0;
1730 }
1731 
1732 void
1733 Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
1734 {
1735  SDL_Mouse *mouse = SDL_GetMouse();
1736  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1737 
1738  /* Enable or disable the event tap as necessary */
1739  Cocoa_EnableMouseEventTap(mouse->driverdata, grabbed);
1740 
1741  /* Move the cursor to the nearest point in the window */
1742  if (grabbed && data && ![data->listener isMoving]) {
1743  int x, y;
1744  CGPoint cgpoint;
1745 
1746  SDL_GetMouseState(&x, &y);
1747  cgpoint.x = window->x + x;
1748  cgpoint.y = window->y + y;
1749 
1750  Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
1751 
1752  DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
1753  CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
1754  }
1755 
1756  if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
1758  && ![data->listener isInFullscreenSpace]) {
1759  /* OpenGL is rendering to the window, so make it visible! */
1760  /* Doing this in 10.11 while in a Space breaks things (bug #3152) */
1761  [data->nswindow setLevel:CGShieldingWindowLevel()];
1762  } else {
1763  [data->nswindow setLevel:kCGNormalWindowLevel];
1764  }
1765  }
1766 }
1767 
1768 void
1770 { @autoreleasepool
1771 {
1772  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1773 
1774  if (data) {
1775  if ([data->listener isInFullscreenSpace]) {
1776  [NSMenu setMenuBarVisible:YES];
1777  }
1778  [data->listener close];
1779  [data->listener release];
1780  if (data->created) {
1781  [data->nswindow close];
1782  }
1783 
1784  NSArray *contexts = [[data->nscontexts copy] autorelease];
1785  for (SDLOpenGLContext *context in contexts) {
1786  /* Calling setWindow:NULL causes the context to remove itself from the context list. */
1787  [context setWindow:NULL];
1788  }
1789  [data->nscontexts release];
1790 
1791  SDL_free(data);
1792  }
1793  window->driverdata = NULL;
1794 }}
1795 
1796 SDL_bool
1798 {
1799  NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1800 
1801  if (info->version.major <= SDL_MAJOR_VERSION) {
1802  info->subsystem = SDL_SYSWM_COCOA;
1803  info->info.cocoa.window = nswindow;
1804  return SDL_TRUE;
1805  } else {
1806  SDL_SetError("Application not compiled with SDL %d.%d",
1808  return SDL_FALSE;
1809  }
1810 }
1811 
1812 SDL_bool
1813 Cocoa_IsWindowInFullscreenSpace(SDL_Window * window)
1814 {
1815  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1816 
1817  if ([data->listener isInFullscreenSpace]) {
1818  return SDL_TRUE;
1819  } else {
1820  return SDL_FALSE;
1821  }
1822 }
1823 
1824 SDL_bool
1825 Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
1826 { @autoreleasepool
1827 {
1828  SDL_bool succeeded = SDL_FALSE;
1829  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1830 
1831  if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
1832  const int maxattempts = 3;
1833  int attempt = 0;
1834  while (++attempt <= maxattempts) {
1835  /* Wait for the transition to complete, so application changes
1836  take effect properly (e.g. setting the window size, etc.)
1837  */
1838  const int limit = 10000;
1839  int count = 0;
1840  while ([data->listener isInFullscreenSpaceTransition]) {
1841  if ( ++count == limit ) {
1842  /* Uh oh, transition isn't completing. Should we assert? */
1843  break;
1844  }
1845  SDL_Delay(1);
1846  SDL_PumpEvents();
1847  }
1848  if ([data->listener isInFullscreenSpace] == (state ? YES : NO))
1849  break;
1850  /* Try again, the last attempt was interrupted by user gestures */
1851  if (![data->listener setFullscreenSpace:(state ? YES : NO)])
1852  break; /* ??? */
1853  }
1854  /* Return TRUE to prevent non-space fullscreen logic from running */
1855  succeeded = SDL_TRUE;
1856  }
1857 
1858  return succeeded;
1859 }}
1860 
1861 int
1863 {
1864  return 0; /* just succeed, the real work is done elsewhere. */
1865 }
1866 
1867 int
1868 Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
1869 {
1870  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
1871  [data->nswindow setAlphaValue:opacity];
1872  return 0;
1873 }
1874 
1875 #endif /* SDL_VIDEO_DRIVER_COCOA */
1876 
1877 /* 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:112
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:499
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
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:544
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:151
void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
#define SDL_GetKeyboardFocus
uint32_t Uint32
Definition: SDL_stdinc.h:181
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:993
void Cocoa_RestoreWindow(_THIS, SDL_Window *window)
int x
Definition: SDL_rect.h:50
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:237
#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:102
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:313
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
#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:3888
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#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:1073
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)
int Cocoa_ResizeWindowShape(SDL_Window *window)
uint16_t Uint16
Definition: SDL_stdinc.h:169
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)
struct SDL_VideoDevice::@34 gl_config
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:101
void * driverdata
Definition: SDL_mouse_c.h:105
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:295
SDL_Renderer * screen
int y
Definition: SDL_rect.h:66
#define SDL_GetMouseState
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)