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
220static Uint32 s_moveHack;
221
222static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
223{
224 r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
225}
226
227static void
228ScheduleContextUpdates(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. */
258static int
259GetHintCtrlClickEmulateRightClick()
260{
262}
263
264static NSUInteger
265GetWindowStyle(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
284static SDL_bool
285SetWindowStyle(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];
321 isMoving = 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
435{
436 return isFullscreenSpace;
437}
438
440{
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
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;
650 _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
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. */
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
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
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) {
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{
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);
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);
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
1292static int
1293SetupWindowData(_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]) {
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
1380int
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
1495int
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
1511void
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
1522void
1524{ @autoreleasepool
1525{
1526 NSImage *nsimage = Cocoa_CreateImage(icon);
1527
1528 if (nsimage) {
1529 [NSApp setApplicationIconImage:nsimage];
1530 }
1531}}
1532
1533void
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
1556void
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
1583void
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
1596void
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
1609void
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
1623void
1625{ @autoreleasepool
1626{
1627 NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
1628
1629 [nswindow orderOut:nil];
1630}}
1631
1632void
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
1650void
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
1662void
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
1676void
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
1689void
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
1700void
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
1715void
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
1791int
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
1817int
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
1841void
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
1877void
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
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
1924Cocoa_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
1936Cocoa_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);
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
1972int
1974{
1975 return 0; /* just succeed, the real work is done elsewhere. */
1976}
1977
1978void
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
1989int
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: */
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:169
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
static const NSUInteger NSEventModifierFlagCapsLock
NSImage * Cocoa_CreateImage(SDL_Surface *surface)
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:52
#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:305
#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
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
Definition: SDL_keyboard.c:865
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:679
@ KMOD_CAPS
Definition: SDL_keycode.h:337
int SDL_SendMouseButtonClicks(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
Definition: SDL_mouse.c:598
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:211
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:301
#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
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_SCANCODE_CAPSLOCK
Definition: SDL_scancode.h:151
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3992
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
@ SDL_SYSWM_COCOA
Definition: SDL_syswm.h:125
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:242
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:364
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:155
#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
@ SDL_TOUCH_DEVICE_DIRECT
Definition: SDL_touch.h:47
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:144
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:1021
@ SDL_HITTEST_DRAGGABLE
Definition: SDL_video.h:1023
@ SDL_WINDOW_ALLOW_HIGHDPI
Definition: SDL_video.h:113
@ SDL_WINDOW_SHOWN
Definition: SDL_video.h:102
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
@ SDL_WINDOW_MINIMIZED
Definition: SDL_video.h:106
@ SDL_WINDOW_INPUT_GRABBED
Definition: SDL_video.h:108
@ SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:105
@ SDL_WINDOW_FULLSCREEN_DESKTOP
Definition: SDL_video.h:111
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
@ SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:107
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:104
@ SDL_WINDOW_INPUT_FOCUS
Definition: SDL_video.h:109
@ 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:233
#define INT_MAX
Definition: SDL_wave.c:31
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:167
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLNativeDisplayType * display_id
Definition: eglext.h:1024
PendingWindowOperation pendingWindowOperation
SDL_WindowData * _data
BOOL isInFullscreenSpaceTransition()
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::@17 info
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:200
Window window
Definition: SDL_syswm.h:221
SDL_version version
Definition: SDL_syswm.h:199
unsigned int modifierFlags
struct SDL_VideoDevice::@262 gl_config
SDL_Window * windows
Definition: SDL_sysvideo.h:317
SDL_Window * window
NSWindow * nswindow
struct SDL_VideoData * videodata
The type used to identify a window.
Definition: SDL_sysvideo.h:74
SDL_Window * next
Definition: SDL_sysvideo.h:114
Uint32 flags
Definition: SDL_sysvideo.h:83
void * driverdata
Definition: SDL_sysvideo.h:111
void * hit_test_data
Definition: SDL_sysvideo.h:107
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:106
Uint8 major
Definition: SDL_version.h:53
SDL_Texture * button
SDL_Renderer * screen
SDL_Rect rect
Definition: testrelative.c:27
static screen_context_t context
Definition: video.c:25