summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/video/cocoa
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/video/cocoa')
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.h36
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.m103
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.h32
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.m483
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.h36
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m720
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.h29
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.m145
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.h63
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.m138
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.h46
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.m490
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.h52
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.m477
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.h34
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.m286
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.h68
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.m436
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.h49
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.m132
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.h45
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.m113
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.h118
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.m262
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.h55
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.m230
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.h155
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.m1905
28 files changed, 6738 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.h
new file mode 100644
index 0000000..54e4c88
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.h
@@ -0,0 +1,36 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoaclipboard_h_
+#define SDL_cocoaclipboard_h_
+
+/* Forward declaration */
+struct SDL_VideoData;
+
+extern int Cocoa_SetClipboardText(_THIS, const char *text);
+extern char *Cocoa_GetClipboardText(_THIS);
+extern SDL_bool Cocoa_HasClipboardText(_THIS);
+extern void Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data);
+
+#endif /* SDL_cocoaclipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.m
new file mode 100644
index 0000000..9c96634
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaclipboard.m
@@ -0,0 +1,103 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoavideo.h"
+#include "../../events/SDL_clipboardevents_c.h"
+
+int
+Cocoa_SetClipboardText(_THIS, const char *text)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ NSPasteboard *pasteboard;
+ NSString *format = NSPasteboardTypeString;
+
+ pasteboard = [NSPasteboard generalPasteboard];
+ data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
+ [pasteboard setString:[NSString stringWithUTF8String:text] forType:format];
+
+ return 0;
+}}
+
+char *
+Cocoa_GetClipboardText(_THIS)
+{ @autoreleasepool
+{
+ NSPasteboard *pasteboard;
+ NSString *format = NSPasteboardTypeString;
+ NSString *available;
+ char *text;
+
+ pasteboard = [NSPasteboard generalPasteboard];
+ available = [pasteboard availableTypeFromArray:[NSArray arrayWithObject:format]];
+ if ([available isEqualToString:format]) {
+ NSString* string;
+ const char *utf8;
+
+ string = [pasteboard stringForType:format];
+ if (string == nil) {
+ utf8 = "";
+ } else {
+ utf8 = [string UTF8String];
+ }
+ text = SDL_strdup(utf8);
+ } else {
+ text = SDL_strdup("");
+ }
+
+ return text;
+}}
+
+SDL_bool
+Cocoa_HasClipboardText(_THIS)
+{
+ SDL_bool result = SDL_FALSE;
+ char *text = Cocoa_GetClipboardText(_this);
+ if (text) {
+ result = text[0] != '\0' ? SDL_TRUE : SDL_FALSE;
+ SDL_free(text);
+ }
+ return result;
+}
+
+void
+Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data)
+{ @autoreleasepool
+{
+ NSPasteboard *pasteboard;
+ NSInteger count;
+
+ pasteboard = [NSPasteboard generalPasteboard];
+ count = [pasteboard changeCount];
+ if (count != data->clipboard_count) {
+ if (data->clipboard_count) {
+ SDL_SendClipboardUpdate();
+ }
+ data->clipboard_count = count;
+ }
+}}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.h
new file mode 100644
index 0000000..986168e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.h
@@ -0,0 +1,32 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoaevents_h_
+#define SDL_cocoaevents_h_
+
+extern void Cocoa_RegisterApp(void);
+extern void Cocoa_PumpEvents(_THIS);
+extern void Cocoa_SuspendScreenSaver(_THIS);
+
+#endif /* SDL_cocoaevents_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.m
new file mode 100644
index 0000000..76d235e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaevents.m
@@ -0,0 +1,483 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+#include "SDL_timer.h"
+
+#include "SDL_cocoavideo.h"
+#include "../../events/SDL_events_c.h"
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+
+/* This define was added in the 10.9 SDK. */
+#ifndef kIOPMAssertPreventUserIdleDisplaySleep
+#define kIOPMAssertPreventUserIdleDisplaySleep kIOPMAssertionTypePreventUserIdleDisplaySleep
+#endif
+
+@interface SDLApplication : NSApplication
+
+- (void)terminate:(id)sender;
+- (void)sendEvent:(NSEvent *)theEvent;
+
++ (void)registerUserDefaults;
+
+@end
+
+@implementation SDLApplication
+
+// Override terminate to handle Quit and System Shutdown smoothly.
+- (void)terminate:(id)sender
+{
+ SDL_SendQuit();
+}
+
+static SDL_bool s_bShouldHandleEventsInSDLApplication = SDL_FALSE;
+
+static void Cocoa_DispatchEvent(NSEvent *theEvent)
+{
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+ switch ([theEvent type]) {
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeOtherMouseDown:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeOtherMouseUp:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeOtherMouseDragged: /* usually middle mouse dragged */
+ case NSEventTypeMouseMoved:
+ case NSEventTypeScrollWheel:
+ Cocoa_HandleMouseEvent(_this, theEvent);
+ break;
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged:
+ Cocoa_HandleKeyEvent(_this, theEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+// Dispatch events here so that we can handle events caught by
+// nextEventMatchingMask in SDL, as well as events caught by other
+// processes (such as CEF) that are passed down to NSApp.
+- (void)sendEvent:(NSEvent *)theEvent
+{
+ if (s_bShouldHandleEventsInSDLApplication) {
+ Cocoa_DispatchEvent(theEvent);
+ }
+
+ [super sendEvent:theEvent];
+}
+
++ (void)registerUserDefaults
+{
+ NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
+ [NSNumber numberWithBool:NO], @"AppleMomentumScrollSupported",
+ [NSNumber numberWithBool:NO], @"ApplePressAndHoldEnabled",
+ [NSNumber numberWithBool:YES], @"ApplePersistenceIgnoreState",
+ nil];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
+ [appDefaults release];
+}
+
+@end // SDLApplication
+
+/* setAppleMenu disappeared from the headers in 10.4 */
+@interface NSApplication(NSAppleMenu)
+- (void)setAppleMenu:(NSMenu *)menu;
+@end
+
+@interface SDLAppDelegate : NSObject <NSApplicationDelegate> {
+@public
+ BOOL seenFirstActivate;
+}
+
+- (id)init;
+@end
+
+@implementation SDLAppDelegate : NSObject
+- (id)init
+{
+ self = [super init];
+ if (self) {
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ seenFirstActivate = NO;
+
+ [center addObserver:self
+ selector:@selector(windowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:nil];
+
+ [center addObserver:self
+ selector:@selector(focusSomeWindow:)
+ name:NSApplicationDidBecomeActiveNotification
+ object:nil];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ [center removeObserver:self name:NSWindowWillCloseNotification object:nil];
+ [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
+
+ [super dealloc];
+}
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+ NSWindow *win = (NSWindow*)[notification object];
+
+ if (![win isKeyWindow]) {
+ return;
+ }
+
+ /* HACK: Make the next window in the z-order key when the key window is
+ * closed. The custom event loop and/or windowing code we have seems to
+ * prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825
+ */
+
+ /* +[NSApp orderedWindows] never includes the 'About' window, but we still
+ * want to try its list first since the behavior in other apps is to only
+ * make the 'About' window key if no other windows are on-screen.
+ */
+ for (NSWindow *window in [NSApp orderedWindows]) {
+ if (window != win && [window canBecomeKeyWindow]) {
+ if (![window isOnActiveSpace]) {
+ continue;
+ }
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+
+ /* If a window wasn't found above, iterate through all visible windows in
+ * the active Space in z-order (including the 'About' window, if it's shown)
+ * and make the first one key.
+ */
+ for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
+ NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
+ if (window && window != win && [window canBecomeKeyWindow]) {
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+}
+
+- (void)focusSomeWindow:(NSNotification *)aNotification
+{
+ /* HACK: Ignore the first call. The application gets a
+ * applicationDidBecomeActive: a little bit after the first window is
+ * created, and if we don't ignore it, a window that has been created with
+ * SDL_WINDOW_MINIMIZED will ~immediately be restored.
+ */
+ if (!seenFirstActivate) {
+ seenFirstActivate = YES;
+ return;
+ }
+
+ SDL_VideoDevice *device = SDL_GetVideoDevice();
+ if (device && device->windows) {
+ SDL_Window *window = device->windows;
+ int i;
+ for (i = 0; i < device->num_displays; ++i) {
+ SDL_Window *fullscreen_window = device->displays[i].fullscreen_window;
+ if (fullscreen_window) {
+ if (fullscreen_window->flags & SDL_WINDOW_MINIMIZED) {
+ SDL_RestoreWindow(fullscreen_window);
+ }
+ return;
+ }
+ }
+
+ if (window->flags & SDL_WINDOW_MINIMIZED) {
+ SDL_RestoreWindow(window);
+ } else {
+ SDL_RaiseWindow(window);
+ }
+ }
+}
+
+- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+{
+ return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ /* The menu bar of SDL apps which don't have the typical .app bundle
+ * structure fails to work the first time a window is created (until it's
+ * de-focused and re-focused), if this call is in Cocoa_RegisterApp instead
+ * of here. https://bugzilla.libsdl.org/show_bug.cgi?id=3051
+ */
+ if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
+ [NSApp activateIgnoringOtherApps:YES];
+ }
+
+ /* If we call this before NSApp activation, macOS might print a complaint
+ * about ApplePersistenceIgnoreState. */
+ [SDLApplication registerUserDefaults];
+}
+@end
+
+static SDLAppDelegate *appDelegate = nil;
+
+static NSString *
+GetApplicationName(void)
+{
+ NSString *appName;
+
+ /* Determine the application name */
+ appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
+ if (!appName) {
+ appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
+ }
+
+ if (![appName length]) {
+ appName = [[NSProcessInfo processInfo] processName];
+ }
+
+ return appName;
+}
+
+static void
+CreateApplicationMenus(void)
+{
+ NSString *appName;
+ NSString *title;
+ NSMenu *appleMenu;
+ NSMenu *serviceMenu;
+ NSMenu *windowMenu;
+ NSMenu *viewMenu;
+ NSMenuItem *menuItem;
+ NSMenu *mainMenu;
+
+ if (NSApp == nil) {
+ return;
+ }
+
+ mainMenu = [[NSMenu alloc] init];
+
+ /* Create the main menu bar */
+ [NSApp setMainMenu:mainMenu];
+
+ [mainMenu release]; /* we're done with it, let NSApp own it. */
+ mainMenu = nil;
+
+ /* Create the application menu */
+ appName = GetApplicationName();
+ appleMenu = [[NSMenu alloc] initWithTitle:@""];
+
+ /* Add menu items */
+ title = [@"About " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ [appleMenu addItemWithTitle:@"Preferences…" action:nil keyEquivalent:@","];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ serviceMenu = [[NSMenu alloc] initWithTitle:@""];
+ menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Services" action:nil keyEquivalent:@""];
+ [menuItem setSubmenu:serviceMenu];
+
+ [NSApp setServicesMenu:serviceMenu];
+ [serviceMenu release];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ title = [@"Hide " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+
+ menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+ [menuItem setKeyEquivalentModifierMask:(NSEventModifierFlagOption|NSEventModifierFlagCommand)];
+
+ [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+ [appleMenu addItem:[NSMenuItem separatorItem]];
+
+ title = [@"Quit " stringByAppendingString:appName];
+ [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+
+ /* Put menu into the menubar */
+ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+ [menuItem setSubmenu:appleMenu];
+ [[NSApp mainMenu] addItem:menuItem];
+ [menuItem release];
+
+ /* Tell the application object that this is now the application menu */
+ [NSApp setAppleMenu:appleMenu];
+ [appleMenu release];
+
+
+ /* Create the window menu */
+ windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+
+ /* Add menu items */
+ [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+
+ [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
+
+ /* Put menu into the menubar */
+ menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+ [menuItem setSubmenu:windowMenu];
+ [[NSApp mainMenu] addItem:menuItem];
+ [menuItem release];
+
+ /* Tell the application object that this is now the window menu */
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenu release];
+
+
+ /* Add the fullscreen view toggle menu option, if supported */
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) {
+ /* Create the view menu */
+ viewMenu = [[NSMenu alloc] initWithTitle:@"View"];
+
+ /* Add menu items */
+ menuItem = [viewMenu addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
+ [menuItem setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
+
+ /* Put menu into the menubar */
+ menuItem = [[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""];
+ [menuItem setSubmenu:viewMenu];
+ [[NSApp mainMenu] addItem:menuItem];
+ [menuItem release];
+
+ [viewMenu release];
+ }
+}
+
+void
+Cocoa_RegisterApp(void)
+{ @autoreleasepool
+{
+ /* This can get called more than once! Be careful what you initialize! */
+
+ if (NSApp == nil) {
+ [SDLApplication sharedApplication];
+ SDL_assert(NSApp != nil);
+
+ s_bShouldHandleEventsInSDLApplication = SDL_TRUE;
+
+ if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+ }
+
+ if ([NSApp mainMenu] == nil) {
+ CreateApplicationMenus();
+ }
+ [NSApp finishLaunching];
+ if ([NSApp delegate]) {
+ /* The SDL app delegate calls this in didFinishLaunching if it's
+ * attached to the NSApp, otherwise we need to call it manually.
+ */
+ [SDLApplication registerUserDefaults];
+ }
+ }
+ if (NSApp && !appDelegate) {
+ appDelegate = [[SDLAppDelegate alloc] init];
+
+ /* If someone else has an app delegate, it means we can't turn a
+ * termination into SDL_Quit, and we can't handle application:openFile:
+ */
+ if (![NSApp delegate]) {
+ [(NSApplication *)NSApp setDelegate:appDelegate];
+ } else {
+ appDelegate->seenFirstActivate = YES;
+ }
+ }
+}}
+
+void
+Cocoa_PumpEvents(_THIS)
+{ @autoreleasepool
+{
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ /* Update activity every 30 seconds to prevent screensaver */
+ SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+ if (_this->suspend_screensaver && !data->screensaver_use_iopm) {
+ Uint32 now = SDL_GetTicks();
+ if (!data->screensaver_activity ||
+ SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
+ UpdateSystemActivity(UsrActivity);
+ data->screensaver_activity = now;
+ }
+ }
+#endif
+
+ for ( ; ; ) {
+ NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
+ if ( event == nil ) {
+ break;
+ }
+
+ if (!s_bShouldHandleEventsInSDLApplication) {
+ Cocoa_DispatchEvent(event);
+ }
+
+ // Pass events down to SDLApplication to be handled in sendEvent:
+ [NSApp sendEvent:event];
+ }
+}}
+
+void
+Cocoa_SuspendScreenSaver(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+
+ if (!data->screensaver_use_iopm) {
+ return;
+ }
+
+ if (data->screensaver_assertion) {
+ IOPMAssertionRelease(data->screensaver_assertion);
+ data->screensaver_assertion = 0;
+ }
+
+ if (_this->suspend_screensaver) {
+ /* FIXME: this should ideally describe the real reason why the game
+ * called SDL_DisableScreenSaver. Note that the name is only meant to be
+ * seen by OS X power users. there's an additional optional human-readable
+ * (localized) reason parameter which we don't set.
+ */
+ NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"];
+ IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep,
+ (CFStringRef) name,
+ NULL, NULL, NULL, 0, NULL,
+ &data->screensaver_assertion);
+ }
+}}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.h
new file mode 100644
index 0000000..7d89523
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.h
@@ -0,0 +1,36 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoakeyboard_h_
+#define SDL_cocoakeyboard_h_
+
+extern void Cocoa_InitKeyboard(_THIS);
+extern void Cocoa_HandleKeyEvent(_THIS, NSEvent * event);
+extern void Cocoa_QuitKeyboard(_THIS);
+
+extern void Cocoa_StartTextInput(_THIS);
+extern void Cocoa_StopTextInput(_THIS);
+extern void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect);
+
+#endif /* SDL_cocoakeyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m
new file mode 100644
index 0000000..8436047
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m
@@ -0,0 +1,720 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoavideo.h"
+
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/scancodes_darwin.h"
+
+#include <Carbon/Carbon.h>
+#include <IOKit/hid/IOHIDLib.h>
+
+/*#define DEBUG_IME NSLog */
+#define DEBUG_IME(...)
+
+@interface SDLTranslatorResponder : NSView <NSTextInputClient> {
+ NSString *_markedText;
+ NSRange _markedRange;
+ NSRange _selectedRange;
+ SDL_Rect _inputRect;
+}
+- (void)doCommandBySelector:(SEL)myselector;
+- (void)setInputRect:(SDL_Rect *)rect;
+@end
+
+@implementation SDLTranslatorResponder
+
+- (void)setInputRect:(SDL_Rect *)rect
+{
+ _inputRect = *rect;
+}
+
+- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
+{
+ /* TODO: Make use of replacementRange? */
+
+ const char *str;
+
+ DEBUG_IME(@"insertText: %@", aString);
+
+ /* Could be NSString or NSAttributedString, so we have
+ * to test and convert it before return as SDL event */
+ if ([aString isKindOfClass: [NSAttributedString class]]) {
+ str = [[aString string] UTF8String];
+ } else {
+ str = [aString UTF8String];
+ }
+
+ SDL_SendKeyboardText(str);
+}
+
+- (void)doCommandBySelector:(SEL)myselector
+{
+ /* No need to do anything since we are not using Cocoa
+ selectors to handle special keys, instead we use SDL
+ key events to do the same job.
+ */
+}
+
+- (BOOL)hasMarkedText
+{
+ return _markedText != nil;
+}
+
+- (NSRange)markedRange
+{
+ return _markedRange;
+}
+
+- (NSRange)selectedRange
+{
+ return _selectedRange;
+}
+
+- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
+{
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ aString = [aString string];
+ }
+
+ if ([aString length] == 0) {
+ [self unmarkText];
+ return;
+ }
+
+ if (_markedText != aString) {
+ [_markedText release];
+ _markedText = [aString retain];
+ }
+
+ _selectedRange = selectedRange;
+ _markedRange = NSMakeRange(0, [aString length]);
+
+ SDL_SendEditingText([aString UTF8String],
+ (int) selectedRange.location, (int) selectedRange.length);
+
+ DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
+ selRange.location, selRange.length);
+}
+
+- (void)unmarkText
+{
+ [_markedText release];
+ _markedText = nil;
+
+ SDL_SendEditingText("", 0, 0);
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ NSWindow *window = [self window];
+ NSRect contentRect = [window contentRectForFrameRect:[window frame]];
+ float windowHeight = contentRect.size.height;
+ NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
+ _inputRect.w, _inputRect.h);
+
+ if (actualRange) {
+ *actualRange = aRange;
+ }
+
+ DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
+ aRange.location, aRange.length, windowHeight,
+ NSStringFromRect(rect));
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ if (![window respondsToSelector:@selector(convertRectToScreen:)]) {
+ rect.origin = [window convertBaseToScreen:rect.origin];
+ } else
+#endif
+ {
+ rect = [window convertRectToScreen:rect];
+ }
+
+ return rect;
+}
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length);
+ return nil;
+}
+
+- (NSInteger)conversationIdentifier
+{
+ return (NSInteger) self;
+}
+
+/* This method returns the index for character that is
+ * nearest to thePoint. thPoint is in screen coordinate system.
+ */
+- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
+{
+ DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
+ return 0;
+}
+
+/* This method is the key to attribute extension.
+ * We could add new attributes through this method.
+ * NSInputServer examines the return value of this
+ * method & constructs appropriate attributed string.
+ */
+- (NSArray *)validAttributesForMarkedText
+{
+ return [NSArray array];
+}
+
+@end
+
+/*------------------------------------------------------------------------------
+Set up a HID callback to properly detect Caps Lock up/down events.
+Derived from:
+http://stackoverflow.com/questions/7190852/using-iohidmanager-to-get-modifier-key-events
+*/
+
+static IOHIDManagerRef s_hidManager = NULL;
+
+static void
+HIDCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value)
+{
+ if (context != s_hidManager) {
+ /* An old callback, ignore it (related to bug 2157 below) */
+ return;
+ }
+
+ IOHIDElementRef elem = IOHIDValueGetElement(value);
+ if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad
+ || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) {
+ return;
+ }
+ CFIndex pressed = IOHIDValueGetIntegerValue(value);
+ SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
+}
+
+static CFDictionaryRef
+CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage)
+{
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (dict) {
+ CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
+ CFRelease(number);
+ number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
+ CFRelease(number);
+ return dict;
+ }
+ }
+ CFRelease(dict);
+ }
+ return NULL;
+}
+
+static void
+QuitHIDCallback()
+{
+ if (!s_hidManager) {
+ return;
+ }
+
+#if 0 /* Releasing here causes a crash on Mac OS X 10.10 and earlier,
+ * so just leak it for now. See bug 2157 for details.
+ */
+ IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, NULL, NULL);
+ IOHIDManagerClose(s_hidManager, 0);
+
+ CFRelease(s_hidManager);
+#endif
+ s_hidManager = NULL;
+}
+
+static void
+InitHIDCallback()
+{
+ s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (!s_hidManager) {
+ return;
+ }
+ CFDictionaryRef keyboard = NULL, keypad = NULL;
+ CFArrayRef matches = NULL;
+ keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
+ if (!keyboard) {
+ goto fail;
+ }
+ keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad);
+ if (!keypad) {
+ goto fail;
+ }
+ CFDictionaryRef matchesList[] = { keyboard, keypad };
+ matches = CFArrayCreate(kCFAllocatorDefault, (const void **)matchesList, 2, NULL);
+ if (!matches) {
+ goto fail;
+ }
+ IOHIDManagerSetDeviceMatchingMultiple(s_hidManager, matches);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, HIDCallback, s_hidManager);
+ IOHIDManagerScheduleWithRunLoop(s_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+ if (IOHIDManagerOpen(s_hidManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) {
+ goto cleanup;
+ }
+
+fail:
+ QuitHIDCallback();
+
+cleanup:
+ if (matches) {
+ CFRelease(matches);
+ }
+ if (keypad) {
+ CFRelease(keypad);
+ }
+ if (keyboard) {
+ CFRelease(keyboard);
+ }
+}
+
+/* This is a helper function for HandleModifierSide. This
+ * function reverts back to behavior before the distinction between
+ * sides was made.
+ */
+static void
+HandleNonDeviceModifier(unsigned int device_independent_mask,
+ unsigned int oldMods,
+ unsigned int newMods,
+ SDL_Scancode scancode)
+{
+ unsigned int oldMask, newMask;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ oldMask = oldMods & device_independent_mask;
+ newMask = newMods & device_independent_mask;
+
+ if (oldMask && oldMask != newMask) {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ } else if (newMask && oldMask != newMask) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ }
+}
+
+/* This is a helper function for HandleModifierSide.
+ * This function sets the actual SDL_PrivateKeyboard event.
+ */
+static void
+HandleModifierOneSide(unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode scancode,
+ unsigned int sided_device_dependent_mask)
+{
+ unsigned int old_dep_mask, new_dep_mask;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ old_dep_mask = oldMods & sided_device_dependent_mask;
+ new_dep_mask = newMods & sided_device_dependent_mask;
+
+ /* We now know that this side bit flipped. But we don't know if
+ * it went pressed to released or released to pressed, so we must
+ * find out which it is.
+ */
+ if (new_dep_mask && old_dep_mask != new_dep_mask) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ } else {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+}
+
+/* This is a helper function for DoSidedModifiers.
+ * This function will figure out if the modifier key is the left or right side,
+ * e.g. left-shift vs right-shift.
+ */
+static void
+HandleModifierSide(int device_independent_mask,
+ unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode left_scancode,
+ SDL_Scancode right_scancode,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask)
+{
+ unsigned int device_dependent_mask = (left_device_dependent_mask |
+ right_device_dependent_mask);
+ unsigned int diff_mod;
+
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ((device_dependent_mask & newMods) == 0) {
+ /* Revert to the old behavior */
+ HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
+ return;
+ }
+
+ /* XOR the previous state against the new state to see if there's a change */
+ diff_mod = (device_dependent_mask & oldMods) ^
+ (device_dependent_mask & newMods);
+ if (diff_mod) {
+ /* A change in state was found. Isolate the left and right bits
+ * to handle them separately just in case the values can simulataneously
+ * change or if the bits don't both exist.
+ */
+ if (left_device_dependent_mask & diff_mod) {
+ HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
+ }
+ if (right_device_dependent_mask & diff_mod) {
+ HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
+ }
+ }
+}
+
+/* This is a helper function for DoSidedModifiers.
+ * This function will release a key press in the case that
+ * it is clear that the modifier has been released (i.e. one side
+ * can't still be down).
+ */
+static void
+ReleaseModifierSide(unsigned int device_independent_mask,
+ unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode left_scancode,
+ SDL_Scancode right_scancode,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask)
+{
+ unsigned int device_dependent_mask = (left_device_dependent_mask |
+ right_device_dependent_mask);
+
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ((device_dependent_mask & oldMods) == 0) {
+ /* In this case, we can't detect the keyboard, so use the left side
+ * to represent both, and release it.
+ */
+ SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+ return;
+ }
+
+ /*
+ * This could have been done in an if-else case because at this point,
+ * we know that all keys have been released when calling this function.
+ * But I'm being paranoid so I want to handle each separately,
+ * so I hope this doesn't cause other problems.
+ */
+ if ( left_device_dependent_mask & oldMods ) {
+ SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+ }
+ if ( right_device_dependent_mask & oldMods ) {
+ SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
+ }
+}
+
+/* This function will handle the modifier keys and also determine the
+ * correct side of the key.
+ */
+static void
+DoSidedModifiers(unsigned short scancode,
+ unsigned int oldMods, unsigned int newMods)
+{
+ /* Set up arrays for the key syms for the left and right side. */
+ const SDL_Scancode left_mapping[] = {
+ SDL_SCANCODE_LSHIFT,
+ SDL_SCANCODE_LCTRL,
+ SDL_SCANCODE_LALT,
+ SDL_SCANCODE_LGUI
+ };
+ const SDL_Scancode right_mapping[] = {
+ SDL_SCANCODE_RSHIFT,
+ SDL_SCANCODE_RCTRL,
+ SDL_SCANCODE_RALT,
+ SDL_SCANCODE_RGUI
+ };
+ /* Set up arrays for the device dependent masks with indices that
+ * correspond to the _mapping arrays
+ */
+ const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
+ const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
+
+ unsigned int i, bit;
+
+ /* Iterate through the bits, testing each against the old modifiers */
+ for (i = 0, bit = NSEventModifierFlagShift; bit <= NSEventModifierFlagCommand; bit <<= 1, ++i) {
+ unsigned int oldMask, newMask;
+
+ oldMask = oldMods & bit;
+ newMask = newMods & bit;
+
+ /* If the bit is set, we must always examine it because the left
+ * and right side keys may alternate or both may be pressed.
+ */
+ if (newMask) {
+ HandleModifierSide(bit, oldMods, newMods,
+ left_mapping[i], right_mapping[i],
+ left_device_mapping[i], right_device_mapping[i]);
+ }
+ /* If the state changed from pressed to unpressed, we must examine
+ * the device dependent bits to release the correct keys.
+ */
+ else if (oldMask && oldMask != newMask) {
+ ReleaseModifierSide(bit, oldMods, newMods,
+ left_mapping[i], right_mapping[i],
+ left_device_mapping[i], right_device_mapping[i]);
+ }
+ }
+}
+
+static void
+HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (modifierFlags == data->modifierFlags) {
+ return;
+ }
+
+ DoSidedModifiers(scancode, data->modifierFlags, modifierFlags);
+ data->modifierFlags = modifierFlags;
+}
+
+static void
+UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
+{
+ TISInputSourceRef key_layout;
+ const void *chr_data;
+ int i;
+ SDL_Scancode scancode;
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
+
+ /* See if the keymap needs to be updated */
+ key_layout = TISCopyCurrentKeyboardLayoutInputSource();
+ if (key_layout == data->key_layout) {
+ return;
+ }
+ data->key_layout = key_layout;
+
+ SDL_GetDefaultKeymap(keymap);
+
+ /* Try Unicode data first */
+ CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
+ if (uchrDataRef) {
+ chr_data = CFDataGetBytePtr(uchrDataRef);
+ } else {
+ goto cleanup;
+ }
+
+ if (chr_data) {
+ UInt32 keyboard_type = LMGetKbdType();
+ OSStatus err;
+
+ for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
+ UniChar s[8];
+ UniCharCount len;
+ UInt32 dead_key_state;
+
+ /* Make sure this scancode is a valid character scancode */
+ scancode = darwin_scancode_table[i];
+ if (scancode == SDL_SCANCODE_UNKNOWN ||
+ (keymap[scancode] & SDLK_SCANCODE_MASK)) {
+ continue;
+ }
+
+ dead_key_state = 0;
+ err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
+ i, kUCKeyActionDown,
+ 0, keyboard_type,
+ kUCKeyTranslateNoDeadKeysMask,
+ &dead_key_state, 8, &len, s);
+ if (err != noErr) {
+ continue;
+ }
+
+ if (len > 0 && s[0] != 0x10) {
+ keymap[scancode] = s[0];
+ }
+ }
+ SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
+ if (send_event) {
+ SDL_SendKeymapChangedEvent();
+ }
+ return;
+ }
+
+cleanup:
+ CFRelease(key_layout);
+}
+
+void
+Cocoa_InitKeyboard(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ UpdateKeymap(data, SDL_FALSE);
+
+ /* Set our own names for the platform-dependent but layout-independent keys */
+ /* This key is NumLock on the MacBook keyboard. :) */
+ /*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/
+ SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option");
+ SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command");
+ SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
+ SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
+
+ data->modifierFlags = [NSEvent modifierFlags];
+ SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSEventModifierFlagCapsLock) != 0);
+
+ InitHIDCallback();
+}
+
+void
+Cocoa_StartTextInput(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ SDL_Window *window = SDL_GetKeyboardFocus();
+ NSWindow *nswindow = nil;
+ if (window) {
+ nswindow = ((SDL_WindowData*)window->driverdata)->nswindow;
+ }
+
+ NSView *parentView = [nswindow contentView];
+
+ /* We only keep one field editor per process, since only the front most
+ * window can receive text input events, so it make no sense to keep more
+ * than one copy. When we switched to another window and requesting for
+ * text input, simply remove the field editor from its superview then add
+ * it to the front most window's content view */
+ if (!data->fieldEdit) {
+ data->fieldEdit =
+ [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
+ }
+
+ if (![[data->fieldEdit superview] isEqual:parentView]) {
+ /* DEBUG_IME(@"add fieldEdit to window contentView"); */
+ [data->fieldEdit removeFromSuperview];
+ [parentView addSubview: data->fieldEdit];
+ [nswindow makeFirstResponder: data->fieldEdit];
+ }
+}}
+
+void
+Cocoa_StopTextInput(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (data && data->fieldEdit) {
+ [data->fieldEdit removeFromSuperview];
+ [data->fieldEdit release];
+ data->fieldEdit = nil;
+ }
+}}
+
+void
+Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (!rect) {
+ SDL_InvalidParamError("rect");
+ return;
+ }
+
+ [data->fieldEdit setInputRect:rect];
+}
+
+void
+Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
+{
+ SDL_VideoData *data = _this ? ((SDL_VideoData *) _this->driverdata) : NULL;
+ if (!data) {
+ return; /* can happen when returning from fullscreen Space on shutdown */
+ }
+
+ unsigned short scancode = [event keyCode];
+ SDL_Scancode code;
+#if 0
+ const char *text;
+#endif
+
+ if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
+ /* see comments in SDL_cocoakeys.h */
+ scancode = 60 - scancode;
+ }
+
+ if (scancode < SDL_arraysize(darwin_scancode_table)) {
+ code = darwin_scancode_table[scancode];
+ } else {
+ /* Hmm, does this ever happen? If so, need to extend the keymap... */
+ code = SDL_SCANCODE_UNKNOWN;
+ }
+
+ switch ([event type]) {
+ case NSEventTypeKeyDown:
+ if (![event isARepeat]) {
+ /* See if we need to rebuild the keyboard layout */
+ UpdateKeymap(data, SDL_TRUE);
+ }
+
+ SDL_SendKeyboardKey(SDL_PRESSED, code);
+#if 1
+ if (code == SDL_SCANCODE_UNKNOWN) {
+ fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list <https://discourse.libsdl.org/> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
+ }
+#endif
+ if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
+ /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
+ [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
+#if 0
+ text = [[event characters] UTF8String];
+ if(text && *text) {
+ SDL_SendKeyboardText(text);
+ [data->fieldEdit setString:@""];
+ }
+#endif
+ }
+ break;
+ case NSEventTypeKeyUp:
+ SDL_SendKeyboardKey(SDL_RELEASED, code);
+ break;
+ case NSEventTypeFlagsChanged:
+ /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
+ HandleModifiers(_this, scancode, [event modifierFlags]);
+ break;
+ default: /* just to avoid compiler warnings */
+ break;
+ }
+}
+
+void
+Cocoa_QuitKeyboard(_THIS)
+{
+ QuitHIDCallback();
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.h
new file mode 100644
index 0000000..74a815a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.h
@@ -0,0 +1,29 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+extern int Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.m
new file mode 100644
index 0000000..a98237f
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamessagebox.m
@@ -0,0 +1,145 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_events.h"
+#include "SDL_timer.h"
+#include "SDL_messagebox.h"
+#include "SDL_cocoavideo.h"
+
+@interface SDLMessageBoxPresenter : NSObject {
+@public
+ NSInteger clicked;
+ NSWindow *nswindow;
+}
+- (id) initWithParentWindow:(SDL_Window *)window;
+- (void) alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
+@end
+
+@implementation SDLMessageBoxPresenter
+- (id) initWithParentWindow:(SDL_Window *)window
+{
+ self = [super init];
+ if (self) {
+ clicked = -1;
+
+ /* Retain the NSWindow because we'll show the alert later on the main thread */
+ if (window) {
+ nswindow = [((SDL_WindowData *) window->driverdata)->nswindow retain];
+ } else {
+ nswindow = NULL;
+ }
+ }
+
+ return self;
+}
+
+- (void)showAlert:(NSAlert*)alert
+{
+ if (nswindow) {
+#ifdef MAC_OS_X_VERSION_10_9
+ if ([alert respondsToSelector:@selector(beginSheetModalForWindow:completionHandler:)]) {
+ [alert beginSheetModalForWindow:nswindow completionHandler:^(NSModalResponse returnCode) {
+ clicked = returnCode;
+ }];
+ } else
+#endif
+ {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+ [alert beginSheetModalForWindow:nswindow modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
+#endif
+ }
+
+ while (clicked < 0) {
+ SDL_PumpEvents();
+ SDL_Delay(100);
+ }
+
+ [nswindow release];
+ } else {
+ clicked = [alert runModal];
+ }
+}
+
+- (void) alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
+{
+ clicked = returnCode;
+}
+
+@end
+
+
+/* Display a Cocoa message box */
+int
+Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{ @autoreleasepool
+{
+ Cocoa_RegisterApp();
+
+ NSAlert* alert = [[[NSAlert alloc] init] autorelease];
+
+ if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
+ [alert setAlertStyle:NSAlertStyleCritical];
+ } else if (messageboxdata->flags & SDL_MESSAGEBOX_WARNING) {
+ [alert setAlertStyle:NSAlertStyleWarning];
+ } else {
+ [alert setAlertStyle:NSAlertStyleInformational];
+ }
+
+ [alert setMessageText:[NSString stringWithUTF8String:messageboxdata->title]];
+ [alert setInformativeText:[NSString stringWithUTF8String:messageboxdata->message]];
+
+ const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
+ int i;
+ for (i = 0; i < messageboxdata->numbuttons; ++i) {
+ NSButton *button = [alert addButtonWithTitle:[NSString stringWithUTF8String:buttons[i].text]];
+ if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
+ [button setKeyEquivalent:@"\r"];
+ } else if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
+ [button setKeyEquivalent:@"\033"];
+ } else {
+ [button setKeyEquivalent:@""];
+ }
+ }
+
+ SDLMessageBoxPresenter* presenter = [[[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window] autorelease];
+
+ [presenter performSelectorOnMainThread:@selector(showAlert:)
+ withObject:alert
+ waitUntilDone:YES];
+
+ int returnValue = 0;
+ NSInteger clicked = presenter->clicked;
+ if (clicked >= NSAlertFirstButtonReturn) {
+ clicked -= NSAlertFirstButtonReturn;
+ *buttonid = buttons[clicked].buttonid;
+ } else {
+ returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
+ }
+
+ return returnValue;
+}}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.h
new file mode 100644
index 0000000..185d45d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.h
@@ -0,0 +1,63 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+ * @author Mark Callow, www.edgewise-consulting.com.
+ *
+ * Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
+ * how to add a CAMetalLayer backed view.
+ */
+
+#ifndef SDL_cocoametalview_h_
+#define SDL_cocoametalview_h_
+
+#import "../SDL_sysvideo.h"
+#import "SDL_cocoawindow.h"
+
+#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
+
+#import <Cocoa/Cocoa.h>
+#import <Metal/Metal.h>
+#import <QuartzCore/CAMetalLayer.h>
+
+#define METALVIEW_TAG 255
+
+@interface SDL_cocoametalview : NSView
+
+- (instancetype)initWithFrame:(NSRect)frame
+ highDPI:(BOOL)highDPI;
+
+/* Override superclass tag so this class can set it. */
+@property (assign, readonly) NSInteger tag;
+
+@property (nonatomic) BOOL highDPI;
+
+@end
+
+SDL_cocoametalview* Cocoa_Mtl_AddMetalView(SDL_Window* window);
+
+void Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
+
+#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
+
+#endif /* SDL_cocoametalview_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.m
new file mode 100644
index 0000000..9447fb8
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoametalview.m
@@ -0,0 +1,138 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+ * @author Mark Callow, www.edgewise-consulting.com.
+ *
+ * Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
+ * how to add a CAMetalLayer backed view.
+ */
+
+#import "SDL_cocoametalview.h"
+
+#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
+
+#include "SDL_assert.h"
+
+@implementation SDL_cocoametalview
+
+/* Return a Metal-compatible layer. */
++ (Class)layerClass
+{
+ return NSClassFromString(@"CAMetalLayer");
+}
+
+/* Indicate the view wants to draw using a backing layer instead of drawRect. */
+- (BOOL)wantsUpdateLayer
+{
+ return YES;
+}
+
+/* When the wantsLayer property is set to YES, this method will be invoked to
+ * return a layer instance.
+ */
+- (CALayer*)makeBackingLayer
+{
+ return [self.class.layerClass layer];
+}
+
+- (instancetype)initWithFrame:(NSRect)frame
+ highDPI:(BOOL)highDPI
+{
+ if ((self = [super initWithFrame:frame])) {
+ self.highDPI = highDPI;
+ self.wantsLayer = YES;
+
+ /* Allow resize. */
+ self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+
+ [self updateDrawableSize];
+ }
+
+ return self;
+}
+
+- (NSInteger)tag
+{
+ return METALVIEW_TAG;
+}
+
+- (void)updateDrawableSize
+{
+ CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer;
+ CGSize size = self.bounds.size;
+ CGSize backingSize = size;
+
+ if (self.highDPI) {
+ /* Note: NSHighResolutionCapable must be set to true in the app's
+ * Info.plist in order for the backing size to be high res.
+ */
+ backingSize = [self convertSizeToBacking:size];
+ }
+
+ metalLayer.contentsScale = backingSize.height / size.height;
+ metalLayer.drawableSize = backingSize;
+}
+
+/* Set the size of the metal drawables when the view is resized. */
+- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
+{
+ [super resizeWithOldSuperviewSize:oldSize];
+ [self updateDrawableSize];
+}
+
+@end
+
+SDL_cocoametalview*
+Cocoa_Mtl_AddMetalView(SDL_Window* window)
+{
+ SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
+ NSView *view = data->nswindow.contentView;
+ BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
+ SDL_cocoametalview *metalview;
+
+ metalview = [[SDL_cocoametalview alloc] initWithFrame:view.frame highDPI:highDPI];
+ [view addSubview:metalview];
+ return metalview;
+}
+
+void
+Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
+{
+ SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
+ NSView *view = data->nswindow.contentView;
+ SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
+ if (metalview) {
+ CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
+ assert(layer != NULL);
+ if (w) {
+ *w = layer.drawableSize.width;
+ }
+ if (h) {
+ *h = layer.drawableSize.height;
+ }
+ } else {
+ SDL_GetWindowSize(window, w, h);
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.h
new file mode 100644
index 0000000..05482e8
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.h
@@ -0,0 +1,46 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoamodes_h_
+#define SDL_cocoamodes_h_
+
+typedef struct
+{
+ CGDirectDisplayID display;
+} SDL_DisplayData;
+
+typedef struct
+{
+ CGDisplayModeRef moderef;
+} SDL_DisplayModeData;
+
+extern void Cocoa_InitModes(_THIS);
+extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern int Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
+extern int Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hpdi, float * vdpi);
+extern int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+extern void Cocoa_QuitModes(_THIS);
+
+#endif /* SDL_cocoamodes_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.m
new file mode 100644
index 0000000..97ccd94
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamodes.m
@@ -0,0 +1,490 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+#include "SDL_assert.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoavideo.h"
+
+/* We need this for IODisplayCreateInfoDictionary and kIODisplayOnlyPreferredName */
+#include <IOKit/graphics/IOGraphicsLib.h>
+
+/* We need this for CVDisplayLinkGetNominalOutputVideoRefreshPeriod */
+#include <CoreVideo/CVBase.h>
+#include <CoreVideo/CVDisplayLink.h>
+
+/* we need this for ShowMenuBar() and HideMenuBar(). */
+#include <Carbon/Carbon.h>
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include <AvailabilityMacros.h>
+
+
+static void
+Cocoa_ToggleMenuBar(const BOOL show)
+{
+ /* !!! FIXME: keep an eye on this.
+ * ShowMenuBar/HideMenuBar is officially unavailable for 64-bit binaries.
+ * It happens to work, as of 10.7, but we're going to see if
+ * we can just simply do without it on newer OSes...
+ */
+#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
+ if (show) {
+ ShowMenuBar();
+ } else {
+ HideMenuBar();
+ }
+#endif
+}
+
+static int
+CG_SetError(const char *prefix, CGDisplayErr result)
+{
+ const char *error;
+
+ switch (result) {
+ case kCGErrorFailure:
+ error = "kCGErrorFailure";
+ break;
+ case kCGErrorIllegalArgument:
+ error = "kCGErrorIllegalArgument";
+ break;
+ case kCGErrorInvalidConnection:
+ error = "kCGErrorInvalidConnection";
+ break;
+ case kCGErrorInvalidContext:
+ error = "kCGErrorInvalidContext";
+ break;
+ case kCGErrorCannotComplete:
+ error = "kCGErrorCannotComplete";
+ break;
+ case kCGErrorNotImplemented:
+ error = "kCGErrorNotImplemented";
+ break;
+ case kCGErrorRangeCheck:
+ error = "kCGErrorRangeCheck";
+ break;
+ case kCGErrorTypeCheck:
+ error = "kCGErrorTypeCheck";
+ break;
+ case kCGErrorInvalidOperation:
+ error = "kCGErrorInvalidOperation";
+ break;
+ case kCGErrorNoneAvailable:
+ error = "kCGErrorNoneAvailable";
+ break;
+ default:
+ error = "Unknown Error";
+ break;
+ }
+ return SDL_SetError("%s: %s", prefix, error);
+}
+
+static SDL_bool
+GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_DisplayMode *mode)
+{
+ SDL_DisplayModeData *data;
+ int width = 0;
+ int height = 0;
+ int bpp = 0;
+ int refreshRate = 0;
+ CFStringRef fmt;
+
+ data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
+ if (!data) {
+ return SDL_FALSE;
+ }
+ data->moderef = vidmode;
+
+ fmt = CGDisplayModeCopyPixelEncoding(vidmode);
+ width = (int) CGDisplayModeGetWidth(vidmode);
+ height = (int) CGDisplayModeGetHeight(vidmode);
+ refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
+
+ if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 32;
+ } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 16;
+ } else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 30;
+ } else {
+ bpp = 0; /* ignore 8-bit and such for now. */
+ }
+
+ CFRelease(fmt);
+
+ /* CGDisplayModeGetRefreshRate returns 0 for many non-CRT displays. */
+ if (refreshRate == 0 && link != NULL) {
+ CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
+ if ((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0) {
+ refreshRate = (int) ((time.timeScale / (double) time.timeValue) + 0.5);
+ }
+ }
+
+ mode->format = SDL_PIXELFORMAT_UNKNOWN;
+ switch (bpp) {
+ case 16:
+ mode->format = SDL_PIXELFORMAT_ARGB1555;
+ break;
+ case 30:
+ mode->format = SDL_PIXELFORMAT_ARGB2101010;
+ break;
+ case 32:
+ mode->format = SDL_PIXELFORMAT_ARGB8888;
+ break;
+ case 8: /* We don't support palettized modes now */
+ default: /* Totally unrecognizable bit depth. */
+ SDL_free(data);
+ return SDL_FALSE;
+ }
+ mode->w = width;
+ mode->h = height;
+ mode->refresh_rate = refreshRate;
+ mode->driverdata = data;
+ return SDL_TRUE;
+}
+
+static const char *
+Cocoa_GetDisplayName(CGDirectDisplayID displayID)
+{
+ CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
+ NSDictionary *localizedNames = [(NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
+ const char* displayName = NULL;
+
+ if ([localizedNames count] > 0) {
+ displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
+ }
+ CFRelease(deviceInfo);
+ return displayName;
+}
+
+void
+Cocoa_InitModes(_THIS)
+{ @autoreleasepool
+{
+ CGDisplayErr result;
+ CGDirectDisplayID *displays;
+ CGDisplayCount numDisplays;
+ int pass, i;
+
+ result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
+ if (result != kCGErrorSuccess) {
+ CG_SetError("CGGetOnlineDisplayList()", result);
+ return;
+ }
+ displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
+ result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
+ if (result != kCGErrorSuccess) {
+ CG_SetError("CGGetOnlineDisplayList()", result);
+ SDL_stack_free(displays);
+ return;
+ }
+
+ /* Pick up the primary display in the first pass, then get the rest */
+ for (pass = 0; pass < 2; ++pass) {
+ for (i = 0; i < numDisplays; ++i) {
+ SDL_VideoDisplay display;
+ SDL_DisplayData *displaydata;
+ SDL_DisplayMode mode;
+ CGDisplayModeRef moderef = NULL;
+ CVDisplayLinkRef link = NULL;
+
+ if (pass == 0) {
+ if (!CGDisplayIsMain(displays[i])) {
+ continue;
+ }
+ } else {
+ if (CGDisplayIsMain(displays[i])) {
+ continue;
+ }
+ }
+
+ if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
+ continue;
+ }
+
+ moderef = CGDisplayCopyDisplayMode(displays[i]);
+
+ if (!moderef) {
+ continue;
+ }
+
+ displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
+ if (!displaydata) {
+ CGDisplayModeRelease(moderef);
+ continue;
+ }
+ displaydata->display = displays[i];
+
+ CVDisplayLinkCreateWithCGDisplay(displays[i], &link);
+
+ SDL_zero(display);
+ /* this returns a stddup'ed string */
+ display.name = (char *)Cocoa_GetDisplayName(displays[i]);
+ if (!GetDisplayMode(_this, moderef, link, &mode)) {
+ CVDisplayLinkRelease(link);
+ CGDisplayModeRelease(moderef);
+ SDL_free(display.name);
+ SDL_free(displaydata);
+ continue;
+ }
+
+ CVDisplayLinkRelease(link);
+
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display);
+ SDL_free(display.name);
+ }
+ }
+ SDL_stack_free(displays);
+}}
+
+int
+Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ CGRect cgrect;
+
+ cgrect = CGDisplayBounds(displaydata->display);
+ rect->x = (int)cgrect.origin.x;
+ rect->y = (int)cgrect.origin.y;
+ rect->w = (int)cgrect.size.width;
+ rect->h = (int)cgrect.size.height;
+ return 0;
+}
+
+int
+Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ const CGDirectDisplayID cgdisplay = displaydata->display;
+ NSArray *screens = [NSScreen screens];
+ NSScreen *screen = nil;
+
+ /* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
+ for (NSScreen *i in screens) {
+ const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ if (thisDisplay == cgdisplay) {
+ screen = i;
+ break;
+ }
+ }
+
+ SDL_assert(screen != nil); /* didn't find it?! */
+ if (screen == nil) {
+ return -1;
+ }
+
+ const CGRect cgrect = CGDisplayBounds(cgdisplay);
+ const NSRect frame = [screen visibleFrame];
+
+ // !!! FIXME: I assume -[NSScreen visibleFrame] is relative to the origin of the screen in question and not the whole desktop.
+ // !!! FIXME: The math vs CGDisplayBounds might be incorrect if that's not the case, though. Check this.
+ rect->x = (int)(cgrect.origin.x + frame.origin.x);
+ rect->y = (int)(cgrect.origin.y + frame.origin.y);
+ rect->w = (int)frame.size.width;
+ rect->h = (int)frame.size.height;
+
+ return 0;
+}
+
+int
+Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
+{
+ const float MM_IN_INCH = 25.4f;
+
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+
+ CGSize displaySize = CGDisplayScreenSize(data->display);
+ int pixelWidth = (int) CGDisplayPixelsWide(data->display);
+ int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
+
+ if (ddpi) {
+ *ddpi = SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH);
+ }
+ if (hdpi) {
+ *hdpi = pixelWidth * MM_IN_INCH / displaySize.width;
+ }
+ if (vdpi) {
+ *vdpi = pixelHeight * MM_IN_INCH / displaySize.height;
+ }
+
+ return 0;
+}
+
+void
+Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
+{
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+ CVDisplayLinkRef link = NULL;
+ CGDisplayModeRef desktopmoderef;
+ SDL_DisplayMode desktopmode;
+ CFArrayRef modes;
+
+ CVDisplayLinkCreateWithCGDisplay(data->display, &link);
+
+ desktopmoderef = CGDisplayCopyDisplayMode(data->display);
+
+ /* CopyAllDisplayModes won't always contain the desktop display mode (if
+ * NULL is passed in) - for example on a retina 15" MBP, System Preferences
+ * allows choosing 1920x1200 but it's not in the list. AddDisplayMode makes
+ * sure there are no duplicates so it's safe to always add the desktop mode
+ * even in cases where it is in the CopyAllDisplayModes list.
+ */
+ if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, link, &desktopmode)) {
+ if (!SDL_AddDisplayMode(display, &desktopmode)) {
+ CGDisplayModeRelease(desktopmoderef);
+ SDL_free(desktopmode.driverdata);
+ }
+ } else {
+ CGDisplayModeRelease(desktopmoderef);
+ }
+
+ modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
+
+ if (modes) {
+ CFIndex i;
+ const CFIndex count = CFArrayGetCount(modes);
+
+ for (i = 0; i < count; i++) {
+ CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+ SDL_DisplayMode mode;
+
+ if (GetDisplayMode(_this, moderef, link, &mode)) {
+ if (SDL_AddDisplayMode(display, &mode)) {
+ CGDisplayModeRetain(moderef);
+ } else {
+ SDL_free(mode.driverdata);
+ }
+ }
+ }
+
+ CFRelease(modes);
+ }
+
+ CVDisplayLinkRelease(link);
+}
+
+int
+Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
+ CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
+ CGError result;
+
+ /* Fade to black to hide resolution-switching flicker */
+ if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
+ CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
+ }
+
+ if (data == display->desktop_mode.driverdata) {
+ /* Restoring desktop mode */
+ CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
+
+ if (CGDisplayIsMain(displaydata->display)) {
+ CGReleaseAllDisplays();
+ } else {
+ CGDisplayRelease(displaydata->display);
+ }
+
+ if (CGDisplayIsMain(displaydata->display)) {
+ Cocoa_ToggleMenuBar(YES);
+ }
+ } else {
+ /* Put up the blanking window (a window above all other windows) */
+ if (CGDisplayIsMain(displaydata->display)) {
+ /* If we don't capture all displays, Cocoa tries to rearrange windows... *sigh* */
+ result = CGCaptureAllDisplays();
+ } else {
+ result = CGDisplayCapture(displaydata->display);
+ }
+ if (result != kCGErrorSuccess) {
+ CG_SetError("CGDisplayCapture()", result);
+ goto ERR_NO_CAPTURE;
+ }
+
+ /* Do the physical switch */
+ result = CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
+ if (result != kCGErrorSuccess) {
+ CG_SetError("CGDisplaySwitchToMode()", result);
+ goto ERR_NO_SWITCH;
+ }
+
+ /* Hide the menu bar so it doesn't intercept events */
+ if (CGDisplayIsMain(displaydata->display)) {
+ Cocoa_ToggleMenuBar(NO);
+ }
+ }
+
+ /* Fade in again (asynchronously) */
+ if (fade_token != kCGDisplayFadeReservationInvalidToken) {
+ CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation(fade_token);
+ }
+
+ return 0;
+
+ /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
+ERR_NO_SWITCH:
+ CGDisplayRelease(displaydata->display);
+ERR_NO_CAPTURE:
+ if (fade_token != kCGDisplayFadeReservationInvalidToken) {
+ CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
+ CGReleaseDisplayFadeReservation(fade_token);
+ }
+ return -1;
+}
+
+void
+Cocoa_QuitModes(_THIS)
+{
+ int i, j;
+
+ for (i = 0; i < _this->num_displays; ++i) {
+ SDL_VideoDisplay *display = &_this->displays[i];
+ SDL_DisplayModeData *mode;
+
+ if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
+ Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
+ }
+
+ mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
+ CGDisplayModeRelease(mode->moderef);
+
+ for (j = 0; j < display->num_display_modes; j++) {
+ mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
+ CGDisplayModeRelease(mode->moderef);
+ }
+
+ }
+ Cocoa_ToggleMenuBar(YES);
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.h
new file mode 100644
index 0000000..b79a3cf
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.h
@@ -0,0 +1,52 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoamouse_h_
+#define SDL_cocoamouse_h_
+
+#include "SDL_cocoavideo.h"
+
+extern void Cocoa_InitMouse(_THIS);
+extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
+extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event);
+extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y);
+extern void Cocoa_QuitMouse(_THIS);
+
+typedef struct {
+ /* Wether we've seen a cursor warp since the last move event. */
+ SDL_bool seenWarp;
+ /* What location our last cursor warp was to. */
+ CGFloat lastWarpX;
+ CGFloat lastWarpY;
+ /* What location we last saw the cursor move to. */
+ CGFloat lastMoveX;
+ CGFloat lastMoveY;
+ void *tapdata;
+} SDL_MouseData;
+
+@interface NSCursor (InvisibleCursor)
++ (NSCursor *)invisibleCursor;
+@end
+
+#endif /* SDL_cocoamouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.m
new file mode 100644
index 0000000..c9db253
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamouse.m
@@ -0,0 +1,477 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_assert.h"
+#include "SDL_events.h"
+#include "SDL_cocoamouse.h"
+#include "SDL_cocoamousetap.h"
+#include "SDL_cocoavideo.h"
+
+#include "../../events/SDL_mouse_c.h"
+
+/* #define DEBUG_COCOAMOUSE */
+
+#ifdef DEBUG_COCOAMOUSE
+#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
+#else
+#define DLog(...) do { } while (0)
+#endif
+
+@implementation NSCursor (InvisibleCursor)
++ (NSCursor *)invisibleCursor
+{
+ static NSCursor *invisibleCursor = NULL;
+ if (!invisibleCursor) {
+ /* RAW 16x16 transparent GIF */
+ static unsigned char cursorBytes[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x10, 0x00, 0x00, 0x02, 0x0E, 0x8C, 0x8F, 0xA9, 0xCB, 0xED,
+ 0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B
+ };
+
+ NSData *cursorData = [NSData dataWithBytesNoCopy:&cursorBytes[0]
+ length:sizeof(cursorBytes)
+ freeWhenDone:NO];
+ NSImage *cursorImage = [[[NSImage alloc] initWithData:cursorData] autorelease];
+ invisibleCursor = [[NSCursor alloc] initWithImage:cursorImage
+ hotSpot:NSZeroPoint];
+ }
+
+ return invisibleCursor;
+}
+@end
+
+
+static SDL_Cursor *
+Cocoa_CreateDefaultCursor()
+{ @autoreleasepool
+{
+ NSCursor *nscursor;
+ SDL_Cursor *cursor = NULL;
+
+ nscursor = [NSCursor arrowCursor];
+
+ if (nscursor) {
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ cursor->driverdata = nscursor;
+ [nscursor retain];
+ }
+ }
+
+ return cursor;
+}}
+
+static SDL_Cursor *
+Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{ @autoreleasepool
+{
+ NSImage *nsimage;
+ NSCursor *nscursor = NULL;
+ SDL_Cursor *cursor = NULL;
+
+ nsimage = Cocoa_CreateImage(surface);
+ if (nsimage) {
+ nscursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(hot_x, hot_y)];
+ }
+
+ if (nscursor) {
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ cursor->driverdata = nscursor;
+ } else {
+ [nscursor release];
+ }
+ }
+
+ return cursor;
+}}
+
+static SDL_Cursor *
+Cocoa_CreateSystemCursor(SDL_SystemCursor id)
+{ @autoreleasepool
+{
+ NSCursor *nscursor = NULL;
+ SDL_Cursor *cursor = NULL;
+
+ switch(id) {
+ case SDL_SYSTEM_CURSOR_ARROW:
+ nscursor = [NSCursor arrowCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_IBEAM:
+ nscursor = [NSCursor IBeamCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_WAIT:
+ nscursor = [NSCursor arrowCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_CROSSHAIR:
+ nscursor = [NSCursor crosshairCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_WAITARROW:
+ nscursor = [NSCursor arrowCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_SIZENWSE:
+ case SDL_SYSTEM_CURSOR_SIZENESW:
+ nscursor = [NSCursor closedHandCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_SIZEWE:
+ nscursor = [NSCursor resizeLeftRightCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_SIZENS:
+ nscursor = [NSCursor resizeUpDownCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_SIZEALL:
+ nscursor = [NSCursor closedHandCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_NO:
+ nscursor = [NSCursor operationNotAllowedCursor];
+ break;
+ case SDL_SYSTEM_CURSOR_HAND:
+ nscursor = [NSCursor pointingHandCursor];
+ break;
+ default:
+ SDL_assert(!"Unknown system cursor");
+ return NULL;
+ }
+
+ if (nscursor) {
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ /* We'll free it later, so retain it here */
+ [nscursor retain];
+ cursor->driverdata = nscursor;
+ }
+ }
+
+ return cursor;
+}}
+
+static void
+Cocoa_FreeCursor(SDL_Cursor * cursor)
+{ @autoreleasepool
+{
+ NSCursor *nscursor = (NSCursor *)cursor->driverdata;
+
+ [nscursor release];
+ SDL_free(cursor);
+}}
+
+static int
+Cocoa_ShowCursor(SDL_Cursor * cursor)
+{ @autoreleasepool
+{
+ SDL_VideoDevice *device = SDL_GetVideoDevice();
+ SDL_Window *window = (device ? device->windows : NULL);
+ for (; window != NULL; window = window->next) {
+ SDL_WindowData *driverdata = (SDL_WindowData *)window->driverdata;
+ if (driverdata) {
+ [driverdata->nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
+ withObject:[driverdata->nswindow contentView]
+ waitUntilDone:NO];
+ }
+ }
+ return 0;
+}}
+
+static SDL_Window *
+SDL_FindWindowAtPoint(const int x, const int y)
+{
+ const SDL_Point pt = { x, y };
+ SDL_Window *i;
+ for (i = SDL_GetVideoDevice()->windows; i; i = i->next) {
+ const SDL_Rect r = { i->x, i->y, i->w, i->h };
+ if (SDL_PointInRect(&pt, &r)) {
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+Cocoa_WarpMouseGlobal(int x, int y)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (mouse->focus) {
+ SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
+ if ([data->listener isMoving]) {
+ DLog("Postponing warp, window being moved.");
+ [data->listener setPendingMoveX:x Y:y];
+ return 0;
+ }
+ }
+ const CGPoint point = CGPointMake((float)x, (float)y);
+
+ Cocoa_HandleMouseWarp(point.x, point.y);
+
+ CGWarpMouseCursorPosition(point);
+
+ /* CGWarpMouse causes a short delay by default, which is preventable by
+ * Calling this directly after. CGSetLocalEventsSuppressionInterval can also
+ * prevent it, but it's deprecated as of OS X 10.6.
+ */
+ if (!mouse->relative_mode) {
+ CGAssociateMouseAndMouseCursorPosition(YES);
+ }
+
+ /* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
+ * other implementations' APIs. Send what's appropriate.
+ */
+ if (!mouse->relative_mode) {
+ SDL_Window *win = SDL_FindWindowAtPoint(x, y);
+ SDL_SetMouseFocus(win);
+ if (win) {
+ SDL_assert(win == mouse->focus);
+ SDL_SendMouseMotion(win, mouse->mouseID, 0, x - win->x, y - win->y);
+ }
+ }
+
+ return 0;
+}
+
+static void
+Cocoa_WarpMouse(SDL_Window * window, int x, int y)
+{
+ Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
+}
+
+static int
+Cocoa_SetRelativeMouseMode(SDL_bool enabled)
+{
+ /* We will re-apply the relative mode when the window gets focus, if it
+ * doesn't have focus right now.
+ */
+ SDL_Window *window = SDL_GetMouseFocus();
+ if (!window) {
+ return 0;
+ }
+
+ /* We will re-apply the relative mode when the window finishes being moved,
+ * if it is being moved right now.
+ */
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ if ([data->listener isMoving]) {
+ return 0;
+ }
+
+ CGError result;
+ if (enabled) {
+ DLog("Turning on.");
+ result = CGAssociateMouseAndMouseCursorPosition(NO);
+ } else {
+ DLog("Turning off.");
+ result = CGAssociateMouseAndMouseCursorPosition(YES);
+ }
+ if (result != kCGErrorSuccess) {
+ return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
+ }
+
+ /* The hide/unhide calls are redundant most of the time, but they fix
+ * https://bugzilla.libsdl.org/show_bug.cgi?id=2550
+ */
+ if (enabled) {
+ [NSCursor hide];
+ } else {
+ [NSCursor unhide];
+ }
+ return 0;
+}
+
+static int
+Cocoa_CaptureMouse(SDL_Window *window)
+{
+ /* our Cocoa event code already tracks the mouse outside the window,
+ so all we have to do here is say "okay" and do what we always do. */
+ return 0;
+}
+
+static Uint32
+Cocoa_GetGlobalMouseState(int *x, int *y)
+{
+ const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
+ const NSPoint cocoaLocation = [NSEvent mouseLocation];
+ Uint32 retval = 0;
+
+ for (NSScreen *screen in [NSScreen screens]) {
+ NSRect frame = [screen frame];
+ if (NSMouseInRect(cocoaLocation, frame, NO)) {
+ *x = (int) cocoaLocation.x;
+ *y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
+ break;
+ }
+ }
+
+ retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
+ retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
+ retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
+ retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
+ retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
+
+ return retval;
+}
+
+void
+Cocoa_InitMouse(_THIS)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ mouse->driverdata = SDL_calloc(1, sizeof(SDL_MouseData));
+
+ mouse->CreateCursor = Cocoa_CreateCursor;
+ mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
+ mouse->ShowCursor = Cocoa_ShowCursor;
+ mouse->FreeCursor = Cocoa_FreeCursor;
+ mouse->WarpMouse = Cocoa_WarpMouse;
+ mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
+ mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
+ mouse->CaptureMouse = Cocoa_CaptureMouse;
+ mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
+
+ SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
+
+ Cocoa_InitMouseEventTap(mouse->driverdata);
+
+ SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
+ const NSPoint location = [NSEvent mouseLocation];
+ driverdata->lastMoveX = location.x;
+ driverdata->lastMoveY = location.y;
+}
+
+void
+Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
+{
+ switch ([event type]) {
+ case NSEventTypeMouseMoved:
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeOtherMouseDragged:
+ break;
+
+ default:
+ /* Ignore any other events. */
+ return;
+ }
+
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata;
+ if (!driverdata) {
+ return; /* can happen when returning from fullscreen Space on shutdown */
+ }
+
+ const SDL_bool seenWarp = driverdata->seenWarp;
+ driverdata->seenWarp = NO;
+
+ const NSPoint location = [NSEvent mouseLocation];
+ const CGFloat lastMoveX = driverdata->lastMoveX;
+ const CGFloat lastMoveY = driverdata->lastMoveY;
+ driverdata->lastMoveX = location.x;
+ driverdata->lastMoveY = location.y;
+ DLog("Last seen mouse: (%g, %g)", location.x, location.y);
+
+ /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
+ if (!mouse->relative_mode) {
+ return;
+ }
+
+ /* Ignore events that aren't inside the client area (i.e. title bar.) */
+ if ([event window]) {
+ NSRect windowRect = [[[event window] contentView] frame];
+ if (!NSMouseInRect([event locationInWindow], windowRect, NO)) {
+ return;
+ }
+ }
+
+ float deltaX = [event deltaX];
+ float deltaY = [event deltaY];
+
+ if (seenWarp) {
+ deltaX += (lastMoveX - driverdata->lastWarpX);
+ deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
+
+ DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
+ }
+
+ SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY);
+}
+
+void
+Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ CGFloat x = -[event deltaX];
+ CGFloat y = [event deltaY];
+ SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
+
+ if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) {
+ if ([event isDirectionInvertedFromDevice] == YES) {
+ direction = SDL_MOUSEWHEEL_FLIPPED;
+ }
+ }
+
+ if (x > 0) {
+ x = SDL_ceil(x);
+ } else if (x < 0) {
+ x = SDL_floor(x);
+ }
+ if (y > 0) {
+ y = SDL_ceil(y);
+ } else if (y < 0) {
+ y = SDL_floor(y);
+ }
+ SDL_SendMouseWheel(window, mouse->mouseID, x, y, direction);
+}
+
+void
+Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
+{
+ /* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
+ * since it gets included in the next movement event.
+ */
+ SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata;
+ driverdata->lastWarpX = x;
+ driverdata->lastWarpY = y;
+ driverdata->seenWarp = SDL_TRUE;
+
+ DLog("(%g, %g)", x, y);
+}
+
+void
+Cocoa_QuitMouse(_THIS)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (mouse) {
+ if (mouse->driverdata) {
+ Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
+ }
+
+ SDL_free(mouse->driverdata);
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.h
new file mode 100644
index 0000000..40ce386
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.h
@@ -0,0 +1,34 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoamousetap_h_
+#define SDL_cocoamousetap_h_
+
+#include "SDL_cocoamouse.h"
+
+extern void Cocoa_InitMouseEventTap(SDL_MouseData *driverdata);
+extern void Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled);
+extern void Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata);
+
+#endif /* SDL_cocoamousetap_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.m
new file mode 100644
index 0000000..aa4f152
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoamousetap.m
@@ -0,0 +1,286 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoamousetap.h"
+
+/* Event taps are forbidden in the Mac App Store, so we can only enable this
+ * code if your app doesn't need to ship through the app store.
+ * This code makes it so that a grabbed cursor cannot "leak" a mouse click
+ * past the edge of the window if moving the cursor too fast.
+ */
+#if SDL_MAC_NO_SANDBOX
+
+#include "SDL_keyboard.h"
+#include "SDL_cocoavideo.h"
+#include "../../thread/SDL_systhread.h"
+
+#include "../../events/SDL_mouse_c.h"
+
+typedef struct {
+ CFMachPortRef tap;
+ CFRunLoopRef runloop;
+ CFRunLoopSourceRef runloopSource;
+ SDL_Thread *thread;
+ SDL_sem *runloopStartedSemaphore;
+} SDL_MouseEventTapData;
+
+static const CGEventMask movementEventsMask =
+ CGEventMaskBit(kCGEventLeftMouseDragged)
+ | CGEventMaskBit(kCGEventRightMouseDragged)
+ | CGEventMaskBit(kCGEventMouseMoved);
+
+static const CGEventMask allGrabbedEventsMask =
+ CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp)
+ | CGEventMaskBit(kCGEventRightMouseDown) | CGEventMaskBit(kCGEventRightMouseUp)
+ | CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp)
+ | CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged)
+ | CGEventMaskBit(kCGEventMouseMoved);
+
+static CGEventRef
+Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)refcon;
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_Window *window = SDL_GetKeyboardFocus();
+ NSWindow *nswindow;
+ NSRect windowRect;
+ CGPoint eventLocation;
+
+ switch (type) {
+ case kCGEventTapDisabledByTimeout:
+ {
+ CGEventTapEnable(tapdata->tap, true);
+ return NULL;
+ }
+ case kCGEventTapDisabledByUserInput:
+ {
+ return NULL;
+ }
+ default:
+ break;
+ }
+
+
+ if (!window || !mouse) {
+ return event;
+ }
+
+ if (mouse->relative_mode) {
+ return event;
+ }
+
+ if (!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
+ return event;
+ }
+
+ /* This is the same coordinate system as Cocoa uses. */
+ nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
+ eventLocation = CGEventGetUnflippedLocation(event);
+ windowRect = [nswindow contentRectForFrameRect:[nswindow frame]];
+
+ if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), windowRect, NO)) {
+
+ /* This is in CGs global screenspace coordinate system, which has a
+ * flipped Y.
+ */
+ CGPoint newLocation = CGEventGetLocation(event);
+
+ if (eventLocation.x < NSMinX(windowRect)) {
+ newLocation.x = NSMinX(windowRect);
+ } else if (eventLocation.x >= NSMaxX(windowRect)) {
+ newLocation.x = NSMaxX(windowRect) - 1.0;
+ }
+
+ if (eventLocation.y <= NSMinY(windowRect)) {
+ newLocation.y -= (NSMinY(windowRect) - eventLocation.y + 1);
+ } else if (eventLocation.y > NSMaxY(windowRect)) {
+ newLocation.y += (eventLocation.y - NSMaxY(windowRect));
+ }
+
+ CGWarpMouseCursorPosition(newLocation);
+ CGAssociateMouseAndMouseCursorPosition(YES);
+
+ if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
+ /* For click events, we just constrain the event to the window, so
+ * no other app receives the click event. We can't due the same to
+ * movement events, since they mean that our warp cursor above
+ * behaves strangely.
+ */
+ CGEventSetLocation(event, newLocation);
+ }
+ }
+
+ return event;
+}
+
+static void
+SemaphorePostCallback(CFRunLoopTimerRef timer, void *info)
+{
+ SDL_SemPost((SDL_sem*)info);
+}
+
+static int
+Cocoa_MouseTapThread(void *data)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
+
+ /* Tap was created on main thread but we own it now. */
+ CFMachPortRef eventTap = tapdata->tap;
+ if (eventTap) {
+ /* Try to create a runloop source we can schedule. */
+ CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
+ if (runloopSource) {
+ tapdata->runloopSource = runloopSource;
+ } else {
+ CFRelease(eventTap);
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ /* TODO: Both here and in the return below, set some state in
+ * tapdata to indicate that initialization failed, which we should
+ * check in InitMouseEventTap, after we move the semaphore check
+ * from Quit to Init.
+ */
+ return 1;
+ }
+ } else {
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ return 1;
+ }
+
+ tapdata->runloop = CFRunLoopGetCurrent();
+ CFRunLoopAddSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
+ CFRunLoopTimerContext context = {.info = tapdata->runloopStartedSemaphore};
+ /* We signal the runloop started semaphore *after* the run loop has started, indicating it's safe to CFRunLoopStop it. */
+ CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, &SemaphorePostCallback, &context);
+ CFRunLoopAddTimer(tapdata->runloop, timer, kCFRunLoopCommonModes);
+ CFRelease(timer);
+
+ /* Run the event loop to handle events in the event tap. */
+ CFRunLoopRun();
+ /* Make sure this is signaled so that SDL_QuitMouseEventTap knows it can safely SDL_WaitThread for us. */
+ if (SDL_SemValue(tapdata->runloopStartedSemaphore) < 1) {
+ SDL_SemPost(tapdata->runloopStartedSemaphore);
+ }
+ CFRunLoopRemoveSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
+
+ /* Clean up. */
+ CGEventTapEnable(tapdata->tap, false);
+ CFRelease(tapdata->runloopSource);
+ CFRelease(tapdata->tap);
+ tapdata->runloopSource = NULL;
+ tapdata->tap = NULL;
+
+ return 0;
+}
+
+void
+Cocoa_InitMouseEventTap(SDL_MouseData* driverdata)
+{
+ SDL_MouseEventTapData *tapdata;
+ driverdata->tapdata = SDL_calloc(1, sizeof(SDL_MouseEventTapData));
+ tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
+
+ tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0);
+ if (tapdata->runloopStartedSemaphore) {
+ tapdata->tap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault, allGrabbedEventsMask,
+ &Cocoa_MouseTapCallback, tapdata);
+ if (tapdata->tap) {
+ /* Tap starts disabled, until app requests mouse grab */
+ CGEventTapEnable(tapdata->tap, false);
+ tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
+ if (tapdata->thread) {
+ /* Success - early out. Ownership transferred to thread. */
+ return;
+ }
+ CFRelease(tapdata->tap);
+ }
+ SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
+ }
+ SDL_free(driverdata->tapdata);
+ driverdata->tapdata = NULL;
+}
+
+void
+Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
+ if (tapdata && tapdata->tap)
+ {
+ CGEventTapEnable(tapdata->tap, !!enabled);
+ }
+}
+
+void
+Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
+{
+ SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
+ int status;
+
+ if (tapdata == NULL) {
+ /* event tap was already cleaned up (possibly due to CGEventTapCreate
+ * returning null.)
+ */
+ return;
+ }
+
+ /* Ensure that the runloop has been started first.
+ * TODO: Move this to InitMouseEventTap, check for error conditions that can
+ * happen in Cocoa_MouseTapThread, and fall back to the non-EventTap way of
+ * grabbing the mouse if it fails to Init.
+ */
+ status = SDL_SemWaitTimeout(tapdata->runloopStartedSemaphore, 5000);
+ if (status > -1) {
+ /* Then stop it, which will cause Cocoa_MouseTapThread to return. */
+ CFRunLoopStop(tapdata->runloop);
+ /* And then wait for Cocoa_MouseTapThread to finish cleaning up. It
+ * releases some of the pointers in tapdata. */
+ SDL_WaitThread(tapdata->thread, &status);
+ }
+
+ SDL_free(driverdata->tapdata);
+ driverdata->tapdata = NULL;
+}
+
+#else /* SDL_MAC_NO_SANDBOX */
+
+void
+Cocoa_InitMouseEventTap(SDL_MouseData *unused)
+{
+}
+
+void
+Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
+{
+}
+
+void
+Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
+{
+}
+
+#endif /* !SDL_MAC_NO_SANDBOX */
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.h
new file mode 100644
index 0000000..81ca5ed
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.h
@@ -0,0 +1,68 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoaopengl_h_
+#define SDL_cocoaopengl_h_
+
+#if SDL_VIDEO_OPENGL_CGL
+
+#include "SDL_atomic.h"
+#import <Cocoa/Cocoa.h>
+
+struct SDL_GLDriverData
+{
+ int initialized;
+};
+
+@interface SDLOpenGLContext : NSOpenGLContext {
+ SDL_atomic_t dirty;
+ SDL_Window *window;
+}
+
+- (id)initWithFormat:(NSOpenGLPixelFormat *)format
+ shareContext:(NSOpenGLContext *)share;
+- (void)scheduleUpdate;
+- (void)updateIfNeeded;
+- (void)setWindow:(SDL_Window *)window;
+
+@end
+
+
+/* OpenGL functions */
+extern int Cocoa_GL_LoadLibrary(_THIS, const char *path);
+extern void *Cocoa_GL_GetProcAddress(_THIS, const char *proc);
+extern void Cocoa_GL_UnloadLibrary(_THIS);
+extern SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window * window);
+extern int Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window,
+ SDL_GLContext context);
+extern void Cocoa_GL_GetDrawableSize(_THIS, SDL_Window * window,
+ int * w, int * h);
+extern int Cocoa_GL_SetSwapInterval(_THIS, int interval);
+extern int Cocoa_GL_GetSwapInterval(_THIS);
+extern int Cocoa_GL_SwapWindow(_THIS, SDL_Window * window);
+extern void Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context);
+
+#endif /* SDL_VIDEO_OPENGL_CGL */
+
+#endif /* SDL_cocoaopengl_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.m
new file mode 100644
index 0000000..9539c17
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengl.m
@@ -0,0 +1,436 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* NSOpenGL implementation of SDL OpenGL support */
+
+#if SDL_VIDEO_OPENGL_CGL
+#include "SDL_cocoavideo.h"
+#include "SDL_cocoaopengl.h"
+#include "SDL_cocoaopengles.h"
+
+#include <OpenGL/CGLTypes.h>
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/CGLRenderers.h>
+
+#include "SDL_loadso.h"
+#include "SDL_opengl.h"
+
+#define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
+
+@implementation SDLOpenGLContext : NSOpenGLContext
+
+- (id)initWithFormat:(NSOpenGLPixelFormat *)format
+ shareContext:(NSOpenGLContext *)share
+{
+ self = [super initWithFormat:format shareContext:share];
+ if (self) {
+ SDL_AtomicSet(&self->dirty, 0);
+ self->window = NULL;
+ }
+ return self;
+}
+
+- (void)scheduleUpdate
+{
+ SDL_AtomicAdd(&self->dirty, 1);
+}
+
+/* This should only be called on the thread on which a user is using the context. */
+- (void)updateIfNeeded
+{
+ int value = SDL_AtomicSet(&self->dirty, 0);
+ if (value > 0) {
+ /* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */
+ [super update];
+ }
+}
+
+/* This should only be called on the thread on which a user is using the context. */
+- (void)update
+{
+ /* This ensures that regular 'update' calls clear the atomic dirty flag. */
+ [self scheduleUpdate];
+ [self updateIfNeeded];
+}
+
+/* Updates the drawable for the contexts and manages related state. */
+- (void)setWindow:(SDL_Window *)newWindow
+{
+ if (self->window) {
+ SDL_WindowData *oldwindowdata = (SDL_WindowData *)self->window->driverdata;
+
+ /* Make sure to remove us from the old window's context list, or we'll get scheduled updates from it too. */
+ NSMutableArray *contexts = oldwindowdata->nscontexts;
+ @synchronized (contexts) {
+ [contexts removeObject:self];
+ }
+ }
+
+ self->window = newWindow;
+
+ if (newWindow) {
+ SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata;
+
+ /* Now sign up for scheduled updates for the new window. */
+ NSMutableArray *contexts = windowdata->nscontexts;
+ @synchronized (contexts) {
+ [contexts addObject:self];
+ }
+
+ if ([self view] != [windowdata->nswindow contentView]) {
+ [self setView:[windowdata->nswindow contentView]];
+ if (self == [NSOpenGLContext currentContext]) {
+ [self update];
+ } else {
+ [self scheduleUpdate];
+ }
+ }
+ } else {
+ [self clearDrawable];
+ if (self == [NSOpenGLContext currentContext]) {
+ [self update];
+ } else {
+ [self scheduleUpdate];
+ }
+ }
+}
+
+@end
+
+
+int
+Cocoa_GL_LoadLibrary(_THIS, const char *path)
+{
+ /* Load the OpenGL library */
+ if (path == NULL) {
+ path = SDL_getenv("SDL_OPENGL_LIBRARY");
+ }
+ if (path == NULL) {
+ path = DEFAULT_OPENGL;
+ }
+ _this->gl_config.dll_handle = SDL_LoadObject(path);
+ if (!_this->gl_config.dll_handle) {
+ return -1;
+ }
+ SDL_strlcpy(_this->gl_config.driver_path, path,
+ SDL_arraysize(_this->gl_config.driver_path));
+ return 0;
+}
+
+void *
+Cocoa_GL_GetProcAddress(_THIS, const char *proc)
+{
+ return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
+}
+
+void
+Cocoa_GL_UnloadLibrary(_THIS)
+{
+ SDL_UnloadObject(_this->gl_config.dll_handle);
+ _this->gl_config.dll_handle = NULL;
+}
+
+SDL_GLContext
+Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
+ SDL_bool lion_or_later = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+ NSOpenGLPixelFormatAttribute attr[32];
+ NSOpenGLPixelFormat *fmt;
+ SDLOpenGLContext *context;
+ NSOpenGLContext *share_context = nil;
+ int i = 0;
+ const char *glversion;
+ int glversion_major;
+ int glversion_minor;
+
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
+#if SDL_VIDEO_OPENGL_EGL
+ /* Switch to EGL based functions */
+ Cocoa_GL_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = Cocoa_GLES_LoadLibrary;
+ _this->GL_GetProcAddress = Cocoa_GLES_GetProcAddress;
+ _this->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary;
+ _this->GL_CreateContext = Cocoa_GLES_CreateContext;
+ _this->GL_MakeCurrent = Cocoa_GLES_MakeCurrent;
+ _this->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval;
+ _this->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval;
+ _this->GL_SwapWindow = Cocoa_GLES_SwapWindow;
+ _this->GL_DeleteContext = Cocoa_GLES_DeleteContext;
+
+ if (Cocoa_GLES_LoadLibrary(_this, NULL) != 0) {
+ return NULL;
+ }
+ return Cocoa_GLES_CreateContext(_this, window);
+#else
+ SDL_SetError("SDL not configured with EGL support");
+ return NULL;
+#endif
+ }
+ if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) && !lion_or_later) {
+ SDL_SetError ("OpenGL Core Profile is not supported on this platform version");
+ return NULL;
+ }
+
+ attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
+
+ /* specify a profile if we're on Lion (10.7) or later. */
+ if (lion_or_later) {
+ NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersionLegacy;
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
+ profile = NSOpenGLProfileVersion3_2Core;
+ }
+ attr[i++] = NSOpenGLPFAOpenGLProfile;
+ attr[i++] = profile;
+ }
+
+ attr[i++] = NSOpenGLPFAColorSize;
+ attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
+
+ attr[i++] = NSOpenGLPFADepthSize;
+ attr[i++] = _this->gl_config.depth_size;
+
+ if (_this->gl_config.double_buffer) {
+ attr[i++] = NSOpenGLPFADoubleBuffer;
+ }
+
+ if (_this->gl_config.stereo) {
+ attr[i++] = NSOpenGLPFAStereo;
+ }
+
+ if (_this->gl_config.stencil_size) {
+ attr[i++] = NSOpenGLPFAStencilSize;
+ attr[i++] = _this->gl_config.stencil_size;
+ }
+
+ if ((_this->gl_config.accum_red_size +
+ _this->gl_config.accum_green_size +
+ _this->gl_config.accum_blue_size +
+ _this->gl_config.accum_alpha_size) > 0) {
+ attr[i++] = NSOpenGLPFAAccumSize;
+ attr[i++] = _this->gl_config.accum_red_size + _this->gl_config.accum_green_size + _this->gl_config.accum_blue_size + _this->gl_config.accum_alpha_size;
+ }
+
+ if (_this->gl_config.multisamplebuffers) {
+ attr[i++] = NSOpenGLPFASampleBuffers;
+ attr[i++] = _this->gl_config.multisamplebuffers;
+ }
+
+ if (_this->gl_config.multisamplesamples) {
+ attr[i++] = NSOpenGLPFASamples;
+ attr[i++] = _this->gl_config.multisamplesamples;
+ attr[i++] = NSOpenGLPFANoRecovery;
+ }
+
+ if (_this->gl_config.accelerated >= 0) {
+ if (_this->gl_config.accelerated) {
+ attr[i++] = NSOpenGLPFAAccelerated;
+ } else {
+ attr[i++] = NSOpenGLPFARendererID;
+ attr[i++] = kCGLRendererGenericFloatID;
+ }
+ }
+
+ attr[i++] = NSOpenGLPFAScreenMask;
+ attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
+ attr[i] = 0;
+
+ fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
+ if (fmt == nil) {
+ SDL_SetError("Failed creating OpenGL pixel format");
+ return NULL;
+ }
+
+ if (_this->gl_config.share_with_current_context) {
+ share_context = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
+ }
+
+ context = [[SDLOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
+
+ [fmt release];
+
+ if (context == nil) {
+ SDL_SetError("Failed creating OpenGL context");
+ return NULL;
+ }
+
+ if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
+ Cocoa_GL_DeleteContext(_this, context);
+ SDL_SetError("Failed making OpenGL context current");
+ return NULL;
+ }
+
+ if (_this->gl_config.major_version < 3 &&
+ _this->gl_config.profile_mask == 0 &&
+ _this->gl_config.flags == 0) {
+ /* This is a legacy profile, so to match other backends, we're done. */
+ } else {
+ const GLubyte *(APIENTRY * glGetStringFunc)(GLenum);
+
+ glGetStringFunc = (const GLubyte *(APIENTRY *)(GLenum)) SDL_GL_GetProcAddress("glGetString");
+ if (!glGetStringFunc) {
+ Cocoa_GL_DeleteContext(_this, context);
+ SDL_SetError ("Failed getting OpenGL glGetString entry point");
+ return NULL;
+ }
+
+ glversion = (const char *)glGetStringFunc(GL_VERSION);
+ if (glversion == NULL) {
+ Cocoa_GL_DeleteContext(_this, context);
+ SDL_SetError ("Failed getting OpenGL context version");
+ return NULL;
+ }
+
+ if (SDL_sscanf(glversion, "%d.%d", &glversion_major, &glversion_minor) != 2) {
+ Cocoa_GL_DeleteContext(_this, context);
+ SDL_SetError ("Failed parsing OpenGL context version");
+ return NULL;
+ }
+
+ if ((glversion_major < _this->gl_config.major_version) ||
+ ((glversion_major == _this->gl_config.major_version) && (glversion_minor < _this->gl_config.minor_version))) {
+ Cocoa_GL_DeleteContext(_this, context);
+ SDL_SetError ("Failed creating OpenGL context at version requested");
+ return NULL;
+ }
+
+ /* In the future we'll want to do this, but to match other platforms
+ we'll leave the OpenGL version the way it is for now
+ */
+ /*_this->gl_config.major_version = glversion_major;*/
+ /*_this->gl_config.minor_version = glversion_minor;*/
+ }
+ return context;
+}}
+
+int
+Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{ @autoreleasepool
+{
+ if (context) {
+ SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
+ [nscontext setWindow:window];
+ [nscontext updateIfNeeded];
+ [nscontext makeCurrentContext];
+ } else {
+ [NSOpenGLContext clearCurrentContext];
+ }
+
+ return 0;
+}}
+
+void
+Cocoa_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+ NSView *contentView = [windata->nswindow contentView];
+ NSRect viewport = [contentView bounds];
+
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ /* This gives us the correct viewport for a Retina-enabled view, only
+ * supported on 10.7+. */
+ if ([contentView respondsToSelector:@selector(convertRectToBacking:)]) {
+ viewport = [contentView convertRectToBacking:viewport];
+ }
+ }
+
+ if (w) {
+ *w = viewport.size.width;
+ }
+
+ if (h) {
+ *h = viewport.size.height;
+ }
+}
+
+int
+Cocoa_GL_SetSwapInterval(_THIS, int interval)
+{ @autoreleasepool
+{
+ NSOpenGLContext *nscontext;
+ GLint value;
+ int status;
+
+ if (interval < 0) { /* no extension for this on Mac OS X at the moment. */
+ return SDL_SetError("Late swap tearing currently unsupported");
+ }
+
+ nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
+ if (nscontext != nil) {
+ value = interval;
+ [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
+ status = 0;
+ } else {
+ status = SDL_SetError("No current OpenGL context");
+ }
+
+ return status;
+}}
+
+int
+Cocoa_GL_GetSwapInterval(_THIS)
+{ @autoreleasepool
+{
+ NSOpenGLContext *nscontext;
+ GLint value;
+ int status = 0;
+
+ nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
+ if (nscontext != nil) {
+ [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
+ status = (int)value;
+ }
+
+ return status;
+}}
+
+int
+Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+
+ /* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two
+ threads try to swap at the same time, so put a mutex around it. */
+ SDL_LockMutex(videodata->swaplock);
+ [nscontext flushBuffer];
+ [nscontext updateIfNeeded];
+ SDL_UnlockMutex(videodata->swaplock);
+ return 0;
+}}
+
+void
+Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
+{ @autoreleasepool
+{
+ SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
+
+ [nscontext setWindow:NULL];
+ [nscontext release];
+}}
+
+#endif /* SDL_VIDEO_OPENGL_CGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.h
new file mode 100644
index 0000000..fc7f5c0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.h
@@ -0,0 +1,49 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoaopengles_h_
+#define SDL_cocoaopengles_h_
+
+#if SDL_VIDEO_OPENGL_EGL
+
+#include "../SDL_sysvideo.h"
+#include "../SDL_egl_c.h"
+
+/* OpenGLES functions */
+#define Cocoa_GLES_GetAttribute SDL_EGL_GetAttribute
+#define Cocoa_GLES_GetProcAddress SDL_EGL_GetProcAddress
+#define Cocoa_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+#define Cocoa_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+#define Cocoa_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+
+extern int Cocoa_GLES_LoadLibrary(_THIS, const char *path);
+extern SDL_GLContext Cocoa_GLES_CreateContext(_THIS, SDL_Window * window);
+extern int Cocoa_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern int Cocoa_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+extern void Cocoa_GLES_DeleteContext(_THIS, SDL_GLContext context);
+extern int Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window);
+
+#endif /* SDL_VIDEO_OPENGL_EGL */
+
+#endif /* SDL_cocoaopengles_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.m
new file mode 100644
index 0000000..e0a05a1
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoaopengles.m
@@ -0,0 +1,132 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA && SDL_VIDEO_OPENGL_EGL
+
+#include "SDL_cocoavideo.h"
+#include "SDL_cocoaopengles.h"
+#include "SDL_cocoaopengl.h"
+#include "SDL_log.h"
+
+/* EGL implementation of SDL OpenGL support */
+
+int
+Cocoa_GLES_LoadLibrary(_THIS, const char *path) {
+
+ /* If the profile requested is not GL ES, switch over to WIN_GL functions */
+ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
+#if SDL_VIDEO_OPENGL_CGL
+ Cocoa_GLES_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
+ _this->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
+ _this->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
+ _this->GL_CreateContext = Cocoa_GL_CreateContext;
+ _this->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
+ _this->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
+ _this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
+ _this->GL_SwapWindow = Cocoa_GL_SwapWindow;
+ _this->GL_DeleteContext = Cocoa_GL_DeleteContext;
+ return Cocoa_GL_LoadLibrary(_this, path);
+#else
+ return SDL_SetError("SDL not configured with OpenGL/CGL support");
+#endif
+ }
+
+ if (_this->egl_data == NULL) {
+ return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0);
+ }
+
+ return 0;
+}
+
+SDL_GLContext
+Cocoa_GLES_CreateContext(_THIS, SDL_Window * window)
+{
+ SDL_GLContext context;
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+
+#if SDL_VIDEO_OPENGL_CGL
+ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
+ /* Switch to CGL based functions */
+ Cocoa_GLES_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
+ _this->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
+ _this->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
+ _this->GL_CreateContext = Cocoa_GL_CreateContext;
+ _this->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
+ _this->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
+ _this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
+ _this->GL_SwapWindow = Cocoa_GL_SwapWindow;
+ _this->GL_DeleteContext = Cocoa_GL_DeleteContext;
+
+ if (Cocoa_GL_LoadLibrary(_this, NULL) != 0) {
+ return NULL;
+ }
+
+ return Cocoa_GL_CreateContext(_this, window);
+ }
+#endif
+
+ context = SDL_EGL_CreateContext(_this, data->egl_surface);
+ return context;
+}
+
+void
+Cocoa_GLES_DeleteContext(_THIS, SDL_GLContext context)
+{
+ SDL_EGL_DeleteContext(_this, context);
+ Cocoa_GLES_UnloadLibrary(_this);
+}
+
+SDL_EGL_SwapWindow_impl(Cocoa)
+SDL_EGL_MakeCurrent_impl(Cocoa)
+
+int
+Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
+{
+ /* The current context is lost in here; save it and reset it. */
+ SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
+ SDL_Window *current_win = SDL_GL_GetCurrentWindow();
+ SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
+
+
+ if (_this->egl_data == NULL) {
+ if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) {
+ SDL_EGL_UnloadLibrary(_this);
+ return -1;
+ }
+ }
+
+ /* Create the GLES window surface */
+ NSView* v = windowdata->nswindow.contentView;
+ windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)[v layer]);
+
+ if (windowdata->egl_surface == EGL_NO_SURFACE) {
+ return SDL_SetError("Could not create GLES window surface");
+ }
+
+ return Cocoa_GLES_MakeCurrent(_this, current_win, current_ctx);
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA && SDL_VIDEO_OPENGL_EGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.h
new file mode 100644
index 0000000..da1b5eb
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.h
@@ -0,0 +1,45 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoashape_h_
+#define SDL_cocoashape_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_video.h"
+#include "SDL_shape.h"
+#include "../SDL_shape_internals.h"
+
+typedef struct {
+ NSGraphicsContext* context;
+ SDL_bool saved;
+
+ SDL_ShapeTree* shape;
+} SDL_ShapeData;
+
+extern SDL_WindowShaper* Cocoa_CreateShaper(SDL_Window* window);
+extern int Cocoa_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
+extern int Cocoa_ResizeWindowShape(SDL_Window *window);
+
+#endif /* SDL_cocoashape_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.m
new file mode 100644
index 0000000..7a2f04f
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoashape.m
@@ -0,0 +1,113 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoavideo.h"
+#include "SDL_shape.h"
+#include "SDL_cocoashape.h"
+#include "../SDL_sysvideo.h"
+#include "SDL_assert.h"
+
+SDL_WindowShaper*
+Cocoa_CreateShaper(SDL_Window* window)
+{
+ SDL_WindowData* windata = (SDL_WindowData*)window->driverdata;
+ [windata->nswindow setOpaque:NO];
+
+ [windata->nswindow setStyleMask:NSWindowStyleMaskBorderless];
+
+ SDL_WindowShaper* result = result = malloc(sizeof(SDL_WindowShaper));
+ result->window = window;
+ result->mode.mode = ShapeModeDefault;
+ result->mode.parameters.binarizationCutoff = 1;
+ result->userx = result->usery = 0;
+ window->shaper = result;
+
+ SDL_ShapeData* data = malloc(sizeof(SDL_ShapeData));
+ result->driverdata = data;
+ data->context = [windata->nswindow graphicsContext];
+ data->saved = SDL_FALSE;
+ data->shape = NULL;
+
+ int resized_properly = Cocoa_ResizeWindowShape(window);
+ SDL_assert(resized_properly == 0);
+ return result;
+}
+
+typedef struct {
+ NSView* view;
+ NSBezierPath* path;
+ SDL_Window* window;
+} SDL_CocoaClosure;
+
+void
+ConvertRects(SDL_ShapeTree* tree, void* closure)
+{
+ SDL_CocoaClosure* data = (SDL_CocoaClosure*)closure;
+ if(tree->kind == OpaqueShape) {
+ NSRect rect = NSMakeRect(tree->data.shape.x,data->window->h - tree->data.shape.y,tree->data.shape.w,tree->data.shape.h);
+ [data->path appendBezierPathWithRect:[data->view convertRect:rect toView:nil]];
+ }
+}
+
+int
+Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
+{ @autoreleasepool
+{
+ SDL_ShapeData* data = (SDL_ShapeData*)shaper->driverdata;
+ SDL_WindowData* windata = (SDL_WindowData*)shaper->window->driverdata;
+ SDL_CocoaClosure closure;
+ if(data->saved == SDL_TRUE) {
+ [data->context restoreGraphicsState];
+ data->saved = SDL_FALSE;
+ }
+
+ /*[data->context saveGraphicsState];*/
+ /*data->saved = SDL_TRUE;*/
+ [NSGraphicsContext setCurrentContext:data->context];
+
+ [[NSColor clearColor] set];
+ NSRectFill([[windata->nswindow contentView] frame]);
+ data->shape = SDL_CalculateShapeTree(*shape_mode,shape);
+
+ closure.view = [windata->nswindow contentView];
+ closure.path = [NSBezierPath bezierPath];
+ closure.window = shaper->window;
+ SDL_TraverseShapeTree(data->shape,&ConvertRects,&closure);
+ [closure.path addClip];
+
+ return 0;
+}}
+
+int
+Cocoa_ResizeWindowShape(SDL_Window *window)
+{
+ SDL_ShapeData* data = window->shaper->driverdata;
+ SDL_assert(data != NULL);
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.h
new file mode 100644
index 0000000..b1c26fa
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.h
@@ -0,0 +1,118 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoavideo_h_
+#define SDL_cocoavideo_h_
+
+#include "SDL_opengl.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <Cocoa/Cocoa.h>
+
+#include "SDL_keycode.h"
+#include "../SDL_sysvideo.h"
+
+#include "SDL_cocoaclipboard.h"
+#include "SDL_cocoaevents.h"
+#include "SDL_cocoakeyboard.h"
+#include "SDL_cocoamodes.h"
+#include "SDL_cocoamouse.h"
+#include "SDL_cocoaopengl.h"
+#include "SDL_cocoawindow.h"
+
+#ifndef MAC_OS_X_VERSION_10_12
+#define DECLARE_EVENT(name) static const NSEventType NSEventType##name = NS##name
+DECLARE_EVENT(LeftMouseDown);
+DECLARE_EVENT(LeftMouseUp);
+DECLARE_EVENT(RightMouseDown);
+DECLARE_EVENT(RightMouseUp);
+DECLARE_EVENT(OtherMouseDown);
+DECLARE_EVENT(OtherMouseUp);
+DECLARE_EVENT(MouseMoved);
+DECLARE_EVENT(LeftMouseDragged);
+DECLARE_EVENT(RightMouseDragged);
+DECLARE_EVENT(OtherMouseDragged);
+DECLARE_EVENT(ScrollWheel);
+DECLARE_EVENT(KeyDown);
+DECLARE_EVENT(KeyUp);
+DECLARE_EVENT(FlagsChanged);
+#undef DECLARE_EVENT
+
+static const NSEventMask NSEventMaskAny = NSAnyEventMask;
+
+#define DECLARE_MODIFIER_FLAG(name) static const NSUInteger NSEventModifierFlag##name = NS##name##KeyMask
+DECLARE_MODIFIER_FLAG(Shift);
+DECLARE_MODIFIER_FLAG(Control);
+DECLARE_MODIFIER_FLAG(Command);
+DECLARE_MODIFIER_FLAG(NumericPad);
+DECLARE_MODIFIER_FLAG(Help);
+DECLARE_MODIFIER_FLAG(Function);
+#undef DECLARE_MODIFIER_FLAG
+static const NSUInteger NSEventModifierFlagCapsLock = NSAlphaShiftKeyMask;
+static const NSUInteger NSEventModifierFlagOption = NSAlternateKeyMask;
+
+#define DECLARE_WINDOW_MASK(name) static const unsigned int NSWindowStyleMask##name = NS##name##WindowMask
+DECLARE_WINDOW_MASK(Borderless);
+DECLARE_WINDOW_MASK(Titled);
+DECLARE_WINDOW_MASK(Closable);
+DECLARE_WINDOW_MASK(Miniaturizable);
+DECLARE_WINDOW_MASK(Resizable);
+DECLARE_WINDOW_MASK(TexturedBackground);
+DECLARE_WINDOW_MASK(UnifiedTitleAndToolbar);
+DECLARE_WINDOW_MASK(FullScreen);
+/*DECLARE_WINDOW_MASK(FullSizeContentView);*/ /* Not used, fails compile on older SDKs */
+static const unsigned int NSWindowStyleMaskUtilityWindow = NSUtilityWindowMask;
+static const unsigned int NSWindowStyleMaskDocModalWindow = NSDocModalWindowMask;
+static const unsigned int NSWindowStyleMaskHUDWindow = NSHUDWindowMask;
+#undef DECLARE_WINDOW_MASK
+
+#define DECLARE_ALERT_STYLE(name) static const NSUInteger NSAlertStyle##name = NS##name##AlertStyle
+DECLARE_ALERT_STYLE(Warning);
+DECLARE_ALERT_STYLE(Informational);
+DECLARE_ALERT_STYLE(Critical);
+#undef DECLARE_ALERT_STYLE
+#endif
+
+/* Private display data */
+
+@class SDLTranslatorResponder;
+
+typedef struct SDL_VideoData
+{
+ int allow_spaces;
+ unsigned int modifierFlags;
+ void *key_layout;
+ SDLTranslatorResponder *fieldEdit;
+ NSInteger clipboard_count;
+ Uint32 screensaver_activity;
+ BOOL screensaver_use_iopm;
+ IOPMAssertionID screensaver_assertion;
+ SDL_mutex *swaplock;
+} SDL_VideoData;
+
+/* Utility functions */
+extern NSImage * Cocoa_CreateImage(SDL_Surface * surface);
+
+#endif /* SDL_cocoavideo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.m
new file mode 100644
index 0000000..20bdfa7
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavideo.m
@@ -0,0 +1,262 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "SDL_cocoavideo.h"
+#include "SDL_cocoashape.h"
+#include "SDL_cocoavulkan.h"
+#include "SDL_assert.h"
+
+/* Initialization/Query functions */
+static int Cocoa_VideoInit(_THIS);
+static void Cocoa_VideoQuit(_THIS);
+
+/* Cocoa driver bootstrap functions */
+
+static int
+Cocoa_Available(void)
+{
+ return (1);
+}
+
+static void
+Cocoa_DeleteDevice(SDL_VideoDevice * device)
+{
+ SDL_free(device->driverdata);
+ SDL_free(device);
+}
+
+static SDL_VideoDevice *
+Cocoa_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+ SDL_VideoData *data;
+
+ Cocoa_RegisterApp();
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (device) {
+ data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+ } else {
+ data = NULL;
+ }
+ if (!data) {
+ SDL_OutOfMemory();
+ SDL_free(device);
+ return NULL;
+ }
+ device->driverdata = data;
+
+ /* Set the function pointers */
+ device->VideoInit = Cocoa_VideoInit;
+ device->VideoQuit = Cocoa_VideoQuit;
+ device->GetDisplayBounds = Cocoa_GetDisplayBounds;
+ device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds;
+ device->GetDisplayDPI = Cocoa_GetDisplayDPI;
+ device->GetDisplayModes = Cocoa_GetDisplayModes;
+ device->SetDisplayMode = Cocoa_SetDisplayMode;
+ device->PumpEvents = Cocoa_PumpEvents;
+ device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
+
+ device->CreateSDLWindow = Cocoa_CreateWindow;
+ device->CreateSDLWindowFrom = Cocoa_CreateWindowFrom;
+ device->SetWindowTitle = Cocoa_SetWindowTitle;
+ device->SetWindowIcon = Cocoa_SetWindowIcon;
+ device->SetWindowPosition = Cocoa_SetWindowPosition;
+ device->SetWindowSize = Cocoa_SetWindowSize;
+ device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
+ device->SetWindowOpacity = Cocoa_SetWindowOpacity;
+ device->ShowWindow = Cocoa_ShowWindow;
+ device->HideWindow = Cocoa_HideWindow;
+ device->RaiseWindow = Cocoa_RaiseWindow;
+ device->MaximizeWindow = Cocoa_MaximizeWindow;
+ device->MinimizeWindow = Cocoa_MinimizeWindow;
+ device->RestoreWindow = Cocoa_RestoreWindow;
+ device->SetWindowBordered = Cocoa_SetWindowBordered;
+ device->SetWindowResizable = Cocoa_SetWindowResizable;
+ device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
+ device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
+ device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
+ device->SetWindowGrab = Cocoa_SetWindowGrab;
+ device->DestroyWindow = Cocoa_DestroyWindow;
+ device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
+ device->SetWindowHitTest = Cocoa_SetWindowHitTest;
+ device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop;
+
+ device->shape_driver.CreateShaper = Cocoa_CreateShaper;
+ device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
+ device->shape_driver.ResizeWindowShape = Cocoa_ResizeWindowShape;
+
+#if SDL_VIDEO_OPENGL_CGL
+ device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
+ device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
+ device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
+ device->GL_CreateContext = Cocoa_GL_CreateContext;
+ device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
+ device->GL_GetDrawableSize = Cocoa_GL_GetDrawableSize;
+ device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
+ device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
+ device->GL_SwapWindow = Cocoa_GL_SwapWindow;
+ device->GL_DeleteContext = Cocoa_GL_DeleteContext;
+#elif SDL_VIDEO_OPENGL_EGL
+ device->GL_LoadLibrary = Cocoa_GLES_LoadLibrary;
+ device->GL_GetProcAddress = Cocoa_GLES_GetProcAddress;
+ device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary;
+ device->GL_CreateContext = Cocoa_GLES_CreateContext;
+ device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent;
+ device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval;
+ device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval;
+ device->GL_SwapWindow = Cocoa_GLES_SwapWindow;
+ device->GL_DeleteContext = Cocoa_GLES_DeleteContext;
+#endif
+
+#if SDL_VIDEO_VULKAN
+ device->Vulkan_LoadLibrary = Cocoa_Vulkan_LoadLibrary;
+ device->Vulkan_UnloadLibrary = Cocoa_Vulkan_UnloadLibrary;
+ device->Vulkan_GetInstanceExtensions = Cocoa_Vulkan_GetInstanceExtensions;
+ device->Vulkan_CreateSurface = Cocoa_Vulkan_CreateSurface;
+ device->Vulkan_GetDrawableSize = Cocoa_Vulkan_GetDrawableSize;
+#endif
+
+ device->StartTextInput = Cocoa_StartTextInput;
+ device->StopTextInput = Cocoa_StopTextInput;
+ device->SetTextInputRect = Cocoa_SetTextInputRect;
+
+ device->SetClipboardText = Cocoa_SetClipboardText;
+ device->GetClipboardText = Cocoa_GetClipboardText;
+ device->HasClipboardText = Cocoa_HasClipboardText;
+
+ device->free = Cocoa_DeleteDevice;
+
+ return device;
+}
+
+VideoBootStrap COCOA_bootstrap = {
+ "cocoa", "SDL Cocoa video driver",
+ Cocoa_Available, Cocoa_CreateDevice
+};
+
+
+int
+Cocoa_VideoInit(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ Cocoa_InitModes(_this);
+ Cocoa_InitKeyboard(_this);
+ Cocoa_InitMouse(_this);
+
+ data->allow_spaces = ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE));
+
+ /* The IOPM assertion API can disable the screensaver as of 10.7. */
+ data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+
+ data->swaplock = SDL_CreateMutex();
+ if (!data->swaplock) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+Cocoa_VideoQuit(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Cocoa_QuitModes(_this);
+ Cocoa_QuitKeyboard(_this);
+ Cocoa_QuitMouse(_this);
+ SDL_DestroyMutex(data->swaplock);
+ data->swaplock = NULL;
+}
+
+/* This function assumes that it's called from within an autorelease pool */
+NSImage *
+Cocoa_CreateImage(SDL_Surface * surface)
+{
+ SDL_Surface *converted;
+ NSBitmapImageRep *imgrep;
+ Uint8 *pixels;
+ int i;
+ NSImage *img;
+
+ converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32, 0);
+ if (!converted) {
+ return nil;
+ }
+
+ imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
+ pixelsWide: converted->w
+ pixelsHigh: converted->h
+ bitsPerSample: 8
+ samplesPerPixel: 4
+ hasAlpha: YES
+ isPlanar: NO
+ colorSpaceName: NSDeviceRGBColorSpace
+ bytesPerRow: converted->pitch
+ bitsPerPixel: converted->format->BitsPerPixel] autorelease];
+ if (imgrep == nil) {
+ SDL_FreeSurface(converted);
+ return nil;
+ }
+
+ /* Copy the pixels */
+ pixels = [imgrep bitmapData];
+ SDL_memcpy(pixels, converted->pixels, converted->h * converted->pitch);
+ SDL_FreeSurface(converted);
+
+ /* Premultiply the alpha channel */
+ for (i = (surface->h * surface->w); i--; ) {
+ Uint8 alpha = pixels[3];
+ pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255);
+ pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255);
+ pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255);
+ pixels += 4;
+ }
+
+ img = [[[NSImage alloc] initWithSize: NSMakeSize(surface->w, surface->h)] autorelease];
+ if (img != nil) {
+ [img addRepresentation: imgrep];
+ }
+ return img;
+}
+
+/*
+ * Mac OS X log support.
+ *
+ * This doesn't really have aything to do with the interfaces of the SDL video
+ * subsystem, but we need to stuff this into an Objective-C source code file.
+ */
+
+void SDL_NSLog(const char *text)
+{
+ NSLog(@"%s", text);
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.h
new file mode 100644
index 0000000..a49c148
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.h
@@ -0,0 +1,55 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
+ * SDL_x11vulkan.h.
+ */
+
+
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoavulkan_h_
+#define SDL_cocoavulkan_h_
+
+#include "../SDL_vulkan_internal.h"
+#include "../SDL_sysvideo.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_COCOA
+
+int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path);
+void Cocoa_Vulkan_UnloadLibrary(_THIS);
+SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names);
+SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface);
+
+void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h);
+
+#endif
+
+#endif /* SDL_cocoavulkan_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.m
new file mode 100644
index 0000000..0e53d21
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoavulkan.m
@@ -0,0 +1,230 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
+ * SDL_x11vulkan.c.
+ */
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_COCOA
+
+#include "SDL_cocoavideo.h"
+#include "SDL_cocoawindow.h"
+#include "SDL_assert.h"
+
+#include "SDL_loadso.h"
+#include "SDL_cocoametalview.h"
+#include "SDL_cocoavulkan.h"
+#include "SDL_syswm.h"
+
+#include <dlfcn.h>
+
+const char* defaultPaths[] = {
+ "vulkan.framework/vulkan",
+ "libvulkan.1.dylib",
+ "MoltenVK.framework/MoltenVK",
+ "libMoltenVK.dylib"
+};
+
+/* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
+#define DEFAULT_HANDLE RTLD_DEFAULT
+
+int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
+{
+ VkExtensionProperties *extensions = NULL;
+ Uint32 extensionCount = 0;
+ SDL_bool hasSurfaceExtension = SDL_FALSE;
+ SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
+
+ if (_this->vulkan_config.loader_handle) {
+ return SDL_SetError("Vulkan/MoltenVK already loaded");
+ }
+
+ /* Load the Vulkan loader library */
+ if (!path) {
+ path = SDL_getenv("SDL_VULKAN_LIBRARY");
+ }
+
+ if (!path) {
+ /* MoltenVK framework, currently, v0.17.0, has a static library and is
+ * the recommended way to use the package. There is likely no object to
+ * load. */
+ vkGetInstanceProcAddr =
+ (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
+ "vkGetInstanceProcAddr");
+ }
+
+ if (vkGetInstanceProcAddr) {
+ _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
+ } else {
+ const char** paths;
+ const char *foundPath = NULL;
+ int numPaths;
+ int i;
+
+ if (path) {
+ paths = &path;
+ numPaths = 1;
+ } else {
+ /* Look for framework or .dylib packaged with the application
+ * instead. */
+ paths = defaultPaths;
+ numPaths = SDL_arraysize(defaultPaths);
+ }
+
+ for (i = 0; i < numPaths && _this->vulkan_config.loader_handle == NULL; i++) {
+ foundPath = paths[i];
+ _this->vulkan_config.loader_handle = SDL_LoadObject(foundPath);
+ }
+
+ if (_this->vulkan_config.loader_handle == NULL) {
+ return SDL_SetError("Failed to load Vulkan/MoltenVK library");
+ }
+
+ SDL_strlcpy(_this->vulkan_config.loader_path, foundPath,
+ SDL_arraysize(_this->vulkan_config.loader_path));
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
+ _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
+ }
+
+ if (!vkGetInstanceProcAddr) {
+ SDL_SetError("Failed to find %s in either executable or %s: %s",
+ "vkGetInstanceProcAddr",
+ _this->vulkan_config.loader_path,
+ (const char *) dlerror());
+ goto fail;
+ }
+
+ _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties =
+ (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
+ VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
+ if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) {
+ goto fail;
+ }
+ extensions = SDL_Vulkan_CreateInstanceExtensionsList(
+ (PFN_vkEnumerateInstanceExtensionProperties)
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
+ &extensionCount);
+ if (!extensions) {
+ goto fail;
+ }
+ for (Uint32 i = 0; i < extensionCount; i++) {
+ if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
+ hasSurfaceExtension = SDL_TRUE;
+ } else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
+ hasMacOSSurfaceExtension = SDL_TRUE;
+ }
+ }
+ SDL_free(extensions);
+ if (!hasSurfaceExtension) {
+ SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+ VK_KHR_SURFACE_EXTENSION_NAME " extension");
+ goto fail;
+ } else if (!hasMacOSSurfaceExtension) {
+ SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+ VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
+ goto fail;
+ }
+ return 0;
+
+fail:
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ _this->vulkan_config.loader_handle = NULL;
+ return -1;
+}
+
+void Cocoa_Vulkan_UnloadLibrary(_THIS)
+{
+ if (_this->vulkan_config.loader_handle) {
+ if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE) {
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ }
+ _this->vulkan_config.loader_handle = NULL;
+ }
+}
+
+SDL_bool Cocoa_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names)
+{
+ static const char *const extensionsForCocoa[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_MACOS_SURFACE_EXTENSION_NAME
+ };
+ if (!_this->vulkan_config.loader_handle) {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+ return SDL_Vulkan_GetInstanceExtensions_Helper(
+ count, names, SDL_arraysize(extensionsForCocoa),
+ extensionsForCocoa);
+}
+
+SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface)
+{
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
+ (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
+ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
+ (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
+ (VkInstance)instance,
+ "vkCreateMacOSSurfaceMVK");
+ VkMacOSSurfaceCreateInfoMVK createInfo = {};
+ VkResult result;
+
+ if (!_this->vulkan_config.loader_handle) {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+
+ if (!vkCreateMacOSSurfaceMVK) {
+ SDL_SetError(VK_MVK_MACOS_SURFACE_EXTENSION_NAME
+ " extension is not enabled in the Vulkan instance.");
+ return SDL_FALSE;
+ }
+ createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.pView = Cocoa_Mtl_AddMetalView(window);
+ result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
+ NULL, surface);
+ if (result != VK_SUCCESS) {
+ SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
+ SDL_Vulkan_GetResultString(result));
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
+{
+ Cocoa_Mtl_GetDrawableSize(window, w, h);
+}
+
+#endif
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.h b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.h
new file mode 100644
index 0000000..2311e3d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.h
@@ -0,0 +1,155 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_cocoawindow_h_
+#define SDL_cocoawindow_h_
+
+#import <Cocoa/Cocoa.h>
+
+#if SDL_VIDEO_OPENGL_EGL
+#include "../SDL_egl_c.h"
+#endif
+
+typedef struct SDL_WindowData SDL_WindowData;
+
+typedef enum
+{
+ PENDING_OPERATION_NONE,
+ PENDING_OPERATION_ENTER_FULLSCREEN,
+ PENDING_OPERATION_LEAVE_FULLSCREEN,
+ PENDING_OPERATION_MINIMIZE
+} PendingWindowOperation;
+
+@interface Cocoa_WindowListener : NSResponder <NSWindowDelegate> {
+ SDL_WindowData *_data;
+ BOOL observingVisible;
+ BOOL wasCtrlLeft;
+ BOOL wasVisible;
+ BOOL isFullscreenSpace;
+ BOOL inFullscreenTransition;
+ PendingWindowOperation pendingWindowOperation;
+ BOOL isMoving;
+ int pendingWindowWarpX, pendingWindowWarpY;
+ BOOL isDragAreaRunning;
+}
+
+-(void) listen:(SDL_WindowData *) data;
+-(void) pauseVisibleObservation;
+-(void) resumeVisibleObservation;
+-(BOOL) setFullscreenSpace:(BOOL) state;
+-(BOOL) isInFullscreenSpace;
+-(BOOL) isInFullscreenSpaceTransition;
+-(void) addPendingWindowOperation:(PendingWindowOperation) operation;
+-(void) close;
+
+-(BOOL) isMoving;
+-(void) setPendingMoveX:(int)x Y:(int)y;
+-(void) windowDidFinishMoving;
+
+/* Window delegate functionality */
+-(BOOL) windowShouldClose:(id) sender;
+-(void) windowDidExpose:(NSNotification *) aNotification;
+-(void) windowDidMove:(NSNotification *) aNotification;
+-(void) windowDidResize:(NSNotification *) aNotification;
+-(void) windowDidMiniaturize:(NSNotification *) aNotification;
+-(void) windowDidDeminiaturize:(NSNotification *) aNotification;
+-(void) windowDidBecomeKey:(NSNotification *) aNotification;
+-(void) windowDidResignKey:(NSNotification *) aNotification;
+-(void) windowDidChangeBackingProperties:(NSNotification *) aNotification;
+-(void) windowWillEnterFullScreen:(NSNotification *) aNotification;
+-(void) windowDidEnterFullScreen:(NSNotification *) aNotification;
+-(void) windowWillExitFullScreen:(NSNotification *) aNotification;
+-(void) windowDidExitFullScreen:(NSNotification *) aNotification;
+-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
+
+/* See if event is in a drag area, toggle on window dragging. */
+-(BOOL) processHitTest:(NSEvent *)theEvent;
+
+/* Window event handling */
+-(void) mouseDown:(NSEvent *) theEvent;
+-(void) rightMouseDown:(NSEvent *) theEvent;
+-(void) otherMouseDown:(NSEvent *) theEvent;
+-(void) mouseUp:(NSEvent *) theEvent;
+-(void) rightMouseUp:(NSEvent *) theEvent;
+-(void) otherMouseUp:(NSEvent *) theEvent;
+-(void) mouseMoved:(NSEvent *) theEvent;
+-(void) mouseDragged:(NSEvent *) theEvent;
+-(void) rightMouseDragged:(NSEvent *) theEvent;
+-(void) otherMouseDragged:(NSEvent *) theEvent;
+-(void) scrollWheel:(NSEvent *) theEvent;
+-(void) touchesBeganWithEvent:(NSEvent *) theEvent;
+-(void) touchesMovedWithEvent:(NSEvent *) theEvent;
+-(void) touchesEndedWithEvent:(NSEvent *) theEvent;
+-(void) touchesCancelledWithEvent:(NSEvent *) theEvent;
+
+/* Touch event handling */
+-(void) handleTouches:(NSTouchPhase) phase withEvent:(NSEvent*) theEvent;
+
+@end
+/* *INDENT-ON* */
+
+@class SDLOpenGLContext;
+
+struct SDL_WindowData
+{
+ SDL_Window *window;
+ NSWindow *nswindow;
+ NSMutableArray *nscontexts;
+ SDL_bool created;
+ SDL_bool inWindowMove;
+ Cocoa_WindowListener *listener;
+ struct SDL_VideoData *videodata;
+#if SDL_VIDEO_OPENGL_EGL
+ EGLSurface egl_surface;
+#endif
+};
+
+extern int Cocoa_CreateWindow(_THIS, SDL_Window * window);
+extern int Cocoa_CreateWindowFrom(_THIS, SDL_Window * window,
+ const void *data);
+extern void Cocoa_SetWindowTitle(_THIS, SDL_Window * window);
+extern void Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
+extern void Cocoa_SetWindowPosition(_THIS, SDL_Window * window);
+extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window);
+extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window);
+extern void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window);
+extern int Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
+extern void Cocoa_ShowWindow(_THIS, SDL_Window * window);
+extern void Cocoa_HideWindow(_THIS, SDL_Window * window);
+extern void Cocoa_RaiseWindow(_THIS, SDL_Window * window);
+extern void Cocoa_MaximizeWindow(_THIS, SDL_Window * window);
+extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
+extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
+extern void Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
+extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
+extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
+extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
+extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
+extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
+extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
+extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
+extern void Cocoa_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
+
+#endif /* SDL_cocoawindow_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.m
new file mode 100644
index 0000000..a8e95cc
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoawindow.m
@@ -0,0 +1,1905 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_COCOA
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
+# error SDL for Mac OS X must be built with a 10.7 SDK or above.
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1070 */
+
+#include "SDL_syswm.h"
+#include "SDL_timer.h" /* For SDL_GetTicks() */
+#include "SDL_hints.h"
+#include "../SDL_sysvideo.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+#include "../../events/SDL_windowevents_c.h"
+#include "../../events/SDL_dropevents_c.h"
+#include "SDL_cocoavideo.h"
+#include "SDL_cocoashape.h"
+#include "SDL_cocoamouse.h"
+#include "SDL_cocoamousetap.h"
+#include "SDL_cocoaopengl.h"
+#include "SDL_cocoaopengles.h"
+#include "SDL_assert.h"
+
+/* #define DEBUG_COCOAWINDOW */
+
+#ifdef DEBUG_COCOAWINDOW
+#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
+#else
+#define DLog(...) do { } while (0)
+#endif
+
+
+#define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN)
+
+
+@interface SDLWindow : NSWindow <NSDraggingDestination>
+/* These are needed for borderless/fullscreen windows */
+- (BOOL)canBecomeKeyWindow;
+- (BOOL)canBecomeMainWindow;
+- (void)sendEvent:(NSEvent *)event;
+- (void)doCommandBySelector:(SEL)aSelector;
+
+/* Handle drag-and-drop of files onto the SDL window. */
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
+- (BOOL)wantsPeriodicDraggingUpdates;
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
+
+- (SDL_Window*)findSDLWindow;
+@end
+
+@implementation SDLWindow
+
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
+{
+ /* Only allow using the macOS native fullscreen toggle menubar item if the
+ * window is resizable and not in a SDL fullscreen mode.
+ */
+ if ([menuItem action] == @selector(toggleFullScreen:)) {
+ SDL_Window *window = [self findSDLWindow];
+ if (window == NULL) {
+ return NO;
+ } else if ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
+ return NO;
+ } else if ((window->flags & SDL_WINDOW_RESIZABLE) == 0) {
+ return NO;
+ }
+ }
+ return [super validateMenuItem:menuItem];
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
+
+- (BOOL)canBecomeMainWindow
+{
+ return YES;
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+ [super sendEvent:event];
+
+ if ([event type] != NSEventTypeLeftMouseUp) {
+ return;
+ }
+
+ id delegate = [self delegate];
+ if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
+ return;
+ }
+
+ if ([delegate isMoving]) {
+ [delegate windowDidFinishMoving];
+ }
+}
+
+/* We'll respond to selectors by doing nothing so we don't beep.
+ * The escape key gets converted to a "cancel" selector, etc.
+ */
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ if (([sender draggingSourceOperationMask] & NSDragOperationGeneric) == NSDragOperationGeneric) {
+ return NSDragOperationGeneric;
+ }
+
+ return NSDragOperationNone; /* no idea what to do with this, reject it. */
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{ @autoreleasepool
+{
+ NSPasteboard *pasteboard = [sender draggingPasteboard];
+ NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
+ NSString *desiredType = [pasteboard availableTypeFromArray:types];
+ SDL_Window *sdlwindow = [self findSDLWindow];
+
+ if (desiredType == nil) {
+ return NO; /* can't accept anything that's being dropped here. */
+ }
+
+ NSData *data = [pasteboard dataForType:desiredType];
+ if (data == nil) {
+ return NO;
+ }
+
+ SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
+ NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
+
+ for (NSString *path in array) {
+ NSURL *fileURL = [NSURL fileURLWithPath:path];
+ NSNumber *isAlias = nil;
+
+ [fileURL getResourceValue:&isAlias forKey:NSURLIsAliasFileKey error:nil];
+
+ /* If the URL is an alias, resolve it. */
+ if ([isAlias boolValue]) {
+ NSURLBookmarkResolutionOptions opts = NSURLBookmarkResolutionWithoutMounting | NSURLBookmarkResolutionWithoutUI;
+ NSData *bookmark = [NSURL bookmarkDataWithContentsOfURL:fileURL error:nil];
+ if (bookmark != nil) {
+ NSURL *resolvedURL = [NSURL URLByResolvingBookmarkData:bookmark
+ options:opts
+ relativeToURL:nil
+ bookmarkDataIsStale:nil
+ error:nil];
+
+ if (resolvedURL != nil) {
+ fileURL = resolvedURL;
+ }
+ }
+ }
+
+ if (!SDL_SendDropFile(sdlwindow, [[fileURL path] UTF8String])) {
+ return NO;
+ }
+ }
+
+ SDL_SendDropComplete(sdlwindow);
+ return YES;
+}}
+
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+ return NO;
+}
+
+- (SDL_Window*)findSDLWindow
+{
+ SDL_Window *sdlwindow = NULL;
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+ /* !!! FIXME: is there a better way to do this? */
+ if (_this) {
+ for (sdlwindow = _this->windows; sdlwindow; sdlwindow = sdlwindow->next) {
+ NSWindow *nswindow = ((SDL_WindowData *) sdlwindow->driverdata)->nswindow;
+ if (nswindow == self) {
+ break;
+ }
+ }
+ }
+
+ return sdlwindow;
+}
+
+@end
+
+
+static Uint32 s_moveHack;
+
+static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
+{
+ r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
+}
+
+static void
+ScheduleContextUpdates(SDL_WindowData *data)
+{
+ NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
+ NSMutableArray *contexts = data->nscontexts;
+ @synchronized (contexts) {
+ for (SDLOpenGLContext *context in contexts) {
+ if (context == currentContext) {
+ [context update];
+ } else {
+ [context scheduleUpdate];
+ }
+ }
+ }
+}
+
+/* !!! FIXME: this should use a hint callback. */
+static int
+GetHintCtrlClickEmulateRightClick()
+{
+ return SDL_GetHintBoolean(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, SDL_FALSE);
+}
+
+static NSUInteger
+GetWindowStyle(SDL_Window * window)
+{
+ NSUInteger style = 0;
+
+ if (window->flags & SDL_WINDOW_FULLSCREEN) {
+ style = NSWindowStyleMaskBorderless;
+ } else {
+ if (window->flags & SDL_WINDOW_BORDERLESS) {
+ style = NSWindowStyleMaskBorderless;
+ } else {
+ style = (NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable);
+ }
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ style |= NSWindowStyleMaskResizable;
+ }
+ }
+ return style;
+}
+
+static SDL_bool
+SetWindowStyle(SDL_Window * window, NSUInteger style)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = data->nswindow;
+
+ /* The view responder chain gets messed with during setStyleMask */
+ if ([[nswindow contentView] nextResponder] == data->listener) {
+ [[nswindow contentView] setNextResponder:nil];
+ }
+
+ [nswindow setStyleMask:style];
+
+ /* The view responder chain gets messed with during setStyleMask */
+ if ([[nswindow contentView] nextResponder] != data->listener) {
+ [[nswindow contentView] setNextResponder:data->listener];
+ }
+
+ return SDL_TRUE;
+}
+
+
+@implementation Cocoa_WindowListener
+
+- (void)listen:(SDL_WindowData *)data
+{
+ NSNotificationCenter *center;
+ NSWindow *window = data->nswindow;
+ NSView *view = [window contentView];
+
+ _data = data;
+ observingVisible = YES;
+ wasCtrlLeft = NO;
+ wasVisible = [window isVisible];
+ isFullscreenSpace = NO;
+ inFullscreenTransition = NO;
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+ isMoving = NO;
+ isDragAreaRunning = NO;
+
+ center = [NSNotificationCenter defaultCenter];
+
+ if ([window delegate] != nil) {
+ [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
+ [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
+ [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
+ [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
+ [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
+ [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
+ [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
+ [center addObserver:self selector:@selector(windowDidChangeBackingProperties:) name:NSWindowDidChangeBackingPropertiesNotification object:window];
+ [center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
+ [center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
+ [center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
+ [center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
+ [center addObserver:self selector:@selector(windowDidFailToEnterFullScreen:) name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
+ [center addObserver:self selector:@selector(windowDidFailToExitFullScreen:) name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
+ } else {
+ [window setDelegate:self];
+ }
+
+ /* Haven't found a delegate / notification that triggers when the window is
+ * ordered out (is not visible any more). You can be ordered out without
+ * minimizing, so DidMiniaturize doesn't work. (e.g. -[NSWindow orderOut:])
+ */
+ [window addObserver:self
+ forKeyPath:@"visible"
+ options:NSKeyValueObservingOptionNew
+ context:NULL];
+
+ [window setNextResponder:self];
+ [window setAcceptsMouseMovedEvents:YES];
+
+ [view setNextResponder:self];
+
+ [view setAcceptsTouchEvents:YES];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+ ofObject:(id)object
+ change:(NSDictionary *)change
+ context:(void *)context
+{
+ if (!observingVisible) {
+ return;
+ }
+
+ if (object == _data->nswindow && [keyPath isEqualToString:@"visible"]) {
+ int newVisibility = [[change objectForKey:@"new"] intValue];
+ if (newVisibility) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ } else {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
+ }
+ }
+}
+
+-(void) pauseVisibleObservation
+{
+ observingVisible = NO;
+ wasVisible = [_data->nswindow isVisible];
+}
+
+-(void) resumeVisibleObservation
+{
+ BOOL isVisible = [_data->nswindow isVisible];
+ observingVisible = YES;
+ if (wasVisible != isVisible) {
+ if (isVisible) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ } else {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
+ }
+
+ wasVisible = isVisible;
+ }
+}
+
+-(BOOL) setFullscreenSpace:(BOOL) state
+{
+ SDL_Window *window = _data->window;
+ NSWindow *nswindow = _data->nswindow;
+ SDL_VideoData *videodata = ((SDL_WindowData *) window->driverdata)->videodata;
+
+ if (!videodata->allow_spaces) {
+ return NO; /* Spaces are forcibly disabled. */
+ } else if (state && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP)) {
+ return NO; /* we only allow you to make a Space on FULLSCREEN_DESKTOP windows. */
+ } else if (!state && ((window->last_fullscreen_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP)) {
+ return NO; /* we only handle leaving the Space on windows that were previously FULLSCREEN_DESKTOP. */
+ } else if (state == isFullscreenSpace) {
+ return YES; /* already there. */
+ }
+
+ if (inFullscreenTransition) {
+ if (state) {
+ [self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
+ } else {
+ [self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
+ }
+ return YES;
+ }
+ inFullscreenTransition = YES;
+
+ /* you need to be FullScreenPrimary, or toggleFullScreen doesn't work. Unset it again in windowDidExitFullScreen. */
+ [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ [nswindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject:nswindow waitUntilDone:NO];
+ return YES;
+}
+
+-(BOOL) isInFullscreenSpace
+{
+ return isFullscreenSpace;
+}
+
+-(BOOL) isInFullscreenSpaceTransition
+{
+ return inFullscreenTransition;
+}
+
+-(void) addPendingWindowOperation:(PendingWindowOperation) operation
+{
+ pendingWindowOperation = operation;
+}
+
+- (void)close
+{
+ NSNotificationCenter *center;
+ NSWindow *window = _data->nswindow;
+ NSView *view = [window contentView];
+
+ center = [NSNotificationCenter defaultCenter];
+
+ if ([window delegate] != self) {
+ [center removeObserver:self name:NSWindowDidExposeNotification object:window];
+ [center removeObserver:self name:NSWindowDidMoveNotification object:window];
+ [center removeObserver:self name:NSWindowDidResizeNotification object:window];
+ [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
+ [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
+ [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
+ [center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
+ [center removeObserver:self name:NSWindowDidChangeBackingPropertiesNotification object:window];
+ [center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
+ [center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
+ [center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
+ [center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
+ [center removeObserver:self name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
+ [center removeObserver:self name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
+ } else {
+ [window setDelegate:nil];
+ }
+
+ [window removeObserver:self forKeyPath:@"visible"];
+
+ if ([window nextResponder] == self) {
+ [window setNextResponder:nil];
+ }
+ if ([view nextResponder] == self) {
+ [view setNextResponder:nil];
+ }
+}
+
+- (BOOL)isMoving
+{
+ return isMoving;
+}
+
+-(void) setPendingMoveX:(int)x Y:(int)y
+{
+ pendingWindowWarpX = x;
+ pendingWindowWarpY = y;
+}
+
+- (void)windowDidFinishMoving
+{
+ if ([self isMoving]) {
+ isMoving = NO;
+
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
+ mouse->WarpMouseGlobal(pendingWindowWarpX, pendingWindowWarpY);
+ pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
+ }
+ if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data->window) {
+ mouse->SetRelativeMouseMode(SDL_TRUE);
+ }
+ }
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
+ return NO;
+}
+
+- (void)windowDidExpose:(NSNotification *)aNotification
+{
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+}
+
+- (void)windowWillMove:(NSNotification *)aNotification
+{
+ if ([_data->nswindow isKindOfClass:[SDLWindow class]]) {
+ pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
+ isMoving = YES;
+ }
+}
+
+- (void)windowDidMove:(NSNotification *)aNotification
+{
+ int x, y;
+ SDL_Window *window = _data->window;
+ NSWindow *nswindow = _data->nswindow;
+ BOOL fullscreen = window->flags & FULLSCREEN_MASK;
+ NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
+ ConvertNSRect([nswindow screen], fullscreen, &rect);
+
+ if (inFullscreenTransition) {
+ /* We'll take care of this at the end of the transition */
+ return;
+ }
+
+ if (s_moveHack) {
+ SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500);
+
+ s_moveHack = 0;
+
+ if (blockMove) {
+ /* Cocoa is adjusting the window in response to a mode change */
+ rect.origin.x = window->x;
+ rect.origin.y = window->y;
+ ConvertNSRect([nswindow screen], fullscreen, &rect);
+ [nswindow setFrameOrigin:rect.origin];
+ return;
+ }
+ }
+
+ x = (int)rect.origin.x;
+ y = (int)rect.origin.y;
+
+ ScheduleContextUpdates(_data);
+
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
+}
+
+- (void)windowDidResize:(NSNotification *)aNotification
+{
+ if (inFullscreenTransition) {
+ /* We'll take care of this at the end of the transition */
+ return;
+ }
+
+ SDL_Window *window = _data->window;
+ NSWindow *nswindow = _data->nswindow;
+ int x, y, w, h;
+ NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
+ ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
+ x = (int)rect.origin.x;
+ y = (int)rect.origin.y;
+ w = (int)rect.size.width;
+ h = (int)rect.size.height;
+
+ if (SDL_IsShapedWindow(window)) {
+ Cocoa_ResizeWindowShape(window);
+ }
+
+ ScheduleContextUpdates(_data);
+
+ /* The window can move during a resize event, such as when maximizing
+ or resizing from a corner */
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
+
+ const BOOL zoomed = [nswindow isZoomed];
+ if (!zoomed) {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+ } else if (zoomed) {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+ }
+}
+
+- (void)windowDidMiniaturize:(NSNotification *)aNotification
+{
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+}
+
+- (void)windowDidDeminiaturize:(NSNotification *)aNotification
+{
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ /* We're going to get keyboard events, since we're key. */
+ /* This needs to be done before restoring the relative mouse mode. */
+ SDL_SetKeyboardFocus(window);
+
+ if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMoving]) {
+ mouse->SetRelativeMouseMode(SDL_TRUE);
+ }
+
+ /* If we just gained focus we need the updated mouse position */
+ if (!mouse->relative_mode) {
+ NSPoint point;
+ int x, y;
+
+ point = [_data->nswindow mouseLocationOutsideOfEventStream];
+ x = (int)point.x;
+ y = (int)(window->h - point.y);
+
+ if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
+ SDL_SendMouseMotion(window, 0, 0, x, y);
+ }
+ }
+
+ /* Check to see if someone updated the clipboard */
+ Cocoa_CheckClipboardUpdate(_data->videodata);
+
+ if ((isFullscreenSpace) && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)) {
+ [NSMenu setMenuBarVisible:NO];
+ }
+
+ const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
+ _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSEventModifierFlagCapsLock) | newflags;
+ SDL_ToggleModState(KMOD_CAPS, newflags != 0);
+}
+
+- (void)windowDidResignKey:(NSNotification *)aNotification
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (mouse->relative_mode && !mouse->relative_mode_warp) {
+ mouse->SetRelativeMouseMode(SDL_FALSE);
+ }
+
+ /* Some other window will get mouse events, since we're not key. */
+ if (SDL_GetMouseFocus() == _data->window) {
+ SDL_SetMouseFocus(NULL);
+ }
+
+ /* Some other window will get keyboard events, since we're not key. */
+ if (SDL_GetKeyboardFocus() == _data->window) {
+ SDL_SetKeyboardFocus(NULL);
+ }
+
+ if (isFullscreenSpace) {
+ [NSMenu setMenuBarVisible:YES];
+ }
+}
+
+- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification
+{
+ NSNumber *oldscale = [[aNotification userInfo] objectForKey:NSBackingPropertyOldScaleFactorKey];
+
+ if (inFullscreenTransition) {
+ return;
+ }
+
+ if ([oldscale doubleValue] != [_data->nswindow backingScaleFactor]) {
+ /* Force a resize event when the backing scale factor changes. */
+ _data->window->w = 0;
+ _data->window->h = 0;
+ [self windowDidResize:aNotification];
+ }
+}
+
+- (void)windowWillEnterFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+
+ SetWindowStyle(window, (NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable));
+
+ isFullscreenSpace = YES;
+ inFullscreenTransition = YES;
+}
+
+- (void)windowDidFailToEnterFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+
+ if (window->is_destroying) {
+ return;
+ }
+
+ SetWindowStyle(window, GetWindowStyle(window));
+
+ isFullscreenSpace = NO;
+ inFullscreenTransition = NO;
+
+ [self windowDidExitFullScreen:nil];
+}
+
+- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = data->nswindow;
+
+ inFullscreenTransition = NO;
+
+ if (pendingWindowOperation == PENDING_OPERATION_LEAVE_FULLSCREEN) {
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+ [self setFullscreenSpace:NO];
+ } else {
+ /* Unset the resizable flag.
+ This is a workaround for https://bugzilla.libsdl.org/show_bug.cgi?id=3697
+ */
+ SetWindowStyle(window, [nswindow styleMask] & (~NSWindowStyleMaskResizable));
+
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ [NSMenu setMenuBarVisible:NO];
+ }
+
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+ /* Force the size change event in case it was delivered earlier
+ while the window was still animating into place.
+ */
+ window->w = 0;
+ window->h = 0;
+ [self windowDidMove:aNotification];
+ [self windowDidResize:aNotification];
+ }
+}
+
+- (void)windowWillExitFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+
+ isFullscreenSpace = NO;
+ inFullscreenTransition = YES;
+
+ /* As of OS X 10.11, the window seems to need to be resizable when exiting
+ a Space, in order for it to resize back to its windowed-mode size.
+ */
+ SetWindowStyle(window, GetWindowStyle(window) | NSWindowStyleMaskResizable);
+}
+
+- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+
+ if (window->is_destroying) {
+ return;
+ }
+
+ SetWindowStyle(window, (NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable));
+
+ isFullscreenSpace = YES;
+ inFullscreenTransition = NO;
+
+ [self windowDidEnterFullScreen:nil];
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)aNotification
+{
+ SDL_Window *window = _data->window;
+ NSWindow *nswindow = _data->nswindow;
+
+ inFullscreenTransition = NO;
+
+ SetWindowStyle(window, GetWindowStyle(window));
+
+ [nswindow setLevel:kCGNormalWindowLevel];
+
+ if (pendingWindowOperation == PENDING_OPERATION_ENTER_FULLSCREEN) {
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+ [self setFullscreenSpace:YES];
+ } else if (pendingWindowOperation == PENDING_OPERATION_MINIMIZE) {
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+ [nswindow miniaturize:nil];
+ } else {
+ /* Adjust the fullscreen toggle button and readd menu now that we're here. */
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
+ [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ } else {
+ [nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
+ }
+ [NSMenu setMenuBarVisible:YES];
+
+ pendingWindowOperation = PENDING_OPERATION_NONE;
+
+#if 0
+/* This fixed bug 3719, which is that changing window size while fullscreen
+ doesn't take effect when leaving fullscreen, but introduces bug 3809,
+ which is that a maximized window doesn't go back to normal size when
+ restored, so this code is disabled until we can properly handle the
+ beginning and end of maximize and restore.
+ */
+ /* Restore windowed size and position in case it changed while fullscreen */
+ {
+ NSRect rect;
+ rect.origin.x = window->windowed.x;
+ rect.origin.y = window->windowed.y;
+ rect.size.width = window->windowed.w;
+ rect.size.height = window->windowed.h;
+ ConvertNSRect([nswindow screen], NO, &rect);
+
+ s_moveHack = 0;
+ [nswindow setContentSize:rect.size];
+ [nswindow setFrameOrigin:rect.origin];
+ s_moveHack = SDL_GetTicks();
+ }
+#endif /* 0 */
+
+ /* Force the size change event in case it was delivered earlier
+ while the window was still animating into place.
+ */
+ window->w = 0;
+ window->h = 0;
+ [self windowDidMove:aNotification];
+ [self windowDidResize:aNotification];
+
+ /* FIXME: Why does the window get hidden? */
+ if (window->flags & SDL_WINDOW_SHOWN) {
+ Cocoa_ShowWindow(SDL_GetVideoDevice(), window);
+ }
+ }
+}
+
+-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions
+{
+ if ((_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ return NSApplicationPresentationFullScreen | NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
+ } else {
+ return proposedOptions;
+ }
+}
+
+
+/* We'll respond to key events by doing nothing so we don't beep.
+ * We could handle key messages here, but we lose some in the NSApp dispatch,
+ * where they get converted to action messages, etc.
+ */
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+ /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
+}
+- (void)keyDown:(NSEvent *)theEvent
+{
+ /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
+}
+- (void)keyUp:(NSEvent *)theEvent
+{
+ /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
+}
+
+/* We'll respond to selectors by doing nothing so we don't beep.
+ * The escape key gets converted to a "cancel" selector, etc.
+ */
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
+}
+
+- (BOOL)processHitTest:(NSEvent *)theEvent
+{
+ SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
+
+ if (_data->window->hit_test) { /* if no hit-test, skip this. */
+ const NSPoint location = [theEvent locationInWindow];
+ const SDL_Point point = { (int) location.x, _data->window->h - (((int) location.y)-1) };
+ const SDL_HitTestResult rc = _data->window->hit_test(_data->window, &point, _data->window->hit_test_data);
+ if (rc == SDL_HITTEST_DRAGGABLE) {
+ if (!isDragAreaRunning) {
+ isDragAreaRunning = YES;
+ [_data->nswindow setMovableByWindowBackground:YES];
+ }
+ return YES; /* dragging! */
+ }
+ }
+
+ if (isDragAreaRunning) {
+ isDragAreaRunning = NO;
+ [_data->nswindow setMovableByWindowBackground:NO];
+ return YES; /* was dragging, drop event. */
+ }
+
+ return NO; /* not a special area, carry on. */
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ int button;
+ int clicks;
+
+ /* Ignore events that aren't inside the client area (i.e. title bar.) */
+ if ([theEvent window]) {
+ NSRect windowRect = [[[theEvent window] contentView] frame];
+ if (!NSMouseInRect([theEvent locationInWindow], windowRect, NO)) {
+ return;
+ }
+ }
+
+ if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
+ return; /* dragging, drop event. */
+ }
+
+ switch ([theEvent buttonNumber]) {
+ case 0:
+ if (([theEvent modifierFlags] & NSEventModifierFlagControl) &&
+ GetHintCtrlClickEmulateRightClick()) {
+ wasCtrlLeft = YES;
+ button = SDL_BUTTON_RIGHT;
+ } else {
+ wasCtrlLeft = NO;
+ button = SDL_BUTTON_LEFT;
+ }
+ break;
+ case 1:
+ button = SDL_BUTTON_RIGHT;
+ break;
+ case 2:
+ button = SDL_BUTTON_MIDDLE;
+ break;
+ default:
+ button = (int) [theEvent buttonNumber] + 1;
+ break;
+ }
+
+ clicks = (int) [theEvent clickCount];
+ SDL_SendMouseButtonClicks(_data->window, 0, SDL_PRESSED, button, clicks);
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent
+{
+ [self mouseDown:theEvent];
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent
+{
+ [self mouseDown:theEvent];
+}
+
+- (void)mouseUp:(NSEvent *)theEvent
+{
+ int button;
+ int clicks;
+
+ if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
+ return; /* stopped dragging, drop event. */
+ }
+
+ switch ([theEvent buttonNumber]) {
+ case 0:
+ if (wasCtrlLeft) {
+ button = SDL_BUTTON_RIGHT;
+ wasCtrlLeft = NO;
+ } else {
+ button = SDL_BUTTON_LEFT;
+ }
+ break;
+ case 1:
+ button = SDL_BUTTON_RIGHT;
+ break;
+ case 2:
+ button = SDL_BUTTON_MIDDLE;
+ break;
+ default:
+ button = (int) [theEvent buttonNumber] + 1;
+ break;
+ }
+
+ clicks = (int) [theEvent clickCount];
+ SDL_SendMouseButtonClicks(_data->window, 0, SDL_RELEASED, button, clicks);
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent
+{
+ [self mouseUp:theEvent];
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent
+{
+ [self mouseUp:theEvent];
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_Window *window = _data->window;
+ NSPoint point;
+ int x, y;
+
+ if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
+ return; /* dragging, drop event. */
+ }
+
+ if (mouse->relative_mode) {
+ return;
+ }
+
+ point = [theEvent locationInWindow];
+ x = (int)point.x;
+ y = (int)(window->h - point.y);
+
+ if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
+ if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
+ if (x < 0) {
+ x = 0;
+ } else if (x >= window->w) {
+ x = window->w - 1;
+ }
+ if (y < 0) {
+ y = 0;
+ } else if (y >= window->h) {
+ y = window->h - 1;
+ }
+
+#if !SDL_MAC_NO_SANDBOX
+ CGPoint cgpoint;
+
+ /* When SDL_MAC_NO_SANDBOX is set, this is handled by
+ * SDL_cocoamousetap.m.
+ */
+
+ cgpoint.x = window->x + x;
+ cgpoint.y = window->y + y;
+
+ CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ CGAssociateMouseAndMouseCursorPosition(YES);
+
+ Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
+#endif
+ }
+ }
+ SDL_SendMouseMotion(window, 0, 0, x, y);
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent
+{
+ [self mouseMoved:theEvent];
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent
+{
+ [self mouseMoved:theEvent];
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent
+{
+ [self mouseMoved:theEvent];
+}
+
+- (void)scrollWheel:(NSEvent *)theEvent
+{
+ Cocoa_HandleMouseWheel(_data->window, theEvent);
+}
+
+- (void)touchesBeganWithEvent:(NSEvent *) theEvent
+{
+ NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
+ int existingTouchCount = 0;
+
+ for (NSTouch* touch in touches) {
+ if ([touch phase] != NSTouchPhaseBegan) {
+ existingTouchCount++;
+ }
+ }
+ if (existingTouchCount == 0) {
+ SDL_TouchID touchID = (SDL_TouchID)(intptr_t)[[touches anyObject] device];
+ int numFingers = SDL_GetNumTouchFingers(touchID);
+ DLog("Reset Lost Fingers: %d", numFingers);
+ for (--numFingers; numFingers >= 0; --numFingers) {
+ SDL_Finger* finger = SDL_GetTouchFinger(touchID, numFingers);
+ SDL_SendTouch(touchID, finger->id, SDL_FALSE, 0, 0, 0);
+ }
+ }
+
+ DLog("Began Fingers: %lu .. existing: %d", (unsigned long)[touches count], existingTouchCount);
+ [self handleTouches:NSTouchPhaseBegan withEvent:theEvent];
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *) theEvent
+{
+ [self handleTouches:NSTouchPhaseMoved withEvent:theEvent];
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *) theEvent
+{
+ [self handleTouches:NSTouchPhaseEnded withEvent:theEvent];
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *) theEvent
+{
+ [self handleTouches:NSTouchPhaseCancelled withEvent:theEvent];
+}
+
+- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
+{
+ NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
+
+ for (NSTouch *touch in touches) {
+ const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
+ if (SDL_AddTouch(touchId, "") < 0) {
+ return;
+ }
+
+ const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
+ float x = [touch normalizedPosition].x;
+ float y = [touch normalizedPosition].y;
+ /* Make the origin the upper left instead of the lower left */
+ y = 1.0f - y;
+
+ switch (phase) {
+ case NSTouchPhaseBegan:
+ SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
+ break;
+ case NSTouchPhaseEnded:
+ case NSTouchPhaseCancelled:
+ SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
+ break;
+ case NSTouchPhaseMoved:
+ SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+@end
+
+@interface SDLView : NSView {
+ SDL_Window *_sdlWindow;
+}
+
+- (void)setSDLWindow:(SDL_Window*)window;
+
+/* The default implementation doesn't pass rightMouseDown to responder chain */
+- (void)rightMouseDown:(NSEvent *)theEvent;
+- (BOOL)mouseDownCanMoveWindow;
+- (void)drawRect:(NSRect)dirtyRect;
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
+- (BOOL)wantsUpdateLayer;
+- (void)updateLayer;
+@end
+
+@implementation SDLView
+
+- (void)setSDLWindow:(SDL_Window*)window
+{
+ _sdlWindow = window;
+}
+
+/* this is used on older macOS revisions. 10.8 and later use updateLayer. */
+- (void)drawRect:(NSRect)dirtyRect
+{
+ /* Force the graphics context to clear to black so we don't get a flash of
+ white until the app is ready to draw. In practice on modern macOS, this
+ only gets called for window creation and other extraordinary events. */
+ [[NSColor blackColor] setFill];
+ NSRectFill(dirtyRect);
+ SDL_SendWindowEvent(_sdlWindow, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+}
+
+-(BOOL) wantsUpdateLayer
+{
+ return YES;
+}
+
+-(void) updateLayer
+{
+ /* Force the graphics context to clear to black so we don't get a flash of
+ white until the app is ready to draw. In practice on modern macOS, this
+ only gets called for window creation and other extraordinary events. */
+ self.layer.backgroundColor = NSColor.blackColor.CGColor;
+ ScheduleContextUpdates((SDL_WindowData *) _sdlWindow->driverdata);
+ SDL_SendWindowEvent(_sdlWindow, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent
+{
+ [[self nextResponder] rightMouseDown:theEvent];
+}
+
+- (BOOL)mouseDownCanMoveWindow
+{
+ /* Always say YES, but this doesn't do anything until we call
+ -[NSWindow setMovableByWindowBackground:YES], which we ninja-toggle
+ during mouse events when we're using a drag area. */
+ return YES;
+}
+
+- (void)resetCursorRects
+{
+ [super resetCursorRects];
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
+ [self addCursorRect:[self bounds]
+ cursor:mouse->cur_cursor->driverdata];
+ } else {
+ [self addCursorRect:[self bounds]
+ cursor:[NSCursor invisibleCursor]];
+ }
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ if (SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)) {
+ return SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+ } else {
+ return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", SDL_FALSE);
+ }
+}
+@end
+
+static int
+SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
+{ @autoreleasepool
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ SDL_WindowData *data;
+
+ /* Allocate the window data */
+ window->driverdata = data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ return SDL_OutOfMemory();
+ }
+ data->window = window;
+ data->nswindow = nswindow;
+ data->created = created;
+ data->videodata = videodata;
+ data->nscontexts = [[NSMutableArray alloc] init];
+
+ /* Create an event listener for the window */
+ data->listener = [[Cocoa_WindowListener alloc] init];
+
+ /* Fill in the SDL window with the window data */
+ {
+ NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
+ ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
+ window->x = (int)rect.origin.x;
+ window->y = (int)rect.origin.y;
+ window->w = (int)rect.size.width;
+ window->h = (int)rect.size.height;
+ }
+
+ /* Set up the listener after we create the view */
+ [data->listener listen:data];
+
+ if ([nswindow isVisible]) {
+ window->flags |= SDL_WINDOW_SHOWN;
+ } else {
+ window->flags &= ~SDL_WINDOW_SHOWN;
+ }
+
+ {
+ unsigned long style = [nswindow styleMask];
+
+ if (style == NSWindowStyleMaskBorderless) {
+ window->flags |= SDL_WINDOW_BORDERLESS;
+ } else {
+ window->flags &= ~SDL_WINDOW_BORDERLESS;
+ }
+ if (style & NSWindowStyleMaskResizable) {
+ window->flags |= SDL_WINDOW_RESIZABLE;
+ } else {
+ window->flags &= ~SDL_WINDOW_RESIZABLE;
+ }
+ }
+
+ /* isZoomed always returns true if the window is not resizable */
+ if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
+ window->flags |= SDL_WINDOW_MAXIMIZED;
+ } else {
+ window->flags &= ~SDL_WINDOW_MAXIMIZED;
+ }
+
+ if ([nswindow isMiniaturized]) {
+ window->flags |= SDL_WINDOW_MINIMIZED;
+ } else {
+ window->flags &= ~SDL_WINDOW_MINIMIZED;
+ }
+
+ if ([nswindow isKeyWindow]) {
+ window->flags |= SDL_WINDOW_INPUT_FOCUS;
+ SDL_SetKeyboardFocus(data->window);
+ }
+
+ /* Prevents the window's "window device" from being destroyed when it is
+ * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
+ */
+ [nswindow setOneShot:NO];
+
+ /* All done! */
+ window->driverdata = data;
+ return 0;
+}}
+
+int
+Cocoa_CreateWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ NSWindow *nswindow;
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ NSRect rect;
+ SDL_Rect bounds;
+ NSUInteger style;
+ NSArray *screens = [NSScreen screens];
+
+ Cocoa_GetDisplayBounds(_this, display, &bounds);
+ rect.origin.x = window->x;
+ rect.origin.y = window->y;
+ rect.size.width = window->w;
+ rect.size.height = window->h;
+ ConvertNSRect([screens objectAtIndex:0], (window->flags & FULLSCREEN_MASK), &rect);
+
+ style = GetWindowStyle(window);
+
+ /* Figure out which screen to place this window */
+ NSScreen *screen = nil;
+ for (NSScreen *candidate in screens) {
+ NSRect screenRect = [candidate frame];
+ if (rect.origin.x >= screenRect.origin.x &&
+ rect.origin.x < screenRect.origin.x + screenRect.size.width &&
+ rect.origin.y >= screenRect.origin.y &&
+ rect.origin.y < screenRect.origin.y + screenRect.size.height) {
+ screen = candidate;
+ rect.origin.x -= screenRect.origin.x;
+ rect.origin.y -= screenRect.origin.y;
+ }
+ }
+
+ @try {
+ nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen];
+ }
+ @catch (NSException *e) {
+ return SDL_SetError("%s", [[e reason] UTF8String]);
+ }
+
+ if (videodata->allow_spaces) {
+ SDL_assert(floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6);
+ SDL_assert([nswindow respondsToSelector:@selector(toggleFullScreen:)]);
+ /* we put FULLSCREEN_DESKTOP windows in their own Space, without a toggle button or menubar, later */
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
+ [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ }
+ }
+
+ /* Create a default view for this window */
+ rect = [nswindow contentRectForFrameRect:[nswindow frame]];
+ SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
+ [contentView setSDLWindow:window];
+
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
+ [contentView setWantsBestResolutionOpenGLSurface:YES];
+ }
+ }
+
+#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_EGL
+ if ((window->flags & SDL_WINDOW_OPENGL) &&
+ _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
+ [contentView setWantsLayer:TRUE];
+ }
+#endif /* SDL_VIDEO_OPENGL_EGL */
+#endif /* SDL_VIDEO_OPENGL_ES2 */
+ [nswindow setContentView:contentView];
+ [contentView release];
+
+ if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
+ [nswindow release];
+ return -1;
+ }
+
+ if (!(window->flags & SDL_WINDOW_OPENGL)) {
+ return 0;
+ }
+
+ /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
+#if SDL_VIDEO_OPENGL_ES2
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
+#if SDL_VIDEO_OPENGL_EGL
+ if (Cocoa_GLES_SetupWindow(_this, window) < 0) {
+ Cocoa_DestroyWindow(_this, window);
+ return -1;
+ }
+ return 0;
+#else
+ return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
+#endif /* SDL_VIDEO_OPENGL_EGL */
+ }
+#endif /* SDL_VIDEO_OPENGL_ES2 */
+ return 0;
+}}
+
+int
+Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
+{ @autoreleasepool
+{
+ NSWindow *nswindow = (NSWindow *) data;
+ NSString *title;
+
+ /* Query the title from the existing window */
+ title = [nswindow title];
+ if (title) {
+ window->title = SDL_strdup([title UTF8String]);
+ }
+
+ return SetupWindowData(_this, window, nswindow, SDL_FALSE);
+}}
+
+void
+Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ const char *title = window->title ? window->title : "";
+ NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
+ NSString *string = [[NSString alloc] initWithUTF8String:title];
+ [nswindow setTitle:string];
+ [string release];
+}}
+
+void
+Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
+{ @autoreleasepool
+{
+ NSImage *nsimage = Cocoa_CreateImage(icon);
+
+ if (nsimage) {
+ [NSApp setApplicationIconImage:nsimage];
+ }
+}}
+
+void
+Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = windata->nswindow;
+ NSRect rect;
+ Uint32 moveHack;
+
+ rect.origin.x = window->x;
+ rect.origin.y = window->y;
+ rect.size.width = window->w;
+ rect.size.height = window->h;
+ ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
+
+ moveHack = s_moveHack;
+ s_moveHack = 0;
+ [nswindow setFrameOrigin:rect.origin];
+ s_moveHack = moveHack;
+
+ ScheduleContextUpdates(windata);
+}}
+
+void
+Cocoa_SetWindowSize(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = windata->nswindow;
+ NSRect rect;
+ Uint32 moveHack;
+
+ /* Cocoa will resize the window from the bottom-left rather than the
+ * top-left when -[nswindow setContentSize:] is used, so we must set the
+ * entire frame based on the new size, in order to preserve the position.
+ */
+ rect.origin.x = window->x;
+ rect.origin.y = window->y;
+ rect.size.width = window->w;
+ rect.size.height = window->h;
+ ConvertNSRect([nswindow screen], (window->flags & FULLSCREEN_MASK), &rect);
+
+ moveHack = s_moveHack;
+ s_moveHack = 0;
+ [nswindow setFrame:[nswindow frameRectForContentRect:rect] display:YES];
+ s_moveHack = moveHack;
+
+ ScheduleContextUpdates(windata);
+}}
+
+void
+Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+
+ NSSize minSize;
+ minSize.width = window->min_w;
+ minSize.height = window->min_h;
+
+ [windata->nswindow setContentMinSize:minSize];
+}}
+
+void
+Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+
+ NSSize maxSize;
+ maxSize.width = window->max_w;
+ maxSize.height = window->max_h;
+
+ [windata->nswindow setContentMaxSize:maxSize];
+}}
+
+void
+Cocoa_ShowWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
+ NSWindow *nswindow = windowData->nswindow;
+
+ if (![nswindow isMiniaturized]) {
+ [windowData->listener pauseVisibleObservation];
+ [nswindow makeKeyAndOrderFront:nil];
+ [windowData->listener resumeVisibleObservation];
+ }
+}}
+
+void
+Cocoa_HideWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
+
+ [nswindow orderOut:nil];
+}}
+
+void
+Cocoa_RaiseWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
+ NSWindow *nswindow = windowData->nswindow;
+
+ /* makeKeyAndOrderFront: has the side-effect of deminiaturizing and showing
+ a minimized or hidden window, so check for that before showing it.
+ */
+ [windowData->listener pauseVisibleObservation];
+ if (![nswindow isMiniaturized] && [nswindow isVisible]) {
+ [NSApp activateIgnoringOtherApps:YES];
+ [nswindow makeKeyAndOrderFront:nil];
+ }
+ [windowData->listener resumeVisibleObservation];
+}}
+
+void
+Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = windata->nswindow;
+
+ [nswindow zoom:nil];
+
+ ScheduleContextUpdates(windata);
+}}
+
+void
+Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = data->nswindow;
+
+ if ([data->listener isInFullscreenSpaceTransition]) {
+ [data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
+ } else {
+ [nswindow miniaturize:nil];
+ }
+}}
+
+void
+Cocoa_RestoreWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
+
+ if ([nswindow isMiniaturized]) {
+ [nswindow deminiaturize:nil];
+ } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
+ [nswindow zoom:nil];
+ }
+}}
+
+void
+Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
+{ @autoreleasepool
+{
+ if (SetWindowStyle(window, GetWindowStyle(window))) {
+ if (bordered) {
+ Cocoa_SetWindowTitle(_this, window); /* this got blanked out. */
+ }
+ }
+}}
+
+void
+Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{ @autoreleasepool
+{
+ /* Don't set this if we're in a space!
+ * The window will get permanently stuck if resizable is false.
+ * -flibit
+ */
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Cocoa_WindowListener *listener = data->listener;
+ if (![listener isInFullscreenSpace]) {
+ SetWindowStyle(window, GetWindowStyle(window));
+ }
+}}
+
+void
+Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+{ @autoreleasepool
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ NSWindow *nswindow = data->nswindow;
+ NSRect rect;
+
+ /* The view responder chain gets messed with during setStyleMask */
+ if ([[nswindow contentView] nextResponder] == data->listener) {
+ [[nswindow contentView] setNextResponder:nil];
+ }
+
+ if (fullscreen) {
+ SDL_Rect bounds;
+
+ Cocoa_GetDisplayBounds(_this, display, &bounds);
+ rect.origin.x = bounds.x;
+ rect.origin.y = bounds.y;
+ rect.size.width = bounds.w;
+ rect.size.height = bounds.h;
+ ConvertNSRect([nswindow screen], fullscreen, &rect);
+
+ /* Hack to fix origin on Mac OS X 10.4 */
+ NSRect screenRect = [[nswindow screen] frame];
+ if (screenRect.size.height >= 1.0f) {
+ rect.origin.y += (screenRect.size.height - rect.size.height);
+ }
+
+ [nswindow setStyleMask:NSWindowStyleMaskBorderless];
+ } else {
+ rect.origin.x = window->windowed.x;
+ rect.origin.y = window->windowed.y;
+ rect.size.width = window->windowed.w;
+ rect.size.height = window->windowed.h;
+ ConvertNSRect([nswindow screen], fullscreen, &rect);
+
+ [nswindow setStyleMask:GetWindowStyle(window)];
+
+ /* Hack to restore window decorations on Mac OS X 10.10 */
+ NSRect frameRect = [nswindow frame];
+ [nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
+ [nswindow setFrame:frameRect display:NO];
+ }
+
+ /* The view responder chain gets messed with during setStyleMask */
+ if ([[nswindow contentView] nextResponder] != data->listener) {
+ [[nswindow contentView] setNextResponder:data->listener];
+ }
+
+ s_moveHack = 0;
+ [nswindow setContentSize:rect.size];
+ [nswindow setFrameOrigin:rect.origin];
+ s_moveHack = SDL_GetTicks();
+
+ /* When the window style changes the title is cleared */
+ if (!fullscreen) {
+ Cocoa_SetWindowTitle(_this, window);
+ }
+
+ if (SDL_ShouldAllowTopmost() && fullscreen) {
+ /* OpenGL is rendering to the window, so make it visible! */
+ [nswindow setLevel:CGShieldingWindowLevel()];
+ } else {
+ [nswindow setLevel:kCGNormalWindowLevel];
+ }
+
+ if ([nswindow isVisible] || fullscreen) {
+ [data->listener pauseVisibleObservation];
+ [nswindow makeKeyAndOrderFront:nil];
+ [data->listener resumeVisibleObservation];
+ }
+
+ ScheduleContextUpdates(data);
+}}
+
+int
+Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
+{
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
+ const uint32_t tableSize = 256;
+ CGGammaValue redTable[tableSize];
+ CGGammaValue greenTable[tableSize];
+ CGGammaValue blueTable[tableSize];
+ uint32_t i;
+ float inv65535 = 1.0f / 65535.0f;
+
+ /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
+ for (i = 0; i < 256; i++) {
+ redTable[i] = ramp[0*256+i] * inv65535;
+ greenTable[i] = ramp[1*256+i] * inv65535;
+ blueTable[i] = ramp[2*256+i] * inv65535;
+ }
+
+ if (CGSetDisplayTransferByTable(display_id, tableSize,
+ redTable, greenTable, blueTable) != CGDisplayNoErr) {
+ return SDL_SetError("CGSetDisplayTransferByTable()");
+ }
+ return 0;
+}
+
+int
+Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
+{
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
+ const uint32_t tableSize = 256;
+ CGGammaValue redTable[tableSize];
+ CGGammaValue greenTable[tableSize];
+ CGGammaValue blueTable[tableSize];
+ uint32_t i, tableCopied;
+
+ if (CGGetDisplayTransferByTable(display_id, tableSize,
+ redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
+ return SDL_SetError("CGGetDisplayTransferByTable()");
+ }
+
+ for (i = 0; i < tableCopied; i++) {
+ ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
+ ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
+ ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
+ }
+ return 0;
+}
+
+void
+Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ /* Enable or disable the event tap as necessary */
+ Cocoa_EnableMouseEventTap(mouse->driverdata, grabbed);
+
+ /* Move the cursor to the nearest point in the window */
+ if (grabbed && data && ![data->listener isMoving]) {
+ int x, y;
+ CGPoint cgpoint;
+
+ SDL_GetMouseState(&x, &y);
+ cgpoint.x = window->x + x;
+ cgpoint.y = window->y + y;
+
+ Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
+
+ DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
+ CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
+ }
+
+ if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
+ if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)
+ && ![data->listener isInFullscreenSpace]) {
+ /* OpenGL is rendering to the window, so make it visible! */
+ /* Doing this in 10.11 while in a Space breaks things (bug #3152) */
+ [data->nswindow setLevel:CGShieldingWindowLevel()];
+ } else {
+ [data->nswindow setLevel:kCGNormalWindowLevel];
+ }
+ }
+}
+
+void
+Cocoa_DestroyWindow(_THIS, SDL_Window * window)
+{ @autoreleasepool
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (data) {
+ if ([data->listener isInFullscreenSpace]) {
+ [NSMenu setMenuBarVisible:YES];
+ }
+ [data->listener close];
+ [data->listener release];
+ if (data->created) {
+ [data->nswindow close];
+ }
+
+ NSArray *contexts = [[data->nscontexts copy] autorelease];
+ for (SDLOpenGLContext *context in contexts) {
+ /* Calling setWindow:NULL causes the context to remove itself from the context list. */
+ [context setWindow:NULL];
+ }
+ [data->nscontexts release];
+
+ SDL_free(data);
+ }
+ window->driverdata = NULL;
+}}
+
+SDL_bool
+Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
+{
+ NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
+
+ if (info->version.major <= SDL_MAJOR_VERSION) {
+ info->subsystem = SDL_SYSWM_COCOA;
+ info->info.cocoa.window = nswindow;
+ return SDL_TRUE;
+ } else {
+ SDL_SetError("Application not compiled with SDL %d.%d",
+ SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+ return SDL_FALSE;
+ }
+}
+
+SDL_bool
+Cocoa_IsWindowInFullscreenSpace(SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if ([data->listener isInFullscreenSpace]) {
+ return SDL_TRUE;
+ } else {
+ return SDL_FALSE;
+ }
+}
+
+SDL_bool
+Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
+{ @autoreleasepool
+{
+ SDL_bool succeeded = SDL_FALSE;
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
+ const int maxattempts = 3;
+ int attempt = 0;
+ while (++attempt <= maxattempts) {
+ /* Wait for the transition to complete, so application changes
+ take effect properly (e.g. setting the window size, etc.)
+ */
+ const int limit = 10000;
+ int count = 0;
+ while ([data->listener isInFullscreenSpaceTransition]) {
+ if ( ++count == limit ) {
+ /* Uh oh, transition isn't completing. Should we assert? */
+ break;
+ }
+ SDL_Delay(1);
+ SDL_PumpEvents();
+ }
+ if ([data->listener isInFullscreenSpace] == (state ? YES : NO))
+ break;
+ /* Try again, the last attempt was interrupted by user gestures */
+ if (![data->listener setFullscreenSpace:(state ? YES : NO)])
+ break; /* ??? */
+ }
+ /* Return TRUE to prevent non-space fullscreen logic from running */
+ succeeded = SDL_TRUE;
+ }
+
+ return succeeded;
+}}
+
+int
+Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
+{
+ return 0; /* just succeed, the real work is done elsewhere. */
+}
+
+void
+Cocoa_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ if (accept) {
+ [data->nswindow registerForDraggedTypes:[NSArray arrayWithObject:(NSString *)kUTTypeFileURL]];
+ } else {
+ [data->nswindow unregisterDraggedTypes];
+ }
+}
+
+int
+Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ [data->nswindow setAlphaValue:opacity];
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */