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