early-access version 1611
This commit is contained in:
36
externals/SDL/src/video/cocoa/SDL_cocoaclipboard.h
vendored
Executable file
36
externals/SDL/src/video/cocoa/SDL_cocoaclipboard.h
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
103
externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m
vendored
Executable file
103
externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m
vendored
Executable file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
32
externals/SDL/src/video/cocoa/SDL_cocoaevents.h
vendored
Executable file
32
externals/SDL/src/video/cocoa/SDL_cocoaevents.h
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
511
externals/SDL/src/video/cocoa/SDL_cocoaevents.m
vendored
Executable file
511
externals/SDL/src/video/cocoa/SDL_cocoaevents.m
vendored
Executable file
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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)) {
|
||||
/* Get more aggressive for Catalina: activate the Dock first so we definitely reset all activation state. */
|
||||
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
|
||||
[i activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||
break;
|
||||
}
|
||||
SDL_Delay(300); /* !!! FIXME: this isn't right. */
|
||||
[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 bool
|
||||
LoadMainMenuNibIfAvailable(void)
|
||||
{
|
||||
NSDictionary *infoDict;
|
||||
NSString *mainNibFileName;
|
||||
bool success = false;
|
||||
|
||||
infoDict = [[NSBundle mainBundle] infoDictionary];
|
||||
if (infoDict) {
|
||||
mainNibFileName = [infoDict valueForKey:@"NSMainNibFile"];
|
||||
|
||||
if (mainNibFileName) {
|
||||
success = [[NSBundle mainBundle] loadNibNamed:mainNibFileName owner:[NSApplication sharedApplication] topLevelObjects:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
CreateApplicationMenus(void)
|
||||
{
|
||||
NSString *appName;
|
||||
NSString *title;
|
||||
NSMenu *appleMenu;
|
||||
NSMenu *serviceMenu;
|
||||
NSMenu *windowMenu;
|
||||
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:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
|
||||
|
||||
[windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
|
||||
|
||||
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
|
||||
|
||||
/* Add the fullscreen toggle menu option, if supported */
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) {
|
||||
/* Cocoa should update the title to Enter or Exit Full Screen automatically.
|
||||
* But if not, then just fallback to Toggle Full Screen.
|
||||
*/
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||
[windowMenu addItem:menuItem];
|
||||
[menuItem release];
|
||||
}
|
||||
|
||||
/* 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];
|
||||
}
|
||||
|
||||
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 there aren't already menus in place, look to see if there's
|
||||
* a nib we should use. If not, then manually create the basic
|
||||
* menus we meed.
|
||||
*/
|
||||
if ([NSApp mainMenu] == nil) {
|
||||
bool nibLoaded;
|
||||
|
||||
nibLoaded = LoadMainMenuNibIfAvailable();
|
||||
if (!nibLoaded) {
|
||||
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: */
|
36
externals/SDL/src/video/cocoa/SDL_cocoakeyboard.h
vendored
Executable file
36
externals/SDL/src/video/cocoa/SDL_cocoakeyboard.h
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
607
externals/SDL/src/video/cocoa/SDL_cocoakeyboard.m
vendored
Executable file
607
externals/SDL/src/video/cocoa/SDL_cocoakeyboard.m
vendored
Executable file
@@ -0,0 +1,607 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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>
|
||||
|
||||
/*#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
|
||||
|
||||
|
||||
/* 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 = (unsigned int)[NSEvent modifierFlags];
|
||||
SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSEventModifierFlagCapsLock) != 0);
|
||||
}
|
||||
|
||||
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, (unsigned int)[event modifierFlags]);
|
||||
break;
|
||||
default: /* just to avoid compiler warnings */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitKeyboard(_THIS)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
29
externals/SDL/src/video/cocoa/SDL_cocoamessagebox.h
vendored
Executable file
29
externals/SDL/src/video/cocoa/SDL_cocoamessagebox.h
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
157
externals/SDL/src/video/cocoa/SDL_cocoamessagebox.m
vendored
Executable file
157
externals/SDL/src/video/cocoa/SDL_cocoamessagebox.m
vendored
Executable file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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) {
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
NSButton *button;
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
|
||||
} else {
|
||||
sdlButton = &messageboxdata->buttons[i];
|
||||
}
|
||||
|
||||
button = [alert addButtonWithTitle:[NSString stringWithUTF8String:sdlButton->text]];
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
|
||||
[button setKeyEquivalent:@"\r"];
|
||||
} else if (sdlButton->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;
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
clicked = messageboxdata->numbuttons - 1 - clicked;
|
||||
}
|
||||
*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: */
|
70
externals/SDL/src/video/cocoa/SDL_cocoametalview.h
vendored
Executable file
70
externals/SDL/src/video/cocoa/SDL_cocoametalview.h
vendored
Executable file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoametalview_h_
|
||||
#define SDL_cocoametalview_h_
|
||||
|
||||
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
|
||||
#import "SDL_cocoawindow.h"
|
||||
|
||||
#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
|
||||
windowID:(Uint32)windowID;
|
||||
|
||||
- (void)updateDrawableSize;
|
||||
|
||||
/* Override superclass tag so this class can set it. */
|
||||
@property (assign, readonly) NSInteger tag;
|
||||
|
||||
@property (nonatomic) BOOL highDPI;
|
||||
@property (nonatomic) Uint32 sdlWindowID;
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView Cocoa_Metal_CreateView(_THIS, SDL_Window * window);
|
||||
void Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view);
|
||||
|
||||
void Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
||||
|
||||
#endif /* SDL_cocoametalview_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
182
externals/SDL/src/video/cocoa/SDL_cocoametalview.m
vendored
Executable file
182
externals/SDL/src/video/cocoa/SDL_cocoametalview.m
vendored
Executable file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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_METAL)
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
static int SDLCALL
|
||||
SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
|
||||
{
|
||||
/* Update the drawable size when SDL receives a size changed event for
|
||||
* the window that contains the metal view. It would be nice to use
|
||||
* - (void)resizeWithOldSuperviewSize:(NSSize)oldSize and
|
||||
* - (void)viewDidChangeBackingProperties instead, but SDL's size change
|
||||
* events don't always happen in the same frame (for example when a
|
||||
* resizable window exits a fullscreen Space via the user pressing the OS
|
||||
* exit-space button). */
|
||||
if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
@autoreleasepool {
|
||||
SDL_cocoametalview *view = (__bridge SDL_cocoametalview *)userdata;
|
||||
if (view.sdlWindowID == event->window.windowID) {
|
||||
[view updateDrawableSize];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@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
|
||||
windowID:(Uint32)windowID;
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
self.highDPI = highDPI;
|
||||
self.sdlWindowID = windowID;
|
||||
self.wantsLayer = YES;
|
||||
|
||||
/* Allow resize. */
|
||||
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
SDL_AddEventWatch(SDL_MetalViewEventWatch, self);
|
||||
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
SDL_DelEventWatch(SDL_MetalViewEventWatch, self);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSInteger)tag
|
||||
{
|
||||
return METALVIEW_TAG;
|
||||
}
|
||||
|
||||
- (void)updateDrawableSize
|
||||
{
|
||||
CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer;
|
||||
NSSize size = self.bounds.size;
|
||||
NSSize 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 = NSSizeToCGSize(backingSize);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView
|
||||
Cocoa_Metal_CreateView(_THIS, SDL_Window * window)
|
||||
{ @autoreleasepool {
|
||||
SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
NSView *view = data->nswindow.contentView;
|
||||
BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
Uint32 windowID = SDL_GetWindowID(window);
|
||||
SDL_cocoametalview *newview;
|
||||
SDL_MetalView metalview;
|
||||
|
||||
newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
|
||||
highDPI:highDPI
|
||||
windowID:windowID];
|
||||
if (newview == nil) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
[view addSubview:newview];
|
||||
|
||||
metalview = (SDL_MetalView)CFBridgingRetain(newview);
|
||||
[newview release];
|
||||
|
||||
return metalview;
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view)
|
||||
{ @autoreleasepool {
|
||||
SDL_cocoametalview *metalview = CFBridgingRelease(view);
|
||||
[metalview removeFromSuperview];
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
{ @autoreleasepool {
|
||||
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;
|
||||
SDL_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_METAL) */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
46
externals/SDL/src/video/cocoa/SDL_cocoamodes.h
vendored
Executable file
46
externals/SDL/src/video/cocoa/SDL_cocoamodes.h
vendored
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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
|
||||
{
|
||||
CFMutableArrayRef modes;
|
||||
} 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: */
|
683
externals/SDL/src/video/cocoa/SDL_cocoamodes.m
vendored
Executable file
683
externals/SDL/src/video/cocoa/SDL_cocoamodes.m
vendored
Executable file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_13
|
||||
#define NSAppKitVersionNumber10_12 1504
|
||||
#endif
|
||||
|
||||
|
||||
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 int
|
||||
GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
|
||||
{
|
||||
int refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
|
||||
|
||||
/* CGDisplayModeGetRefreshRate can return 0 (eg for built-in 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);
|
||||
}
|
||||
}
|
||||
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HasValidDisplayModeFlags(CGDisplayModeRef vidmode)
|
||||
{
|
||||
uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
|
||||
|
||||
/* Filter out modes which have flags that we don't want. */
|
||||
if (ioflags & (kDisplayModeNeverShowFlag | kDisplayModeNotGraphicsQualityFlag)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Filter out modes which don't have flags that we want. */
|
||||
if (!(ioflags & kDisplayModeValidFlag) || !(ioflags & kDisplayModeSafeFlag)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static Uint32
|
||||
GetDisplayModePixelFormat(CGDisplayModeRef vidmode)
|
||||
{
|
||||
/* This API is deprecated in 10.11 with no good replacement (as of 10.15). */
|
||||
CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
|
||||
Uint32 pixelformat = SDL_PIXELFORMAT_UNKNOWN;
|
||||
|
||||
if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB8888;
|
||||
} else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB1555;
|
||||
} else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB2101010;
|
||||
} else {
|
||||
/* ignore 8-bit and such for now. */
|
||||
}
|
||||
|
||||
CFRelease(fmt);
|
||||
|
||||
return pixelformat;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayModeData *data;
|
||||
bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
|
||||
int width = (int) CGDisplayModeGetWidth(vidmode);
|
||||
int height = (int) CGDisplayModeGetHeight(vidmode);
|
||||
uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
|
||||
int refreshrate = GetDisplayModeRefreshRate(vidmode, link);
|
||||
Uint32 format = GetDisplayModePixelFormat(vidmode);
|
||||
bool interlaced = (ioflags & kDisplayModeInterlacedFlag) != 0;
|
||||
CFMutableArrayRef modes;
|
||||
|
||||
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!HasValidDisplayModeFlags(vidmode)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
modes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
CFArrayAppendValue(modes, vidmode);
|
||||
|
||||
/* If a list of possible diplay modes is passed in, use it to filter out
|
||||
* modes that have duplicate sizes. We don't just rely on SDL's higher level
|
||||
* duplicate filtering because this code can choose what properties are
|
||||
* prefered, and it can add CGDisplayModes to the DisplayModeData's list of
|
||||
* modes to try (see comment below for why that's necessary).
|
||||
* CGDisplayModeGetPixelWidth and friends are only available in 10.8+. */
|
||||
#ifdef MAC_OS_X_VERSION_10_8
|
||||
if (modelist != NULL && floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
|
||||
int pixelW = (int) CGDisplayModeGetPixelWidth(vidmode);
|
||||
int pixelH = (int) CGDisplayModeGetPixelHeight(vidmode);
|
||||
|
||||
CFIndex modescount = CFArrayGetCount(modelist);
|
||||
|
||||
for (int i = 0; i < modescount; i++) {
|
||||
CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
|
||||
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
|
||||
|
||||
if (CFEqual(vidmode, othermode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!HasValidDisplayModeFlags(othermode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int otherW = (int) CGDisplayModeGetWidth(othermode);
|
||||
int otherH = (int) CGDisplayModeGetHeight(othermode);
|
||||
int otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
|
||||
int otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
|
||||
int otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
||||
Uint32 otherformat = GetDisplayModePixelFormat(othermode);
|
||||
bool otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
||||
|
||||
/* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi
|
||||
* mode in the list with the same size in points.
|
||||
*/
|
||||
if (width == pixelW && height == pixelH
|
||||
&& width == otherW && height == otherH
|
||||
&& refreshrate == otherrefresh && format == otherformat
|
||||
&& (otherpixelW != otherW || otherpixelH != otherH)) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Ignore this mode if it's interlaced and there's a non-interlaced
|
||||
* mode in the list with the same properties.
|
||||
*/
|
||||
if (interlaced && ((otherioflags & kDisplayModeInterlacedFlag) == 0)
|
||||
&& width == otherW && height == otherH && pixelW == otherpixelW
|
||||
&& pixelH == otherpixelH && refreshrate == otherrefresh
|
||||
&& format == otherformat && usableForGUI == otherGUI) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Ignore this mode if it's not usable for desktop UI and its
|
||||
* properties are equal to another GUI-capable mode in the list.
|
||||
*/
|
||||
if (width == otherW && height == otherH && pixelW == otherpixelW
|
||||
&& pixelH == otherpixelH && !usableForGUI && otherGUI
|
||||
&& refreshrate == otherrefresh && format == otherformat) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If multiple modes have the exact same properties, they'll all
|
||||
* go in the list of modes to try when SetDisplayMode is called.
|
||||
* This is needed because kCGDisplayShowDuplicateLowResolutionModes
|
||||
* (which is used to expose highdpi display modes) can make the
|
||||
* list of modes contain duplicates (according to their properties
|
||||
* obtained via public APIs) which don't work with SetDisplayMode.
|
||||
* Those duplicate non-functional modes *do* have different pixel
|
||||
* formats according to their internal data structure viewed with
|
||||
* NSLog, but currently no public API can detect that.
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=4822
|
||||
*
|
||||
* As of macOS 10.15.0, those duplicates have the exact same
|
||||
* properties via public APIs in every way (even their IO flags and
|
||||
* CGDisplayModeGetIODisplayModeID is the same), so we could test
|
||||
* those for equality here too, but I'm intentionally not doing that
|
||||
* in case there are duplicate modes with different IO flags or IO
|
||||
* display mode IDs in the future. In that case I think it's better
|
||||
* to try them all in SetDisplayMode than to risk one of them being
|
||||
* correct but it being filtered out by SDL_AddDisplayMode as being
|
||||
* a duplicate.
|
||||
*/
|
||||
if (width == otherW && height == otherH && pixelW == otherpixelW
|
||||
&& pixelH == otherpixelH && usableForGUI == otherGUI
|
||||
&& refreshrate == otherrefresh && format == otherformat) {
|
||||
CFArrayAppendValue(modes, othermode);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
data->modes = modes;
|
||||
mode->format = format;
|
||||
mode->w = width;
|
||||
mode->h = height;
|
||||
mode->refresh_rate = refreshrate;
|
||||
mode->driverdata = data;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||
{
|
||||
/* This API is deprecated in 10.9 with no good replacement (as of 10.15). */
|
||||
io_service_t servicePort = CGDisplayIOServicePort(displayID);
|
||||
CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(servicePort, 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;
|
||||
SDL_bool isstack;
|
||||
int pass, i;
|
||||
|
||||
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
return;
|
||||
}
|
||||
displays = SDL_small_alloc(CGDirectDisplayID, numDisplays, &isstack);
|
||||
result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
SDL_small_free(displays, isstack);
|
||||
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, NULL, link, &mode)) {
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
SDL_free(display.name);
|
||||
SDL_free(displaydata);
|
||||
continue;
|
||||
}
|
||||
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
SDL_free(display.name);
|
||||
}
|
||||
}
|
||||
SDL_small_free(displays, isstack);
|
||||
}}
|
||||
|
||||
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 NSRect frame = [screen visibleFrame];
|
||||
rect->x = (int)frame.origin.x;
|
||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||
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)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
const float MM_IN_INCH = 25.4f;
|
||||
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
|
||||
/* we need the backingScaleFactor for Retina displays, which is only exposed through NSScreen, not CGDisplay, afaik, so find our screen... */
|
||||
CGFloat scaleFactor = 1.0f;
|
||||
NSArray *screens = [NSScreen screens];
|
||||
for (NSScreen *screen in screens) {
|
||||
const CGDirectDisplayID dpyid = (const CGDirectDisplayID ) [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
||||
if (dpyid == data->display) {
|
||||
if ([screen respondsToSelector:@selector(backingScaleFactor)]) { // Mac OS X 10.7 and later
|
||||
scaleFactor = [screen backingScaleFactor];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CGSize displaySize = CGDisplayScreenSize(data->display);
|
||||
const int pixelWidth = (int) CGDisplayPixelsWide(data->display);
|
||||
const int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
|
||||
|
||||
if (ddpi) {
|
||||
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH)) * scaleFactor;
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width) * scaleFactor;
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height) * scaleFactor;
|
||||
}
|
||||
|
||||
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;
|
||||
CFDictionaryRef dict = NULL;
|
||||
|
||||
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, NULL, link, &desktopmode)) {
|
||||
if (!SDL_AddDisplayMode(display, &desktopmode)) {
|
||||
CFRelease(((SDL_DisplayModeData*)desktopmode.driverdata)->modes);
|
||||
SDL_free(desktopmode.driverdata);
|
||||
}
|
||||
}
|
||||
|
||||
CGDisplayModeRelease(desktopmoderef);
|
||||
|
||||
/* By default, CGDisplayCopyAllDisplayModes will only get a subset of the
|
||||
* system's available modes. For example on a 15" 2016 MBP, users can
|
||||
* choose 1920x1080@2x in System Preferences but it won't show up here,
|
||||
* unless we specify the option below.
|
||||
* The display modes returned by CGDisplayCopyAllDisplayModes are also not
|
||||
* high dpi-capable unless this option is set.
|
||||
* macOS 10.15 also seems to have a bug where entering, exiting, and
|
||||
* re-entering exclusive fullscreen with a low dpi display mode can cause
|
||||
* the content of the screen to move up, which this setting avoids:
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=4822
|
||||
*/
|
||||
#ifdef MAC_OS_X_VERSION_10_8
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
|
||||
const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
|
||||
const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
|
||||
dict = CFDictionaryCreate(NULL,
|
||||
(const void **)dictkeys,
|
||||
(const void **)dictvalues,
|
||||
1,
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
}
|
||||
#endif
|
||||
|
||||
modes = CGDisplayCopyAllDisplayModes(data->display, dict);
|
||||
|
||||
if (dict) {
|
||||
CFRelease(dict);
|
||||
}
|
||||
|
||||
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, modes, link, &mode)) {
|
||||
if (!SDL_AddDisplayMode(display, &mode)) {
|
||||
CFRelease(((SDL_DisplayModeData*)mode.driverdata)->modes);
|
||||
SDL_free(mode.driverdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(modes);
|
||||
}
|
||||
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
|
||||
static CGError
|
||||
SetDisplayModeForDisplay(CGDirectDisplayID display, SDL_DisplayModeData *data)
|
||||
{
|
||||
/* SDL_DisplayModeData can contain multiple CGDisplayModes to try (with
|
||||
* identical properties), some of which might not work. See GetDisplayMode.
|
||||
*/
|
||||
CGError result = kCGErrorFailure;
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(data->modes); i++) {
|
||||
CGDisplayModeRef moderef = (CGDisplayModeRef)CFArrayGetValueAtIndex(data->modes, i);
|
||||
result = CGDisplaySetDisplayMode(display, moderef, NULL);
|
||||
if (result == kCGErrorSuccess) {
|
||||
/* If this mode works, try it first next time. */
|
||||
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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 */
|
||||
SetDisplayModeForDisplay(displaydata->display, data);
|
||||
|
||||
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 = SetDisplayModeForDisplay(displaydata->display, data);
|
||||
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:
|
||||
if (CGDisplayIsMain(displaydata->display)) {
|
||||
CGReleaseAllDisplays();
|
||||
} else {
|
||||
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;
|
||||
CFRelease(mode->modes);
|
||||
|
||||
for (j = 0; j < display->num_display_modes; j++) {
|
||||
mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
|
||||
CFRelease(mode->modes);
|
||||
}
|
||||
}
|
||||
Cocoa_ToggleMenuBar(YES);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
52
externals/SDL/src/video/cocoa/SDL_cocoamouse.h
vendored
Executable file
52
externals/SDL/src/video/cocoa/SDL_cocoamouse.h
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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 int 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: */
|
481
externals/SDL/src/video/cocoa/SDL_cocoamouse.m
vendored
Executable file
481
externals/SDL/src/video/cocoa/SDL_cocoamouse.m
vendored
Executable file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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;
|
||||
|
||||
*x = (int) cocoaLocation.x;
|
||||
*y = (int) (CGDisplayPixelsHigh(kCGDirectMainDisplay) - cocoaLocation.y);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_InitMouse(_THIS)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseData *driverdata = (SDL_MouseData*) SDL_calloc(1, sizeof(SDL_MouseData));
|
||||
if (driverdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
mouse->driverdata = driverdata;
|
||||
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(driverdata);
|
||||
|
||||
const NSPoint location = [NSEvent mouseLocation];
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
SDL_MouseID mouseID = mouse ? mouse->mouseID : 0;
|
||||
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, mouseID, 1, (int)deltaX, (int)deltaY);
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_MouseID mouseID = mouse->mouseID;
|
||||
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, 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);
|
||||
mouse->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
34
externals/SDL/src/video/cocoa/SDL_cocoamousetap.h
vendored
Executable file
34
externals/SDL/src/video/cocoa/SDL_cocoamousetap.h
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
286
externals/SDL/src/video/cocoa/SDL_cocoamousetap.m
vendored
Executable file
286
externals/SDL/src/video/cocoa/SDL_cocoamousetap.m
vendored
Executable file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
77
externals/SDL/src/video/cocoa/SDL_cocoaopengl.h
vendored
Executable file
77
externals/SDL/src/video/cocoa/SDL_cocoaopengl.h
vendored
Executable file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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>
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
||||
|
||||
#endif /* SDL_cocoaopengl_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
459
externals/SDL/src/video/cocoa/SDL_cocoaopengl.m
vendored
Executable file
459
externals/SDL/src/video/cocoa/SDL_cocoaopengl.m
vendored
Executable file
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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"
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
@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;
|
||||
NSView *contentview = windowdata->sdlContentView;
|
||||
|
||||
/* This should never be nil since sdlContentView is only nil if the
|
||||
window was created via SDL_CreateWindowFrom, and SDL doesn't allow
|
||||
OpenGL contexts to be created in that case. However, it doesn't hurt
|
||||
to check. */
|
||||
if (contentview == nil) {
|
||||
/* Prefer to access the cached content view above instead of this,
|
||||
since as of Xcode 11 + SDK 10.15, [window contentView] causes
|
||||
Apple's Main Thread Checker to output a warning. */
|
||||
contentview = [windowdata->nswindow contentView];
|
||||
}
|
||||
|
||||
/* Now sign up for scheduled updates for the new window. */
|
||||
NSMutableArray *contexts = windowdata->nscontexts;
|
||||
@synchronized (contexts) {
|
||||
[contexts addObject:self];
|
||||
}
|
||||
|
||||
if ([self view] != contentview) {
|
||||
[self setView: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];
|
||||
}}
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
49
externals/SDL/src/video/cocoa/SDL_cocoaopengles.h
vendored
Executable file
49
externals/SDL/src/video/cocoa/SDL_cocoaopengles.h
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
132
externals/SDL/src/video/cocoa/SDL_cocoaopengles.m
vendored
Executable file
132
externals/SDL/src/video/cocoa/SDL_cocoaopengles.m
vendored
Executable file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
45
externals/SDL/src/video/cocoa/SDL_cocoashape.h
vendored
Executable file
45
externals/SDL/src/video/cocoa/SDL_cocoashape.h
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
113
externals/SDL/src/video/cocoa/SDL_cocoashape.m
vendored
Executable file
113
externals/SDL/src/video/cocoa/SDL_cocoashape.m
vendored
Executable file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
123
externals/SDL/src/video/cocoa/SDL_cocoavideo.h
vendored
Executable file
123
externals/SDL/src/video/cocoa/SDL_cocoavideo.h
vendored
Executable file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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);
|
||||
|
||||
/* Fix build with the 10.11 SDK */
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
#define NSEventSubtypeMouseEvent NSMouseEventSubtype
|
||||
#endif
|
||||
|
||||
#endif /* SDL_cocoavideo_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
273
externals/SDL/src/video/cocoa/SDL_cocoavideo.m
vendored
Executable file
273
externals/SDL/src/video/cocoa/SDL_cocoavideo.m
vendored
Executable file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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_cocoametalview.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
|
||||
|
||||
#if SDL_VIDEO_METAL
|
||||
device->Metal_CreateView = Cocoa_Metal_CreateView;
|
||||
device->Metal_DestroyView = Cocoa_Metal_DestroyView;
|
||||
#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);
|
||||
if (Cocoa_InitMouse(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* NOTE: This is copypasted in src/video/uikit/SDL_uikitvideo.m! Be sure both
|
||||
* versions remain identical!
|
||||
*/
|
||||
|
||||
void SDL_NSLog(const char *text)
|
||||
{
|
||||
NSLog(@"%s", text);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
55
externals/SDL/src/video/cocoa/SDL_cocoavulkan.h
vendored
Executable file
55
externals/SDL/src/video/cocoa/SDL_cocoavulkan.h
vendored
Executable file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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: */
|
244
externals/SDL/src/video/cocoa/SDL_cocoavulkan.m
vendored
Executable file
244
externals/SDL/src/video/cocoa/SDL_cocoavulkan.m
vendored
Executable file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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",
|
||||
"libvulkan.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 Portability library is already loaded.");
|
||||
}
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if (!path) {
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
/* Handle the case where Vulkan Portability is linked statically. */
|
||||
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 Portability 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 Vulkan Portability library doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
} else if (!hasMacOSSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan Portability library 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;
|
||||
SDL_MetalView metalview;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
metalview = Cocoa_Metal_CreateView(_this, window);
|
||||
if (metalview == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pView = (const void *)metalview;
|
||||
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
Cocoa_Metal_DestroyView(_this, metalview);
|
||||
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call
|
||||
* Metal_DestroyView from. Right now the metal view's ref count is +2 (one
|
||||
* from returning a new view object in CreateView, and one because it's
|
||||
* a subview of the window.) If we release the view here to make it +1, it
|
||||
* will be destroyed when the window is destroyed. */
|
||||
CFBridgingRelease(metalview);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
Cocoa_Metal_GetDrawableSize(window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab: */
|
156
externals/SDL/src/video/cocoa/SDL_cocoawindow.h
vendored
Executable file
156
externals/SDL/src/video/cocoa/SDL_cocoawindow.h
vendored
Executable file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 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;
|
||||
NSView *sdlContentView; /* nil if window is created via CreateWindowFrom */
|
||||
NSMutableArray *nscontexts;
|
||||
SDL_bool created;
|
||||
SDL_bool inWindowFullscreenTransition;
|
||||
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: */
|
2096
externals/SDL/src/video/cocoa/SDL_cocoawindow.m
vendored
Executable file
2096
externals/SDL/src/video/cocoa/SDL_cocoawindow.m
vendored
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user