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