early-access version 1611
This commit is contained in:
47
externals/SDL/src/video/uikit/SDL_uikitappdelegate.h
vendored
Executable file
47
externals/SDL/src/video/uikit/SDL_uikitappdelegate.h
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SDLLaunchScreenController : UIViewController
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
|
||||
- (void)loadView;
|
||||
|
||||
@end
|
||||
|
||||
@interface SDLUIKitDelegate : NSObject<UIApplicationDelegate>
|
||||
|
||||
+ (id)sharedAppDelegate;
|
||||
+ (NSString *)getAppDelegateClassName;
|
||||
|
||||
- (void)hideLaunchScreen;
|
||||
|
||||
/* This property is marked as optional, and is only intended to be used when
|
||||
* the app's UI is storyboard-based. SDL is not storyboard-based, however
|
||||
* several major third-party ad APIs (e.g. Google admob) incorrectly assume this
|
||||
* property always exists, and will crash if it doesn't. */
|
||||
@property (nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
527
externals/SDL/src/video/uikit/SDL_uikitappdelegate.m
vendored
Executable file
527
externals/SDL/src/video/uikit/SDL_uikitappdelegate.m
vendored
Executable file
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_main.h"
|
||||
|
||||
#import "SDL_uikitappdelegate.h"
|
||||
#import "SDL_uikitmodes.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
static SDL_main_func forward_main;
|
||||
static int forward_argc;
|
||||
static char **forward_argv;
|
||||
static int exit_status;
|
||||
|
||||
#if defined(SDL_MAIN_NEEDED) && !defined(IOS_DYLIB)
|
||||
/* SDL is being built as a static library, include main() */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return SDL_UIKitRunApp(argc, argv, SDL_main);
|
||||
}
|
||||
#endif /* SDL_MAIN_NEEDED && !IOS_DYLIB */
|
||||
|
||||
int SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* store arguments */
|
||||
forward_main = mainFunction;
|
||||
forward_argc = argc;
|
||||
forward_argv = (char **)malloc((argc+1) * sizeof(char *));
|
||||
for (i = 0; i < argc; i++) {
|
||||
forward_argv[i] = malloc( (strlen(argv[i])+1) * sizeof(char));
|
||||
strcpy(forward_argv[i], argv[i]);
|
||||
}
|
||||
forward_argv[i] = NULL;
|
||||
|
||||
/* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
|
||||
@autoreleasepool {
|
||||
UIApplicationMain(argc, argv, nil, [SDLUIKitDelegate getAppDelegateClassName]);
|
||||
}
|
||||
|
||||
/* free the memory we used to hold copies of argc and argv */
|
||||
for (i = 0; i < forward_argc; i++) {
|
||||
free(forward_argv[i]);
|
||||
}
|
||||
free(forward_argv);
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
BOOL disable = (hint && *hint != '0');
|
||||
[UIApplication sharedApplication].idleTimerDisabled = disable;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
/* Load a launch image using the old UILaunchImageFile-era naming rules. */
|
||||
static UIImage *
|
||||
SDL_LoadLaunchImageNamed(NSString *name, int screenh)
|
||||
{
|
||||
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
|
||||
UIUserInterfaceIdiom idiom = [UIDevice currentDevice].userInterfaceIdiom;
|
||||
UIImage *image = nil;
|
||||
|
||||
if (idiom == UIUserInterfaceIdiomPhone && screenh == 568) {
|
||||
/* The image name for the iPhone 5 uses its height as a suffix. */
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-568h", name]];
|
||||
} else if (idiom == UIUserInterfaceIdiomPad) {
|
||||
/* iPad apps can launch in any orientation. */
|
||||
if (UIInterfaceOrientationIsLandscape(curorient)) {
|
||||
if (curorient == UIInterfaceOrientationLandscapeLeft) {
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeLeft", name]];
|
||||
} else {
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeRight", name]];
|
||||
}
|
||||
if (!image) {
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Landscape", name]];
|
||||
}
|
||||
} else {
|
||||
if (curorient == UIInterfaceOrientationPortraitUpsideDown) {
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-PortraitUpsideDown", name]];
|
||||
}
|
||||
if (!image) {
|
||||
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Portrait", name]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
image = [UIImage imageNamed:name];
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
@interface SDLLaunchScreenController ()
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (NSUInteger)supportedInterfaceOrientations;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLLaunchScreenController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithNibName:nil bundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
||||
{
|
||||
if (!(self = [super initWithNibName:nil bundle:nil])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *screenname = nibNameOrNil;
|
||||
NSBundle *bundle = nibBundleOrNil;
|
||||
BOOL atleastiOS8 = UIKit_IsSystemVersionAtLeast(8.0);
|
||||
|
||||
/* Launch screens were added in iOS 8. Otherwise we use launch images. */
|
||||
if (screenname && atleastiOS8) {
|
||||
@try {
|
||||
self.view = [bundle loadNibNamed:screenname owner:self options:nil][0];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
/* If a launch screen name is specified but it fails to load, iOS
|
||||
* displays a blank screen rather than falling back to an image. */
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.view) {
|
||||
NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
|
||||
NSString *imagename = nil;
|
||||
UIImage *image = nil;
|
||||
|
||||
int screenw = (int)([UIScreen mainScreen].bounds.size.width + 0.5);
|
||||
int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5);
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
/* We always want portrait-oriented size, to match UILaunchImageSize. */
|
||||
if (screenw > screenh) {
|
||||
int width = screenw;
|
||||
screenw = screenh;
|
||||
screenh = width;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Xcode 5 introduced a dictionary of launch images in Info.plist. */
|
||||
if (launchimages) {
|
||||
for (NSDictionary *dict in launchimages) {
|
||||
NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
|
||||
NSString *sizestring = dict[@"UILaunchImageSize"];
|
||||
|
||||
/* Ignore this image if the current version is too low. */
|
||||
if (minversion && !UIKit_IsSystemVersionAtLeast(minversion.doubleValue)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore this image if the size doesn't match. */
|
||||
if (sizestring) {
|
||||
CGSize size = CGSizeFromString(sizestring);
|
||||
if ((int)(size.width + 0.5) != screenw || (int)(size.height + 0.5) != screenh) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
NSString *orientstring = dict[@"UILaunchImageOrientation"];
|
||||
|
||||
if (orientstring) {
|
||||
if ([orientstring isEqualToString:@"PortraitUpsideDown"]) {
|
||||
orientmask = UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
} else if ([orientstring isEqualToString:@"Landscape"]) {
|
||||
orientmask = UIInterfaceOrientationMaskLandscape;
|
||||
} else if ([orientstring isEqualToString:@"LandscapeLeft"]) {
|
||||
orientmask = UIInterfaceOrientationMaskLandscapeLeft;
|
||||
} else if ([orientstring isEqualToString:@"LandscapeRight"]) {
|
||||
orientmask = UIInterfaceOrientationMaskLandscapeRight;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore this image if the orientation doesn't match. */
|
||||
if ((orientmask & (1 << curorient)) == 0) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
imagename = dict[@"UILaunchImageName"];
|
||||
}
|
||||
|
||||
if (imagename) {
|
||||
image = [UIImage imageNamed:imagename];
|
||||
}
|
||||
}
|
||||
#if !TARGET_OS_TV
|
||||
else {
|
||||
imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"];
|
||||
|
||||
if (imagename) {
|
||||
image = SDL_LoadLaunchImageNamed(imagename, screenh);
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
image = SDL_LoadLaunchImageNamed(@"Default", screenh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (image) {
|
||||
UIImageView *view = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIImageOrientation imageorient = UIImageOrientationUp;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
/* Bugs observed / workaround tested in iOS 8.3, 7.1, and 6.1. */
|
||||
if (UIInterfaceOrientationIsLandscape(curorient)) {
|
||||
if (atleastiOS8 && image.size.width < image.size.height) {
|
||||
/* On iOS 8, portrait launch images displayed in forced-
|
||||
* landscape mode (e.g. a standard Default.png on an iPhone
|
||||
* when Info.plist only supports landscape orientations) need
|
||||
* to be rotated to display in the expected orientation. */
|
||||
if (curorient == UIInterfaceOrientationLandscapeLeft) {
|
||||
imageorient = UIImageOrientationRight;
|
||||
} else if (curorient == UIInterfaceOrientationLandscapeRight) {
|
||||
imageorient = UIImageOrientationLeft;
|
||||
}
|
||||
} else if (!atleastiOS8 && image.size.width > image.size.height) {
|
||||
/* On iOS 7 and below, landscape launch images displayed in
|
||||
* landscape mode (e.g. landscape iPad launch images) need
|
||||
* to be rotated to display in the expected orientation. */
|
||||
if (curorient == UIInterfaceOrientationLandscapeLeft) {
|
||||
imageorient = UIImageOrientationLeft;
|
||||
} else if (curorient == UIInterfaceOrientationLandscapeRight) {
|
||||
imageorient = UIImageOrientationRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create the properly oriented image. */
|
||||
view.image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:imageorient];
|
||||
|
||||
self.view = view;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (BOOL)shouldAutorotate
|
||||
{
|
||||
/* If YES, the launch image will be incorrectly rotated in some cases. */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
/* We keep the supported orientations unrestricted to avoid the case where
|
||||
* there are no common orientations between the ones set in Info.plist and
|
||||
* the ones set here (it will cause an exception in that case.) */
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLUIKitDelegate {
|
||||
UIWindow *launchWindow;
|
||||
}
|
||||
|
||||
/* convenience method */
|
||||
+ (id)sharedAppDelegate
|
||||
{
|
||||
/* the delegate is set in UIApplicationMain(), which is guaranteed to be
|
||||
* called before this method */
|
||||
return [UIApplication sharedApplication].delegate;
|
||||
}
|
||||
|
||||
+ (NSString *)getAppDelegateClassName
|
||||
{
|
||||
/* subclassing notice: when you subclass this appdelegate, make sure to add
|
||||
* a category to override this method and return the actual name of the
|
||||
* delegate */
|
||||
return @"SDLUIKitDelegate";
|
||||
}
|
||||
|
||||
- (void)hideLaunchScreen
|
||||
{
|
||||
UIWindow *window = launchWindow;
|
||||
|
||||
if (!window || window.hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
launchWindow = nil;
|
||||
|
||||
/* Do a nice animated fade-out (roughly matches the real launch behavior.) */
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
window.alpha = 0.0;
|
||||
} completion:^(BOOL finished) {
|
||||
window.hidden = YES;
|
||||
UIKit_ForceUpdateHomeIndicator(); /* Wait for launch screen to hide so settings are applied to the actual view controller. */
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)postFinishLaunch
|
||||
{
|
||||
/* Hide the launch screen the next time the run loop is run. SDL apps will
|
||||
* have a chance to load resources while the launch screen is still up. */
|
||||
[self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0];
|
||||
|
||||
/* run the user's application, passing argc and argv */
|
||||
SDL_iPhoneSetEventPump(SDL_TRUE);
|
||||
exit_status = forward_main(forward_argc, forward_argv);
|
||||
SDL_iPhoneSetEventPump(SDL_FALSE);
|
||||
|
||||
if (launchWindow) {
|
||||
launchWindow.hidden = YES;
|
||||
launchWindow = nil;
|
||||
}
|
||||
|
||||
/* exit, passing the return status from the user's application */
|
||||
/* We don't actually exit to support applications that do setup in their
|
||||
* main function and then allow the Cocoa event loop to run. */
|
||||
/* exit(exit_status); */
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
|
||||
#if SDL_IPHONE_LAUNCHSCREEN
|
||||
/* The normal launch screen is displayed until didFinishLaunching returns,
|
||||
* but SDL_main is called after that happens and there may be a noticeable
|
||||
* delay between the start of SDL_main and when the first real frame is
|
||||
* displayed (e.g. if resources are loaded before SDL_GL_SwapWindow is
|
||||
* called), so we show the launch screen programmatically until the first
|
||||
* time events are pumped. */
|
||||
UIViewController *vc = nil;
|
||||
NSString *screenname = nil;
|
||||
|
||||
/* tvOS only uses a plain launch image. */
|
||||
#if !TARGET_OS_TV
|
||||
screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
|
||||
|
||||
if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) {
|
||||
@try {
|
||||
/* The launch storyboard is actually a nib in some older versions of
|
||||
* Xcode. We'll try to load it as a storyboard first, as it's more
|
||||
* modern. */
|
||||
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:screenname bundle:bundle];
|
||||
vc = [storyboard instantiateInitialViewController];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
/* Do nothing (there's more code to execute below). */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vc == nil) {
|
||||
vc = [[SDLLaunchScreenController alloc] initWithNibName:screenname bundle:bundle];
|
||||
}
|
||||
|
||||
if (vc.view) {
|
||||
launchWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
|
||||
/* We don't want the launch window immediately hidden when a real SDL
|
||||
* window is shown - we fade it out ourselves when we're ready. */
|
||||
launchWindow.windowLevel = UIWindowLevelNormal + 1.0;
|
||||
|
||||
/* Show the window but don't make it key. Events should always go to
|
||||
* other windows when possible. */
|
||||
launchWindow.hidden = NO;
|
||||
|
||||
launchWindow.rootViewController = vc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set working directory to resource path */
|
||||
[[NSFileManager defaultManager] changeCurrentDirectoryPath:[bundle resourcePath]];
|
||||
|
||||
/* register a callback for the idletimer hint */
|
||||
SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED,
|
||||
SDL_IdleTimerDisabledChanged, NULL);
|
||||
|
||||
SDL_SetMainReady();
|
||||
[self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UIWindow *)window
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
if (_this) {
|
||||
SDL_Window *window = NULL;
|
||||
for (window = _this->windows; window != NULL; window = window->next) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
if (data != nil) {
|
||||
return data.uiwindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setWindow:(UIWindow *)window
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
|
||||
{
|
||||
SDL_OnApplicationDidChangeStatusBarOrientation();
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application
|
||||
{
|
||||
SDL_OnApplicationWillTerminate();
|
||||
}
|
||||
|
||||
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
|
||||
{
|
||||
SDL_OnApplicationDidReceiveMemoryWarning();
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication*)application
|
||||
{
|
||||
SDL_OnApplicationWillResignActive();
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication*)application
|
||||
{
|
||||
SDL_OnApplicationDidEnterBackground();
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication*)application
|
||||
{
|
||||
SDL_OnApplicationWillEnterForeground();
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication*)application
|
||||
{
|
||||
SDL_OnApplicationDidBecomeActive();
|
||||
}
|
||||
|
||||
- (void)sendDropFileForURL:(NSURL *)url
|
||||
{
|
||||
NSURL *fileURL = url.filePathURL;
|
||||
if (fileURL != nil) {
|
||||
SDL_SendDropFile(NULL, fileURL.path.UTF8String);
|
||||
} else {
|
||||
SDL_SendDropFile(NULL, url.absoluteString.UTF8String);
|
||||
}
|
||||
SDL_SendDropComplete(NULL);
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV || (defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0)
|
||||
|
||||
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
|
||||
{
|
||||
/* TODO: Handle options */
|
||||
[self sendDropFileForURL:url];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
|
||||
{
|
||||
[self sendDropFileForURL:url];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
35
externals/SDL/src/video/uikit/SDL_uikitclipboard.h
vendored
Executable file
35
externals/SDL/src/video/uikit/SDL_uikitclipboard.h
vendored
Executable file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
#ifndef SDL_uikitclipboard_h_
|
||||
#define SDL_uikitclipboard_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
extern int UIKit_SetClipboardText(_THIS, const char *text);
|
||||
extern char *UIKit_GetClipboardText(_THIS);
|
||||
extern SDL_bool UIKit_HasClipboardText(_THIS);
|
||||
|
||||
extern void UIKit_InitClipboard(_THIS);
|
||||
extern void UIKit_QuitClipboard(_THIS);
|
||||
|
||||
#endif /* SDL_uikitclipboard_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
111
externals/SDL/src/video/uikit/SDL_uikitclipboard.m
vendored
Executable file
111
externals/SDL/src/video/uikit/SDL_uikitclipboard.m
vendored
Executable file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "../../events/SDL_clipboardevents_c.h"
|
||||
|
||||
#import <UIKit/UIPasteboard.h>
|
||||
|
||||
int
|
||||
UIKit_SetClipboardText(_THIS, const char *text)
|
||||
{
|
||||
#if TARGET_OS_TV
|
||||
return SDL_SetError("The clipboard is not available on tvOS");
|
||||
#else
|
||||
@autoreleasepool {
|
||||
[UIPasteboard generalPasteboard].string = @(text);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
UIKit_GetClipboardText(_THIS)
|
||||
{
|
||||
#if TARGET_OS_TV
|
||||
return SDL_strdup(""); // Unsupported.
|
||||
#else
|
||||
@autoreleasepool {
|
||||
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
|
||||
NSString *string = pasteboard.string;
|
||||
|
||||
if (string != nil) {
|
||||
return SDL_strdup(string.UTF8String);
|
||||
} else {
|
||||
return SDL_strdup("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_HasClipboardText(_THIS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
#if !TARGET_OS_TV
|
||||
if ([UIPasteboard generalPasteboard].string != nil) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_InitClipboard(_THIS)
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
@autoreleasepool {
|
||||
SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
id observer = [center addObserverForName:UIPasteboardChangedNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
SDL_SendClipboardUpdate();
|
||||
}];
|
||||
|
||||
data.pasteboardObserver = observer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_QuitClipboard(_THIS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (data.pasteboardObserver != nil) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:data.pasteboardObserver];
|
||||
}
|
||||
|
||||
data.pasteboardObserver = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
30
externals/SDL/src/video/uikit/SDL_uikitevents.h
vendored
Executable file
30
externals/SDL/src/video/uikit/SDL_uikitevents.h
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
#ifndef SDL_uikitevents_h_
|
||||
#define SDL_uikitevents_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
extern void UIKit_PumpEvents(_THIS);
|
||||
|
||||
#endif /* SDL_uikitevents_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
75
externals/SDL/src/video/uikit/SDL_uikitevents.m
vendored
Executable file
75
externals/SDL/src/video/uikit/SDL_uikitevents.m
vendored
Executable file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitevents.h"
|
||||
#include "SDL_uikitopengles.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
static BOOL UIKit_EventPumpEnabled = YES;
|
||||
|
||||
void
|
||||
SDL_iPhoneSetEventPump(SDL_bool enabled)
|
||||
{
|
||||
UIKit_EventPumpEnabled = enabled;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_PumpEvents(_THIS)
|
||||
{
|
||||
if (!UIKit_EventPumpEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let the run loop run for a short amount of time: long enough for
|
||||
touch events to get processed (which is important to get certain
|
||||
elements of Game Center's GKLeaderboardViewController to respond
|
||||
to touch input), but not long enough to introduce a significant
|
||||
delay in the rest of the app.
|
||||
*/
|
||||
const CFTimeInterval seconds = 0.000002;
|
||||
|
||||
/* Pump most event types. */
|
||||
SInt32 result;
|
||||
do {
|
||||
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, TRUE);
|
||||
} while (result == kCFRunLoopRunHandledSource);
|
||||
|
||||
/* Make sure UIScrollView objects scroll properly. */
|
||||
do {
|
||||
result = CFRunLoopRunInMode((CFStringRef)UITrackingRunLoopMode, seconds, TRUE);
|
||||
} while(result == kCFRunLoopRunHandledSource);
|
||||
|
||||
/* See the comment in the function definition. */
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
UIKit_GL_RestoreCurrentContext();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
31
externals/SDL/src/video/uikit/SDL_uikitmessagebox.h
vendored
Executable file
31
externals/SDL/src/video/uikit/SDL_uikitmessagebox.h
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
extern SDL_bool UIKit_ShowingMessageBox(void);
|
||||
|
||||
extern int UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
211
externals/SDL/src/video/uikit/SDL_uikitmessagebox.m
vendored
Executable file
211
externals/SDL/src/video/uikit/SDL_uikitmessagebox.m
vendored
Executable file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
|
||||
/* Display a UIKit message box */
|
||||
|
||||
static SDL_bool s_showingMessageBox = SDL_FALSE;
|
||||
|
||||
SDL_bool
|
||||
UIKit_ShowingMessageBox(void)
|
||||
{
|
||||
return s_showingMessageBox;
|
||||
}
|
||||
|
||||
static void
|
||||
UIKit_WaitUntilMessageBoxClosed(const SDL_MessageBoxData *messageboxdata, int *clickedindex)
|
||||
{
|
||||
*clickedindex = messageboxdata->numbuttons;
|
||||
|
||||
@autoreleasepool {
|
||||
/* Run the main event loop until the alert has finished */
|
||||
/* Note that this needs to be done on the main thread */
|
||||
s_showingMessageBox = SDL_TRUE;
|
||||
while ((*clickedindex) == messageboxdata->numbuttons) {
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
}
|
||||
s_showingMessageBox = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL
|
||||
UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
int i;
|
||||
int __block clickedindex = messageboxdata->numbuttons;
|
||||
UIWindow *window = nil;
|
||||
UIWindow *alertwindow = nil;
|
||||
|
||||
if (![UIAlertController class]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
UIAlertController *alert;
|
||||
alert = [UIAlertController alertControllerWithTitle:@(messageboxdata->title)
|
||||
message:@(messageboxdata->message)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; i++) {
|
||||
UIAlertAction *action;
|
||||
UIAlertActionStyle style = UIAlertActionStyleDefault;
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
|
||||
} else {
|
||||
sdlButton = &messageboxdata->buttons[i];
|
||||
}
|
||||
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
|
||||
style = UIAlertActionStyleCancel;
|
||||
}
|
||||
|
||||
action = [UIAlertAction actionWithTitle:@(sdlButton->text)
|
||||
style:style
|
||||
handler:^(UIAlertAction *action) {
|
||||
clickedindex = (int)(sdlButton - messageboxdata->buttons);
|
||||
}];
|
||||
[alert addAction:action];
|
||||
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
|
||||
alert.preferredAction = action;
|
||||
}
|
||||
}
|
||||
|
||||
if (messageboxdata->window) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) messageboxdata->window->driverdata;
|
||||
window = data.uiwindow;
|
||||
}
|
||||
|
||||
if (window == nil || window.rootViewController == nil) {
|
||||
alertwindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
alertwindow.rootViewController = [UIViewController new];
|
||||
alertwindow.windowLevel = UIWindowLevelAlert;
|
||||
|
||||
window = alertwindow;
|
||||
|
||||
[alertwindow makeKeyAndVisible];
|
||||
}
|
||||
|
||||
[window.rootViewController presentViewController:alert animated:YES completion:nil];
|
||||
UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
|
||||
|
||||
if (alertwindow) {
|
||||
alertwindow.hidden = YES;
|
||||
}
|
||||
|
||||
UIKit_ForceUpdateHomeIndicator();
|
||||
|
||||
*buttonid = messageboxdata->buttons[clickedindex].buttonid;
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
|
||||
@interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
|
||||
|
||||
@property (nonatomic, assign) int *clickedIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLAlertViewDelegate
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
if (_clickedIndex != NULL) {
|
||||
*_clickedIndex = (int) buttonIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
|
||||
|
||||
static BOOL
|
||||
UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
/* UIAlertView is deprecated in iOS 8+ in favor of UIAlertController. */
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
|
||||
int i;
|
||||
int clickedindex = messageboxdata->numbuttons;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
UIAlertView *alert = [[UIAlertView alloc] init];
|
||||
SDLAlertViewDelegate *delegate = [[SDLAlertViewDelegate alloc] init];
|
||||
|
||||
alert.delegate = delegate;
|
||||
alert.title = @(messageboxdata->title);
|
||||
alert.message = @(messageboxdata->message);
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; i++) {
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
|
||||
} else {
|
||||
sdlButton = &messageboxdata->buttons[i];
|
||||
}
|
||||
[alert addButtonWithTitle:@(sdlButton->text)];
|
||||
}
|
||||
|
||||
delegate.clickedIndex = &clickedindex;
|
||||
|
||||
[alert show];
|
||||
|
||||
UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex);
|
||||
|
||||
alert.delegate = nil;
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
clickedindex = messageboxdata->numbuttons - 1 - clickedindex;
|
||||
}
|
||||
*buttonid = messageboxdata->buttons[clickedindex].buttonid;
|
||||
return YES;
|
||||
#else
|
||||
return NO;
|
||||
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
BOOL success = NO;
|
||||
|
||||
@autoreleasepool {
|
||||
success = UIKit_ShowMessageBoxAlertController(messageboxdata, buttonid);
|
||||
if (!success) {
|
||||
success = UIKit_ShowMessageBoxAlertView(messageboxdata, buttonid);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return SDL_SetError("Could not show message box.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
59
externals/SDL/src/video/uikit/SDL_uikitmetalview.h
vendored
Executable file
59
externals/SDL/src/video/uikit/SDL_uikitmetalview.h
vendored
Executable file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef SDL_uikitmetalview_h_
|
||||
#define SDL_uikitmetalview_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#define METALVIEW_TAG 255
|
||||
|
||||
@interface SDL_uikitmetalview : SDL_uikitview
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale;
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView UIKit_Metal_CreateView(_THIS, SDL_Window * window);
|
||||
void UIKit_Metal_DestroyView(_THIS, SDL_MetalView view);
|
||||
|
||||
void UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
||||
|
||||
#endif /* SDL_uikitmetalview_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
135
externals/SDL/src/video/uikit/SDL_uikitmetalview.m
vendored
Executable file
135
externals/SDL/src/video/uikit/SDL_uikitmetalview.m
vendored
Executable file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
#import "SDL_uikitmetalview.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
|
||||
@implementation SDL_uikitmetalview
|
||||
|
||||
/* Returns a Metal-compatible layer. */
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [CAMetalLayer class];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
self.tag = METALVIEW_TAG;
|
||||
self.layer.contentsScale = scale;
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Set the size of the metal drawables when the view is resized. */
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
- (void)updateDrawableSize
|
||||
{
|
||||
CGSize size = self.bounds.size;
|
||||
size.width *= self.layer.contentsScale;
|
||||
size.height *= self.layer.contentsScale;
|
||||
((CAMetalLayer *)self.layer).drawableSize = size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView
|
||||
UIKit_Metal_CreateView(_THIS, SDL_Window * window)
|
||||
{ @autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
CGFloat scale = 1.0;
|
||||
SDL_uikitmetalview *metalview;
|
||||
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
/* Set the scale to the natural scale factor of the screen - then
|
||||
* the backing dimensions of the Metal view will match the pixel
|
||||
* dimensions of the screen rather than the dimensions in points
|
||||
* yielding high resolution on retine displays.
|
||||
*/
|
||||
if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
|
||||
scale = data.uiwindow.screen.nativeScale;
|
||||
} else {
|
||||
scale = data.uiwindow.screen.scale;
|
||||
}
|
||||
}
|
||||
|
||||
metalview = [[SDL_uikitmetalview alloc] initWithFrame:data.uiwindow.bounds
|
||||
scale:scale];
|
||||
[metalview setSDLWindow:window];
|
||||
|
||||
return (void*)CFBridgingRetain(metalview);
|
||||
}}
|
||||
|
||||
void
|
||||
UIKit_Metal_DestroyView(_THIS, SDL_MetalView view)
|
||||
{ @autoreleasepool {
|
||||
SDL_uikitmetalview *metalview = CFBridgingRelease(view);
|
||||
|
||||
if ([metalview isKindOfClass:[SDL_uikitmetalview class]]) {
|
||||
[metalview setSDLWindow:NULL];
|
||||
}
|
||||
}}
|
||||
|
||||
void
|
||||
UIKit_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
|
||||
SDL_uikitmetalview* metalview = [view viewWithTag:METALVIEW_TAG];
|
||||
if (metalview) {
|
||||
CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
|
||||
assert(layer != NULL);
|
||||
if (w) {
|
||||
*w = layer.drawableSize.width;
|
||||
}
|
||||
if (h) {
|
||||
*h = layer.drawableSize.height;
|
||||
}
|
||||
} else {
|
||||
SDL_GetWindowSize(window, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
54
externals/SDL/src/video/uikit/SDL_uikitmodes.h
vendored
Executable file
54
externals/SDL/src/video/uikit/SDL_uikitmodes.h
vendored
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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_uikitmodes_h_
|
||||
#define SDL_uikitmodes_h_
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
|
||||
@interface SDL_DisplayData : NSObject
|
||||
|
||||
- (instancetype)initWithScreen:(UIScreen*)screen;
|
||||
|
||||
@property (nonatomic, strong) UIScreen *uiscreen;
|
||||
@property (nonatomic) float screenDPI;
|
||||
|
||||
@end
|
||||
|
||||
@interface SDL_DisplayModeData : NSObject
|
||||
|
||||
@property (nonatomic, strong) UIScreenMode *uiscreenmode;
|
||||
|
||||
@end
|
||||
|
||||
extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
|
||||
|
||||
extern int UIKit_InitModes(_THIS);
|
||||
extern void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
|
||||
extern int UIKit_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
|
||||
extern int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
||||
extern void UIKit_QuitModes(_THIS);
|
||||
extern int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
|
||||
|
||||
#endif /* SDL_uikitmodes_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
542
externals/SDL/src/video/uikit/SDL_uikitmodes.m
vendored
Executable file
542
externals/SDL/src/video/uikit/SDL_uikitmodes.m
vendored
Executable file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#import <sys/utsname.h>
|
||||
|
||||
@implementation SDL_DisplayData
|
||||
|
||||
- (instancetype)initWithScreen:(UIScreen*)screen
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.uiscreen = screen;
|
||||
|
||||
/*
|
||||
* A well up to date list of device info can be found here:
|
||||
* https://github.com/lmirosevic/GBDeviceInfo/blob/master/GBDeviceInfo/GBDeviceInfo_iOS.m
|
||||
*/
|
||||
NSDictionary* devices = @{
|
||||
@"iPhone1,1": @163,
|
||||
@"iPhone1,2": @163,
|
||||
@"iPhone2,1": @163,
|
||||
@"iPhone3,1": @326,
|
||||
@"iPhone3,2": @326,
|
||||
@"iPhone3,3": @326,
|
||||
@"iPhone4,1": @326,
|
||||
@"iPhone5,1": @326,
|
||||
@"iPhone5,2": @326,
|
||||
@"iPhone5,3": @326,
|
||||
@"iPhone5,4": @326,
|
||||
@"iPhone6,1": @326,
|
||||
@"iPhone6,2": @326,
|
||||
@"iPhone7,1": @401,
|
||||
@"iPhone7,2": @326,
|
||||
@"iPhone8,1": @326,
|
||||
@"iPhone8,2": @401,
|
||||
@"iPhone8,4": @326,
|
||||
@"iPhone9,1": @326,
|
||||
@"iPhone9,2": @401,
|
||||
@"iPhone9,3": @326,
|
||||
@"iPhone9,4": @401,
|
||||
@"iPhone10,1": @326,
|
||||
@"iPhone10,2": @401,
|
||||
@"iPhone10,3": @458,
|
||||
@"iPhone10,4": @326,
|
||||
@"iPhone10,5": @401,
|
||||
@"iPhone10,6": @458,
|
||||
@"iPhone11,2": @458,
|
||||
@"iPhone11,4": @458,
|
||||
@"iPhone11,6": @458,
|
||||
@"iPhone11,8": @326,
|
||||
@"iPhone12,1": @326,
|
||||
@"iPhone12,3": @458,
|
||||
@"iPhone12,5": @458,
|
||||
@"iPad1,1": @132,
|
||||
@"iPad2,1": @132,
|
||||
@"iPad2,2": @132,
|
||||
@"iPad2,3": @132,
|
||||
@"iPad2,4": @132,
|
||||
@"iPad2,5": @163,
|
||||
@"iPad2,6": @163,
|
||||
@"iPad2,7": @163,
|
||||
@"iPad3,1": @264,
|
||||
@"iPad3,2": @264,
|
||||
@"iPad3,3": @264,
|
||||
@"iPad3,4": @264,
|
||||
@"iPad3,5": @264,
|
||||
@"iPad3,6": @264,
|
||||
@"iPad4,1": @264,
|
||||
@"iPad4,2": @264,
|
||||
@"iPad4,3": @264,
|
||||
@"iPad4,4": @326,
|
||||
@"iPad4,5": @326,
|
||||
@"iPad4,6": @326,
|
||||
@"iPad4,7": @326,
|
||||
@"iPad4,8": @326,
|
||||
@"iPad4,9": @326,
|
||||
@"iPad5,1": @326,
|
||||
@"iPad5,2": @326,
|
||||
@"iPad5,3": @264,
|
||||
@"iPad5,4": @264,
|
||||
@"iPad6,3": @264,
|
||||
@"iPad6,4": @264,
|
||||
@"iPad6,7": @264,
|
||||
@"iPad6,8": @264,
|
||||
@"iPad6,11": @264,
|
||||
@"iPad6,12": @264,
|
||||
@"iPad7,1": @264,
|
||||
@"iPad7,2": @264,
|
||||
@"iPad7,3": @264,
|
||||
@"iPad7,4": @264,
|
||||
@"iPad7,5": @264,
|
||||
@"iPad7,6": @264,
|
||||
@"iPad7,11": @264,
|
||||
@"iPad7,12": @264,
|
||||
@"iPad8,1": @264,
|
||||
@"iPad8,2": @264,
|
||||
@"iPad8,3": @264,
|
||||
@"iPad8,4": @264,
|
||||
@"iPad8,5": @264,
|
||||
@"iPad8,6": @264,
|
||||
@"iPad8,7": @264,
|
||||
@"iPad8,8": @264,
|
||||
@"iPad11,1": @326,
|
||||
@"iPad11,2": @326,
|
||||
@"iPad11,3": @326,
|
||||
@"iPad11,4": @326,
|
||||
@"iPod1,1": @163,
|
||||
@"iPod2,1": @163,
|
||||
@"iPod3,1": @163,
|
||||
@"iPod4,1": @326,
|
||||
@"iPod5,1": @326,
|
||||
@"iPod7,1": @326,
|
||||
@"iPod9,1": @326,
|
||||
};
|
||||
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
NSString* deviceName =
|
||||
[NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
|
||||
id foundDPI = devices[deviceName];
|
||||
if (foundDPI) {
|
||||
self.screenDPI = (float)[foundDPI integerValue];
|
||||
} else {
|
||||
/*
|
||||
* Estimate the DPI based on the screen scale multiplied by the base DPI for the device
|
||||
* type (e.g. based on iPhone 1 and iPad 1)
|
||||
*/
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
|
||||
float scale = (float)screen.nativeScale;
|
||||
#else
|
||||
float scale = (float)screen.scale;
|
||||
#endif
|
||||
float defaultDPI;
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
defaultDPI = 132.0f;
|
||||
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
defaultDPI = 163.0f;
|
||||
} else {
|
||||
defaultDPI = 160.0f;
|
||||
}
|
||||
self.screenDPI = scale * defaultDPI;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@synthesize uiscreen;
|
||||
@synthesize screenDPI;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDL_DisplayModeData
|
||||
|
||||
@synthesize uiscreenmode;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static int
|
||||
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
|
||||
UIScreenMode * uiscreenmode)
|
||||
{
|
||||
SDL_DisplayModeData *data = nil;
|
||||
|
||||
if (uiscreenmode != nil) {
|
||||
/* Allocate the display mode data */
|
||||
data = [[SDL_DisplayModeData alloc] init];
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
data.uiscreenmode = uiscreenmode;
|
||||
}
|
||||
|
||||
mode->driverdata = (void *) CFBridgingRetain(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
|
||||
{
|
||||
if (mode->driverdata != NULL) {
|
||||
CFRelease(mode->driverdata);
|
||||
mode->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static NSUInteger
|
||||
UIKit_GetDisplayModeRefreshRate(UIScreen *uiscreen)
|
||||
{
|
||||
#ifdef __IPHONE_10_3
|
||||
if ([uiscreen respondsToSelector:@selector(maximumFramesPerSecond)]) {
|
||||
return uiscreen.maximumFramesPerSecond;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
||||
UIScreen * uiscreen, UIScreenMode * uiscreenmode)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
|
||||
mode.w = w;
|
||||
mode.h = h;
|
||||
|
||||
if (SDL_AddDisplayMode(display, &mode)) {
|
||||
return 0;
|
||||
} else {
|
||||
UIKit_FreeDisplayModeData(&mode);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, UIScreen * uiscreen,
|
||||
UIScreenMode * uiscreenmode, SDL_bool addRotation)
|
||||
{
|
||||
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreen, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addRotation) {
|
||||
/* Add the rotated version */
|
||||
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreen, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
UIKit_AddDisplay(UIScreen *uiscreen)
|
||||
{
|
||||
UIScreenMode *uiscreenmode = uiscreen.currentMode;
|
||||
CGSize size = uiscreen.bounds.size;
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
|
||||
/* Make sure the width/height are oriented correctly */
|
||||
if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) {
|
||||
CGFloat height = size.width;
|
||||
size.width = size.height;
|
||||
size.height = height;
|
||||
}
|
||||
|
||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
|
||||
mode.w = (int) size.width;
|
||||
mode.h = (int) size.height;
|
||||
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_zero(display);
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
|
||||
/* Allocate the display data */
|
||||
SDL_DisplayData *data = [[SDL_DisplayData alloc] initWithScreen:uiscreen];
|
||||
if (!data) {
|
||||
UIKit_FreeDisplayModeData(&display.desktop_mode);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
display.driverdata = (void *) CFBridgingRetain(data);
|
||||
SDL_AddVideoDisplay(&display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
if (uiscreen == [UIScreen mainScreen]) {
|
||||
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
|
||||
} else
|
||||
#endif /* !TARGET_OS_TV */
|
||||
{
|
||||
CGSize size = uiscreen.bounds.size;
|
||||
return (size.width > size.height);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_InitModes(_THIS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
for (UIScreen *uiscreen in [UIScreen screens]) {
|
||||
if (UIKit_AddDisplay(uiscreen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#if !TARGET_OS_TV
|
||||
SDL_OnApplicationDidChangeStatusBarOrientation();
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
|
||||
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
|
||||
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
|
||||
CGFloat scale = data.uiscreen.scale;
|
||||
NSArray *availableModes = nil;
|
||||
|
||||
#if TARGET_OS_TV
|
||||
addRotation = SDL_FALSE;
|
||||
availableModes = @[data.uiscreen.currentMode];
|
||||
#else
|
||||
availableModes = data.uiscreen.availableModes;
|
||||
#endif
|
||||
|
||||
for (UIScreenMode *uimode in availableModes) {
|
||||
/* The size of a UIScreenMode is in pixels, but we deal exclusively
|
||||
* in points (except in SDL_GL_GetDrawableSize.)
|
||||
*
|
||||
* For devices such as iPhone 6/7/8 Plus, the UIScreenMode reported
|
||||
* by iOS is not in physical pixels of the display, but rather the
|
||||
* point size times the scale. For example, on iOS 12.2 on iPhone 8
|
||||
* Plus the uimode.size is 1242x2208 and the uiscreen.scale is 3
|
||||
* thus this will give the size in points which is 414x736. The code
|
||||
* used to use the nativeScale, assuming UIScreenMode returned raw
|
||||
* physical pixels (as suggested by its documentation, but in
|
||||
* practice it is returning the retina pixels). */
|
||||
int w = (int)(uimode.size.width / scale);
|
||||
int h = (int)(uimode.size.height / scale);
|
||||
|
||||
/* Make sure the width/height are oriented correctly */
|
||||
if (isLandscape != (w > h)) {
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
}
|
||||
|
||||
UIKit_AddDisplayMode(display, w, h, data.uiscreen, uimode, addRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
float dpi = data.screenDPI;
|
||||
|
||||
if (ddpi) {
|
||||
*ddpi = dpi * (float)SDL_sqrt(2.0);
|
||||
}
|
||||
if (hdpi) {
|
||||
*hdpi = dpi;
|
||||
}
|
||||
if (vdpi) {
|
||||
*vdpi = dpi;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
|
||||
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
|
||||
#endif
|
||||
|
||||
if (data.uiscreen == [UIScreen mainScreen]) {
|
||||
/* [UIApplication setStatusBarOrientation:] no longer works reliably
|
||||
* in recent iOS versions, so we can't rotate the screen when setting
|
||||
* the display mode. */
|
||||
if (mode->w > mode->h) {
|
||||
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
return SDL_SetError("Screen orientation does not match display mode size");
|
||||
}
|
||||
} else if (mode->w < mode->h) {
|
||||
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
return SDL_SetError("Screen orientation does not match display mode size");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
|
||||
{
|
||||
@autoreleasepool {
|
||||
int displayIndex = (int) (display - _this->displays);
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
CGRect frame = data.uiscreen.bounds;
|
||||
|
||||
/* the default function iterates displays to make a fake offset,
|
||||
as if all the displays were side-by-side, which is fine for iOS. */
|
||||
if (SDL_GetDisplayBounds(displayIndex, rect) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
|
||||
if (!UIKit_IsSystemVersionAtLeast(7.0)) {
|
||||
frame = [data.uiscreen applicationFrame];
|
||||
}
|
||||
#endif
|
||||
|
||||
rect->x += frame.origin.x;
|
||||
rect->y += frame.origin.y;
|
||||
rect->w = frame.size.width;
|
||||
rect->h = frame.size.height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_QuitModes(_THIS)
|
||||
{
|
||||
/* Release Objective-C objects, so higher level doesn't free() them. */
|
||||
int i, j;
|
||||
@autoreleasepool {
|
||||
for (i = 0; i < _this->num_displays; i++) {
|
||||
SDL_VideoDisplay *display = &_this->displays[i];
|
||||
|
||||
UIKit_FreeDisplayModeData(&display->desktop_mode);
|
||||
for (j = 0; j < display->num_display_modes; j++) {
|
||||
SDL_DisplayMode *mode = &display->display_modes[j];
|
||||
UIKit_FreeDisplayModeData(mode);
|
||||
}
|
||||
|
||||
if (display->driverdata != NULL) {
|
||||
CFRelease(display->driverdata);
|
||||
display->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
void SDL_OnApplicationDidChangeStatusBarOrientation()
|
||||
{
|
||||
BOOL isLandscape = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
|
||||
SDL_VideoDisplay *display = SDL_GetDisplay(0);
|
||||
|
||||
if (display) {
|
||||
SDL_DisplayMode *desktopmode = &display->desktop_mode;
|
||||
SDL_DisplayMode *currentmode = &display->current_mode;
|
||||
SDL_DisplayOrientation orientation = SDL_ORIENTATION_UNKNOWN;
|
||||
|
||||
/* The desktop display mode should be kept in sync with the screen
|
||||
* orientation so that updating a window's fullscreen state to
|
||||
* SDL_WINDOW_FULLSCREEN_DESKTOP keeps the window dimensions in the
|
||||
* correct orientation. */
|
||||
if (isLandscape != (desktopmode->w > desktopmode->h)) {
|
||||
int height = desktopmode->w;
|
||||
desktopmode->w = desktopmode->h;
|
||||
desktopmode->h = height;
|
||||
}
|
||||
|
||||
/* Same deal with the current mode + SDL_GetCurrentDisplayMode. */
|
||||
if (isLandscape != (currentmode->w > currentmode->h)) {
|
||||
int height = currentmode->w;
|
||||
currentmode->w = currentmode->h;
|
||||
currentmode->h = height;
|
||||
}
|
||||
|
||||
switch ([UIApplication sharedApplication].statusBarOrientation) {
|
||||
case UIInterfaceOrientationPortrait:
|
||||
orientation = SDL_ORIENTATION_PORTRAIT;
|
||||
break;
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
orientation = SDL_ORIENTATION_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
/* Bug: UIInterfaceOrientationLandscapeLeft/Right are reversed - http://openradar.appspot.com/7216046 */
|
||||
orientation = SDL_ORIENTATION_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
/* Bug: UIInterfaceOrientationLandscapeLeft/Right are reversed - http://openradar.appspot.com/7216046 */
|
||||
orientation = SDL_ORIENTATION_LANDSCAPE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SDL_SendDisplayEvent(display, SDL_DISPLAYEVENT_ORIENTATION, orientation);
|
||||
}
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
44
externals/SDL/src/video/uikit/SDL_uikitopengles.h
vendored
Executable file
44
externals/SDL/src/video/uikit/SDL_uikitopengles.h
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
#ifndef SDL_uikitopengles_
|
||||
#define SDL_uikitopengles_
|
||||
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
extern int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window,
|
||||
SDL_GLContext context);
|
||||
extern void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window,
|
||||
int * w, int * h);
|
||||
extern int UIKit_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window);
|
||||
extern void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context);
|
||||
extern void *UIKit_GL_GetProcAddress(_THIS, const char *proc);
|
||||
extern int UIKit_GL_LoadLibrary(_THIS, const char *path);
|
||||
|
||||
extern void UIKit_GL_RestoreCurrentContext(void);
|
||||
|
||||
#endif // SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
|
||||
#endif /* SDL_uikitopengles_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
249
externals/SDL/src/video/uikit/SDL_uikitopengles.m
vendored
Executable file
249
externals/SDL/src/video/uikit/SDL_uikitopengles.m
vendored
Executable file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
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_UIKIT && (SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2)
|
||||
|
||||
#include "SDL_uikitopengles.h"
|
||||
#import "SDL_uikitopenglview.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_uikitevents.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../power/uikit/SDL_syspower.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
@interface SDLEAGLContext : EAGLContext
|
||||
|
||||
/* The OpenGL ES context owns a view / drawable. */
|
||||
@property (nonatomic, strong) SDL_uikitopenglview *sdlView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLEAGLContext
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
/* When the context is deallocated, its view should be removed from any
|
||||
* SDL window that it's attached to. */
|
||||
[self.sdlView setSDLWindow:NULL];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void *
|
||||
UIKit_GL_GetProcAddress(_THIS, const char *proc)
|
||||
{
|
||||
/* Look through all SO's for the proc symbol. Here's why:
|
||||
* -Looking for the path to the OpenGL Library seems not to work in the iOS Simulator.
|
||||
* -We don't know that the path won't change in the future. */
|
||||
return dlsym(RTLD_DEFAULT, proc);
|
||||
}
|
||||
|
||||
/*
|
||||
note that SDL_GL_DeleteContext makes it current without passing the window
|
||||
*/
|
||||
int
|
||||
UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLEAGLContext *eaglcontext = (__bridge SDLEAGLContext *) context;
|
||||
|
||||
if (![EAGLContext setCurrentContext:eaglcontext]) {
|
||||
return SDL_SetError("Could not make EAGL context current");
|
||||
}
|
||||
|
||||
if (eaglcontext) {
|
||||
[eaglcontext.sdlView setSDLWindow:window];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
UIView *view = data.viewcontroller.view;
|
||||
if ([view isKindOfClass:[SDL_uikitopenglview class]]) {
|
||||
SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view;
|
||||
if (w) {
|
||||
*w = glview.backingWidth;
|
||||
}
|
||||
if (h) {
|
||||
*h = glview.backingHeight;
|
||||
}
|
||||
} else {
|
||||
SDL_GetWindowSize(window, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_GL_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
/* We shouldn't pass a path to this function, since we've already loaded the
|
||||
* library. */
|
||||
if (path != NULL) {
|
||||
return SDL_SetError("iOS GL Load Library just here for compatibility");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLEAGLContext *context = (__bridge SDLEAGLContext *) SDL_GL_GetCurrentContext();
|
||||
|
||||
#if SDL_POWER_UIKIT
|
||||
/* Check once a frame to see if we should turn off the battery monitor. */
|
||||
SDL_UIKit_UpdateBatteryMonitoring();
|
||||
#endif
|
||||
|
||||
[context.sdlView swapBuffers];
|
||||
|
||||
/* You need to pump events in order for the OS to make changes visible.
|
||||
* We don't pump events here because we don't want iOS application events
|
||||
* (low memory, terminate, etc.) to happen inside low level rendering. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_GLContext
|
||||
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLEAGLContext *context = nil;
|
||||
SDL_uikitopenglview *view;
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
||||
EAGLSharegroup *sharegroup = nil;
|
||||
CGFloat scale = 1.0;
|
||||
int samples = 0;
|
||||
int major = _this->gl_config.major_version;
|
||||
int minor = _this->gl_config.minor_version;
|
||||
|
||||
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
||||
* versions. */
|
||||
EAGLRenderingAPI api = major;
|
||||
|
||||
/* iOS currently doesn't support GLES >3.0. iOS 6 also only supports up
|
||||
* to GLES 2.0. */
|
||||
if (major > 3 || (major == 3 && (minor > 0 || !UIKit_IsSystemVersionAtLeast(7.0)))) {
|
||||
SDL_SetError("OpenGL ES %d.%d context could not be created", major, minor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->gl_config.multisamplebuffers > 0) {
|
||||
samples = _this->gl_config.multisamplesamples;
|
||||
}
|
||||
|
||||
if (_this->gl_config.share_with_current_context) {
|
||||
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
||||
sharegroup = context.sharegroup;
|
||||
}
|
||||
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
/* Set the scale to the natural scale factor of the screen - the
|
||||
* backing dimensions of the OpenGL view will match the pixel
|
||||
* dimensions of the screen rather than the dimensions in points. */
|
||||
if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
|
||||
scale = data.uiwindow.screen.nativeScale;
|
||||
} else {
|
||||
scale = data.uiwindow.screen.scale;
|
||||
}
|
||||
}
|
||||
|
||||
context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:sharegroup];
|
||||
if (!context) {
|
||||
SDL_SetError("OpenGL ES %d context could not be created", _this->gl_config.major_version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* construct our view, passing in SDL's OpenGL configuration data */
|
||||
view = [[SDL_uikitopenglview alloc] initWithFrame:frame
|
||||
scale:scale
|
||||
retainBacking:_this->gl_config.retained_backing
|
||||
rBits:_this->gl_config.red_size
|
||||
gBits:_this->gl_config.green_size
|
||||
bBits:_this->gl_config.blue_size
|
||||
aBits:_this->gl_config.alpha_size
|
||||
depthBits:_this->gl_config.depth_size
|
||||
stencilBits:_this->gl_config.stencil_size
|
||||
sRGB:_this->gl_config.framebuffer_srgb_capable
|
||||
multisamples:samples
|
||||
context:context];
|
||||
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The context owns the view / drawable. */
|
||||
context.sdlView = view;
|
||||
|
||||
if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
|
||||
UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We return a +1'd context. The window's driverdata owns the view (via
|
||||
* MakeCurrent.) */
|
||||
return (SDL_GLContext) CFBridgingRetain(context);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
/* The context was retained in SDL_GL_CreateContext, so we release it
|
||||
* here. The context's view will be detached from its window when the
|
||||
* context is deallocated. */
|
||||
CFRelease(context);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_GL_RestoreCurrentContext(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
/* Some iOS system functionality (such as Dictation on the on-screen
|
||||
keyboard) uses its own OpenGL ES context but doesn't restore the
|
||||
previous one when it's done. This is a workaround to make sure the
|
||||
expected SDL-created OpenGL ES context is active after the OS is
|
||||
finished running its own code for the frame. If this isn't done, the
|
||||
app may crash or have other nasty symptoms when Dictation is used.
|
||||
*/
|
||||
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
||||
if (context != NULL && [EAGLContext currentContext] != context) {
|
||||
[EAGLContext setCurrentContext:context];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
64
externals/SDL/src/video/uikit/SDL_uikitopenglview.h
vendored
Executable file
64
externals/SDL/src/video/uikit/SDL_uikitopenglview.h
vendored
Executable file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
|
||||
#import "SDL_uikitview.h"
|
||||
#include "SDL_uikitvideo.h"
|
||||
|
||||
@interface SDL_uikitopenglview : SDL_uikitview
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
retainBacking:(BOOL)retained
|
||||
rBits:(int)rBits
|
||||
gBits:(int)gBits
|
||||
bBits:(int)bBits
|
||||
aBits:(int)aBits
|
||||
depthBits:(int)depthBits
|
||||
stencilBits:(int)stencilBits
|
||||
sRGB:(BOOL)sRGB
|
||||
multisamples:(int)multisamples
|
||||
context:(EAGLContext *)glcontext;
|
||||
|
||||
@property (nonatomic, readonly, weak) EAGLContext *context;
|
||||
|
||||
/* The width and height of the drawable in pixels (as opposed to points.) */
|
||||
@property (nonatomic, readonly) int backingWidth;
|
||||
@property (nonatomic, readonly) int backingHeight;
|
||||
|
||||
@property (nonatomic, readonly) GLuint drawableRenderbuffer;
|
||||
@property (nonatomic, readonly) GLuint drawableFramebuffer;
|
||||
@property (nonatomic, readonly) GLuint msaaResolveFramebuffer;
|
||||
|
||||
- (void)swapBuffers;
|
||||
|
||||
- (void)updateFrame;
|
||||
|
||||
@end
|
||||
|
||||
#endif // SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
384
externals/SDL/src/video/uikit/SDL_uikitopenglview.m
vendored
Executable file
384
externals/SDL/src/video/uikit/SDL_uikitopenglview.m
vendored
Executable file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
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_UIKIT && (SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2)
|
||||
|
||||
#include <OpenGLES/EAGLDrawable.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#import "SDL_uikitopenglview.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
|
||||
@implementation SDL_uikitopenglview {
|
||||
/* The renderbuffer and framebuffer used to render to this layer. */
|
||||
GLuint viewRenderbuffer, viewFramebuffer;
|
||||
|
||||
/* The depth buffer that is attached to viewFramebuffer, if it exists. */
|
||||
GLuint depthRenderbuffer;
|
||||
|
||||
GLenum colorBufferFormat;
|
||||
|
||||
/* format of depthRenderbuffer */
|
||||
GLenum depthBufferFormat;
|
||||
|
||||
/* The framebuffer and renderbuffer used for rendering with MSAA. */
|
||||
GLuint msaaFramebuffer, msaaRenderbuffer;
|
||||
|
||||
/* The number of MSAA samples. */
|
||||
int samples;
|
||||
|
||||
BOOL retainedBacking;
|
||||
}
|
||||
|
||||
@synthesize context;
|
||||
@synthesize backingWidth;
|
||||
@synthesize backingHeight;
|
||||
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [CAEAGLLayer class];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
retainBacking:(BOOL)retained
|
||||
rBits:(int)rBits
|
||||
gBits:(int)gBits
|
||||
bBits:(int)bBits
|
||||
aBits:(int)aBits
|
||||
depthBits:(int)depthBits
|
||||
stencilBits:(int)stencilBits
|
||||
sRGB:(BOOL)sRGB
|
||||
multisamples:(int)multisamples
|
||||
context:(EAGLContext *)glcontext
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
const BOOL useStencilBuffer = (stencilBits != 0);
|
||||
const BOOL useDepthBuffer = (depthBits != 0);
|
||||
NSString *colorFormat = nil;
|
||||
|
||||
context = glcontext;
|
||||
samples = multisamples;
|
||||
retainedBacking = retained;
|
||||
|
||||
if (!context || ![EAGLContext setCurrentContext:context]) {
|
||||
SDL_SetError("Could not create OpenGL ES drawable (could not make context current)");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (samples > 0) {
|
||||
GLint maxsamples = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxsamples);
|
||||
|
||||
/* Clamp the samples to the max supported count. */
|
||||
samples = MIN(samples, maxsamples);
|
||||
}
|
||||
|
||||
if (sRGB) {
|
||||
/* sRGB EAGL drawable support was added in iOS 7. */
|
||||
if (UIKit_IsSystemVersionAtLeast(7.0)) {
|
||||
colorFormat = kEAGLColorFormatSRGBA8;
|
||||
colorBufferFormat = GL_SRGB8_ALPHA8;
|
||||
} else {
|
||||
SDL_SetError("sRGB drawables are not supported.");
|
||||
return nil;
|
||||
}
|
||||
} else if (rBits >= 8 || gBits >= 8 || bBits >= 8 || aBits > 0) {
|
||||
/* if user specifically requests rbg888 or some color format higher than 16bpp */
|
||||
colorFormat = kEAGLColorFormatRGBA8;
|
||||
colorBufferFormat = GL_RGBA8;
|
||||
} else {
|
||||
/* default case (potentially faster) */
|
||||
colorFormat = kEAGLColorFormatRGB565;
|
||||
colorBufferFormat = GL_RGB565;
|
||||
}
|
||||
|
||||
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
|
||||
|
||||
eaglLayer.opaque = YES;
|
||||
eaglLayer.drawableProperties = @{
|
||||
kEAGLDrawablePropertyRetainedBacking:@(retained),
|
||||
kEAGLDrawablePropertyColorFormat:colorFormat
|
||||
};
|
||||
|
||||
/* Set the appropriate scale (for retina display support) */
|
||||
self.contentScaleFactor = scale;
|
||||
|
||||
/* Create the color Renderbuffer Object */
|
||||
glGenRenderbuffers(1, &viewRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
|
||||
if (![context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]) {
|
||||
SDL_SetError("Failed to create OpenGL ES drawable");
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Create the Framebuffer Object */
|
||||
glGenFramebuffers(1, &viewFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
|
||||
|
||||
/* attach the color renderbuffer to the FBO */
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
|
||||
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
SDL_SetError("Failed creating OpenGL ES framebuffer");
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* When MSAA is used we'll use a separate framebuffer for rendering to,
|
||||
* since we'll need to do an explicit MSAA resolve before presenting. */
|
||||
if (samples > 0) {
|
||||
glGenFramebuffers(1, &msaaFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer);
|
||||
|
||||
glGenRenderbuffers(1, &msaaRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderbuffer);
|
||||
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, colorBufferFormat, backingWidth, backingHeight);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaRenderbuffer);
|
||||
}
|
||||
|
||||
if (useDepthBuffer || useStencilBuffer) {
|
||||
if (useStencilBuffer) {
|
||||
/* Apparently you need to pack stencil and depth into one buffer. */
|
||||
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
|
||||
} else if (useDepthBuffer) {
|
||||
/* iOS only uses 32-bit float (exposed as fixed point 24-bit)
|
||||
* depth buffers. */
|
||||
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
|
||||
}
|
||||
|
||||
glGenRenderbuffers(1, &depthRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||
|
||||
if (samples > 0) {
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, depthBufferFormat, backingWidth, backingHeight);
|
||||
} else {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
if (useDepthBuffer) {
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
|
||||
}
|
||||
if (useStencilBuffer) {
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
SDL_SetError("Failed creating OpenGL ES framebuffer");
|
||||
return nil;
|
||||
}
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
|
||||
[self setDebugLabels];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GLuint)drawableRenderbuffer
|
||||
{
|
||||
return viewRenderbuffer;
|
||||
}
|
||||
|
||||
- (GLuint)drawableFramebuffer
|
||||
{
|
||||
/* When MSAA is used, the MSAA draw framebuffer is used for drawing. */
|
||||
if (msaaFramebuffer) {
|
||||
return msaaFramebuffer;
|
||||
} else {
|
||||
return viewFramebuffer;
|
||||
}
|
||||
}
|
||||
|
||||
- (GLuint)msaaResolveFramebuffer
|
||||
{
|
||||
/* When MSAA is used, the MSAA draw framebuffer is used for drawing and the
|
||||
* view framebuffer is used as a MSAA resolve framebuffer. */
|
||||
if (msaaFramebuffer) {
|
||||
return viewFramebuffer;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateFrame
|
||||
{
|
||||
GLint prevRenderbuffer = 0;
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
|
||||
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
||||
|
||||
if (msaaRenderbuffer != 0) {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderbuffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, colorBufferFormat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
if (depthRenderbuffer != 0) {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||
|
||||
if (samples > 0) {
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, depthBufferFormat, backingWidth, backingHeight);
|
||||
} else {
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||
}
|
||||
}
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, prevRenderbuffer);
|
||||
}
|
||||
|
||||
- (void)setDebugLabels
|
||||
{
|
||||
if (viewFramebuffer != 0) {
|
||||
glLabelObjectEXT(GL_FRAMEBUFFER, viewFramebuffer, 0, "context FBO");
|
||||
}
|
||||
|
||||
if (viewRenderbuffer != 0) {
|
||||
glLabelObjectEXT(GL_RENDERBUFFER, viewRenderbuffer, 0, "context color buffer");
|
||||
}
|
||||
|
||||
if (depthRenderbuffer != 0) {
|
||||
if (depthBufferFormat == GL_DEPTH24_STENCIL8_OES) {
|
||||
glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth-stencil buffer");
|
||||
} else {
|
||||
glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth buffer");
|
||||
}
|
||||
}
|
||||
|
||||
if (msaaFramebuffer != 0) {
|
||||
glLabelObjectEXT(GL_FRAMEBUFFER, msaaFramebuffer, 0, "context MSAA FBO");
|
||||
}
|
||||
|
||||
if (msaaRenderbuffer != 0) {
|
||||
glLabelObjectEXT(GL_RENDERBUFFER, msaaRenderbuffer, 0, "context MSAA renderbuffer");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)swapBuffers
|
||||
{
|
||||
if (msaaFramebuffer) {
|
||||
const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, viewFramebuffer);
|
||||
|
||||
/* OpenGL ES 3+ provides explicit MSAA resolves via glBlitFramebuffer.
|
||||
* In OpenGL ES 1 and 2, MSAA resolves must be done via an extension. */
|
||||
if (context.API >= kEAGLRenderingAPIOpenGLES3) {
|
||||
int w = backingWidth;
|
||||
int h = backingHeight;
|
||||
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
if (!retainedBacking) {
|
||||
/* Discard the contents of the MSAA drawable color buffer. */
|
||||
glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, attachments);
|
||||
}
|
||||
} else {
|
||||
glResolveMultisampleFramebufferAPPLE();
|
||||
|
||||
if (!retainedBacking) {
|
||||
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER, 1, attachments);
|
||||
}
|
||||
}
|
||||
|
||||
/* We assume the "drawable framebuffer" (MSAA draw framebuffer) was
|
||||
* previously bound... */
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFramebuffer);
|
||||
}
|
||||
|
||||
/* viewRenderbuffer should always be bound here. Code that binds something
|
||||
* else is responsible for rebinding viewRenderbuffer, to reduce duplicate
|
||||
* state changes. */
|
||||
[context presentRenderbuffer:GL_RENDERBUFFER];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
int width = (int) (self.bounds.size.width * self.contentScaleFactor);
|
||||
int height = (int) (self.bounds.size.height * self.contentScaleFactor);
|
||||
|
||||
/* Update the color and depth buffer storage if the layer size has changed. */
|
||||
if (width != backingWidth || height != backingHeight) {
|
||||
EAGLContext *prevContext = [EAGLContext currentContext];
|
||||
if (prevContext != context) {
|
||||
[EAGLContext setCurrentContext:context];
|
||||
}
|
||||
|
||||
[self updateFrame];
|
||||
|
||||
if (prevContext != context) {
|
||||
[EAGLContext setCurrentContext:prevContext];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)destroyFramebuffer
|
||||
{
|
||||
if (viewFramebuffer != 0) {
|
||||
glDeleteFramebuffers(1, &viewFramebuffer);
|
||||
viewFramebuffer = 0;
|
||||
}
|
||||
|
||||
if (viewRenderbuffer != 0) {
|
||||
glDeleteRenderbuffers(1, &viewRenderbuffer);
|
||||
viewRenderbuffer = 0;
|
||||
}
|
||||
|
||||
if (depthRenderbuffer != 0) {
|
||||
glDeleteRenderbuffers(1, &depthRenderbuffer);
|
||||
depthRenderbuffer = 0;
|
||||
}
|
||||
|
||||
if (msaaFramebuffer != 0) {
|
||||
glDeleteFramebuffers(1, &msaaFramebuffer);
|
||||
msaaFramebuffer = 0;
|
||||
}
|
||||
|
||||
if (msaaRenderbuffer != 0) {
|
||||
glDeleteRenderbuffers(1, &msaaRenderbuffer);
|
||||
msaaRenderbuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (context && context == [EAGLContext currentContext]) {
|
||||
[self destroyFramebuffer];
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
48
externals/SDL/src/video/uikit/SDL_uikitvideo.h
vendored
Executable file
48
externals/SDL/src/video/uikit/SDL_uikitvideo.h
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
#ifndef SDL_uikitvideo_h_
|
||||
#define SDL_uikitvideo_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@interface SDL_VideoData : NSObject
|
||||
|
||||
@property (nonatomic, assign) id pasteboardObserver;
|
||||
|
||||
@end
|
||||
|
||||
CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
|
||||
|
||||
#endif /* __OBJC__ */
|
||||
|
||||
void UIKit_SuspendScreenSaver(_THIS);
|
||||
|
||||
void UIKit_ForceUpdateHomeIndicator(void);
|
||||
|
||||
SDL_bool UIKit_IsSystemVersionAtLeast(double version);
|
||||
|
||||
#endif /* SDL_uikitvideo_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
295
externals/SDL/src/video/uikit/SDL_uikitvideo.m
vendored
Executable file
295
externals/SDL/src/video/uikit/SDL_uikitvideo.m
vendored
Executable file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitevents.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_uikitopengles.h"
|
||||
#include "SDL_uikitclipboard.h"
|
||||
#include "SDL_uikitvulkan.h"
|
||||
#include "SDL_uikitmetalview.h"
|
||||
|
||||
#define UIKITVID_DRIVER_NAME "uikit"
|
||||
|
||||
@implementation SDL_VideoData
|
||||
|
||||
@end
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int UIKit_VideoInit(_THIS);
|
||||
static void UIKit_VideoQuit(_THIS);
|
||||
|
||||
/* DUMMY driver bootstrap functions */
|
||||
|
||||
static int
|
||||
UIKit_Available(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void UIKit_DeleteDevice(SDL_VideoDevice * device)
|
||||
{
|
||||
@autoreleasepool {
|
||||
CFRelease(device->driverdata);
|
||||
SDL_free(device);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *
|
||||
UIKit_CreateDevice(int devindex)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDevice *device;
|
||||
SDL_VideoData *data;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device) {
|
||||
data = [SDL_VideoData new];
|
||||
} else {
|
||||
SDL_free(device);
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
|
||||
device->driverdata = (void *) CFBridgingRetain(data);
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = UIKit_VideoInit;
|
||||
device->VideoQuit = UIKit_VideoQuit;
|
||||
device->GetDisplayModes = UIKit_GetDisplayModes;
|
||||
device->SetDisplayMode = UIKit_SetDisplayMode;
|
||||
device->PumpEvents = UIKit_PumpEvents;
|
||||
device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
|
||||
device->CreateSDLWindow = UIKit_CreateWindow;
|
||||
device->SetWindowTitle = UIKit_SetWindowTitle;
|
||||
device->ShowWindow = UIKit_ShowWindow;
|
||||
device->HideWindow = UIKit_HideWindow;
|
||||
device->RaiseWindow = UIKit_RaiseWindow;
|
||||
device->SetWindowBordered = UIKit_SetWindowBordered;
|
||||
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
|
||||
device->DestroyWindow = UIKit_DestroyWindow;
|
||||
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
|
||||
device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
|
||||
device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
|
||||
device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
|
||||
device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
|
||||
device->SetTextInputRect = UIKit_SetTextInputRect;
|
||||
#endif
|
||||
|
||||
device->SetClipboardText = UIKit_SetClipboardText;
|
||||
device->GetClipboardText = UIKit_GetClipboardText;
|
||||
device->HasClipboardText = UIKit_HasClipboardText;
|
||||
|
||||
/* OpenGL (ES) functions */
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
|
||||
device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
|
||||
device->GL_SwapWindow = UIKit_GL_SwapWindow;
|
||||
device->GL_CreateContext = UIKit_GL_CreateContext;
|
||||
device->GL_DeleteContext = UIKit_GL_DeleteContext;
|
||||
device->GL_GetProcAddress = UIKit_GL_GetProcAddress;
|
||||
device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
|
||||
#endif
|
||||
device->free = UIKit_DeleteDevice;
|
||||
|
||||
#if SDL_VIDEO_VULKAN
|
||||
device->Vulkan_LoadLibrary = UIKit_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = UIKit_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions
|
||||
= UIKit_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = UIKit_Vulkan_CreateSurface;
|
||||
device->Vulkan_GetDrawableSize = UIKit_Vulkan_GetDrawableSize;
|
||||
#endif
|
||||
|
||||
#if SDL_VIDEO_METAL
|
||||
device->Metal_CreateView = UIKit_Metal_CreateView;
|
||||
device->Metal_DestroyView = UIKit_Metal_DestroyView;
|
||||
#endif
|
||||
|
||||
device->gl_config.accelerated = 1;
|
||||
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
VideoBootStrap UIKIT_bootstrap = {
|
||||
UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
|
||||
UIKit_Available, UIKit_CreateDevice
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
UIKit_VideoInit(_THIS)
|
||||
{
|
||||
_this->gl_config.driver_loaded = 1;
|
||||
|
||||
if (UIKit_InitModes(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_VideoQuit(_THIS)
|
||||
{
|
||||
UIKit_QuitModes(_this);
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SuspendScreenSaver(_THIS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
/* Ignore ScreenSaver API calls if the idle timer hint has been set. */
|
||||
/* FIXME: The idle timer hint should be deprecated for SDL 2.1. */
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_IDLE_TIMER_DISABLED, SDL_FALSE)) {
|
||||
UIApplication *app = [UIApplication sharedApplication];
|
||||
|
||||
/* Prevent the display from dimming and going to sleep. */
|
||||
app.idleTimerDisabled = (_this->suspend_screensaver != SDL_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_IsSystemVersionAtLeast(double version)
|
||||
{
|
||||
return [[UIDevice currentDevice].systemVersion doubleValue] >= version;
|
||||
}
|
||||
|
||||
CGRect
|
||||
UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
|
||||
{
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
CGRect frame = screen.bounds;
|
||||
|
||||
/* Use the UIWindow bounds instead of the UIScreen bounds, when possible.
|
||||
* The uiwindow bounds may be smaller than the screen bounds when Split View
|
||||
* is used on an iPad. */
|
||||
if (data != nil && data.uiwindow != nil) {
|
||||
frame = data.uiwindow.bounds;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0)
|
||||
BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(7.0);
|
||||
|
||||
/* The view should always show behind the status bar in iOS 7+. */
|
||||
if (!hasiOS7 && !(window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN))) {
|
||||
frame = screen.applicationFrame;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
/* iOS 10 seems to have a bug where, in certain conditions, putting the
|
||||
* device to sleep with the a landscape-only app open, re-orienting the
|
||||
* device to portrait, and turning it back on will result in the screen
|
||||
* bounds returning portrait orientation despite the app being in landscape.
|
||||
* This is a workaround until a better solution can be found.
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=3505
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=3465
|
||||
* https://forums.developer.apple.com/thread/65337 */
|
||||
if (UIKit_IsSystemVersionAtLeast(8.0)) {
|
||||
UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
|
||||
BOOL landscape = UIInterfaceOrientationIsLandscape(orient);
|
||||
BOOL fullscreen = CGRectEqualToRect(screen.bounds, frame);
|
||||
|
||||
/* The orientation flip doesn't make sense when the window is smaller
|
||||
* than the screen (iPad Split View, for example). */
|
||||
if (fullscreen && (landscape != (frame.size.width > frame.size.height))) {
|
||||
float height = frame.size.width;
|
||||
frame.size.width = frame.size.height;
|
||||
frame.size.height = height;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_ForceUpdateHomeIndicator()
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
/* Force the main SDL window to re-evaluate home indicator state */
|
||||
SDL_Window *focus = SDL_GetFocusWindow();
|
||||
if (focus) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) focus->driverdata;
|
||||
if (data != nil) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
||||
if ([data.viewcontroller respondsToSelector:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden)]) {
|
||||
[data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden) withObject:nil waitUntilDone:NO];
|
||||
[data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfScreenEdgesDeferringSystemGestures) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
}
|
||||
|
||||
/*
|
||||
* iOS 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 from src/video/cocoa/SDL_cocoavideo.m! Thus, if
|
||||
* Cocoa is supported, we use that one instead. Be sure both versions remain
|
||||
* identical!
|
||||
*/
|
||||
|
||||
#if !defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
void SDL_NSLog(const char *text)
|
||||
{
|
||||
NSLog(@"%s", text);
|
||||
}
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/*
|
||||
* iOS Tablet detection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
SDL_bool SDL_IsIPad(void)
|
||||
{
|
||||
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
41
externals/SDL/src/video/uikit/SDL_uikitview.h
vendored
Executable file
41
externals/SDL/src/video/uikit/SDL_uikitview.h
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_touch.h"
|
||||
|
||||
@interface SDL_uikitview : UIView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame;
|
||||
|
||||
- (void)setSDLWindow:(SDL_Window *)window;
|
||||
|
||||
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize;
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
|
||||
@end
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
348
externals/SDL/src/video/uikit/SDL_uikitview.m
vendored
Executable file
348
externals/SDL/src/video/uikit/SDL_uikitview.m
vendored
Executable file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_uikitview.h"
|
||||
|
||||
#include "SDL_hints.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#import "SDL_uikitappdelegate.h"
|
||||
#import "SDL_uikitmodes.h"
|
||||
#import "SDL_uikitwindow.h"
|
||||
|
||||
/* This is defined in SDL_sysjoystick.m */
|
||||
extern int SDL_AppleTVRemoteOpenedAsJoystick;
|
||||
|
||||
@implementation SDL_uikitview {
|
||||
SDL_Window *sdlwindow;
|
||||
|
||||
SDL_TouchID directTouchId;
|
||||
SDL_TouchID indirectTouchId;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
#if TARGET_OS_TV
|
||||
/* Apple TV Remote touchpad swipe gestures. */
|
||||
UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
|
||||
swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
|
||||
[self addGestureRecognizer:swipeUp];
|
||||
|
||||
UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
|
||||
swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
|
||||
[self addGestureRecognizer:swipeDown];
|
||||
|
||||
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
|
||||
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
|
||||
[self addGestureRecognizer:swipeLeft];
|
||||
|
||||
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
|
||||
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
|
||||
[self addGestureRecognizer:swipeRight];
|
||||
#endif
|
||||
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.autoresizesSubviews = YES;
|
||||
|
||||
directTouchId = 1;
|
||||
indirectTouchId = 2;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
self.multipleTouchEnabled = YES;
|
||||
SDL_AddTouch(directTouchId, SDL_TOUCH_DEVICE_DIRECT, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSDLWindow:(SDL_Window *)window
|
||||
{
|
||||
SDL_WindowData *data = nil;
|
||||
|
||||
if (window == sdlwindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove ourself from the old window. */
|
||||
if (sdlwindow) {
|
||||
SDL_uikitview *view = nil;
|
||||
data = (__bridge SDL_WindowData *) sdlwindow->driverdata;
|
||||
|
||||
[data.views removeObject:self];
|
||||
|
||||
[self removeFromSuperview];
|
||||
|
||||
/* Restore the next-oldest view in the old window. */
|
||||
view = data.views.lastObject;
|
||||
|
||||
data.viewcontroller.view = view;
|
||||
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.rootViewController = data.viewcontroller;
|
||||
|
||||
[data.uiwindow layoutIfNeeded];
|
||||
}
|
||||
|
||||
/* Add ourself to the new window. */
|
||||
if (window) {
|
||||
data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
|
||||
/* Make sure the SDL window has a strong reference to this view. */
|
||||
[data.views addObject:self];
|
||||
|
||||
/* Replace the view controller's old view with this one. */
|
||||
[data.viewcontroller.view removeFromSuperview];
|
||||
data.viewcontroller.view = self;
|
||||
|
||||
/* The root view controller handles rotation and the status bar.
|
||||
* Assigning it also adds the controller's view to the window. We
|
||||
* explicitly re-set it to make sure the view is properly attached to
|
||||
* the window. Just adding the sub-view if the root view controller is
|
||||
* already correct causes orientation issues on iOS 7 and below. */
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.rootViewController = data.viewcontroller;
|
||||
|
||||
/* The view's bounds may not be correct until the next event cycle. That
|
||||
* might happen after the current dimensions are queried, so we force a
|
||||
* layout now to immediately update the bounds. */
|
||||
[data.uiwindow layoutIfNeeded];
|
||||
}
|
||||
|
||||
sdlwindow = window;
|
||||
}
|
||||
|
||||
- (SDL_TouchDeviceType)touchTypeForTouch:(UITouch *)touch
|
||||
{
|
||||
#ifdef __IPHONE_9_0
|
||||
if ([touch respondsToSelector:@selector((type))]) {
|
||||
if (touch.type == UITouchTypeIndirect) {
|
||||
return SDL_TOUCH_DEVICE_INDIRECT_RELATIVE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_TOUCH_DEVICE_DIRECT;
|
||||
}
|
||||
|
||||
- (SDL_TouchID)touchIdForType:(SDL_TouchDeviceType)type
|
||||
{
|
||||
switch (type) {
|
||||
case SDL_TOUCH_DEVICE_DIRECT:
|
||||
default:
|
||||
return directTouchId;
|
||||
case SDL_TOUCH_DEVICE_INDIRECT_RELATIVE:
|
||||
return indirectTouchId;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
|
||||
{
|
||||
CGPoint point = [touch locationInView:self];
|
||||
|
||||
if (normalize) {
|
||||
CGRect bounds = self.bounds;
|
||||
point.x /= bounds.size.width;
|
||||
point.y /= bounds.size.height;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
- (float)pressureForTouch:(UITouch *)touch
|
||||
{
|
||||
#ifdef __IPHONE_9_0
|
||||
if ([touch respondsToSelector:@selector(force)]) {
|
||||
return (float) touch.force;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
|
||||
SDL_TouchID touchId = [self touchIdForType:touchType];
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (SDL_AddTouch(touchId, touchType, "") < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
|
||||
SDL_TRUE, locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
|
||||
SDL_TouchID touchId = [self touchIdForType:touchType];
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (SDL_AddTouch(touchId, touchType, "") < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
|
||||
SDL_FALSE, locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
[self touchesEnded:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
for (UITouch *touch in touches) {
|
||||
SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
|
||||
SDL_TouchID touchId = [self touchIdForType:touchType];
|
||||
float pressure = [self pressureForTouch:touch];
|
||||
|
||||
if (SDL_AddTouch(touchId, touchType, "") < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
|
||||
locationInView.x, locationInView.y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV || defined(__IPHONE_9_1)
|
||||
- (SDL_Scancode)scancodeFromPressType:(UIPressType)presstype
|
||||
{
|
||||
switch (presstype) {
|
||||
case UIPressTypeUpArrow:
|
||||
return SDL_SCANCODE_UP;
|
||||
case UIPressTypeDownArrow:
|
||||
return SDL_SCANCODE_DOWN;
|
||||
case UIPressTypeLeftArrow:
|
||||
return SDL_SCANCODE_LEFT;
|
||||
case UIPressTypeRightArrow:
|
||||
return SDL_SCANCODE_RIGHT;
|
||||
case UIPressTypeSelect:
|
||||
/* HIG says: "primary button behavior" */
|
||||
return SDL_SCANCODE_RETURN;
|
||||
case UIPressTypeMenu:
|
||||
/* HIG says: "returns to previous screen" */
|
||||
return SDL_SCANCODE_ESCAPE;
|
||||
case UIPressTypePlayPause:
|
||||
/* HIG says: "secondary button behavior" */
|
||||
return SDL_SCANCODE_PAUSE;
|
||||
default:
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
|
||||
{
|
||||
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
|
||||
for (UIPress *press in presses) {
|
||||
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
}
|
||||
}
|
||||
[super pressesBegan:presses withEvent:event];
|
||||
}
|
||||
|
||||
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
|
||||
{
|
||||
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
|
||||
for (UIPress *press in presses) {
|
||||
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
[super pressesEnded:presses withEvent:event];
|
||||
}
|
||||
|
||||
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
|
||||
{
|
||||
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
|
||||
for (UIPress *press in presses) {
|
||||
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
[super pressesCancelled:presses withEvent:event];
|
||||
}
|
||||
|
||||
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
|
||||
{
|
||||
/* This is only called when the force of a press changes. */
|
||||
[super pressesChanged:presses withEvent:event];
|
||||
}
|
||||
#endif /* TARGET_OS_TV || defined(__IPHONE_9_1) */
|
||||
|
||||
#if TARGET_OS_TV
|
||||
-(void)swipeGesture:(UISwipeGestureRecognizer *)gesture
|
||||
{
|
||||
/* Swipe gestures don't trigger begin states. */
|
||||
if (gesture.state == UIGestureRecognizerStateEnded) {
|
||||
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
|
||||
/* Send arrow key presses for now, as we don't have an external API
|
||||
* which better maps to swipe gestures. */
|
||||
switch (gesture.direction) {
|
||||
case UISwipeGestureRecognizerDirectionUp:
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_UP);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_UP);
|
||||
break;
|
||||
case UISwipeGestureRecognizerDirectionDown:
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DOWN);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DOWN);
|
||||
break;
|
||||
case UISwipeGestureRecognizerDirectionLeft:
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LEFT);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LEFT);
|
||||
break;
|
||||
case UISwipeGestureRecognizerDirectionRight:
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RIGHT);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TARGET_OS_TV */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
91
externals/SDL/src/video/uikit/SDL_uikitviewcontroller.h
vendored
Executable file
91
externals/SDL/src/video/uikit/SDL_uikitviewcontroller.h
vendored
Executable file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_touch.h"
|
||||
|
||||
#if TARGET_OS_TV
|
||||
#import <GameController/GameController.h>
|
||||
#define SDLRootViewController GCEventViewController
|
||||
#else
|
||||
#define SDLRootViewController UIViewController
|
||||
#endif
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
@interface SDL_uikitviewcontroller : SDLRootViewController <UITextFieldDelegate>
|
||||
#else
|
||||
@interface SDL_uikitviewcontroller : SDLRootViewController
|
||||
#endif
|
||||
|
||||
@property (nonatomic, assign) SDL_Window *window;
|
||||
|
||||
- (instancetype)initWithSDLWindow:(SDL_Window *)_window;
|
||||
|
||||
- (void)setAnimationCallback:(int)interval
|
||||
callback:(void (*)(void*))callback
|
||||
callbackParam:(void*)callbackParam;
|
||||
|
||||
- (void)startAnimation;
|
||||
- (void)stopAnimation;
|
||||
|
||||
- (void)doLoop:(CADisplayLink*)sender;
|
||||
|
||||
- (void)loadView;
|
||||
- (void)viewDidLayoutSubviews;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (NSUInteger)supportedInterfaceOrientations;
|
||||
- (BOOL)prefersStatusBarHidden;
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden;
|
||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures;
|
||||
|
||||
@property (nonatomic, assign) int homeIndicatorHidden;
|
||||
#endif
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
- (void)showKeyboard;
|
||||
- (void)hideKeyboard;
|
||||
- (void)initKeyboard;
|
||||
- (void)deinitKeyboard;
|
||||
|
||||
- (void)keyboardWillShow:(NSNotification *)notification;
|
||||
- (void)keyboardWillHide:(NSNotification *)notification;
|
||||
|
||||
- (void)updateKeyboard;
|
||||
|
||||
@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible;
|
||||
@property (nonatomic, assign) SDL_Rect textInputRect;
|
||||
@property (nonatomic, assign) int keyboardHeight;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
SDL_bool UIKit_HasScreenKeyboardSupport(_THIS);
|
||||
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window);
|
||||
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window);
|
||||
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window);
|
||||
void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect);
|
||||
#endif
|
599
externals/SDL/src/video/uikit/SDL_uikitviewcontroller.m
vendored
Executable file
599
externals/SDL/src/video/uikit/SDL_uikitviewcontroller.m
vendored
Executable file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#import "SDL_uikitviewcontroller.h"
|
||||
#import "SDL_uikitmessagebox.h"
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_uikitopengles.h"
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
#include "keyinfotable.h"
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_TV
|
||||
static void SDLCALL
|
||||
SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *viewcontroller = (__bridge SDL_uikitviewcontroller *) userdata;
|
||||
viewcontroller.controllerUserInteractionEnabled = hint && (*hint != '0');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
static void SDLCALL
|
||||
SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *viewcontroller = (__bridge SDL_uikitviewcontroller *) userdata;
|
||||
viewcontroller.homeIndicatorHidden = (hint && *hint) ? SDL_atoi(hint) : -1;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
||||
if ([viewcontroller respondsToSelector:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden)]) {
|
||||
[viewcontroller setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||
[viewcontroller setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@implementation SDL_uikitviewcontroller {
|
||||
CADisplayLink *displayLink;
|
||||
int animationInterval;
|
||||
void (*animationCallback)(void*);
|
||||
void *animationCallbackParam;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
UITextField *textField;
|
||||
BOOL hardwareKeyboard;
|
||||
BOOL showingKeyboard;
|
||||
BOOL rotatingOrientation;
|
||||
NSString *changeText;
|
||||
NSString *obligateForBackspace;
|
||||
#endif
|
||||
}
|
||||
|
||||
@synthesize window;
|
||||
|
||||
- (instancetype)initWithSDLWindow:(SDL_Window *)_window
|
||||
{
|
||||
if (self = [super initWithNibName:nil bundle:nil]) {
|
||||
self.window = _window;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
[self initKeyboard];
|
||||
hardwareKeyboard = NO;
|
||||
showingKeyboard = NO;
|
||||
rotatingOrientation = NO;
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_TV
|
||||
SDL_AddHintCallback(SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS,
|
||||
SDL_AppleTVControllerUIHintChanged,
|
||||
(__bridge void *) self);
|
||||
#endif
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,
|
||||
SDL_HideHomeIndicatorHintChanged,
|
||||
(__bridge void *) self);
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
[self deinitKeyboard];
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_TV
|
||||
SDL_DelHintCallback(SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS,
|
||||
SDL_AppleTVControllerUIHintChanged,
|
||||
(__bridge void *) self);
|
||||
#endif
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
SDL_DelHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,
|
||||
SDL_HideHomeIndicatorHintChanged,
|
||||
(__bridge void *) self);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setAnimationCallback:(int)interval
|
||||
callback:(void (*)(void*))callback
|
||||
callbackParam:(void*)callbackParam
|
||||
{
|
||||
[self stopAnimation];
|
||||
|
||||
animationInterval = interval;
|
||||
animationCallback = callback;
|
||||
animationCallbackParam = callbackParam;
|
||||
|
||||
if (animationCallback) {
|
||||
[self startAnimation];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startAnimation
|
||||
{
|
||||
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(doLoop:)];
|
||||
|
||||
#ifdef __IPHONE_10_3
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
|
||||
if ([displayLink respondsToSelector:@selector(preferredFramesPerSecond)]
|
||||
&& data != nil && data.uiwindow != nil
|
||||
&& [data.uiwindow.screen respondsToSelector:@selector(maximumFramesPerSecond)]) {
|
||||
displayLink.preferredFramesPerSecond = data.uiwindow.screen.maximumFramesPerSecond / animationInterval;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 100300
|
||||
[displayLink setFrameInterval:animationInterval];
|
||||
#endif
|
||||
}
|
||||
|
||||
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)stopAnimation
|
||||
{
|
||||
[displayLink invalidate];
|
||||
displayLink = nil;
|
||||
}
|
||||
|
||||
- (void)doLoop:(CADisplayLink*)sender
|
||||
{
|
||||
/* Don't run the game loop while a messagebox is up */
|
||||
if (!UIKit_ShowingMessageBox()) {
|
||||
/* See the comment in the function definition. */
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
UIKit_GL_RestoreCurrentContext();
|
||||
#endif
|
||||
|
||||
animationCallback(animationCallbackParam);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
const CGSize size = self.view.bounds.size;
|
||||
int w = (int) size.width;
|
||||
int h = (int) size.height;
|
||||
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
return UIKit_GetSupportedOrientations(window);
|
||||
}
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient
|
||||
{
|
||||
return ([self supportedInterfaceOrientations] & (1 << orient)) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
BOOL hidden = (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
|
||||
return hidden;
|
||||
}
|
||||
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden
|
||||
{
|
||||
BOOL hidden = NO;
|
||||
if (self.homeIndicatorHidden == 1) {
|
||||
hidden = YES;
|
||||
}
|
||||
return hidden;
|
||||
}
|
||||
|
||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
|
||||
{
|
||||
if (self.homeIndicatorHidden >= 0) {
|
||||
if (self.homeIndicatorHidden == 2) {
|
||||
return UIRectEdgeAll;
|
||||
} else {
|
||||
return UIRectEdgeNone;
|
||||
}
|
||||
}
|
||||
|
||||
/* By default, fullscreen and borderless windows get all screen gestures */
|
||||
if ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0) {
|
||||
return UIRectEdgeAll;
|
||||
} else {
|
||||
return UIRectEdgeNone;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
---- Keyboard related functionality below this line ----
|
||||
*/
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
|
||||
@synthesize textInputRect;
|
||||
@synthesize keyboardHeight;
|
||||
@synthesize keyboardVisible;
|
||||
|
||||
/* Set ourselves up as a UITextFieldDelegate */
|
||||
- (void)initKeyboard
|
||||
{
|
||||
changeText = nil;
|
||||
obligateForBackspace = @" "; /* 64 space */
|
||||
textField = [[UITextField alloc] initWithFrame:CGRectZero];
|
||||
textField.delegate = self;
|
||||
/* placeholder so there is something to delete! */
|
||||
textField.text = obligateForBackspace;
|
||||
|
||||
/* set UITextInputTrait properties, mostly to defaults */
|
||||
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
textField.enablesReturnKeyAutomatically = NO;
|
||||
textField.keyboardAppearance = UIKeyboardAppearanceDefault;
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
textField.returnKeyType = UIReturnKeyDefault;
|
||||
textField.secureTextEntry = NO;
|
||||
|
||||
textField.hidden = YES;
|
||||
keyboardVisible = NO;
|
||||
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
#if !TARGET_OS_TV
|
||||
[center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
|
||||
[center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
|
||||
#endif
|
||||
[center addObserver:self selector:@selector(textFieldTextDidChange:) name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (NSArray *)keyCommands
|
||||
{
|
||||
NSMutableArray *commands = [[NSMutableArray alloc] init];
|
||||
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:kNilOptions action:@selector(handleCommand:)]];
|
||||
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:kNilOptions action:@selector(handleCommand:)]];
|
||||
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:kNilOptions action:@selector(handleCommand:)]];
|
||||
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:kNilOptions action:@selector(handleCommand:)]];
|
||||
[commands addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:kNilOptions action:@selector(handleCommand:)]];
|
||||
return [NSArray arrayWithArray:commands];
|
||||
}
|
||||
|
||||
- (void)handleCommand:(UIKeyCommand *)keyCommand
|
||||
{
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
NSString *input = keyCommand.input;
|
||||
|
||||
if (input == UIKeyInputUpArrow) {
|
||||
scancode = SDL_SCANCODE_UP;
|
||||
} else if (input == UIKeyInputDownArrow) {
|
||||
scancode = SDL_SCANCODE_DOWN;
|
||||
} else if (input == UIKeyInputLeftArrow) {
|
||||
scancode = SDL_SCANCODE_LEFT;
|
||||
} else if (input == UIKeyInputRightArrow) {
|
||||
scancode = SDL_SCANCODE_RIGHT;
|
||||
} else if (input == UIKeyInputEscape) {
|
||||
scancode = SDL_SCANCODE_ESCAPE;
|
||||
}
|
||||
|
||||
if (scancode != SDL_SCANCODE_UNKNOWN) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setView:(UIView *)view
|
||||
{
|
||||
[super setView:view];
|
||||
|
||||
[view addSubview:textField];
|
||||
|
||||
if (keyboardVisible) {
|
||||
[self showKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
/* willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation are deprecated in iOS 8+ in favor of viewWillTransitionToSize */
|
||||
#if TARGET_OS_TV || __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
|
||||
{
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
rotatingOrientation = YES;
|
||||
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {}
|
||||
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
||||
self->rotatingOrientation = NO;
|
||||
}];
|
||||
}
|
||||
#else
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
|
||||
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
||||
rotatingOrientation = YES;
|
||||
}
|
||||
|
||||
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
|
||||
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
|
||||
rotatingOrientation = NO;
|
||||
}
|
||||
#endif /* TARGET_OS_TV || __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000 */
|
||||
|
||||
- (void)deinitKeyboard
|
||||
{
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
#if !TARGET_OS_TV
|
||||
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
|
||||
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
|
||||
#endif
|
||||
[center removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
/* reveal onscreen virtual keyboard */
|
||||
- (void)showKeyboard
|
||||
{
|
||||
keyboardVisible = YES;
|
||||
if (textField.window) {
|
||||
showingKeyboard = YES;
|
||||
[textField becomeFirstResponder];
|
||||
showingKeyboard = NO;
|
||||
}
|
||||
}
|
||||
|
||||
/* hide onscreen virtual keyboard */
|
||||
- (void)hideKeyboard
|
||||
{
|
||||
keyboardVisible = NO;
|
||||
[textField resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)keyboardWillShow:(NSNotification *)notification
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
CGRect kbrect = [[notification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
|
||||
/* The keyboard rect is in the coordinate space of the screen/window, but we
|
||||
* want its height in the coordinate space of the view. */
|
||||
kbrect = [self.view convertRect:kbrect fromView:nil];
|
||||
|
||||
[self setKeyboardHeight:(int)kbrect.size.height];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)keyboardWillHide:(NSNotification *)notification
|
||||
{
|
||||
if (!showingKeyboard && !rotatingOrientation) {
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
[self setKeyboardHeight:0];
|
||||
}
|
||||
|
||||
- (void)textFieldTextDidChange:(NSNotification *)notification
|
||||
{
|
||||
if (changeText!=nil && textField.markedTextRange == nil)
|
||||
{
|
||||
NSUInteger len = changeText.length;
|
||||
if (len > 0) {
|
||||
/* Go through all the characters in the string we've been sent and
|
||||
* convert them to key presses */
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
unichar c = [changeText characterAtIndex:i];
|
||||
SDL_Scancode code;
|
||||
Uint16 mod;
|
||||
|
||||
if (c < 127) {
|
||||
/* Figure out the SDL_Scancode and SDL_keymod for this unichar */
|
||||
code = unicharToUIKeyInfoTable[c].code;
|
||||
mod = unicharToUIKeyInfoTable[c].mod;
|
||||
} else {
|
||||
/* We only deal with ASCII right now */
|
||||
code = SDL_SCANCODE_UNKNOWN;
|
||||
mod = 0;
|
||||
}
|
||||
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift down */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
|
||||
/* send a keydown and keyup even for the character */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, code);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, code);
|
||||
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift back up */
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
}
|
||||
SDL_SendKeyboardText([changeText UTF8String]);
|
||||
}
|
||||
changeText = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateKeyboard
|
||||
{
|
||||
CGAffineTransform t = self.view.transform;
|
||||
CGPoint offset = CGPointMake(0.0, 0.0);
|
||||
CGRect frame = UIKit_ComputeViewFrame(window, self.view.window.screen);
|
||||
|
||||
if (self.keyboardHeight) {
|
||||
int rectbottom = self.textInputRect.y + self.textInputRect.h;
|
||||
int keybottom = self.view.bounds.size.height - self.keyboardHeight;
|
||||
if (keybottom < rectbottom) {
|
||||
offset.y = keybottom - rectbottom;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply this view's transform (except any translation) to the offset, in
|
||||
* order to orient it correctly relative to the frame's coordinate space. */
|
||||
t.tx = 0.0;
|
||||
t.ty = 0.0;
|
||||
offset = CGPointApplyAffineTransform(offset, t);
|
||||
|
||||
/* Apply the updated offset to the view's frame. */
|
||||
frame.origin.x += offset.x;
|
||||
frame.origin.y += offset.y;
|
||||
|
||||
self.view.frame = frame;
|
||||
}
|
||||
|
||||
- (void)setKeyboardHeight:(int)height
|
||||
{
|
||||
keyboardVisible = height > 0;
|
||||
keyboardHeight = height;
|
||||
[self updateKeyboard];
|
||||
}
|
||||
|
||||
/* UITextFieldDelegate method. Invoked when user types something. */
|
||||
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
NSUInteger len = string.length;
|
||||
if (len == 0) {
|
||||
changeText = nil;
|
||||
if (textField.markedTextRange == nil) {
|
||||
/* it wants to replace text with nothing, ie a delete */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE);
|
||||
}
|
||||
if (textField.text.length < 16) {
|
||||
textField.text = obligateForBackspace;
|
||||
}
|
||||
} else {
|
||||
changeText = string;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* Terminates the editing session */
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
|
||||
{
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
|
||||
if (keyboardVisible &&
|
||||
SDL_GetHintBoolean(SDL_HINT_RETURN_KEY_HIDES_IME, SDL_FALSE)) {
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
/* iPhone keyboard addition functions */
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
|
||||
static SDL_uikitviewcontroller *
|
||||
GetWindowViewController(SDL_Window * window)
|
||||
{
|
||||
if (!window || !window->driverdata) {
|
||||
SDL_SetError("Invalid window");
|
||||
return nil;
|
||||
}
|
||||
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
|
||||
return data.viewcontroller;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_HasScreenKeyboardSupport(_THIS)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *vc = GetWindowViewController(window);
|
||||
[vc showKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *vc = GetWindowViewController(window);
|
||||
[vc hideKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *vc = GetWindowViewController(window);
|
||||
if (vc != nil) {
|
||||
return vc.keyboardVisible;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
|
||||
{
|
||||
if (!rect) {
|
||||
SDL_InvalidParamError("rect");
|
||||
return;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_uikitviewcontroller *vc = GetWindowViewController(SDL_GetFocusWindow());
|
||||
if (vc != nil) {
|
||||
vc.textInputRect = *rect;
|
||||
|
||||
if (vc.keyboardVisible) {
|
||||
[vc updateKeyboard];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_IPHONE_KEYBOARD */
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
54
externals/SDL/src/video/uikit/SDL_uikitvulkan.h
vendored
Executable file
54
externals/SDL/src/video/uikit/SDL_uikitvulkan.h
vendored
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
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_uikitvulkan_h_
|
||||
#define SDL_uikitvulkan_h_
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_UIKIT
|
||||
|
||||
int UIKit_Vulkan_LoadLibrary(_THIS, const char *path);
|
||||
void UIKit_Vulkan_UnloadLibrary(_THIS);
|
||||
SDL_bool UIKit_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_uikitvulkan_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
251
externals/SDL/src/video/uikit/SDL_uikitvulkan.m
vendored
Executable file
251
externals/SDL/src/video/uikit/SDL_uikitvulkan.m
vendored
Executable file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_uikitvulkan.h"
|
||||
#include "SDL_uikitmetalview.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
const char* defaultPaths[] = {
|
||||
"libvulkan.dylib",
|
||||
};
|
||||
|
||||
/* Since libSDL is static, could use RTLD_SELF. Using RTLD_DEFAULT is future
|
||||
* proofing. */
|
||||
#define DEFAULT_HANDLE RTLD_DEFAULT
|
||||
|
||||
int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasIOSSurfaceExtension = 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 the .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, path,
|
||||
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",
|
||||
"linked Vulkan Portability library",
|
||||
(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) {
|
||||
SDL_SetError("No vkEnumerateInstanceExtensionProperties found.");
|
||||
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_IOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasIOSSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(extensions);
|
||||
|
||||
if (!hasSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan Portability doesn't implement the "
|
||||
VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
} else if (!hasIOSSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan Portability doesn't implement the "
|
||||
VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void UIKit_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 UIKit_Vulkan_GetInstanceExtensions(_THIS,
|
||||
SDL_Window *window,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForUIKit[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_MVK_IOS_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(extensionsForUIKit),
|
||||
extensionsForUIKit);
|
||||
}
|
||||
|
||||
SDL_bool UIKit_Vulkan_CreateSurface(_THIS,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateIOSSurfaceMVK vkCreateIOSSurfaceMVK =
|
||||
(PFN_vkCreateIOSSurfaceMVK)vkGetInstanceProcAddr(
|
||||
(VkInstance)instance,
|
||||
"vkCreateIOSSurfaceMVK");
|
||||
VkIOSSurfaceCreateInfoMVK createInfo = {};
|
||||
VkResult result;
|
||||
SDL_MetalView metalview;
|
||||
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!vkCreateIOSSurfaceMVK) {
|
||||
SDL_SetError(VK_MVK_IOS_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
metalview = UIKit_Metal_CreateView(_this, window);
|
||||
if (metalview == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pView = (const void *)metalview;
|
||||
result = vkCreateIOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
UIKit_Metal_DestroyView(_this, metalview);
|
||||
SDL_SetError("vkCreateIOSSurfaceMVK 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 UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||
{
|
||||
UIKit_Metal_GetDrawableSize(window, w, h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
56
externals/SDL/src/video/uikit/SDL_uikitwindow.h
vendored
Executable file
56
externals/SDL/src/video/uikit/SDL_uikitwindow.h
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
#ifndef SDL_uikitwindow_h_
|
||||
#define SDL_uikitwindow_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#import "SDL_uikitvideo.h"
|
||||
#import "SDL_uikitview.h"
|
||||
#import "SDL_uikitviewcontroller.h"
|
||||
|
||||
extern int UIKit_CreateWindow(_THIS, SDL_Window * window);
|
||||
extern void UIKit_SetWindowTitle(_THIS, SDL_Window * window);
|
||||
extern void UIKit_ShowWindow(_THIS, SDL_Window * window);
|
||||
extern void UIKit_HideWindow(_THIS, SDL_Window * window);
|
||||
extern void UIKit_RaiseWindow(_THIS, SDL_Window * window);
|
||||
extern void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
|
||||
extern void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
|
||||
extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
|
||||
struct SDL_SysWMinfo * info);
|
||||
|
||||
extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window * window);
|
||||
|
||||
@class UIWindow;
|
||||
|
||||
@interface SDL_WindowData : NSObject
|
||||
|
||||
@property (nonatomic, strong) UIWindow *uiwindow;
|
||||
@property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller;
|
||||
|
||||
/* Array of SDL_uikitviews owned by this window. */
|
||||
@property (nonatomic, copy) NSMutableArray *views;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SDL_uikitwindow_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
479
externals/SDL/src/video/uikit/SDL_uikitwindow.m
vendored
Executable file
479
externals/SDL/src/video/uikit/SDL_uikitwindow.m
vendored
Executable file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
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_UIKIT
|
||||
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_uikitvideo.h"
|
||||
#include "SDL_uikitevents.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
#include "SDL_uikitwindow.h"
|
||||
#import "SDL_uikitappdelegate.h"
|
||||
|
||||
#import "SDL_uikitview.h"
|
||||
#import "SDL_uikitopenglview.h"
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
@implementation SDL_WindowData
|
||||
|
||||
@synthesize uiwindow;
|
||||
@synthesize viewcontroller;
|
||||
@synthesize views;
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
views = [NSMutableArray new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface SDL_uikitwindow : UIWindow
|
||||
|
||||
- (void)layoutSubviews;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDL_uikitwindow
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
/* Workaround to fix window orientation issues in iOS 8. */
|
||||
/* As of July 1 2019, I haven't been able to reproduce any orientation
|
||||
* issues with this disabled on iOS 12. The issue this is meant to fix might
|
||||
* only happen on iOS 8, or it might have been fixed another way with other
|
||||
* code... This code prevents split view (iOS 9+) from working on iPads, so
|
||||
* we want to avoid using it if possible. */
|
||||
if (!UIKit_IsSystemVersionAtLeast(9.0)) {
|
||||
self.frame = self.screen.bounds;
|
||||
}
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static int
|
||||
SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
|
||||
{
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
SDL_uikitview *view;
|
||||
|
||||
CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen);
|
||||
int width = (int) frame.size.width;
|
||||
int height = (int) frame.size.height;
|
||||
|
||||
SDL_WindowData *data = [[SDL_WindowData alloc] init];
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
window->driverdata = (void *) CFBridgingRetain(data);
|
||||
|
||||
data.uiwindow = uiwindow;
|
||||
|
||||
/* only one window on iOS, always shown */
|
||||
window->flags &= ~SDL_WINDOW_HIDDEN;
|
||||
|
||||
if (displaydata.uiscreen != [UIScreen mainScreen]) {
|
||||
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizable */
|
||||
window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
|
||||
window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
||||
/* SDL_CreateWindow sets the window w&h to the display's bounds if the
|
||||
* fullscreen flag is set. But the display bounds orientation might not
|
||||
* match what we want, and GetSupportedOrientations call below uses the
|
||||
* window w&h. They're overridden below anyway, so we'll just set them
|
||||
* to the requested size for the purposes of determining orientation. */
|
||||
window->w = window->windowed.w;
|
||||
window->h = window->windowed.h;
|
||||
|
||||
NSUInteger orients = UIKit_GetSupportedOrientations(window);
|
||||
BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0;
|
||||
BOOL supportsPortrait = (orients & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown)) != 0;
|
||||
|
||||
/* Make sure the width/height are oriented correctly */
|
||||
if ((width > height && !supportsLandscape) || (height > width && !supportsPortrait)) {
|
||||
int temp = width;
|
||||
width = height;
|
||||
height = temp;
|
||||
}
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
window->w = width;
|
||||
window->h = height;
|
||||
|
||||
/* The View Controller will handle rotating the view when the device
|
||||
* orientation changes. This will trigger resize events, if appropriate. */
|
||||
data.viewcontroller = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window];
|
||||
|
||||
/* The window will initially contain a generic view so resizes, touch events,
|
||||
* etc. can be handled without an active OpenGL view/context. */
|
||||
view = [[SDL_uikitview alloc] initWithFrame:frame];
|
||||
|
||||
/* Sets this view as the controller's view, and adds the view to the window
|
||||
* heirarchy. */
|
||||
[view setSDLWindow:window];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
|
||||
/* SDL currently puts this window at the start of display's linked list. We rely on this. */
|
||||
SDL_assert(_this->windows == window);
|
||||
|
||||
/* We currently only handle a single window per display on iOS */
|
||||
if (window->next != NULL) {
|
||||
return SDL_SetError("Only one window allowed per display.");
|
||||
}
|
||||
|
||||
/* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
|
||||
* user, so it's in standby), try to force the display to a resolution
|
||||
* that most closely matches the desired window size. */
|
||||
#if !TARGET_OS_TV
|
||||
const CGSize origsize = data.uiscreen.currentMode.size;
|
||||
if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
|
||||
if (display->num_display_modes == 0) {
|
||||
_this->GetDisplayModes(_this, display);
|
||||
}
|
||||
|
||||
int i;
|
||||
const SDL_DisplayMode *bestmode = NULL;
|
||||
for (i = display->num_display_modes; i >= 0; i--) {
|
||||
const SDL_DisplayMode *mode = &display->display_modes[i];
|
||||
if ((mode->w >= window->w) && (mode->h >= window->h)) {
|
||||
bestmode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestmode) {
|
||||
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)bestmode->driverdata;
|
||||
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
|
||||
|
||||
/* desktop_mode doesn't change here (the higher level will
|
||||
* use it to set all the screens back to their defaults
|
||||
* upon window destruction, SDL_Quit(), etc. */
|
||||
display->current_mode = *bestmode;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.uiscreen == [UIScreen mainScreen]) {
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||
} else {
|
||||
[UIApplication sharedApplication].statusBarHidden = NO;
|
||||
}
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
/* ignore the size user requested, and make a fullscreen window */
|
||||
/* !!! FIXME: can we have a smaller view? */
|
||||
UIWindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data.uiscreen.bounds];
|
||||
|
||||
/* put the window on an external display if appropriate. */
|
||||
if (data.uiscreen != [UIScreen mainScreen]) {
|
||||
[uiwindow setScreen:data.uiscreen];
|
||||
}
|
||||
|
||||
if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetWindowTitle(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
data.viewcontroller.title = @(window->title);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_ShowWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
[data.uiwindow makeKeyAndVisible];
|
||||
|
||||
/* Make this window the current mouse focus for touch input */
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_HideWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
data.uiwindow.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_RaiseWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
/* We don't currently offer a concept of "raising" the SDL window, since
|
||||
* we only allow one per display, in the iOS fashion.
|
||||
* However, we use this entry point to rebind the context to the view
|
||||
* during OnWindowRestored processing. */
|
||||
_this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
|
||||
}
|
||||
|
||||
static void
|
||||
UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
if (data.uiwindow.screen == [UIScreen mainScreen]) {
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) {
|
||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||
} else {
|
||||
[UIApplication sharedApplication].statusBarHidden = NO;
|
||||
}
|
||||
|
||||
/* iOS 7+ won't update the status bar until we tell it to. */
|
||||
if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
|
||||
[viewcontroller setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the view's frame to account for the status bar change. */
|
||||
viewcontroller.view.frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
#ifdef SDL_IPHONE_KEYBOARD
|
||||
/* Make sure the view is offset correctly when the keyboard is visible. */
|
||||
[viewcontroller updateKeyboard];
|
||||
#endif
|
||||
|
||||
[viewcontroller.view setNeedsLayout];
|
||||
[viewcontroller.view layoutIfNeeded];
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
||||
{
|
||||
@autoreleasepool {
|
||||
UIKit_UpdateWindowBorder(_this, window);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||
{
|
||||
@autoreleasepool {
|
||||
UIKit_UpdateWindowBorder(_this, window);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
if (window->driverdata != NULL) {
|
||||
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
||||
NSArray *views = nil;
|
||||
|
||||
[data.viewcontroller stopAnimation];
|
||||
|
||||
/* Detach all views from this window. We use a copy of the array
|
||||
* because setSDLWindow will remove the object from the original
|
||||
* array, which would be undesirable if we were iterating over it. */
|
||||
views = [data.views copy];
|
||||
for (SDL_uikitview *view in views) {
|
||||
[view setSDLWindow:NULL];
|
||||
}
|
||||
|
||||
/* iOS may still hold a reference to the window after we release it.
|
||||
* We want to make sure the SDL view controller isn't accessed in
|
||||
* that case, because it would contain an invalid pointer to the old
|
||||
* SDL window. */
|
||||
data.uiwindow.rootViewController = nil;
|
||||
data.uiwindow.hidden = YES;
|
||||
}
|
||||
}
|
||||
window->driverdata = NULL;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||
int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
|
||||
|
||||
info->subsystem = SDL_SYSWM_UIKIT;
|
||||
info->info.uikit.window = data.uiwindow;
|
||||
|
||||
/* These struct members were added in SDL 2.0.4. */
|
||||
if (versionnum >= SDL_VERSIONNUM(2,0,4)) {
|
||||
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
|
||||
if ([data.viewcontroller.view isKindOfClass:[SDL_uikitopenglview class]]) {
|
||||
SDL_uikitopenglview *glview = (SDL_uikitopenglview *)data.viewcontroller.view;
|
||||
info->info.uikit.framebuffer = glview.drawableFramebuffer;
|
||||
info->info.uikit.colorbuffer = glview.drawableRenderbuffer;
|
||||
info->info.uikit.resolveFramebuffer = glview.msaaResolveFramebuffer;
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
info->info.uikit.framebuffer = 0;
|
||||
info->info.uikit.colorbuffer = 0;
|
||||
info->info.uikit.resolveFramebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
SDL_SetError("Application not compiled with SDL %d.%d",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
NSUInteger
|
||||
UIKit_GetSupportedOrientations(SDL_Window * window)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
|
||||
NSUInteger validOrientations = UIInterfaceOrientationMaskAll;
|
||||
NSUInteger orientationMask = 0;
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
UIApplication *app = [UIApplication sharedApplication];
|
||||
|
||||
/* Get all possible valid orientations. If the app delegate doesn't tell
|
||||
* us, we get the orientations from Info.plist via UIApplication. */
|
||||
if ([app.delegate respondsToSelector:@selector(application:supportedInterfaceOrientationsForWindow:)]) {
|
||||
validOrientations = [app.delegate application:app supportedInterfaceOrientationsForWindow:data.uiwindow];
|
||||
} else if ([app respondsToSelector:@selector(supportedInterfaceOrientationsForWindow:)]) {
|
||||
validOrientations = [app supportedInterfaceOrientationsForWindow:data.uiwindow];
|
||||
}
|
||||
|
||||
if (hint != NULL) {
|
||||
NSArray *orientations = [@(hint) componentsSeparatedByString:@" "];
|
||||
|
||||
if ([orientations containsObject:@"LandscapeLeft"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskLandscapeLeft;
|
||||
}
|
||||
if ([orientations containsObject:@"LandscapeRight"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskLandscapeRight;
|
||||
}
|
||||
if ([orientations containsObject:@"Portrait"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskPortrait;
|
||||
}
|
||||
if ([orientations containsObject:@"PortraitUpsideDown"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
}
|
||||
}
|
||||
|
||||
if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
/* any orientation is okay. */
|
||||
orientationMask = UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
if (orientationMask == 0) {
|
||||
if (window->w >= window->h) {
|
||||
orientationMask |= UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
if (window->h >= window->w) {
|
||||
orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't allow upside-down orientation on phones, so answering calls is in the natural orientation */
|
||||
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
|
||||
orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
}
|
||||
|
||||
/* If none of the specified orientations are actually supported by the
|
||||
* app, we'll revert to what the app supports. An exception would be
|
||||
* thrown by the system otherwise. */
|
||||
if ((validOrientations & orientationMask) == 0) {
|
||||
orientationMask = validOrientations;
|
||||
}
|
||||
}
|
||||
|
||||
return orientationMask;
|
||||
}
|
||||
#endif /* !TARGET_OS_TV */
|
||||
|
||||
int
|
||||
SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
|
||||
{
|
||||
if (!window || !window->driverdata) {
|
||||
return SDL_SetError("Invalid window");
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
[data.viewcontroller setAnimationCallback:interval
|
||||
callback:callback
|
||||
callbackParam:callbackParam];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
174
externals/SDL/src/video/uikit/keyinfotable.h
vendored
Executable file
174
externals/SDL/src/video/uikit/keyinfotable.h
vendored
Executable file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef _UIKIT_KeyInfo
|
||||
#define _UIKIT_KeyInfo
|
||||
|
||||
#include "SDL_scancode.h"
|
||||
|
||||
/*
|
||||
This file is used by the keyboard code in SDL_uikitview.m to convert between characters
|
||||
passed in from the iPhone's virtual keyboard, and tuples of SDL_Scancode and SDL_keymods.
|
||||
For example unicharToUIKeyInfoTable['a'] would give you the scan code and keymod for lower
|
||||
case a.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Scancode code;
|
||||
Uint16 mod;
|
||||
} UIKitKeyInfo;
|
||||
|
||||
/* So far only ASCII characters here */
|
||||
static UIKitKeyInfo unicharToUIKeyInfoTable[] = {
|
||||
/* 0 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 1 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 2 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 3 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 4 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 5 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 6 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 7 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 8 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 9 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 10 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 11 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 12 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 13 */ { SDL_SCANCODE_RETURN, 0 },
|
||||
/* 14 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 15 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 16 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 17 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 18 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 19 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 20 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 21 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 22 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 23 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 24 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 25 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 26 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 27 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 28 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 29 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 30 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 31 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 32 */ { SDL_SCANCODE_SPACE, 0 },
|
||||
/* 33 */ { SDL_SCANCODE_1, KMOD_SHIFT }, /* plus shift modifier '!' */
|
||||
/* 34 */ { SDL_SCANCODE_APOSTROPHE, KMOD_SHIFT }, /* plus shift modifier '"' */
|
||||
/* 35 */ { SDL_SCANCODE_3, KMOD_SHIFT }, /* plus shift modifier '#' */
|
||||
/* 36 */ { SDL_SCANCODE_4, KMOD_SHIFT }, /* plus shift modifier '$' */
|
||||
/* 37 */ { SDL_SCANCODE_5, KMOD_SHIFT }, /* plus shift modifier '%' */
|
||||
/* 38 */ { SDL_SCANCODE_7, KMOD_SHIFT }, /* plus shift modifier '&' */
|
||||
/* 39 */ { SDL_SCANCODE_APOSTROPHE, 0 }, /* ''' */
|
||||
/* 40 */ { SDL_SCANCODE_9, KMOD_SHIFT }, /* plus shift modifier '(' */
|
||||
/* 41 */ { SDL_SCANCODE_0, KMOD_SHIFT }, /* plus shift modifier ')' */
|
||||
/* 42 */ { SDL_SCANCODE_8, KMOD_SHIFT }, /* '*' */
|
||||
/* 43 */ { SDL_SCANCODE_EQUALS, KMOD_SHIFT }, /* plus shift modifier '+' */
|
||||
/* 44 */ { SDL_SCANCODE_COMMA, 0 }, /* ',' */
|
||||
/* 45 */ { SDL_SCANCODE_MINUS, 0 }, /* '-' */
|
||||
/* 46 */ { SDL_SCANCODE_PERIOD, 0 }, /* '.' */
|
||||
/* 47 */ { SDL_SCANCODE_SLASH, 0 }, /* '/' */
|
||||
/* 48 */ { SDL_SCANCODE_0, 0 },
|
||||
/* 49 */ { SDL_SCANCODE_1, 0 },
|
||||
/* 50 */ { SDL_SCANCODE_2, 0 },
|
||||
/* 51 */ { SDL_SCANCODE_3, 0 },
|
||||
/* 52 */ { SDL_SCANCODE_4, 0 },
|
||||
/* 53 */ { SDL_SCANCODE_5, 0 },
|
||||
/* 54 */ { SDL_SCANCODE_6, 0 },
|
||||
/* 55 */ { SDL_SCANCODE_7, 0 },
|
||||
/* 56 */ { SDL_SCANCODE_8, 0 },
|
||||
/* 57 */ { SDL_SCANCODE_9, 0 },
|
||||
/* 58 */ { SDL_SCANCODE_SEMICOLON, KMOD_SHIFT }, /* plus shift modifier ';' */
|
||||
/* 59 */ { SDL_SCANCODE_SEMICOLON, 0 },
|
||||
/* 60 */ { SDL_SCANCODE_COMMA, KMOD_SHIFT }, /* plus shift modifier '<' */
|
||||
/* 61 */ { SDL_SCANCODE_EQUALS, 0 },
|
||||
/* 62 */ { SDL_SCANCODE_PERIOD, KMOD_SHIFT }, /* plus shift modifier '>' */
|
||||
/* 63 */ { SDL_SCANCODE_SLASH, KMOD_SHIFT }, /* plus shift modifier '?' */
|
||||
/* 64 */ { SDL_SCANCODE_2, KMOD_SHIFT }, /* plus shift modifier '@' */
|
||||
/* 65 */ { SDL_SCANCODE_A, KMOD_SHIFT }, /* all the following need shift modifiers */
|
||||
/* 66 */ { SDL_SCANCODE_B, KMOD_SHIFT },
|
||||
/* 67 */ { SDL_SCANCODE_C, KMOD_SHIFT },
|
||||
/* 68 */ { SDL_SCANCODE_D, KMOD_SHIFT },
|
||||
/* 69 */ { SDL_SCANCODE_E, KMOD_SHIFT },
|
||||
/* 70 */ { SDL_SCANCODE_F, KMOD_SHIFT },
|
||||
/* 71 */ { SDL_SCANCODE_G, KMOD_SHIFT },
|
||||
/* 72 */ { SDL_SCANCODE_H, KMOD_SHIFT },
|
||||
/* 73 */ { SDL_SCANCODE_I, KMOD_SHIFT },
|
||||
/* 74 */ { SDL_SCANCODE_J, KMOD_SHIFT },
|
||||
/* 75 */ { SDL_SCANCODE_K, KMOD_SHIFT },
|
||||
/* 76 */ { SDL_SCANCODE_L, KMOD_SHIFT },
|
||||
/* 77 */ { SDL_SCANCODE_M, KMOD_SHIFT },
|
||||
/* 78 */ { SDL_SCANCODE_N, KMOD_SHIFT },
|
||||
/* 79 */ { SDL_SCANCODE_O, KMOD_SHIFT },
|
||||
/* 80 */ { SDL_SCANCODE_P, KMOD_SHIFT },
|
||||
/* 81 */ { SDL_SCANCODE_Q, KMOD_SHIFT },
|
||||
/* 82 */ { SDL_SCANCODE_R, KMOD_SHIFT },
|
||||
/* 83 */ { SDL_SCANCODE_S, KMOD_SHIFT },
|
||||
/* 84 */ { SDL_SCANCODE_T, KMOD_SHIFT },
|
||||
/* 85 */ { SDL_SCANCODE_U, KMOD_SHIFT },
|
||||
/* 86 */ { SDL_SCANCODE_V, KMOD_SHIFT },
|
||||
/* 87 */ { SDL_SCANCODE_W, KMOD_SHIFT },
|
||||
/* 88 */ { SDL_SCANCODE_X, KMOD_SHIFT },
|
||||
/* 89 */ { SDL_SCANCODE_Y, KMOD_SHIFT },
|
||||
/* 90 */ { SDL_SCANCODE_Z, KMOD_SHIFT },
|
||||
/* 91 */ { SDL_SCANCODE_LEFTBRACKET, 0 },
|
||||
/* 92 */ { SDL_SCANCODE_BACKSLASH, 0 },
|
||||
/* 93 */ { SDL_SCANCODE_RIGHTBRACKET, 0 },
|
||||
/* 94 */ { SDL_SCANCODE_6, KMOD_SHIFT }, /* plus shift modifier '^' */
|
||||
/* 95 */ { SDL_SCANCODE_MINUS, KMOD_SHIFT }, /* plus shift modifier '_' */
|
||||
/* 96 */ { SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* '`' */
|
||||
/* 97 */ { SDL_SCANCODE_A, 0 },
|
||||
/* 98 */ { SDL_SCANCODE_B, 0 },
|
||||
/* 99 */ { SDL_SCANCODE_C, 0 },
|
||||
/* 100 */{ SDL_SCANCODE_D, 0 },
|
||||
/* 101 */{ SDL_SCANCODE_E, 0 },
|
||||
/* 102 */{ SDL_SCANCODE_F, 0 },
|
||||
/* 103 */{ SDL_SCANCODE_G, 0 },
|
||||
/* 104 */{ SDL_SCANCODE_H, 0 },
|
||||
/* 105 */{ SDL_SCANCODE_I, 0 },
|
||||
/* 106 */{ SDL_SCANCODE_J, 0 },
|
||||
/* 107 */{ SDL_SCANCODE_K, 0 },
|
||||
/* 108 */{ SDL_SCANCODE_L, 0 },
|
||||
/* 109 */{ SDL_SCANCODE_M, 0 },
|
||||
/* 110 */{ SDL_SCANCODE_N, 0 },
|
||||
/* 111 */{ SDL_SCANCODE_O, 0 },
|
||||
/* 112 */{ SDL_SCANCODE_P, 0 },
|
||||
/* 113 */{ SDL_SCANCODE_Q, 0 },
|
||||
/* 114 */{ SDL_SCANCODE_R, 0 },
|
||||
/* 115 */{ SDL_SCANCODE_S, 0 },
|
||||
/* 116 */{ SDL_SCANCODE_T, 0 },
|
||||
/* 117 */{ SDL_SCANCODE_U, 0 },
|
||||
/* 118 */{ SDL_SCANCODE_V, 0 },
|
||||
/* 119 */{ SDL_SCANCODE_W, 0 },
|
||||
/* 120 */{ SDL_SCANCODE_X, 0 },
|
||||
/* 121 */{ SDL_SCANCODE_Y, 0 },
|
||||
/* 122 */{ SDL_SCANCODE_Z, 0 },
|
||||
/* 123 */{ SDL_SCANCODE_LEFTBRACKET, KMOD_SHIFT }, /* plus shift modifier '{' */
|
||||
/* 124 */{ SDL_SCANCODE_BACKSLASH, KMOD_SHIFT }, /* plus shift modifier '|' */
|
||||
/* 125 */{ SDL_SCANCODE_RIGHTBRACKET, KMOD_SHIFT }, /* plus shift modifier '}' */
|
||||
/* 126 */{ SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* plus shift modifier '~' */
|
||||
/* 127 */{ SDL_SCANCODE_BACKSPACE, KMOD_SHIFT }
|
||||
};
|
||||
|
||||
#endif /* _UIKIT_KeyInfo */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
Reference in New Issue
Block a user