diff options
Diffstat (limited to 'source/3rd-party/SDL2/src/video/uikit')
27 files changed, 4688 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.h new file mode 100644 index 0000000..34b0138 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.h @@ -0,0 +1,47 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.m new file mode 100644 index 0000000..15762d2 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitappdelegate.m @@ -0,0 +1,516 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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 int forward_argc; +static char **forward_argv; +static int exit_status; + +int main(int argc, char **argv) +{ + int i; + + /* store arguments */ + 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; + }]; +} + +- (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 = SDL_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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.h new file mode 100644 index 0000000..c4b689d --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.m new file mode 100644 index 0000000..b1d4f6d --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitclipboard.m @@ -0,0 +1,111 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.h new file mode 100644 index 0000000..0c48829 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.h @@ -0,0 +1,30 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.m new file mode 100644 index 0000000..d64e330 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitevents.m @@ -0,0 +1,73 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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. */ + UIKit_GL_RestoreCurrentContext(); +} + +#endif /* SDL_VIDEO_DRIVER_UIKIT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.h new file mode 100644 index 0000000..a766b57 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.m new file mode 100644 index 0000000..cf2a8f3 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmessagebox.m @@ -0,0 +1,208 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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) +{ +#ifdef __IPHONE_8_0 + int i; + int __block clickedindex = messageboxdata->numbuttons; + const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; + 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; + + if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) { + style = UIAlertActionStyleCancel; + } + + action = [UIAlertAction actionWithTitle:@(buttons[i].text) + style:style + handler:^(UIAlertAction *action) { + clickedindex = i; + }]; + [alert addAction: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; + } + +#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) { + if (@available(iOS 11.0, *)) { + [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden) withObject:nil waitUntilDone:NO]; + [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfScreenEdgesDeferringSystemGestures) withObject:nil waitUntilDone:NO]; + } + } + } +#endif /* !TARGET_OS_TV */ + + *buttonid = messageboxdata->buttons[clickedindex].buttonid; + return YES; +#else + return NO; +#endif /* __IPHONE_8_0 */ +} + +/* 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++) { + [alert addButtonWithTitle:@(buttons[i].text)]; + } + + delegate.clickedIndex = &clickedindex; + + [alert show]; + + UIKit_WaitUntilMessageBoxClosed(messageboxdata, &clickedindex); + + alert.delegate = nil; + + *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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.h new file mode 100644 index 0000000..bc97778 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.h @@ -0,0 +1,58 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +/* + * @author Mark Callow, www.edgewise-consulting.com. + * + * Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing + * how to add a CAMetalLayer backed view. + */ + +#ifndef SDL_uikitmetalview_h_ +#define SDL_uikitmetalview_h_ + +#import "../SDL_sysvideo.h" +#import "SDL_uikitwindow.h" + +#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN) + +#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_uikitmetalview* UIKit_Mtl_AddMetalView(SDL_Window* window); + +void UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h); + +#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN) */ + +#endif /* SDL_uikitmetalview_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.m new file mode 100644 index 0000000..436e742 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmetalview.m @@ -0,0 +1,132 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +/* + * @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_RENDER_METAL || SDL_VIDEO_VULKAN) + +#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_uikitmetalview* +UIKit_Mtl_AddMetalView(SDL_Window* window) +{ + SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata; + SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view; + CGFloat scale = 1.0; + + if ([view isKindOfClass:[SDL_uikitmetalview class]]) { + return (SDL_uikitmetalview *)view; + } + + 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. + */ +#ifdef __IPHONE_8_0 + if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) { + scale = data.uiwindow.screen.nativeScale; + } else +#endif + { + scale = data.uiwindow.screen.scale; + } + } + SDL_uikitmetalview *metalview + = [[SDL_uikitmetalview alloc] initWithFrame:view.frame + scale:scale]; + [metalview setSDLWindow:window]; + + return metalview; +} + +void +UIKit_Mtl_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_RENDER_METAL || SDL_VIDEO_VULKAN) */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.h new file mode 100644 index 0000000..b5c0c65 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.h @@ -0,0 +1,54 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_uikitmodes_h_ +#define SDL_uikitmodes_h_ + +#include "SDL_uikitvideo.h" + +@interface SDL_DisplayData : NSObject + +@property (nonatomic, strong) UIScreen *uiscreen; + +@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_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +extern void UIKit_QuitModes(_THIS); +extern int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); + +#if !TARGET_OS_TV +extern void SDL_OnApplicationDidChangeStatusBarOrientation(void); +#endif + +#endif /* SDL_uikitmodes_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.m new file mode 100644 index 0000000..7ddf107 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitmodes.m @@ -0,0 +1,380 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +#include "SDL_assert.h" +#include "SDL_uikitmodes.h" + +#include "../../events/SDL_events_c.h" + +@implementation SDL_DisplayData + +@synthesize uiscreen; + +@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] init]; + if (!data) { + UIKit_FreeDisplayModeData(&display.desktop_mode); + return SDL_OutOfMemory(); + } + + data.uiscreen = uiscreen; + + 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 + +#ifdef __IPHONE_8_0 + /* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than + * 1242x2208 (414x736@3x), so we should use the native scale. */ + if ([data.uiscreen respondsToSelector:@selector(nativeScale)]) { + scale = data.uiscreen.nativeScale; + } +#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.) */ + 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_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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.h new file mode 100644 index 0000000..6b57289 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.h @@ -0,0 +1,40 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef SDL_uikitopengles_ +#define SDL_uikitopengles_ + +#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_uikitopengles_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.m new file mode 100644 index 0000000..2f6dec4 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopengles.m @@ -0,0 +1,250 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +#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; + } + } + } +} + +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. */ +#ifdef __IPHONE_8_0 + if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) { + scale = data.uiwindow.screen.nativeScale; + } else +#endif + { + 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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.h new file mode 100644 index 0000000..8d12c9f --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.h @@ -0,0 +1,60 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#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 + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.m new file mode 100644 index 0000000..9024376 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitopenglview.m @@ -0,0 +1,384 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.h new file mode 100644 index 0000000..e24183a --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.h @@ -0,0 +1,46 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#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); + +SDL_bool UIKit_IsSystemVersionAtLeast(double version); + +#endif /* SDL_uikitvideo_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.m new file mode 100644 index 0000000..10d1dde --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvideo.m @@ -0,0 +1,249 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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" + +#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 */ + 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; + 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 + + 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) +{ + CGRect frame = screen.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 isLandscape = UIInterfaceOrientationIsLandscape(orient); + + if (isLandscape != (frame.size.width > frame.size.height)) { + float height = frame.size.width; + frame.size.width = frame.size.height; + frame.size.height = height; + } + } +#endif + + return frame; +} + +/* + * 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. + */ + +void SDL_NSLog(const char *text) +{ + NSLog(@"%s", text); +} + +/* + * 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 (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); +} + +#endif /* SDL_VIDEO_DRIVER_UIKIT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.h new file mode 100644 index 0000000..4457f6c --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.h @@ -0,0 +1,41 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.m new file mode 100644 index 0000000..caabfac --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitview.m @@ -0,0 +1,328 @@ + /* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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 touchId; + UITouch * __weak firstFingerDown; +} + +- (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; + +#if !TARGET_OS_TV + self.multipleTouchEnabled = YES; +#endif + + touchId = 1; + SDL_AddTouch(touchId, ""); + } + + 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; +} + +- (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) { + float pressure = [self pressureForTouch:touch]; + + if (!firstFingerDown) { + CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; + int clicks = (int) touch.tapCount; + + /* send mouse moved event */ + SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); + + /* send mouse down event */ + SDL_SendMouseButtonClicks(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT, clicks); + + firstFingerDown = touch; + } + + CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; + SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), + SDL_TRUE, locationInView.x, locationInView.y, pressure); + } +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + for (UITouch *touch in touches) { + float pressure = [self pressureForTouch:touch]; + + if (touch == firstFingerDown) { + /* send mouse up */ + int clicks = (int) touch.tapCount; + SDL_SendMouseButtonClicks(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT, clicks); + firstFingerDown = nil; + } + + CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; + SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), + 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) { + float pressure = [self pressureForTouch:touch]; + + if (touch == firstFingerDown) { + CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; + + /* send moved event */ + SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y); + } + + CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; + SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), + 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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.h new file mode 100644 index 0000000..fffb142 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.h @@ -0,0 +1,91 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#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 diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.m new file mode 100644 index 0000000..49a39b6 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitviewcontroller.m @@ -0,0 +1,553 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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; + if (@available(iOS 11.0, *)) { + [viewcontroller setNeedsUpdateOfHomeIndicatorAutoHidden]; + [viewcontroller setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; + } + } +} +#endif + +@implementation SDL_uikitviewcontroller { + CADisplayLink *displayLink; + int animationInterval; + void (*animationCallback)(void*); + void *animationCallbackParam; + +#if SDL_IPHONE_KEYBOARD + UITextField *textField; + 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]; + rotatingOrientation = FALSE; +#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. */ + UIKit_GL_RestoreCurrentContext(); + + 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]; +} + +- (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 = TRUE; + [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {} + completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { + rotatingOrientation = FALSE; + }]; +} +#else +- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { + [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; + rotatingOrientation = TRUE; +} + +- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { + [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; + rotatingOrientation = FALSE; +} +#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) { + [textField becomeFirstResponder]; + } +} + +/* 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 (!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 (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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.h new file mode 100644 index 0000000..e3ec350 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.h @@ -0,0 +1,54 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's + * SDL_x11vulkan.h. + */ + +#include "../../SDL_internal.h" + +#ifndef SDL_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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.m new file mode 100644 index 0000000..771c7a4 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitvulkan.m @@ -0,0 +1,222 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's + * SDL_x11vulkan.c. + */ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_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> + +#define DEFAULT_MOLTENVK "libMoltenVK.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("MoltenVK/Vulkan already loaded"); + } + + /* Load the Vulkan loader library */ + if (!path) { + path = SDL_getenv("SDL_VULKAN_LIBRARY"); + } + + if (!path) { + /* MoltenVK framework, currently, v0.17.0, has a static library and is + * the recommended way to use the package. There is likely no object to + * load. */ + vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE, + "vkGetInstanceProcAddr"); + } + + if (vkGetInstanceProcAddr) { + _this->vulkan_config.loader_handle = DEFAULT_HANDLE; + } else { + if (!path) { + /* Look for the .dylib packaged with the application instead. */ + path = DEFAULT_MOLTENVK; + } + + _this->vulkan_config.loader_handle = SDL_LoadObject(path); + if (!_this->vulkan_config.loader_handle) { + return -1; + } + 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", + DEFAULT_MOLTENVK, + (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 MoltenVK/Vulkan doesn't implement the " + VK_KHR_SURFACE_EXTENSION_NAME " extension"); + goto fail; + } else if (!hasIOSSurfaceExtension) { + SDL_SetError("Installed MoltenVK/Vulkan 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; + + 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; + } + + createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.pView = (__bridge void *)UIKit_Mtl_AddMetalView(window); + result = vkCreateIOSSurfaceMVK(instance, &createInfo, + NULL, surface); + if (result != VK_SUCCESS) { + SDL_SetError("vkCreateIOSSurfaceMVK failed: %s", + SDL_Vulkan_GetResultString(result)); + return SDL_FALSE; + } + + return SDL_TRUE; +} + +void UIKit_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h) +{ + UIKit_Mtl_GetDrawableSize(window, w, h); +} + +#endif + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.h b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.h new file mode 100644 index 0000000..46073ee --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.h @@ -0,0 +1,56 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.m b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.m new file mode 100644 index 0000000..d01cff3 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/SDL_uikitwindow.m @@ -0,0 +1,465 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_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+. */ + 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]; + + /* Make this window the current mouse focus for touch input */ + if (displaydata.uiscreen == [UIScreen mainScreen]) { + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(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]; + } +} + +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 ([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 { + 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: */ diff --git a/source/3rd-party/SDL2/src/video/uikit/keyinfotable.h b/source/3rd-party/SDL2/src/video/uikit/keyinfotable.h new file mode 100644 index 0000000..3b23837 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/uikit/keyinfotable.h @@ -0,0 +1,174 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#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: */ |