mirror of https://github.com/encounter/SDL.git
Merged default into iOS-improvements
This commit is contained in:
commit
fb6d185a8a
|
@ -8,6 +8,9 @@ Makefile
|
|||
sdl-config
|
||||
SDL2.spec
|
||||
build
|
||||
Build
|
||||
*xcuserdata*
|
||||
*xcworkspacedata*
|
||||
|
||||
# for Xcode
|
||||
*.orig
|
||||
|
|
|
@ -387,6 +387,9 @@ main(int argc, char *argv[])
|
|||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
|
||||
/* create main window and renderer */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||
SDL_WINDOW_OPENGL |
|
||||
|
|
|
@ -1274,8 +1274,14 @@
|
|||
FD6526640DE8FCCB002AD96B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
||||
GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES;
|
||||
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
PRODUCT_NAME = SDL2;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
|
@ -1284,8 +1290,14 @@
|
|||
FD6526650DE8FCCB002AD96B /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
||||
GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES;
|
||||
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
PRODUCT_NAME = SDL2;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
|
|
|
@ -261,8 +261,9 @@ extern "C" {
|
|||
#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling whether an Android built-in accelerometer should be
|
||||
* listed as a joystick device, rather than listing actual joysticks only.
|
||||
* \brief A variable controlling whether the Android / iOS built-in
|
||||
* accelerometer should be listed as a joystick device, rather than listing
|
||||
* actual joysticks only.
|
||||
*
|
||||
* This variable can be set to the following values:
|
||||
* "0" - List only real joysticks and accept input from them
|
||||
|
@ -345,7 +346,7 @@ extern "C" {
|
|||
|
||||
|
||||
/**
|
||||
* \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac)
|
||||
* \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS)
|
||||
*/
|
||||
#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
|
||||
|
||||
|
|
|
@ -70,6 +70,16 @@ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *a
|
|||
extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
|
||||
extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
|
||||
|
||||
/* Returns the OpenGL Renderbuffer Object associated with the window's main view.
|
||||
The Renderbuffer must be bound when calling SDL_GL_SwapWindow.
|
||||
*/
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_iPhoneGetViewRenderbuffer(SDL_Window * window);
|
||||
|
||||
/* Returns the OpenGL Framebuffer Object associated with the window's main view.
|
||||
The Framebuffer must be bound when rendering to the screen.
|
||||
*/
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_iPhoneGetViewFramebuffer(SDL_Window * window);
|
||||
|
||||
#endif /* __IPHONEOS__ */
|
||||
|
||||
|
||||
|
|
|
@ -50,14 +50,13 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
|||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fp = fopen(file, mode);
|
||||
}
|
||||
|
||||
return fp;
|
||||
}}
|
||||
|
||||
#endif /* __MACOSX__ */
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -41,6 +41,7 @@ SDL_GetBasePath(void)
|
|||
const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||
const char *base = NULL;
|
||||
char *retval = NULL;
|
||||
|
||||
if (baseType == NULL) {
|
||||
baseType = "resource";
|
||||
}
|
||||
|
@ -52,6 +53,7 @@ SDL_GetBasePath(void)
|
|||
/* this returns the exedir for non-bundled and the resourceDir for bundled apps */
|
||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||
}
|
||||
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + 2;
|
||||
retval = (char *) SDL_malloc(len);
|
||||
|
@ -69,9 +71,10 @@ char *
|
|||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
char *retval = NULL;
|
||||
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
|
||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||
NSString *str = [array objectAtIndex:0];
|
||||
const char *base = [str fileSystemRepresentation];
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
/* This is the iOS implementation of the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
@ -32,9 +33,10 @@
|
|||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "SDL_config_iphoneos.h"
|
||||
|
||||
const char *accelerometerName = "iOS accelerometer";
|
||||
const char *accelerometerName = "iOS Accelerometer";
|
||||
|
||||
static CMMotionManager *motionManager = nil;
|
||||
static int numjoysticks = 0;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
|
@ -44,12 +46,18 @@ static CMMotionManager *motionManager = nil;
|
|||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
return (1);
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
numjoysticks = 1;
|
||||
}
|
||||
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return 1;
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
|
@ -82,6 +90,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
|||
joystick->nballs = 0;
|
||||
joystick->nbuttons = 0;
|
||||
|
||||
@autoreleasepool {
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
|
@ -89,6 +98,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
|||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,11 +115,13 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
|||
const SInt16 maxsint16 = 0x7FFF;
|
||||
CMAcceleration accel;
|
||||
|
||||
@autoreleasepool {
|
||||
if (!motionManager.accelerometerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
accel = [[motionManager accelerometerData] acceleration];
|
||||
accel = motionManager.accelerometerData.acceleration;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert accelerometer data from floating point to Sint16, which is what
|
||||
|
@ -153,7 +165,9 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
|||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
@autoreleasepool {
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
}
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
|
@ -161,10 +175,11 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
|||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
if (motionManager != nil) {
|
||||
[motionManager release];
|
||||
@autoreleasepool {
|
||||
motionManager = nil;
|
||||
}
|
||||
|
||||
numjoysticks = 0;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
|
|
|
@ -50,11 +50,12 @@ SDL_UIKit_UpdateBatteryMonitoring(void)
|
|||
SDL_bool
|
||||
SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
||||
{
|
||||
@autoreleasepool {
|
||||
UIDevice *uidev = [UIDevice currentDevice];
|
||||
|
||||
if (!SDL_UIKitLastPowerInfoQuery) {
|
||||
SDL_assert([uidev isBatteryMonitoringEnabled] == NO);
|
||||
[uidev setBatteryMonitoringEnabled:YES];
|
||||
SDL_assert(uidev.isBatteryMonitoringEnabled == NO);
|
||||
uidev.batteryMonitoringEnabled = YES;
|
||||
}
|
||||
|
||||
/* UIKit_GL_SwapWindow() (etc) will check this and disable the battery
|
||||
|
@ -66,8 +67,7 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
|||
|
||||
*seconds = -1; /* no API to estimate this in UIKit. */
|
||||
|
||||
switch ([uidev batteryState])
|
||||
{
|
||||
switch (uidev.batteryState) {
|
||||
case UIDeviceBatteryStateCharging:
|
||||
*state = SDL_POWERSTATE_CHARGING;
|
||||
break;
|
||||
|
@ -86,10 +86,11 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
|||
break;
|
||||
}
|
||||
|
||||
const float level = [uidev batteryLevel];
|
||||
const float level = uidev.batteryLevel;
|
||||
*percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
|
||||
return SDL_TRUE; /* always the definitive answer on iOS. */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_POWER_UIKIT */
|
||||
#endif /* SDL_POWER_DISABLED */
|
||||
|
|
|
@ -39,12 +39,10 @@
|
|||
static int forward_argc;
|
||||
static char **forward_argv;
|
||||
static int exit_status;
|
||||
static UIWindow *launch_window;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
/* store arguments */
|
||||
forward_argc = argc;
|
||||
|
@ -56,7 +54,9 @@ int main(int argc, char **argv)
|
|||
forward_argv[i] = NULL;
|
||||
|
||||
/* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
|
||||
UIApplicationMain(argc, argv, NULL, [SDLUIKitDelegate getAppDelegateClassName]);
|
||||
@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++) {
|
||||
|
@ -64,7 +64,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
free(forward_argv);
|
||||
|
||||
[pool release];
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
|
@ -75,97 +74,12 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
|||
[UIApplication sharedApplication].idleTimerDisabled = disable;
|
||||
}
|
||||
|
||||
@interface SDL_splashviewcontroller : UIViewController {
|
||||
UIImageView *splash;
|
||||
UIImage *splashPortrait;
|
||||
UIImage *splashLandscape;
|
||||
}
|
||||
|
||||
- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation;
|
||||
@end
|
||||
|
||||
@implementation SDL_splashviewcontroller
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
self->splash = [[UIImageView alloc] init];
|
||||
[self setView:self->splash];
|
||||
|
||||
CGSize size = [UIScreen mainScreen].bounds.size;
|
||||
float height = SDL_max(size.width, size.height);
|
||||
self->splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]];
|
||||
if (!self->splashPortrait) {
|
||||
self->splashPortrait = [UIImage imageNamed:@"Default.png"];
|
||||
}
|
||||
self->splashLandscape = [UIImage imageNamed:@"Default-Landscape.png"];
|
||||
if (!self->splashLandscape && self->splashPortrait) {
|
||||
self->splashLandscape = [[UIImage alloc] initWithCGImage: self->splashPortrait.CGImage
|
||||
scale: 1.0
|
||||
orientation: UIImageOrientationRight];
|
||||
}
|
||||
if (self->splashPortrait) {
|
||||
[self->splashPortrait retain];
|
||||
}
|
||||
if (self->splashLandscape) {
|
||||
[self->splashLandscape retain];
|
||||
}
|
||||
|
||||
[self updateSplashImage:[[UIApplication sharedApplication] statusBarOrientation]];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
NSUInteger orientationMask = UIInterfaceOrientationMaskAll;
|
||||
|
||||
/* Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation */
|
||||
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
|
||||
orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
}
|
||||
return orientationMask;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient
|
||||
{
|
||||
NSUInteger orientationMask = [self supportedInterfaceOrientations];
|
||||
return (orientationMask & (1 << orient));
|
||||
}
|
||||
|
||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
|
||||
{
|
||||
[self updateSplashImage:interfaceOrientation];
|
||||
}
|
||||
|
||||
- (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
UIImage *image;
|
||||
|
||||
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
|
||||
image = self->splashLandscape;
|
||||
} else {
|
||||
image = self->splashPortrait;
|
||||
}
|
||||
if (image)
|
||||
{
|
||||
splash.image = image;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation SDLUIKitDelegate
|
||||
|
||||
/* convenience method */
|
||||
+ (id) sharedAppDelegate
|
||||
{
|
||||
/* the delegate is set in UIApplicationMain(), which is garaunteed to be called before this method */
|
||||
/* the delegate is set in UIApplicationMain(), which is guaranteed to be called before this method */
|
||||
return [[UIApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
|
@ -189,12 +103,6 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
|||
exit_status = SDL_main(forward_argc, forward_argv);
|
||||
SDL_iPhoneSetEventPump(SDL_FALSE);
|
||||
|
||||
/* If we showed a splash image, clean it up */
|
||||
if (launch_window) {
|
||||
[launch_window release];
|
||||
launch_window = NULL;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
@ -204,14 +112,6 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
|||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
/* Keep the launch image up until we set a video mode */
|
||||
launch_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
|
||||
UIViewController *splashViewController = [[SDL_splashviewcontroller alloc] init];
|
||||
launch_window.rootViewController = splashViewController;
|
||||
[launch_window addSubview:splashViewController.view];
|
||||
[launch_window makeKeyAndVisible];
|
||||
|
||||
/* Set working directory to resource path */
|
||||
[[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]];
|
||||
|
||||
|
@ -235,6 +135,35 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
|||
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
|
||||
{
|
||||
BOOL isLandscape = UIInterfaceOrientationIsLandscape(application.statusBarOrientation);
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this && _this->num_displays > 0) {
|
||||
SDL_DisplayMode *desktopmode = &_this->displays[0].desktop_mode;
|
||||
SDL_DisplayMode *currentmode = &_this->displays[0].current_mode;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) applicationWillResignActive:(UIApplication*)application
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
|
|
@ -40,8 +40,9 @@ SDL_iPhoneSetEventPump(SDL_bool enabled)
|
|||
void
|
||||
UIKit_PumpEvents(_THIS)
|
||||
{
|
||||
if (!UIKit_EventPumpEnabled)
|
||||
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
|
||||
|
|
|
@ -30,17 +30,16 @@
|
|||
|
||||
static SDL_bool s_showingMessageBox = SDL_FALSE;
|
||||
|
||||
@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate> {
|
||||
@private
|
||||
int *clickedButtonIndex;
|
||||
}
|
||||
@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate>
|
||||
|
||||
- (id)initWithButtonIndex:(int *)_buttonIndex;
|
||||
- (id)initWithButtonIndex:(int *)buttonIndex;
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIKit_UIAlertViewDelegate
|
||||
@implementation UIKit_UIAlertViewDelegate {
|
||||
int *clickedButtonIndex;
|
||||
}
|
||||
|
||||
- (id)initWithButtonIndex:(int *)buttonIndex
|
||||
{
|
||||
|
@ -48,12 +47,13 @@ static SDL_bool s_showingMessageBox = SDL_FALSE;
|
|||
if (self == nil) {
|
||||
return nil;
|
||||
}
|
||||
self->clickedButtonIndex = buttonIndex;
|
||||
|
||||
clickedButtonIndex = buttonIndex;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
*clickedButtonIndex = (int)buttonIndex;
|
||||
}
|
||||
|
@ -71,19 +71,19 @@ int
|
|||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
int clicked;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
UIAlertView* alert = [[UIAlertView alloc] init];
|
||||
|
||||
alert.title = [NSString stringWithUTF8String:messageboxdata->title];
|
||||
alert.message = [NSString stringWithUTF8String:messageboxdata->message];
|
||||
alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked];
|
||||
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
int i;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
|
||||
@autoreleasepool {
|
||||
UIAlertView* alert = [[UIAlertView alloc] init];
|
||||
UIKit_UIAlertViewDelegate *delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked];
|
||||
|
||||
alert.title = @(messageboxdata->title);
|
||||
alert.message = @(messageboxdata->message);
|
||||
alert.delegate = delegate;
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
[alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]];
|
||||
[alert addButtonWithTitle:@(buttons[i].text)];
|
||||
}
|
||||
|
||||
/* Set up for showing the alert */
|
||||
|
@ -101,10 +101,8 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
|
||||
*buttonid = messageboxdata->buttons[clicked].buttonid;
|
||||
|
||||
[alert.delegate release];
|
||||
[alert release];
|
||||
|
||||
[pool release];
|
||||
alert.delegate = nil;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,17 +25,17 @@
|
|||
|
||||
#include "SDL_uikitvideo.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UIScreen *uiscreen;
|
||||
CGFloat scale;
|
||||
} SDL_DisplayData;
|
||||
@interface SDL_DisplayData : NSObject
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UIScreenMode *uiscreenmode;
|
||||
CGFloat scale;
|
||||
} SDL_DisplayModeData;
|
||||
@property (nonatomic, strong) UIScreen *uiscreen;
|
||||
|
||||
@end
|
||||
|
||||
@interface SDL_DisplayModeData : NSObject
|
||||
|
||||
@property (nonatomic, strong) UIScreenMode *uiscreenmode;
|
||||
|
||||
@end
|
||||
|
||||
extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
|
||||
|
||||
|
|
|
@ -25,27 +25,36 @@
|
|||
#include "SDL_assert.h"
|
||||
#include "SDL_uikitmodes.h"
|
||||
|
||||
@implementation SDL_DisplayData
|
||||
|
||||
@synthesize uiscreen;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDL_DisplayModeData
|
||||
|
||||
@synthesize uiscreenmode;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static int
|
||||
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
|
||||
UIScreenMode * uiscreenmode, CGFloat scale)
|
||||
UIScreenMode * uiscreenmode)
|
||||
{
|
||||
SDL_DisplayModeData *data = NULL;
|
||||
SDL_DisplayModeData *data = nil;
|
||||
|
||||
if (uiscreenmode != nil) {
|
||||
/* Allocate the display mode data */
|
||||
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
|
||||
data = [[SDL_DisplayModeData alloc] init];
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
data->uiscreenmode = uiscreenmode;
|
||||
[data->uiscreenmode retain];
|
||||
|
||||
data->scale = scale;
|
||||
data.uiscreenmode = uiscreenmode;
|
||||
}
|
||||
|
||||
mode->driverdata = data;
|
||||
mode->driverdata = (void *) CFBridgingRetain(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -54,23 +63,21 @@ static void
|
|||
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
|
||||
{
|
||||
if (mode->driverdata != NULL) {
|
||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata;
|
||||
[data->uiscreenmode release];
|
||||
SDL_free(data);
|
||||
CFRelease(mode->driverdata);
|
||||
mode->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
||||
UIScreenMode * uiscreenmode, CGFloat scale)
|
||||
UIScreenMode * uiscreenmode)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
|
||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||
mode.refresh_rate = 0;
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -85,16 +92,16 @@ UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
|||
}
|
||||
|
||||
static int
|
||||
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale,
|
||||
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
||||
UIScreenMode * uiscreenmode, SDL_bool addRotation)
|
||||
{
|
||||
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) {
|
||||
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addRotation) {
|
||||
/* Add the rotated version */
|
||||
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) {
|
||||
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -114,24 +121,16 @@ UIKit_AddDisplay(UIScreen *uiscreen)
|
|||
size.height = height;
|
||||
}
|
||||
|
||||
/* When dealing with UIKit all coordinates are specified in terms of
|
||||
* what Apple refers to as points. [UIScreen scale] indicates the
|
||||
* relationship between points and pixels. Since SDL has no notion
|
||||
* of points, we must compensate in all cases where dealing with such
|
||||
* units.
|
||||
*/
|
||||
CGFloat scale = [uiscreen scale];
|
||||
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayMode mode;
|
||||
SDL_zero(mode);
|
||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||
mode.w = (int)(size.width * scale);
|
||||
mode.h = (int)(size.height * scale);
|
||||
mode.w = (int) size.width;
|
||||
mode.h = (int) size.height;
|
||||
|
||||
UIScreenMode *uiscreenmode = [uiscreen currentMode];
|
||||
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
|
||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -140,19 +139,18 @@ UIKit_AddDisplay(UIScreen *uiscreen)
|
|||
display.current_mode = mode;
|
||||
|
||||
/* Allocate the display data */
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data));
|
||||
SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
|
||||
if (!data) {
|
||||
UIKit_FreeDisplayModeData(&display.desktop_mode);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
[uiscreen retain];
|
||||
data->uiscreen = uiscreen;
|
||||
data->scale = scale;
|
||||
data.uiscreen = uiscreen;
|
||||
|
||||
display.driverdata = data;
|
||||
display.driverdata = (void *) CFBridgingRetain(data);
|
||||
SDL_AddVideoDisplay(&display);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -170,11 +168,13 @@ UIKit_IsDisplayLandscape(UIScreen *uiscreen)
|
|||
int
|
||||
UIKit_InitModes(_THIS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
for (UIScreen *uiscreen in [UIScreen screens]) {
|
||||
if (UIKit_AddDisplay(uiscreen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -182,15 +182,26 @@ UIKit_InitModes(_THIS)
|
|||
void
|
||||
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
||||
{
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
@autoreleasepool {
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
|
||||
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen);
|
||||
SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]);
|
||||
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
|
||||
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
|
||||
CGFloat scale = data.uiscreen.scale;
|
||||
|
||||
for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
|
||||
CGSize size = [uimode size];
|
||||
int w = (int)size.width;
|
||||
int h = (int)size.height;
|
||||
#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 [data.uiscreen 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)) {
|
||||
|
@ -200,16 +211,7 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
|||
}
|
||||
|
||||
/* Add the native screen resolution. */
|
||||
UIKit_AddDisplayMode(display, w, h, data->scale, uimode, addRotation);
|
||||
|
||||
if (data->scale != 1.0f) {
|
||||
/* Add the native screen resolution divided by its scale.
|
||||
* This is so devices capable of e.g. 640x960 also advertise 320x480.
|
||||
*/
|
||||
UIKit_AddDisplayMode(display,
|
||||
(int)(size.width / data->scale),
|
||||
(int)(size.height / data->scale),
|
||||
1.0f, uimode, addRotation);
|
||||
UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,22 +219,24 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
|||
int
|
||||
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||
{
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
|
||||
@autoreleasepool {
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
|
||||
|
||||
[data->uiscreen setCurrentMode:modedata->uiscreenmode];
|
||||
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
|
||||
|
||||
if (data->uiscreen == [UIScreen mainScreen]) {
|
||||
if (data.uiscreen == [UIScreen mainScreen]) {
|
||||
if (mode->w > mode->h) {
|
||||
if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
|
||||
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
|
||||
}
|
||||
} else if (mode->w < mode->h) {
|
||||
if (UIKit_IsDisplayLandscape(data->uiscreen)) {
|
||||
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,6 +246,7 @@ 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];
|
||||
|
||||
|
@ -251,12 +256,13 @@ UIKit_QuitModes(_THIS)
|
|||
UIKit_FreeDisplayModeData(mode);
|
||||
}
|
||||
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
[data->uiscreen release];
|
||||
SDL_free(data);
|
||||
if (display->driverdata != NULL) {
|
||||
CFRelease(display->driverdata);
|
||||
display->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
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 void 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);
|
||||
|
|
|
@ -49,12 +49,30 @@ UIKit_GL_GetProcAddress(_THIS, const char *proc)
|
|||
/*
|
||||
note that SDL_GL_Delete context makes it current without passing the window
|
||||
*/
|
||||
int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
int
|
||||
UIKit_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
[EAGLContext setCurrentContext: context];
|
||||
@autoreleasepool {
|
||||
[EAGLContext setCurrentContext:(__bridge EAGLContext *)context];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UIKit_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
|
||||
if (w) {
|
||||
*w = data.view.backingWidth;
|
||||
}
|
||||
if (h) {
|
||||
*h = data.view.backingHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
UIKit_GL_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
|
@ -71,48 +89,60 @@ UIKit_GL_LoadLibrary(_THIS, const char *path)
|
|||
|
||||
void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
|
||||
#if SDL_POWER_UIKIT
|
||||
/* Check once a frame to see if we should turn off the battery monitor. */
|
||||
SDL_UIKit_UpdateBatteryMonitoring();
|
||||
#endif
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
|
||||
if (nil == data->view) {
|
||||
if (data.view == nil) {
|
||||
return;
|
||||
}
|
||||
[data->view swapBuffers];
|
||||
[data.view 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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
SDL_GLContext
|
||||
UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitopenglview *view;
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = display->driverdata;
|
||||
SDL_DisplayModeData *displaymodedata = display->current_mode.driverdata;
|
||||
UIWindow *uiwindow = data->uiwindow;
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
UIWindow *uiwindow = data.uiwindow;
|
||||
CGRect frame = UIKit_ComputeViewFrame(window, uiwindow.screen);
|
||||
EAGLSharegroup *share_group = nil;
|
||||
CGFloat scale = 1.0;
|
||||
|
||||
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 ([uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
|
||||
scale = uiwindow.screen.nativeScale;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
scale = uiwindow.screen.scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->gl_config.share_with_current_context) {
|
||||
SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
|
||||
share_group = [view.context sharegroup];
|
||||
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
||||
share_group = context.sharegroup;
|
||||
}
|
||||
|
||||
/* construct our view, passing in SDL's OpenGL configuration data */
|
||||
CGRect frame;
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
frame = [displaydata->uiscreen bounds];
|
||||
} else {
|
||||
frame = [displaydata->uiscreen applicationFrame];
|
||||
}
|
||||
view = [[SDL_uikitopenglview alloc] initWithFrame: frame
|
||||
scale: displaymodedata->scale
|
||||
scale: scale
|
||||
retainBacking: _this->gl_config.retained_backing
|
||||
rBits: _this->gl_config.red_size
|
||||
gBits: _this->gl_config.green_size
|
||||
|
@ -120,68 +150,105 @@ SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
|||
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
|
||||
majorVersion: _this->gl_config.major_version
|
||||
shareGroup: share_group];
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->view = view;
|
||||
view->viewcontroller = data->viewcontroller;
|
||||
if (view->viewcontroller != nil) {
|
||||
[view->viewcontroller setView:view];
|
||||
[view->viewcontroller retain];
|
||||
data.view = view;
|
||||
view.viewcontroller = data.viewcontroller;
|
||||
if (view.viewcontroller != nil) {
|
||||
view.viewcontroller.view = view;
|
||||
}
|
||||
[uiwindow addSubview: view];
|
||||
|
||||
/* The view controller needs to be the root in order to control rotation on iOS 6.0 */
|
||||
if (uiwindow.rootViewController == nil) {
|
||||
uiwindow.rootViewController = view->viewcontroller;
|
||||
uiwindow.rootViewController = view.viewcontroller;
|
||||
}
|
||||
|
||||
EAGLContext *context = view.context;
|
||||
if (UIKit_GL_MakeCurrent(_this, window, context) < 0) {
|
||||
UIKit_GL_DeleteContext(_this, context);
|
||||
if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
|
||||
UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make this window the current mouse focus for touch input */
|
||||
if (displaydata->uiscreen == [UIScreen mainScreen]) {
|
||||
if (uiwindow.screen == [UIScreen mainScreen]) {
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
|
||||
return context;
|
||||
/* We return a +1'd context. The window's driverdata owns the view. */
|
||||
return (SDL_GLContext) CFBridgingRetain(context);
|
||||
}
|
||||
}
|
||||
|
||||
void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
void
|
||||
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
/* Transfer ownership the +1'd context to ARC. */
|
||||
EAGLContext *eaglcontext = (EAGLContext *) CFBridgingRelease(context);
|
||||
SDL_Window *window;
|
||||
|
||||
/* Find the view associated with this context */
|
||||
for (window = _this->windows; window; window = window->next) {
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
SDL_uikitopenglview *view = data->view;
|
||||
if (view.context == context) {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
SDL_uikitopenglview *view = data.view;
|
||||
if (view.context == eaglcontext) {
|
||||
/* the delegate has retained the view, this will release him */
|
||||
if (view->viewcontroller) {
|
||||
if (view.viewcontroller) {
|
||||
UIWindow *uiwindow = (UIWindow *)view.superview;
|
||||
if (uiwindow.rootViewController == view->viewcontroller) {
|
||||
if (uiwindow.rootViewController == view.viewcontroller) {
|
||||
uiwindow.rootViewController = nil;
|
||||
}
|
||||
[view->viewcontroller setView:nil];
|
||||
[view->viewcontroller release];
|
||||
view.viewcontroller.view = nil;
|
||||
view.viewcontroller = nil;
|
||||
}
|
||||
[view removeFromSuperview];
|
||||
|
||||
/* FIXME: This doesn't actually call view dealloc - what is holding a reference to it? */
|
||||
[view release];
|
||||
data.view = nil;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* View not found... delete the context anyway? */
|
||||
[(EAGLContext *)context release];
|
||||
Uint32 SDL_iPhoneGetViewRenderbuffer(SDL_Window * window)
|
||||
{
|
||||
if (!window) {
|
||||
SDL_SetError("Invalid window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
if (data.view != nil) {
|
||||
return data.view.drawableRenderbuffer;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 SDL_iPhoneGetViewFramebuffer(SDL_Window * window)
|
||||
{
|
||||
if (!window) {
|
||||
SDL_SetError("Invalid window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||
if (data.view != nil) {
|
||||
return data.view.drawableFramebuffer;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
|
|
@ -21,42 +21,14 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <OpenGLES/ES1/gl.h>
|
||||
#import <OpenGLES/ES1/glext.h>
|
||||
#import <OpenGLES/gltypes.h>
|
||||
#import "SDL_uikitview.h"
|
||||
/*
|
||||
This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
|
||||
The view content is basically an EAGL surface you render your OpenGL scene into.
|
||||
Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
|
||||
*/
|
||||
@interface SDL_uikitopenglview : SDL_uikitview {
|
||||
|
||||
@private
|
||||
/* The pixel dimensions of the backbuffer */
|
||||
GLint backingWidth;
|
||||
GLint backingHeight;
|
||||
|
||||
EAGLContext *context;
|
||||
|
||||
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
|
||||
GLuint viewRenderbuffer, viewFramebuffer;
|
||||
|
||||
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
|
||||
GLuint depthRenderbuffer;
|
||||
|
||||
/* format of depthRenderbuffer */
|
||||
GLenum depthBufferFormat;
|
||||
|
||||
id displayLink;
|
||||
int animationInterval;
|
||||
void (*animationCallback)(void*);
|
||||
void *animationCallbackParam;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain, readonly) EAGLContext *context;
|
||||
|
||||
- (void)swapBuffers;
|
||||
- (void)setCurrentContext;
|
||||
@interface SDL_uikitopenglview : SDL_uikitview
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
scale:(CGFloat)scale
|
||||
|
@ -67,9 +39,22 @@
|
|||
aBits:(int)aBits
|
||||
depthBits:(int)depthBits
|
||||
stencilBits:(int)stencilBits
|
||||
sRGB:(BOOL)sRGB
|
||||
majorVersion:(int)majorVersion
|
||||
shareGroup:(EAGLSharegroup*)shareGroup;
|
||||
|
||||
@property (nonatomic, strong, readonly) 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;
|
||||
|
||||
- (void)swapBuffers;
|
||||
- (void)setCurrentContext;
|
||||
|
||||
- (void)updateFrame;
|
||||
|
||||
- (void)setAnimationCallback:(int)interval
|
||||
|
|
|
@ -24,14 +24,36 @@
|
|||
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
#include <OpenGLES/EAGLDrawable.h>
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#include "SDL_uikitopenglview.h"
|
||||
#include "SDL_uikitmessagebox.h"
|
||||
#include "SDL_uikitvideo.h"
|
||||
|
||||
|
||||
@implementation SDL_uikitopenglview
|
||||
@implementation SDL_uikitopenglview {
|
||||
|
||||
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
|
||||
GLuint viewRenderbuffer, viewFramebuffer;
|
||||
|
||||
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
|
||||
GLuint depthRenderbuffer;
|
||||
|
||||
/* format of depthRenderbuffer */
|
||||
GLenum depthBufferFormat;
|
||||
|
||||
id displayLink;
|
||||
int animationInterval;
|
||||
void (*animationCallback)(void*);
|
||||
void *animationCallbackParam;
|
||||
|
||||
}
|
||||
|
||||
@synthesize context;
|
||||
|
||||
@synthesize backingWidth;
|
||||
@synthesize backingHeight;
|
||||
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return [CAEAGLLayer class];
|
||||
|
@ -46,22 +68,38 @@
|
|||
aBits:(int)aBits
|
||||
depthBits:(int)depthBits
|
||||
stencilBits:(int)stencilBits
|
||||
sRGB:(BOOL)sRGB
|
||||
majorVersion:(int)majorVersion
|
||||
shareGroup:(EAGLSharegroup*)shareGroup
|
||||
{
|
||||
depthBufferFormat = 0;
|
||||
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
const BOOL useStencilBuffer = (stencilBits != 0);
|
||||
const BOOL useDepthBuffer = (depthBits != 0);
|
||||
NSString *colorFormat = nil;
|
||||
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.autoresizesSubviews = YES;
|
||||
|
||||
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
||||
versions, and this allows us to handle future OpenGL ES versions.
|
||||
*/
|
||||
EAGLRenderingAPI api = majorVersion;
|
||||
|
||||
if (rBits == 8 && gBits == 8 && bBits == 8) {
|
||||
context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
|
||||
if (!context || ![EAGLContext setCurrentContext:context]) {
|
||||
SDL_SetError("OpenGL ES %d not supported", majorVersion);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (sRGB) {
|
||||
/* sRGB EAGL drawable support was added in iOS 7. */
|
||||
if (UIKit_IsSystemVersionAtLeast(@"7.0")) {
|
||||
colorFormat = kEAGLColorFormatSRGBA8;
|
||||
} else {
|
||||
SDL_SetError("sRGB drawables are not supported.");
|
||||
return nil;
|
||||
}
|
||||
} else if (rBits >= 8 || gBits >= 8 || bBits >= 8) {
|
||||
/* if user specifically requests rbg888 or some color format higher than 16bpp */
|
||||
colorFormat = kEAGLColorFormatRGBA8;
|
||||
} else {
|
||||
|
@ -73,85 +111,95 @@
|
|||
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
|
||||
|
||||
eaglLayer.opaque = YES;
|
||||
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
|
||||
|
||||
context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
|
||||
if (!context || ![EAGLContext setCurrentContext:context]) {
|
||||
[self release];
|
||||
SDL_SetError("OpenGL ES %d not supported", majorVersion);
|
||||
return nil;
|
||||
}
|
||||
eaglLayer.drawableProperties = @{
|
||||
kEAGLDrawablePropertyRetainedBacking: @(retained),
|
||||
kEAGLDrawablePropertyColorFormat: colorFormat
|
||||
};
|
||||
|
||||
/* Set the appropriate scale (for retina display support) */
|
||||
self.contentScaleFactor = scale;
|
||||
|
||||
/* create the buffers */
|
||||
glGenFramebuffersOES(1, &viewFramebuffer);
|
||||
glGenRenderbuffersOES(1, &viewRenderbuffer);
|
||||
/* Create the color Renderbuffer Object */
|
||||
glGenRenderbuffers(1, &viewRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
if (![context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]) {
|
||||
SDL_SetError("Failed to create OpenGL ES drawable");
|
||||
return nil;
|
||||
}
|
||||
|
||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
|
||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
|
||||
/* 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 ((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 has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
|
||||
/* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16 */
|
||||
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
|
||||
}
|
||||
|
||||
glGenRenderbuffersOES(1, &depthRenderbuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
|
||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
|
||||
glGenRenderbuffers(1, &depthRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||
if (useDepthBuffer) {
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
|
||||
}
|
||||
if (useStencilBuffer) {
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
|
||||
return NO;
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
SDL_SetError("Failed creating OpenGL ES framebuffer");
|
||||
return nil;
|
||||
}
|
||||
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
/* end create buffers */
|
||||
|
||||
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
|
||||
self.autoresizesSubviews = YES;
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GLuint)drawableRenderbuffer
|
||||
{
|
||||
return viewRenderbuffer;
|
||||
}
|
||||
|
||||
- (GLuint)drawableFramebuffer
|
||||
{
|
||||
return viewFramebuffer;
|
||||
}
|
||||
|
||||
- (void)updateFrame
|
||||
{
|
||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0);
|
||||
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
|
||||
glDeleteRenderbuffers(1, &viewRenderbuffer);
|
||||
|
||||
glGenRenderbuffersOES(1, &viewRenderbuffer);
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
|
||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
glGenRenderbuffers(1, &viewRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
|
||||
|
||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
|
||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
||||
|
||||
if (depthRenderbuffer != 0) {
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
|
||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||
}
|
||||
|
||||
- (void)setAnimationCallback:(int)interval
|
||||
|
@ -164,9 +212,10 @@
|
|||
animationCallback = callback;
|
||||
animationCallbackParam = callbackParam;
|
||||
|
||||
if (animationCallback)
|
||||
if (animationCallback) {
|
||||
[self startAnimation];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startAnimation
|
||||
{
|
||||
|
@ -194,31 +243,36 @@
|
|||
[EAGLContext setCurrentContext:context];
|
||||
}
|
||||
|
||||
|
||||
- (void)swapBuffers
|
||||
{
|
||||
/* 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_OES];
|
||||
else is responsible for rebinding viewRenderbuffer, to reduce duplicate
|
||||
state changes. */
|
||||
[context presentRenderbuffer:GL_RENDERBUFFER];
|
||||
}
|
||||
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
[EAGLContext setCurrentContext:context];
|
||||
[self updateFrame];
|
||||
}
|
||||
|
||||
- (void)destroyFramebuffer
|
||||
{
|
||||
glDeleteFramebuffersOES(1, &viewFramebuffer);
|
||||
if (viewFramebuffer != 0) {
|
||||
glDeleteFramebuffers(1, &viewFramebuffer);
|
||||
viewFramebuffer = 0;
|
||||
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
|
||||
viewRenderbuffer = 0;
|
||||
}
|
||||
|
||||
if (depthRenderbuffer) {
|
||||
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
|
||||
if (viewRenderbuffer != 0) {
|
||||
glDeleteRenderbuffers(1, &viewRenderbuffer);
|
||||
viewRenderbuffer = 0;
|
||||
}
|
||||
|
||||
if (depthRenderbuffer != 0) {
|
||||
glDeleteRenderbuffers(1, &depthRenderbuffer);
|
||||
depthRenderbuffer = 0;
|
||||
}
|
||||
}
|
||||
|
@ -226,12 +280,10 @@
|
|||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self destroyFramebuffer];
|
||||
if ([EAGLContext currentContext] == context) {
|
||||
[self destroyFramebuffer];
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
[context release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -25,20 +25,8 @@
|
|||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#ifndef __IPHONE_6_0
|
||||
/* This enum isn't available in older SDKs, but we use it for our own purposes on iOS 5.1 and for the system on iOS 6.0 */
|
||||
enum UIInterfaceOrientationMask
|
||||
{
|
||||
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
|
||||
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
|
||||
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
|
||||
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
|
||||
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
|
||||
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
|
||||
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
|
||||
};
|
||||
#endif /* !__IPHONE_6_0 */
|
||||
|
||||
BOOL UIKit_IsSystemVersionAtLeast(NSString *version);
|
||||
CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
|
||||
|
||||
#endif /* _SDL_uikitvideo_h */
|
||||
|
||||
|
|
|
@ -78,12 +78,11 @@ UIKit_CreateDevice(int devindex)
|
|||
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;
|
||||
|
||||
/* !!! FIXME: implement SetWindowBordered */
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
|
||||
device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
|
||||
|
@ -94,6 +93,7 @@ UIKit_CreateDevice(int devindex)
|
|||
|
||||
/* 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;
|
||||
|
@ -129,6 +129,26 @@ UIKit_VideoQuit(_THIS)
|
|||
UIKit_QuitModes(_this);
|
||||
}
|
||||
|
||||
BOOL
|
||||
UIKit_IsSystemVersionAtLeast(NSString *version)
|
||||
{
|
||||
NSString *sysversion = [UIDevice currentDevice].systemVersion;
|
||||
return [sysversion compare:version options:NSNumericSearch] != NSOrderedAscending;
|
||||
}
|
||||
|
||||
CGRect
|
||||
UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
|
||||
{
|
||||
BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(@"7.0");
|
||||
|
||||
if (hasiOS7 || (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN))) {
|
||||
/* The view should always show behind the status bar in iOS 7+. */
|
||||
return screen.bounds;
|
||||
} else {
|
||||
return screen.applicationFrame;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* iOS log support.
|
||||
*
|
||||
|
|
|
@ -24,34 +24,14 @@
|
|||
|
||||
#include "SDL_touch.h"
|
||||
|
||||
#define IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
|
||||
#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
#define MAX_SIMULTANEOUS_TOUCHES 5
|
||||
#endif
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
@interface SDL_uikitview : UIView<UITextFieldDelegate> {
|
||||
@interface SDL_uikitview : UIView <UITextFieldDelegate>
|
||||
#else
|
||||
@interface SDL_uikitview : UIView {
|
||||
@interface SDL_uikitview : UIView
|
||||
#endif
|
||||
|
||||
SDL_TouchID touchId;
|
||||
UITouch *leftFingerDown;
|
||||
#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
UITouch *finger[MAX_SIMULTANEOUS_TOUCHES];
|
||||
#endif
|
||||
@property (nonatomic, weak) SDL_uikitviewcontroller *viewcontroller;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
UITextField *textField;
|
||||
BOOL keyboardVisible;
|
||||
SDL_Rect textInputRect;
|
||||
int keyboardHeight;
|
||||
#endif
|
||||
|
||||
@public
|
||||
SDL_uikitviewcontroller *viewcontroller;
|
||||
}
|
||||
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize;
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
|
@ -61,7 +41,8 @@
|
|||
- (void)showKeyboard;
|
||||
- (void)hideKeyboard;
|
||||
- (void)initializeKeyboard;
|
||||
@property (readonly) BOOL keyboardVisible;
|
||||
|
||||
@property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible;
|
||||
@property (nonatomic, assign) SDL_Rect textInputRect;
|
||||
@property (nonatomic, assign) int keyboardHeight;
|
||||
|
||||
|
|
|
@ -37,17 +37,22 @@
|
|||
|
||||
void _uikit_keyboard_init();
|
||||
|
||||
@implementation SDL_uikitview
|
||||
@implementation SDL_uikitview {
|
||||
|
||||
SDL_TouchID touchId;
|
||||
UITouch *leftFingerDown;
|
||||
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
UITextField *textField;
|
||||
#endif
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@synthesize viewcontroller;
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame: frame];
|
||||
|
||||
if (self = [super initWithFrame: frame]) {
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
[self initializeKeyboard];
|
||||
#endif
|
||||
|
@ -56,6 +61,7 @@ void _uikit_keyboard_init() ;
|
|||
|
||||
touchId = 1;
|
||||
SDL_AddTouch(touchId, "");
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
|
@ -65,91 +71,48 @@ void _uikit_keyboard_init() ;
|
|||
{
|
||||
CGPoint point = [touch locationInView: self];
|
||||
|
||||
/* Get the display scale and apply that to the input coordinates */
|
||||
SDL_Window *window = self->viewcontroller.window;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
|
||||
if (normalize) {
|
||||
CGRect bounds = [self bounds];
|
||||
CGRect bounds = self.bounds;
|
||||
point.x /= bounds.size.width;
|
||||
point.y /= bounds.size.height;
|
||||
} else {
|
||||
point.x *= displaymodedata->scale;
|
||||
point.y *= displaymodedata->scale;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while (touch) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (!leftFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
/* send moved event */
|
||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
SDL_SendMouseMotion(self.viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
|
||||
/* send mouse down event */
|
||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||
SDL_SendMouseButton(self.viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||
|
||||
leftFingerDown = touch;
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
/* FIXME: TODO: Using touch as the fingerId is potentially dangerous
|
||||
* It is also much more efficient than storing the UITouch pointer
|
||||
* and comparing it to the incoming event.
|
||||
*/
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == NULL) {
|
||||
finger[i] = touch;
|
||||
SDL_SendTouch(touchId, i,
|
||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while(touch) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch == leftFingerDown) {
|
||||
/* send mouse up */
|
||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
SDL_SendMouseButton(self.viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
leftFingerDown = nil;
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
SDL_SendTouch(touchId, (long)touch,
|
||||
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == touch) {
|
||||
SDL_SendTouch(touchId, i,
|
||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
||||
finger[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,32 +128,17 @@ void _uikit_keyboard_init() ;
|
|||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
||||
|
||||
while (touch) {
|
||||
for (UITouch *touch in touches) {
|
||||
if (touch == leftFingerDown) {
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||
|
||||
/* send moved event */
|
||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
SDL_SendMouseMotion(self.viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||
}
|
||||
|
||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
||||
SDL_SendTouchMotion(touchId, (long)touch,
|
||||
SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
|
||||
locationInView.x, locationInView.y, 1.0f);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
|
||||
if (finger[i] == touch) {
|
||||
SDL_SendTouchMotion(touchId, i,
|
||||
locationInView.x, locationInView.y, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
touch = (UITouch*)[enumerator nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,14 +147,9 @@ void _uikit_keyboard_init() ;
|
|||
*/
|
||||
#if SDL_IPHONE_KEYBOARD
|
||||
|
||||
@synthesize textInputRect = textInputRect;
|
||||
@synthesize keyboardHeight = keyboardHeight;
|
||||
|
||||
/* Is the iPhone virtual keyboard visible onscreen? */
|
||||
- (BOOL)keyboardVisible
|
||||
{
|
||||
return keyboardVisible;
|
||||
}
|
||||
@synthesize textInputRect;
|
||||
@synthesize keyboardHeight;
|
||||
@synthesize keyboardVisible;
|
||||
|
||||
/* Set ourselves up as a UITextFieldDelegate */
|
||||
- (void)initializeKeyboard
|
||||
|
@ -229,7 +172,6 @@ void _uikit_keyboard_init() ;
|
|||
keyboardVisible = NO;
|
||||
/* add the UITextField (hidden) to our view */
|
||||
[self addSubview: textField];
|
||||
[textField release];
|
||||
|
||||
_uikit_keyboard_init();
|
||||
}
|
||||
|
@ -318,8 +260,8 @@ static SDL_uikitview * getWindowView(SDL_Window * window)
|
|||
return nil;
|
||||
}
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = data != NULL ? data->view : nil;
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
SDL_uikitview *view = data != nil ? data.view : nil;
|
||||
|
||||
if (view == nil) {
|
||||
SDL_SetError("Window has no view");
|
||||
|
@ -335,44 +277,49 @@ SDL_bool UIKit_HasScreenKeyboardSupport(_THIS)
|
|||
|
||||
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view != nil) {
|
||||
[view showKeyboard];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view != nil) {
|
||||
[view hideKeyboard];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_uikitview *view = getWindowView(window);
|
||||
if (view == nil) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return view.keyboardVisible;
|
||||
return view.isKeyboardVisible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _uikit_keyboard_update() {
|
||||
SDL_Window *window = SDL_GetFocusWindow();
|
||||
if (!window) { return; }
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||
if (!data) { return; }
|
||||
SDL_uikitview *view = data->view;
|
||||
SDL_uikitview *view = data.view;
|
||||
if (!view) { return; }
|
||||
|
||||
SDL_Rect r = view.textInputRect;
|
||||
int height = view.keyboardHeight;
|
||||
int offsetx = 0;
|
||||
int offsety = 0;
|
||||
float scale = [UIScreen mainScreen].scale;
|
||||
if (height) {
|
||||
int sw,sh;
|
||||
SDL_GetWindowSize(window,&sw,&sh);
|
||||
|
@ -394,9 +341,6 @@ void _uikit_keyboard_update() {
|
|||
offsety = -offsety;
|
||||
}
|
||||
|
||||
offsetx /= scale;
|
||||
offsety /= scale;
|
||||
|
||||
view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
|
||||
}
|
||||
|
||||
|
@ -406,6 +350,7 @@ void _uikit_keyboard_set_height(int height) {
|
|||
return;
|
||||
}
|
||||
|
||||
view.keyboardVisible = height > 0;
|
||||
view.keyboardHeight = height;
|
||||
_uikit_keyboard_update();
|
||||
}
|
||||
|
@ -418,13 +363,12 @@ void _uikit_keyboard_init() {
|
|||
queue:queue
|
||||
usingBlock:^(NSNotification *notification) {
|
||||
int height = 0;
|
||||
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
|
||||
CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
|
||||
height = keyboardSize.height;
|
||||
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
|
||||
height = keyboardSize.width;
|
||||
}
|
||||
height *= [UIScreen mainScreen].scale;
|
||||
_uikit_keyboard_set_height(height);
|
||||
}
|
||||
];
|
||||
|
@ -445,6 +389,7 @@ UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
|
|||
return;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
|
||||
if (view == nil) {
|
||||
return;
|
||||
|
@ -452,6 +397,7 @@ UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
|
|||
|
||||
view.textInputRect = *rect;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_IPHONE_KEYBOARD */
|
||||
|
|
|
@ -23,12 +23,9 @@
|
|||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
@interface SDL_uikitviewcontroller : UIViewController {
|
||||
@private
|
||||
SDL_Window *window;
|
||||
}
|
||||
@interface SDL_uikitviewcontroller : UIViewController
|
||||
|
||||
@property (readwrite) SDL_Window *window;
|
||||
@property (nonatomic, assign) SDL_Window *window;
|
||||
|
||||
- (id)initWithSDLWindow:(SDL_Window *)_window;
|
||||
- (void)loadView;
|
||||
|
@ -36,5 +33,6 @@
|
|||
- (NSUInteger)supportedInterfaceOrientations;
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
|
||||
- (BOOL)prefersStatusBarHidden;
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle;
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,12 +40,9 @@
|
|||
|
||||
- (id)initWithSDLWindow:(SDL_Window *)_window
|
||||
{
|
||||
self = [self init];
|
||||
if (self == nil) {
|
||||
return nil;
|
||||
}
|
||||
if (self = [super initWithNibName:nil bundle:nil]) {
|
||||
self.window = _window;
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -56,31 +53,20 @@
|
|||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
if (self->window->flags & SDL_WINDOW_RESIZABLE) {
|
||||
SDL_WindowData *data = self->window->driverdata;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(self->window);
|
||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
const CGSize size = data->view.bounds.size;
|
||||
int w, h;
|
||||
const CGSize size = self.view.bounds.size;
|
||||
int w = (int) size.width;
|
||||
int h = (int) size.height;
|
||||
|
||||
w = (int)(size.width * displaymodedata->scale);
|
||||
h = (int)(size.height * displaymodedata->scale);
|
||||
|
||||
SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
NSUInteger orientationMask = 0;
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
|
||||
|
||||
const char *orientationsCString;
|
||||
if ((orientationsCString = SDL_GetHint(SDL_HINT_ORIENTATIONS)) != NULL) {
|
||||
BOOL rotate = NO;
|
||||
NSString *orientationsNSString = [NSString stringWithCString:orientationsCString
|
||||
encoding:NSUTF8StringEncoding];
|
||||
NSArray *orientations = [orientationsNSString componentsSeparatedByCharactersInSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString:@" "]];
|
||||
if (hint != NULL) {
|
||||
NSArray *orientations = [@(hint) componentsSeparatedByString:@" "];
|
||||
|
||||
if ([orientations containsObject:@"LandscapeLeft"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskLandscapeLeft;
|
||||
|
@ -94,14 +80,17 @@
|
|||
if ([orientations containsObject:@"PortraitUpsideDown"]) {
|
||||
orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (self->window->flags & SDL_WINDOW_RESIZABLE) {
|
||||
if (orientationMask == 0 && (window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
orientationMask = UIInterfaceOrientationMaskAll; /* any orientation is okay. */
|
||||
} else {
|
||||
if (self->window->w >= self->window->h) {
|
||||
}
|
||||
|
||||
if (orientationMask == 0) {
|
||||
if (window->w >= window->h) {
|
||||
orientationMask |= UIInterfaceOrientationMaskLandscape;
|
||||
}
|
||||
if (self->window->h >= self->window->w) {
|
||||
if (window->h >= window->w) {
|
||||
orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
|
||||
}
|
||||
}
|
||||
|
@ -121,13 +110,19 @@
|
|||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
if (self->window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
/* We assume most games don't have a bright white background. */
|
||||
return UIStatusBarStyleLightContent;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
|
|
@ -26,12 +26,11 @@
|
|||
#import "SDL_uikitopenglview.h"
|
||||
#import "SDL_uikitviewcontroller.h"
|
||||
|
||||
typedef struct SDL_WindowData SDL_WindowData;
|
||||
|
||||
extern int UIKit_CreateWindow(_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,
|
||||
|
@ -39,12 +38,17 @@ extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
|
|||
|
||||
@class UIWindow;
|
||||
|
||||
struct SDL_WindowData
|
||||
{
|
||||
UIWindow *uiwindow;
|
||||
SDL_uikitopenglview *view;
|
||||
SDL_uikitviewcontroller *viewcontroller;
|
||||
};
|
||||
@interface SDL_uikitwindow : UIWindow
|
||||
|
||||
@end
|
||||
|
||||
@interface SDL_WindowData : NSObject
|
||||
|
||||
@property (nonatomic, strong) SDL_uikitwindow *uiwindow;
|
||||
@property (nonatomic, strong) SDL_uikitopenglview *view;
|
||||
@property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* _SDL_uikitwindow_h */
|
||||
|
||||
|
|
|
@ -41,43 +41,56 @@
|
|||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
@implementation SDL_uikitwindow
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
/* This seems to be needed on iOS 8, otherwise the window's frame is put in
|
||||
* an unexpected position when the screen or device is rotated.
|
||||
* FIXME: is there a better solution to that problem than this ugly hack?
|
||||
*/
|
||||
self.frame = self.screen.bounds;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDL_WindowData
|
||||
|
||||
@synthesize uiwindow;
|
||||
@synthesize view;
|
||||
@synthesize viewcontroller;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
|
||||
static int SetupWindowData(_THIS, SDL_Window *window, SDL_uikitwindow *uiwindow, SDL_bool created)
|
||||
{
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
||||
SDL_WindowData *data;
|
||||
SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
|
||||
/* Allocate the window data */
|
||||
data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
|
||||
SDL_WindowData *data = [[SDL_WindowData alloc] init];
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
data->uiwindow = uiwindow;
|
||||
data->viewcontroller = nil;
|
||||
data->view = nil;
|
||||
|
||||
data.uiwindow = uiwindow;
|
||||
|
||||
/* Fill in the SDL window with the window data */
|
||||
{
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
|
||||
CGRect bounds;
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
bounds = [displaydata->uiscreen bounds];
|
||||
} else {
|
||||
bounds = [displaydata->uiscreen applicationFrame];
|
||||
}
|
||||
CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen);
|
||||
|
||||
/* Get frame dimensions in pixels */
|
||||
int width = (int)(bounds.size.width * displaymodedata->scale);
|
||||
int height = (int)(bounds.size.height * displaymodedata->scale);
|
||||
/* Get frame dimensions */
|
||||
int width = (int) frame.size.width;
|
||||
int height = (int) frame.size.height;
|
||||
|
||||
/* Make sure the width/height are oriented correctly */
|
||||
if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
|
||||
if (UIKit_IsDisplayLandscape(displaydata.uiscreen) != (width > height)) {
|
||||
int temp = width;
|
||||
width = height;
|
||||
height = temp;
|
||||
|
@ -87,7 +100,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
|||
window->h = height;
|
||||
}
|
||||
|
||||
window->driverdata = data;
|
||||
window->driverdata = (void *) CFBridgingRetain(data);
|
||||
|
||||
/* only one window on iOS, always shown */
|
||||
window->flags &= ~SDL_WINDOW_HIDDEN;
|
||||
|
@ -96,7 +109,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
|||
* This is only set if the window is on the main screen. Other screens
|
||||
* just force the window to have the borderless flag.
|
||||
*/
|
||||
if (displaydata->uiscreen == [UIScreen mainScreen]) {
|
||||
if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
||||
window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
|
||||
|
||||
/* This was setup earlier for our window, and in iOS 7 is controlled by the view, not the application
|
||||
|
@ -116,10 +129,8 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
|||
* device orientation changes. This will trigger resize events, if
|
||||
* appropriate.
|
||||
*/
|
||||
SDL_uikitviewcontroller *controller;
|
||||
controller = [SDL_uikitviewcontroller alloc];
|
||||
data->viewcontroller = [controller initWithSDLWindow:window];
|
||||
[data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */
|
||||
data.viewcontroller = [[SDL_uikitviewcontroller alloc] initWithSDLWindow:window];
|
||||
data.viewcontroller.title = @"SDL App"; /* !!! FIXME: hook up SDL_SetWindowTitle() */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -127,10 +138,11 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
|||
int
|
||||
UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
||||
const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
|
||||
const CGSize origsize = [[data->uiscreen currentMode] size];
|
||||
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||
const BOOL external = ([UIScreen mainScreen] != data.uiscreen);
|
||||
const CGSize origsize = [[data.uiscreen currentMode] size];
|
||||
|
||||
/* SDL currently puts this window at the start of display's linked list. We rely on this. */
|
||||
SDL_assert(_this->windows == window);
|
||||
|
@ -158,8 +170,8 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
|
||||
if (bestmode) {
|
||||
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
|
||||
[data->uiscreen setCurrentMode:modedata->uiscreenmode];
|
||||
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
|
||||
|
@ -169,7 +181,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
}
|
||||
|
||||
if (data->uiscreen == [UIScreen mainScreen]) {
|
||||
if (data.uiscreen == [UIScreen mainScreen]) {
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||
} else {
|
||||
|
@ -179,11 +191,11 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|||
|
||||
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
if (window->w > window->h) {
|
||||
if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
|
||||
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
|
||||
}
|
||||
} else if (window->w < window->h) {
|
||||
if (UIKit_IsDisplayLandscape(data->uiscreen)) {
|
||||
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
|
||||
}
|
||||
}
|
||||
|
@ -191,8 +203,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|||
|
||||
/* ignore the size user requested, and make a fullscreen window */
|
||||
/* !!! FIXME: can we have a smaller view? */
|
||||
UIWindow *uiwindow = [UIWindow alloc];
|
||||
uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
|
||||
SDL_uikitwindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data.uiscreen.bounds];
|
||||
|
||||
/* put the window on an external display if appropriate. This implicitly
|
||||
* does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
|
||||
|
@ -200,33 +211,37 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
|||
* status bar real estate.
|
||||
*/
|
||||
if (external) {
|
||||
[uiwindow setScreen:data->uiscreen];
|
||||
[uiwindow setScreen:data.uiscreen];
|
||||
}
|
||||
|
||||
if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
||||
[uiwindow release];
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_ShowWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
||||
@autoreleasepool {
|
||||
UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow;
|
||||
|
||||
[uiwindow makeKeyAndVisible];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_HideWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
||||
@autoreleasepool {
|
||||
UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow;
|
||||
|
||||
uiwindow.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_RaiseWindow(_THIS, SDL_Window * window)
|
||||
|
@ -239,69 +254,80 @@ UIKit_RaiseWindow(_THIS, SDL_Window * window)
|
|||
_this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
|
||||
}
|
||||
|
||||
void
|
||||
UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||
static void
|
||||
UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
||||
SDL_WindowData *windowdata = (__bridge SDL_WindowData *) window->driverdata;
|
||||
SDL_uikitviewcontroller *viewcontroller = windowdata.viewcontroller;
|
||||
CGRect frame;
|
||||
|
||||
if (fullscreen) {
|
||||
if (windowdata.uiwindow.screen == [UIScreen mainScreen]) {
|
||||
if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) {
|
||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||
} else {
|
||||
[UIApplication sharedApplication].statusBarHidden = NO;
|
||||
}
|
||||
|
||||
CGRect bounds;
|
||||
if (fullscreen) {
|
||||
bounds = [displaydata->uiscreen bounds];
|
||||
} else {
|
||||
bounds = [displaydata->uiscreen applicationFrame];
|
||||
/* iOS 7+ won't update the status bar until we tell it to. */
|
||||
if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
|
||||
[viewcontroller setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
/* Get frame dimensions in pixels */
|
||||
int width = (int)(bounds.size.width * displaymodedata->scale);
|
||||
int height = (int)(bounds.size.height * displaymodedata->scale);
|
||||
/* Update the view's frame to account for the status bar change. */
|
||||
frame = UIKit_ComputeViewFrame(window, windowdata.uiwindow.screen);
|
||||
|
||||
windowdata.view.frame = frame;
|
||||
[windowdata.view setNeedsLayout];
|
||||
[windowdata.view layoutIfNeeded];
|
||||
|
||||
/* Get frame dimensions */
|
||||
int width = (int) frame.size.width;
|
||||
int height = (int) frame.size.height;
|
||||
|
||||
/* We can pick either width or height here and we'll rotate the
|
||||
screen to match, so we pick the closest to what we wanted.
|
||||
*/
|
||||
if (window->w >= window->h) {
|
||||
if (width > height) {
|
||||
window->w = width;
|
||||
window->h = height;
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_max(width, height), SDL_min(width, height));
|
||||
} else {
|
||||
window->w = height;
|
||||
window->h = width;
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, SDL_min(width, height), SDL_max(width, height));
|
||||
}
|
||||
} else {
|
||||
if (width > height) {
|
||||
window->w = height;
|
||||
window->h = width;
|
||||
} else {
|
||||
window->w = width;
|
||||
window->h = height;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||
|
||||
if (data) {
|
||||
[data->viewcontroller release];
|
||||
[data->uiwindow release];
|
||||
SDL_free(data);
|
||||
@autoreleasepool {
|
||||
if (window->driverdata != NULL) {
|
||||
CFRelease(window->driverdata);
|
||||
}
|
||||
}
|
||||
|
||||
window->driverdata = NULL;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
||||
@autoreleasepool {
|
||||
UIWindow *uiwindow = ((__bridge SDL_WindowData *) window->driverdata).uiwindow;
|
||||
|
||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||
info->subsystem = SDL_SYSWM_UIKIT;
|
||||
|
@ -313,17 +339,21 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
|
||||
{
|
||||
SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
|
||||
@autoreleasepool {
|
||||
SDL_WindowData *data = window ? (__bridge SDL_WindowData *)window->driverdata : nil;
|
||||
|
||||
if (!data || !data->view) {
|
||||
if (!data || !data.view) {
|
||||
return SDL_SetError("Invalid window or view not set");
|
||||
}
|
||||
|
||||
[data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
|
||||
[data.view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue