Merged default into iOS-improvements
commit
df98b11c47
|
@ -8,6 +8,9 @@ Makefile
|
||||||
sdl-config
|
sdl-config
|
||||||
SDL2.spec
|
SDL2.spec
|
||||||
build
|
build
|
||||||
|
Build
|
||||||
|
*xcuserdata*
|
||||||
|
*xcworkspacedata*
|
||||||
|
|
||||||
# for Xcode
|
# for Xcode
|
||||||
*.orig
|
*.orig
|
||||||
|
|
|
@ -387,6 +387,9 @@ main(int argc, char *argv[])
|
||||||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
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 */
|
/* create main window and renderer */
|
||||||
window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
|
window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||||
SDL_WINDOW_OPENGL |
|
SDL_WINDOW_OPENGL |
|
||||||
|
|
|
@ -1274,8 +1274,14 @@
|
||||||
FD6526640DE8FCCB002AD96B /* Debug */ = {
|
FD6526640DE8FCCB002AD96B /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
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;
|
PRODUCT_NAME = SDL2;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
};
|
};
|
||||||
|
@ -1284,8 +1290,14 @@
|
||||||
FD6526650DE8FCCB002AD96B /* Release */ = {
|
FD6526650DE8FCCB002AD96B /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
|
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;
|
PRODUCT_NAME = SDL2;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
};
|
};
|
||||||
|
|
|
@ -145,6 +145,9 @@
|
||||||
/* enable iPhone keyboard support */
|
/* enable iPhone keyboard support */
|
||||||
#define SDL_IPHONE_KEYBOARD 1
|
#define SDL_IPHONE_KEYBOARD 1
|
||||||
|
|
||||||
|
/* enable iOS extended launch screen */
|
||||||
|
#define SDL_IPHONE_LAUNCHSCREEN 1
|
||||||
|
|
||||||
/* enable joystick subsystem */
|
/* enable joystick subsystem */
|
||||||
#define SDL_JOYSTICK_DISABLED 0
|
#define SDL_JOYSTICK_DISABLED 0
|
||||||
|
|
||||||
|
|
|
@ -261,8 +261,9 @@ extern "C" {
|
||||||
#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
|
#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A variable controlling whether an Android built-in accelerometer should be
|
* \brief A variable controlling whether the Android / iOS built-in
|
||||||
* listed as a joystick device, rather than listing actual joysticks only.
|
* accelerometer should be listed as a joystick device, rather than listing
|
||||||
|
* actual joysticks only.
|
||||||
*
|
*
|
||||||
* This variable can be set to the following values:
|
* This variable can be set to the following values:
|
||||||
* "0" - List only real joysticks and accept input from them
|
* "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"
|
#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,20 @@ 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 int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
|
||||||
extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
|
extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief 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__ */
|
#endif /* __IPHONEOS__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,9 @@
|
||||||
#ifndef SDL_IPHONE_KEYBOARD
|
#ifndef SDL_IPHONE_KEYBOARD
|
||||||
#define SDL_IPHONE_KEYBOARD 1
|
#define SDL_IPHONE_KEYBOARD 1
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SDL_IPHONE_LAUNCHSCREEN
|
||||||
|
#define SDL_IPHONE_LAUNCHSCREEN 1
|
||||||
|
#endif
|
||||||
#ifndef SDL_POWER_UIKIT
|
#ifndef SDL_POWER_UIKIT
|
||||||
#define SDL_POWER_UIKIT 1
|
#define SDL_POWER_UIKIT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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];
|
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fp = fopen(file, mode);
|
fp = fopen(file, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* __MACOSX__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* 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* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||||
const char *base = NULL;
|
const char *base = NULL;
|
||||||
char *retval = NULL;
|
char *retval = NULL;
|
||||||
|
|
||||||
if (baseType == NULL) {
|
if (baseType == NULL) {
|
||||||
baseType = "resource";
|
baseType = "resource";
|
||||||
}
|
}
|
||||||
|
@ -52,6 +53,7 @@ SDL_GetBasePath(void)
|
||||||
/* this returns the exedir for non-bundled and the resourceDir for bundled apps */
|
/* this returns the exedir for non-bundled and the resourceDir for bundled apps */
|
||||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base) {
|
if (base) {
|
||||||
const size_t len = SDL_strlen(base) + 2;
|
const size_t len = SDL_strlen(base) + 2;
|
||||||
retval = (char *) SDL_malloc(len);
|
retval = (char *) SDL_malloc(len);
|
||||||
|
@ -69,9 +71,10 @@ char *
|
||||||
SDL_GetPrefPath(const char *org, const char *app)
|
SDL_GetPrefPath(const char *org, const char *app)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
|
||||||
char *retval = NULL;
|
char *retval = NULL;
|
||||||
|
|
||||||
|
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||||
|
|
||||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||||
NSString *str = [array objectAtIndex:0];
|
NSString *str = [array objectAtIndex:0];
|
||||||
const char *base = [str fileSystemRepresentation];
|
const char *base = [str fileSystemRepresentation];
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
/* This is the iOS implementation of the SDL joystick API */
|
/* This is the iOS implementation of the SDL joystick API */
|
||||||
|
|
||||||
#include "SDL_joystick.h"
|
#include "SDL_joystick.h"
|
||||||
|
#include "SDL_hints.h"
|
||||||
#include "SDL_stdinc.h"
|
#include "SDL_stdinc.h"
|
||||||
#include "../SDL_sysjoystick.h"
|
#include "../SDL_sysjoystick.h"
|
||||||
#include "../SDL_joystick_c.h"
|
#include "../SDL_joystick_c.h"
|
||||||
|
@ -32,9 +33,10 @@
|
||||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||||
#import "SDL_config_iphoneos.h"
|
#import "SDL_config_iphoneos.h"
|
||||||
|
|
||||||
const char *accelerometerName = "iOS accelerometer";
|
const char *accelerometerName = "iOS Accelerometer";
|
||||||
|
|
||||||
static CMMotionManager *motionManager = nil;
|
static CMMotionManager *motionManager = nil;
|
||||||
|
static int numjoysticks = 0;
|
||||||
|
|
||||||
/* Function to scan the system for joysticks.
|
/* Function to scan the system for joysticks.
|
||||||
* Joystick 0 should be the system default joystick.
|
* Joystick 0 should be the system default joystick.
|
||||||
|
@ -43,12 +45,18 @@ static CMMotionManager *motionManager = nil;
|
||||||
int
|
int
|
||||||
SDL_SYS_JoystickInit(void)
|
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()
|
int SDL_SYS_NumJoysticks()
|
||||||
{
|
{
|
||||||
return 1;
|
return numjoysticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SYS_JoystickDetect()
|
void SDL_SYS_JoystickDetect()
|
||||||
|
@ -81,6 +89,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||||
joystick->nballs = 0;
|
joystick->nballs = 0;
|
||||||
joystick->nbuttons = 0;
|
joystick->nbuttons = 0;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
if (motionManager == nil) {
|
if (motionManager == nil) {
|
||||||
motionManager = [[CMMotionManager alloc] init];
|
motionManager = [[CMMotionManager alloc] init];
|
||||||
}
|
}
|
||||||
|
@ -88,6 +97,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||||
/* Shorter times between updates can significantly increase CPU usage. */
|
/* Shorter times between updates can significantly increase CPU usage. */
|
||||||
motionManager.accelerometerUpdateInterval = 0.1;
|
motionManager.accelerometerUpdateInterval = 0.1;
|
||||||
[motionManager startAccelerometerUpdates];
|
[motionManager startAccelerometerUpdates];
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -104,11 +114,13 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||||
const SInt16 maxsint16 = 0x7FFF;
|
const SInt16 maxsint16 = 0x7FFF;
|
||||||
CMAcceleration accel;
|
CMAcceleration accel;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
if (!motionManager.accelerometerActive) {
|
if (!motionManager.accelerometerActive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
accel = [[motionManager accelerometerData] acceleration];
|
accel = motionManager.accelerometerData.acceleration;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert accelerometer data from floating point to Sint16, which is what
|
Convert accelerometer data from floating point to Sint16, which is what
|
||||||
|
@ -152,17 +164,20 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||||
void
|
void
|
||||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
[motionManager stopAccelerometerUpdates];
|
[motionManager stopAccelerometerUpdates];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function to perform any system-specific joystick related cleanup */
|
/* Function to perform any system-specific joystick related cleanup */
|
||||||
void
|
void
|
||||||
SDL_SYS_JoystickQuit(void)
|
SDL_SYS_JoystickQuit(void)
|
||||||
{
|
{
|
||||||
if (motionManager != nil) {
|
@autoreleasepool {
|
||||||
[motionManager release];
|
|
||||||
motionManager = nil;
|
motionManager = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numjoysticks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||||
|
|
|
@ -50,11 +50,12 @@ SDL_UIKit_UpdateBatteryMonitoring(void)
|
||||||
SDL_bool
|
SDL_bool
|
||||||
SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
UIDevice *uidev = [UIDevice currentDevice];
|
UIDevice *uidev = [UIDevice currentDevice];
|
||||||
|
|
||||||
if (!SDL_UIKitLastPowerInfoQuery) {
|
if (!SDL_UIKitLastPowerInfoQuery) {
|
||||||
SDL_assert([uidev isBatteryMonitoringEnabled] == NO);
|
SDL_assert(uidev.isBatteryMonitoringEnabled == NO);
|
||||||
[uidev setBatteryMonitoringEnabled:YES];
|
uidev.batteryMonitoringEnabled = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UIKit_GL_SwapWindow() (etc) will check this and disable the battery
|
/* 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. */
|
*seconds = -1; /* no API to estimate this in UIKit. */
|
||||||
|
|
||||||
switch ([uidev batteryState])
|
switch (uidev.batteryState) {
|
||||||
{
|
|
||||||
case UIDeviceBatteryStateCharging:
|
case UIDeviceBatteryStateCharging:
|
||||||
*state = SDL_POWERSTATE_CHARGING;
|
*state = SDL_POWERSTATE_CHARGING;
|
||||||
break;
|
break;
|
||||||
|
@ -86,9 +86,10 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float level = [uidev batteryLevel];
|
const float level = uidev.batteryLevel;
|
||||||
*percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
|
*percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
|
||||||
return SDL_TRUE; /* always the definitive answer on iOS. */
|
return SDL_TRUE; /* always the definitive answer on iOS. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_POWER_UIKIT */
|
#endif /* SDL_POWER_UIKIT */
|
||||||
|
|
|
@ -55,6 +55,7 @@ static const float inv255f = 1.0f / 255.0f;
|
||||||
static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
|
static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
|
||||||
static void GLES_WindowEvent(SDL_Renderer * renderer,
|
static void GLES_WindowEvent(SDL_Renderer * renderer,
|
||||||
const SDL_WindowEvent *event);
|
const SDL_WindowEvent *event);
|
||||||
|
static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
|
||||||
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
|
||||||
static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
const SDL_Rect * rect, const void *pixels,
|
const SDL_Rect * rect, const void *pixels,
|
||||||
|
@ -321,6 +322,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->WindowEvent = GLES_WindowEvent;
|
renderer->WindowEvent = GLES_WindowEvent;
|
||||||
|
renderer->GetOutputSize = GLES_GetOutputSize;
|
||||||
renderer->CreateTexture = GLES_CreateTexture;
|
renderer->CreateTexture = GLES_CreateTexture;
|
||||||
renderer->UpdateTexture = GLES_UpdateTexture;
|
renderer->UpdateTexture = GLES_UpdateTexture;
|
||||||
renderer->LockTexture = GLES_LockTexture;
|
renderer->LockTexture = GLES_LockTexture;
|
||||||
|
@ -438,6 +440,13 @@ GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
|
||||||
|
{
|
||||||
|
SDL_GL_GetDrawableSize(renderer->window, w, h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_INLINE int
|
static SDL_INLINE int
|
||||||
power_of_2(int input)
|
power_of_2(int input)
|
||||||
{
|
{
|
||||||
|
|
|
@ -369,6 +369,13 @@ GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
|
||||||
|
{
|
||||||
|
SDL_GL_GetDrawableSize(renderer->window, w, h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GLES2_UpdateViewport(SDL_Renderer * renderer)
|
GLES2_UpdateViewport(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
|
@ -2059,6 +2066,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
|
|
||||||
/* Populate the function pointers for the module */
|
/* Populate the function pointers for the module */
|
||||||
renderer->WindowEvent = &GLES2_WindowEvent;
|
renderer->WindowEvent = &GLES2_WindowEvent;
|
||||||
|
renderer->GetOutputSize = &GLES2_GetOutputSize;
|
||||||
renderer->CreateTexture = &GLES2_CreateTexture;
|
renderer->CreateTexture = &GLES2_CreateTexture;
|
||||||
renderer->UpdateTexture = &GLES2_UpdateTexture;
|
renderer->UpdateTexture = &GLES2_UpdateTexture;
|
||||||
renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
|
renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
|
||||||
|
|
|
@ -1107,22 +1107,22 @@ SDL_RestoreMousePosition(SDL_Window *window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
{
|
{
|
||||||
SDL_VideoDisplay *display;
|
SDL_VideoDisplay *display;
|
||||||
SDL_Window *other;
|
SDL_Window *other;
|
||||||
|
|
||||||
CHECK_WINDOW_MAGIC(window,);
|
CHECK_WINDOW_MAGIC(window,-1);
|
||||||
|
|
||||||
/* if we are in the process of hiding don't go back to fullscreen */
|
/* if we are in the process of hiding don't go back to fullscreen */
|
||||||
if ( window->is_hiding && fullscreen )
|
if ( window->is_hiding && fullscreen )
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
#ifdef __MACOSX__
|
#ifdef __MACOSX__
|
||||||
if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
|
if (Cocoa_SetWindowFullscreenSpace(window, fullscreen)) {
|
||||||
window->last_fullscreen_flags = window->flags;
|
window->last_fullscreen_flags = window->flags;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1139,7 +1139,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
/* See if anything needs to be done now */
|
/* See if anything needs to be done now */
|
||||||
if ((display->fullscreen_window == window) == fullscreen) {
|
if ((display->fullscreen_window == window) == fullscreen) {
|
||||||
if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
|
if ((window->last_fullscreen_flags & FULLSCREEN_MASK) == (window->flags & FULLSCREEN_MASK)) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,9 +1168,13 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
|
|
||||||
/* only do the mode change if we want exclusive fullscreen */
|
/* only do the mode change if we want exclusive fullscreen */
|
||||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||||
SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
|
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SDL_SetDisplayModeForDisplay(display, NULL);
|
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_this->SetWindowFullscreen) {
|
if (_this->SetWindowFullscreen) {
|
||||||
|
@ -1189,7 +1193,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
SDL_RestoreMousePosition(other);
|
SDL_RestoreMousePosition(other);
|
||||||
|
|
||||||
window->last_fullscreen_flags = window->flags;
|
window->last_fullscreen_flags = window->flags;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1209,6 +1213,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
||||||
SDL_RestoreMousePosition(window);
|
SDL_RestoreMousePosition(window);
|
||||||
|
|
||||||
window->last_fullscreen_flags = window->flags;
|
window->last_fullscreen_flags = window->flags;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CREATE_FLAGS \
|
#define CREATE_FLAGS \
|
||||||
|
@ -1935,9 +1940,7 @@ SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags)
|
||||||
window->flags &= ~FULLSCREEN_MASK;
|
window->flags &= ~FULLSCREEN_MASK;
|
||||||
window->flags |= flags;
|
window->flags |= flags;
|
||||||
|
|
||||||
SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
|
return SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_Surface *
|
static SDL_Surface *
|
||||||
|
|
|
@ -21,12 +21,21 @@
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@interface SDLUIKitDelegate : NSObject<UIApplicationDelegate> {
|
@interface SDLLaunchScreenController : UIViewController
|
||||||
}
|
|
||||||
|
|
||||||
+ (id) sharedAppDelegate;
|
- (instancetype)init;
|
||||||
|
- (void)loadView;
|
||||||
|
- (NSUInteger)supportedInterfaceOrientations;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface SDLUIKitDelegate : NSObject<UIApplicationDelegate>
|
||||||
|
|
||||||
|
+ (id)sharedAppDelegate;
|
||||||
+ (NSString *)getAppDelegateClassName;
|
+ (NSString *)getAppDelegateClassName;
|
||||||
|
|
||||||
|
- (void)hideLaunchScreen;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -28,8 +28,10 @@
|
||||||
#include "SDL_system.h"
|
#include "SDL_system.h"
|
||||||
#include "SDL_main.h"
|
#include "SDL_main.h"
|
||||||
|
|
||||||
#include "SDL_uikitappdelegate.h"
|
#import "SDL_uikitappdelegate.h"
|
||||||
#include "SDL_uikitmodes.h"
|
#import "SDL_uikitmodes.h"
|
||||||
|
#import "SDL_uikitwindow.h"
|
||||||
|
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
|
|
||||||
#ifdef main
|
#ifdef main
|
||||||
|
@ -39,12 +41,10 @@
|
||||||
static int forward_argc;
|
static int forward_argc;
|
||||||
static char **forward_argv;
|
static char **forward_argv;
|
||||||
static int exit_status;
|
static int exit_status;
|
||||||
static UIWindow *launch_window;
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
/* store arguments */
|
/* store arguments */
|
||||||
forward_argc = argc;
|
forward_argc = argc;
|
||||||
|
@ -56,7 +56,9 @@ int main(int argc, char **argv)
|
||||||
forward_argv[i] = NULL;
|
forward_argv[i] = NULL;
|
||||||
|
|
||||||
/* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
|
/* 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 */
|
/* free the memory we used to hold copies of argc and argv */
|
||||||
for (i = 0; i < forward_argc; i++) {
|
for (i = 0; i < forward_argc; i++) {
|
||||||
|
@ -64,7 +66,6 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
free(forward_argv);
|
free(forward_argv);
|
||||||
|
|
||||||
[pool release];
|
|
||||||
return exit_status;
|
return exit_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,224 +76,262 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
||||||
[UIApplication sharedApplication].idleTimerDisabled = disable;
|
[UIApplication sharedApplication].idleTimerDisabled = disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load a launch image using the old UILaunchImageFile-era naming rules. */
|
||||||
@interface SDL_launchscreenviewcontroller : UIViewController {
|
static UIImage *
|
||||||
|
SDL_LoadLaunchImageNamed(NSString *name, int screenh)
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation SDL_launchscreenviewcontroller
|
|
||||||
|
|
||||||
- (id)init
|
|
||||||
{
|
{
|
||||||
self = [super init];
|
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
|
||||||
if (self == nil) {
|
UIUserInterfaceIdiom idiom = [UIDevice currentDevice].userInterfaceIdiom;
|
||||||
return nil;
|
UIImage *image = nil;
|
||||||
}
|
|
||||||
|
|
||||||
NSString* launch_screen_name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
|
if (idiom == UIUserInterfaceIdiomPhone && screenh == 568) {
|
||||||
|
/* The image name for the iPhone 5 uses its height as a suffix. */
|
||||||
if(launch_screen_name) {
|
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-568h", name]];
|
||||||
// TODO: If the NIB is not in the bundle, this will throw an exception. We might consider a pre-emptive check, but returning a useless viewcontroller isn't helpful and the check should be outside.
|
} else if (idiom == UIUserInterfaceIdiomPad) {
|
||||||
UIView* launch_screen = [[[NSBundle mainBundle] loadNibNamed:launch_screen_name owner:self options:nil] objectAtIndex:0];
|
/* iPad apps can launch in any orientation. */
|
||||||
CGSize size = [UIScreen mainScreen].bounds.size;
|
if (UIInterfaceOrientationIsLandscape(curorient)) {
|
||||||
|
if (curorient == UIInterfaceOrientationLandscapeLeft) {
|
||||||
CGRect bounds = CGRectMake(0, 0, size.width, size.height);
|
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeLeft", name]];
|
||||||
|
|
||||||
[launch_screen setFrame:bounds];
|
|
||||||
[self setView:launch_screen];
|
|
||||||
[launch_screen release];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
@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);
|
|
||||||
/* FIXME: Some where around iOS 7, UILaunchImages in the Info.plist was introduced which explicitly maps image names to devices and orientations.
|
|
||||||
This gets rid of the hardcoded magic file names and allows more control for OS version, orientation, retina, and device.
|
|
||||||
But this existing code needs to be modified to look in the Info.plist for each key and act appropriately for the correct iOS version.
|
|
||||||
But iOS 8 superscedes this process and introduces the LaunchScreen NIB which uses autolayout to handle all orientations and devices.
|
|
||||||
Since we now have a LaunchScreen solution, this may never get fixed,
|
|
||||||
but this note is here for anybody trying to debug their program on iOS 7 and doesn't understand why their Info.plist isn't working.
|
|
||||||
*/
|
|
||||||
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 {
|
} else {
|
||||||
image = self->splashPortrait;
|
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeRight", name]];
|
||||||
}
|
}
|
||||||
if (image)
|
if (!image) {
|
||||||
{
|
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Landscape", name]];
|
||||||
splash.image = image;
|
|
||||||
}
|
}
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation SDLLaunchScreenController {
|
||||||
|
UIInterfaceOrientationMask supportedOrientations;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (!(self = [super initWithNibName:nil bundle:nil])) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSBundle *bundle = [NSBundle mainBundle];
|
||||||
|
NSString *screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
|
||||||
|
|
||||||
|
/* Normally we don't want to rotate from the initial orientation. */
|
||||||
|
supportedOrientations = (1 << [UIApplication sharedApplication].statusBarOrientation);
|
||||||
|
|
||||||
|
/* Launch screens were added in iOS 8. Otherwise we use launch images. */
|
||||||
|
if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) {
|
||||||
|
@try {
|
||||||
|
self.view = [bundle loadNibNamed:screenname owner:self options:nil][0];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
/* iOS displays a blank screen rather than falling back to an image,
|
||||||
|
* if a launch screen name is specified but it fails to load. */
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.view) {
|
||||||
|
NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
|
||||||
|
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* We always want portrait-oriented size, to match UILaunchImageSize. */
|
||||||
|
if (screenw > screenh) {
|
||||||
|
int width = screenw;
|
||||||
|
screenw = screenh;
|
||||||
|
screenh = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Xcode 5 introduced a dictionary of launch images in Info.plist. */
|
||||||
|
if (launchimages) {
|
||||||
|
for (NSDictionary *dict in launchimages) {
|
||||||
|
UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||||
|
NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
|
||||||
|
NSString *sizestring = dict[@"UILaunchImageSize"];
|
||||||
|
NSString *orientstring = dict[@"UILaunchImageOrientation"];
|
||||||
|
|
||||||
|
/* 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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagename = dict[@"UILaunchImageName"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imagename) {
|
||||||
|
image = [UIImage imageNamed:imagename];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"];
|
||||||
|
|
||||||
|
if (imagename) {
|
||||||
|
image = SDL_LoadLaunchImageNamed(imagename, screenh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!image) {
|
||||||
|
image = SDL_LoadLaunchImageNamed(@"Default", screenh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
if (image.size.width > image.size.height) {
|
||||||
|
supportedOrientations = UIInterfaceOrientationMaskLandscape;
|
||||||
|
} else {
|
||||||
|
supportedOrientations = UIInterfaceOrientationMaskPortrait;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view = [[UIImageView alloc] initWithImage:image];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadView
|
||||||
|
{
|
||||||
|
/* Do nothing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)supportedInterfaceOrientations
|
||||||
|
{
|
||||||
|
return supportedOrientations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation SDLUIKitDelegate {
|
||||||
@implementation SDLUIKitDelegate
|
UIWindow *launchWindow;
|
||||||
|
}
|
||||||
|
|
||||||
/* convenience method */
|
/* convenience method */
|
||||||
+ (id) sharedAppDelegate
|
+ (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
|
||||||
return [[UIApplication sharedApplication] delegate];
|
* called before this method */
|
||||||
|
return [UIApplication sharedApplication].delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)getAppDelegateClassName
|
+ (NSString *)getAppDelegateClassName
|
||||||
{
|
{
|
||||||
/* subclassing notice: when you subclass this appdelegate, make sure to add a category to override
|
/* subclassing notice: when you subclass this appdelegate, make sure to add
|
||||||
this method and return the actual name of the delegate */
|
* a category to override this method and return the actual name of the
|
||||||
|
* delegate */
|
||||||
return @"SDLUIKitDelegate";
|
return @"SDLUIKitDelegate";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (void)hideLaunchScreen
|
||||||
{
|
{
|
||||||
self = [super init];
|
UIWindow *window = launchWindow;
|
||||||
return self;
|
|
||||||
|
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
|
- (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 */
|
/* run the user's application, passing argc and argv */
|
||||||
SDL_iPhoneSetEventPump(SDL_TRUE);
|
SDL_iPhoneSetEventPump(SDL_TRUE);
|
||||||
exit_status = SDL_main(forward_argc, forward_argv);
|
exit_status = SDL_main(forward_argc, forward_argv);
|
||||||
SDL_iPhoneSetEventPump(SDL_FALSE);
|
SDL_iPhoneSetEventPump(SDL_FALSE);
|
||||||
|
|
||||||
/* If we showed a splash image, clean it up */
|
if (launchWindow) {
|
||||||
if (launch_window) {
|
launchWindow.hidden = YES;
|
||||||
[launch_window release];
|
launchWindow = nil;
|
||||||
launch_window = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exit, passing the return status from the user's application */
|
/* exit, passing the return status from the user's application */
|
||||||
/* We don't actually exit to support applications that do setup in
|
/* We don't actually exit to support applications that do setup in their
|
||||||
* their main function and then allow the Cocoa event loop to run.
|
* main function and then allow the Cocoa event loop to run. */
|
||||||
*/
|
|
||||||
/* exit(exit_status); */
|
/* exit(exit_status); */
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
{
|
{
|
||||||
/* Keep the launch image up until we set a video mode */
|
NSBundle *bundle = [NSBundle mainBundle];
|
||||||
launch_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||||
|
|
||||||
/* iOS 8 introduces LaunchScreen NIBs which use autolayout to handle all devices and orientations with a single NIB instead of multiple launch images.
|
#if SDL_IPHONE_LAUNCHSCREEN
|
||||||
This is also the only way to get the App Store badge "Optimized for iPhone 6 and iPhone 6 Plus".
|
/* The normal launch screen is displayed until didFinishLaunching returns,
|
||||||
So if the application is running on iOS 8 or greater AND has specified a LaunchScreen in their Info.plist, we should use the LaunchScreen NIB.
|
* but SDL_main is called after that happens and there may be a noticeable
|
||||||
Otherwise, we should fallback to the legacy behavior of launch screen images.
|
* 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
|
||||||
NSString* launch_screen_name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
|
* called), so we show the launch screen programmatically until the first
|
||||||
if( ([[UIDevice currentDevice].systemVersion intValue] >= 8) && (nil != launch_screen_name) ) {
|
* time events are pumped. */
|
||||||
// iOS 8.0 and above uses LaunchScreen.xib
|
UIViewController *viewcontroller = [[SDLLaunchScreenController alloc] init];
|
||||||
SDL_launchscreenviewcontroller* launch_screen_view_controller = [[SDL_launchscreenviewcontroller alloc] init];
|
|
||||||
launch_window.rootViewController = launch_screen_view_controller;
|
|
||||||
[launch_window addSubview:launch_screen_view_controller.view];
|
|
||||||
[launch_window makeKeyAndVisible];
|
|
||||||
} else {
|
|
||||||
// Anything less than iOS 8.0
|
|
||||||
|
|
||||||
UIViewController *splashViewController = [[SDL_splashviewcontroller alloc] init];
|
if (viewcontroller.view) {
|
||||||
launch_window.rootViewController = splashViewController;
|
launchWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||||
[launch_window addSubview:splashViewController.view];
|
|
||||||
[launch_window makeKeyAndVisible];
|
/* 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 = viewcontroller;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set working directory to resource path */
|
/* Set working directory to resource path */
|
||||||
[[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]];
|
[[NSFileManager defaultManager] changeCurrentDirectoryPath:[bundle resourcePath]];
|
||||||
|
|
||||||
/* register a callback for the idletimer hint */
|
/* register a callback for the idletimer hint */
|
||||||
SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED,
|
SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED,
|
||||||
|
@ -314,7 +353,35 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
||||||
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationWillResignActive:(UIApplication*)application
|
- (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();
|
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||||
if (_this) {
|
if (_this) {
|
||||||
|
@ -327,17 +394,17 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
||||||
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationDidEnterBackground:(UIApplication*)application
|
- (void)applicationDidEnterBackground:(UIApplication*)application
|
||||||
{
|
{
|
||||||
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationWillEnterForeground:(UIApplication*)application
|
- (void)applicationWillEnterForeground:(UIApplication*)application
|
||||||
{
|
{
|
||||||
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
|
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationDidBecomeActive:(UIApplication*)application
|
- (void)applicationDidBecomeActive:(UIApplication*)application
|
||||||
{
|
{
|
||||||
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
||||||
|
|
||||||
|
@ -353,11 +420,11 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
|
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
|
||||||
{
|
{
|
||||||
NSURL *fileURL = [url filePathURL];
|
NSURL *fileURL = url.filePathURL;
|
||||||
if (fileURL != nil) {
|
if (fileURL != nil) {
|
||||||
SDL_SendDropFile([[fileURL path] UTF8String]);
|
SDL_SendDropFile([fileURL.path UTF8String]);
|
||||||
} else {
|
} else {
|
||||||
SDL_SendDropFile([[url absoluteString] UTF8String]);
|
SDL_SendDropFile([url.absoluteString UTF8String]);
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,9 @@ SDL_iPhoneSetEventPump(SDL_bool enabled)
|
||||||
void
|
void
|
||||||
UIKit_PumpEvents(_THIS)
|
UIKit_PumpEvents(_THIS)
|
||||||
{
|
{
|
||||||
if (!UIKit_EventPumpEnabled)
|
if (!UIKit_EventPumpEnabled) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Let the run loop run for a short amount of time: long enough for
|
/* 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
|
touch events to get processed (which is important to get certain
|
||||||
|
|
|
@ -30,35 +30,20 @@
|
||||||
|
|
||||||
static SDL_bool s_showingMessageBox = SDL_FALSE;
|
static SDL_bool s_showingMessageBox = SDL_FALSE;
|
||||||
|
|
||||||
@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate> {
|
@interface SDLAlertViewDelegate : NSObject <UIAlertViewDelegate>
|
||||||
@private
|
|
||||||
int *clickedButtonIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithButtonIndex:(int *)_buttonIndex;
|
@property (nonatomic, assign) int clickedIndex;
|
||||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation UIKit_UIAlertViewDelegate
|
@implementation SDLAlertViewDelegate
|
||||||
|
|
||||||
- (id)initWithButtonIndex:(int *)buttonIndex
|
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||||
{
|
{
|
||||||
self = [self init];
|
_clickedIndex = (int)buttonIndex;
|
||||||
if (self == nil) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
self->clickedButtonIndex = buttonIndex;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
|
@end
|
||||||
{
|
|
||||||
*clickedButtonIndex = (int)buttonIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end /* UIKit_UIAlertViewDelegate */
|
|
||||||
|
|
||||||
|
|
||||||
SDL_bool
|
SDL_bool
|
||||||
|
@ -70,41 +55,38 @@ UIKit_ShowingMessageBox()
|
||||||
int
|
int
|
||||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
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;
|
int i;
|
||||||
|
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
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) {
|
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 */
|
/* Set up for showing the alert */
|
||||||
clicked = messageboxdata->numbuttons;
|
delegate.clickedIndex = messageboxdata->numbuttons;
|
||||||
|
|
||||||
[alert show];
|
[alert show];
|
||||||
|
|
||||||
/* Run the main event loop until the alert has finished */
|
/* Run the main event loop until the alert has finished */
|
||||||
/* Note that this needs to be done on the main thread */
|
/* Note that this needs to be done on the main thread */
|
||||||
s_showingMessageBox = SDL_TRUE;
|
s_showingMessageBox = SDL_TRUE;
|
||||||
while (clicked == messageboxdata->numbuttons) {
|
while (delegate.clickedIndex == messageboxdata->numbuttons) {
|
||||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||||
}
|
}
|
||||||
s_showingMessageBox = SDL_FALSE;
|
s_showingMessageBox = SDL_FALSE;
|
||||||
|
|
||||||
*buttonid = messageboxdata->buttons[clicked].buttonid;
|
*buttonid = messageboxdata->buttons[delegate.clickedIndex].buttonid;
|
||||||
|
|
||||||
[alert.delegate release];
|
alert.delegate = nil;
|
||||||
[alert release];
|
}
|
||||||
|
|
||||||
[pool release];
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,17 +25,17 @@
|
||||||
|
|
||||||
#include "SDL_uikitvideo.h"
|
#include "SDL_uikitvideo.h"
|
||||||
|
|
||||||
typedef struct
|
@interface SDL_DisplayData : NSObject
|
||||||
{
|
|
||||||
UIScreen *uiscreen;
|
|
||||||
CGFloat scale;
|
|
||||||
} SDL_DisplayData;
|
|
||||||
|
|
||||||
typedef struct
|
@property (nonatomic, strong) UIScreen *uiscreen;
|
||||||
{
|
|
||||||
UIScreenMode *uiscreenmode;
|
@end
|
||||||
CGFloat scale;
|
|
||||||
} SDL_DisplayModeData;
|
@interface SDL_DisplayModeData : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, strong) UIScreenMode *uiscreenmode;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
|
extern SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen);
|
||||||
|
|
||||||
|
|
|
@ -25,27 +25,36 @@
|
||||||
#include "SDL_assert.h"
|
#include "SDL_assert.h"
|
||||||
#include "SDL_uikitmodes.h"
|
#include "SDL_uikitmodes.h"
|
||||||
|
|
||||||
|
@implementation SDL_DisplayData
|
||||||
|
|
||||||
|
@synthesize uiscreen;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SDL_DisplayModeData
|
||||||
|
|
||||||
|
@synthesize uiscreenmode;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
|
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
|
||||||
UIScreenMode * uiscreenmode, CGFloat scale)
|
UIScreenMode * uiscreenmode)
|
||||||
{
|
{
|
||||||
SDL_DisplayModeData *data = NULL;
|
SDL_DisplayModeData *data = nil;
|
||||||
|
|
||||||
if (uiscreenmode != nil) {
|
if (uiscreenmode != nil) {
|
||||||
/* Allocate the display mode data */
|
/* Allocate the display mode data */
|
||||||
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
|
data = [[SDL_DisplayModeData alloc] init];
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
data->uiscreenmode = uiscreenmode;
|
data.uiscreenmode = uiscreenmode;
|
||||||
[data->uiscreenmode retain];
|
|
||||||
|
|
||||||
data->scale = scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mode->driverdata = data;
|
mode->driverdata = (void *) CFBridgingRetain(data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -54,23 +63,21 @@ static void
|
||||||
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
|
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
|
||||||
{
|
{
|
||||||
if (mode->driverdata != NULL) {
|
if (mode->driverdata != NULL) {
|
||||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata;
|
CFRelease(mode->driverdata);
|
||||||
[data->uiscreenmode release];
|
|
||||||
SDL_free(data);
|
|
||||||
mode->driverdata = NULL;
|
mode->driverdata = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
||||||
UIScreenMode * uiscreenmode, CGFloat scale)
|
UIScreenMode * uiscreenmode)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
SDL_zero(mode);
|
SDL_zero(mode);
|
||||||
|
|
||||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||||
mode.refresh_rate = 0;
|
mode.refresh_rate = 0;
|
||||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
|
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,16 +92,16 @@ UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
UIScreenMode * uiscreenmode, SDL_bool addRotation)
|
||||||
{
|
{
|
||||||
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) {
|
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addRotation) {
|
if (addRotation) {
|
||||||
/* Add the rotated version */
|
/* Add the rotated version */
|
||||||
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) {
|
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +112,7 @@ UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale,
|
||||||
static int
|
static int
|
||||||
UIKit_AddDisplay(UIScreen *uiscreen)
|
UIKit_AddDisplay(UIScreen *uiscreen)
|
||||||
{
|
{
|
||||||
CGSize size = [uiscreen bounds].size;
|
CGSize size = uiscreen.bounds.size;
|
||||||
|
|
||||||
/* Make sure the width/height are oriented correctly */
|
/* Make sure the width/height are oriented correctly */
|
||||||
if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) {
|
if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) {
|
||||||
|
@ -114,24 +121,16 @@ UIKit_AddDisplay(UIScreen *uiscreen)
|
||||||
size.height = height;
|
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_VideoDisplay display;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
SDL_zero(mode);
|
SDL_zero(mode);
|
||||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||||
mode.w = (int)(size.width * scale);
|
mode.w = (int) size.width;
|
||||||
mode.h = (int)(size.height * scale);
|
mode.h = (int) size.height;
|
||||||
|
|
||||||
UIScreenMode * uiscreenmode = [uiscreen currentMode];
|
UIScreenMode *uiscreenmode = uiscreen.currentMode;
|
||||||
|
|
||||||
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) {
|
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,17 +139,15 @@ UIKit_AddDisplay(UIScreen *uiscreen)
|
||||||
display.current_mode = mode;
|
display.current_mode = mode;
|
||||||
|
|
||||||
/* Allocate the display data */
|
/* Allocate the display data */
|
||||||
SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data));
|
SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
|
||||||
if (!data) {
|
if (!data) {
|
||||||
UIKit_FreeDisplayModeData(&display.desktop_mode);
|
UIKit_FreeDisplayModeData(&display.desktop_mode);
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
[uiscreen retain];
|
data.uiscreen = uiscreen;
|
||||||
data->uiscreen = uiscreen;
|
|
||||||
data->scale = scale;
|
|
||||||
|
|
||||||
display.driverdata = data;
|
display.driverdata = (void *) CFBridgingRetain(data);
|
||||||
SDL_AddVideoDisplay(&display);
|
SDL_AddVideoDisplay(&display);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -160,9 +157,9 @@ SDL_bool
|
||||||
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
|
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
|
||||||
{
|
{
|
||||||
if (uiscreen == [UIScreen mainScreen]) {
|
if (uiscreen == [UIScreen mainScreen]) {
|
||||||
return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]);
|
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
|
||||||
} else {
|
} else {
|
||||||
CGSize size = [uiscreen bounds].size;
|
CGSize size = uiscreen.bounds.size;
|
||||||
return (size.width > size.height);
|
return (size.width > size.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,11 +167,13 @@ UIKit_IsDisplayLandscape(UIScreen *uiscreen)
|
||||||
int
|
int
|
||||||
UIKit_InitModes(_THIS)
|
UIKit_InitModes(_THIS)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
for (UIScreen *uiscreen in [UIScreen screens]) {
|
for (UIScreen *uiscreen in [UIScreen screens]) {
|
||||||
if (UIKit_AddDisplay(uiscreen) < 0) {
|
if (UIKit_AddDisplay(uiscreen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -182,15 +181,26 @@ UIKit_InitModes(_THIS)
|
||||||
void
|
void
|
||||||
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
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 isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
|
||||||
SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]);
|
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
|
||||||
|
CGFloat scale = data.uiscreen.scale;
|
||||||
|
|
||||||
for (UIScreenMode *uimode in [data->uiscreen availableModes]) {
|
#ifdef __IPHONE_8_0
|
||||||
CGSize size = [uimode size];
|
/* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than
|
||||||
int w = (int)size.width;
|
* 1242x2208 (414x736@3x), so we should use the native scale. */
|
||||||
int h = (int)size.height;
|
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 */
|
/* Make sure the width/height are oriented correctly */
|
||||||
if (isLandscape != (w > h)) {
|
if (isLandscape != (w > h)) {
|
||||||
|
@ -199,17 +209,7 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
||||||
h = tmp;
|
h = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the native screen resolution. */
|
UIKit_AddDisplayMode(display, w, h, uimode, addRotation);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,19 +217,24 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
|
||||||
int
|
int
|
||||||
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||||
{
|
{
|
||||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
@autoreleasepool {
|
||||||
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
|
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]) {
|
||||||
|
/* [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 (mode->w > mode->h) {
|
||||||
if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
|
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
|
return SDL_SetError("Screen orientation does not match display mode size");
|
||||||
}
|
}
|
||||||
} else if (mode->w < mode->h) {
|
} else if (mode->w < mode->h) {
|
||||||
if (UIKit_IsDisplayLandscape(data->uiscreen)) {
|
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
|
||||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
|
return SDL_SetError("Screen orientation does not match display mode size");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +247,7 @@ UIKit_QuitModes(_THIS)
|
||||||
{
|
{
|
||||||
/* Release Objective-C objects, so higher level doesn't free() them. */
|
/* Release Objective-C objects, so higher level doesn't free() them. */
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@autoreleasepool {
|
||||||
for (i = 0; i < _this->num_displays; i++) {
|
for (i = 0; i < _this->num_displays; i++) {
|
||||||
SDL_VideoDisplay *display = &_this->displays[i];
|
SDL_VideoDisplay *display = &_this->displays[i];
|
||||||
|
|
||||||
|
@ -251,11 +257,12 @@ UIKit_QuitModes(_THIS)
|
||||||
UIKit_FreeDisplayModeData(mode);
|
UIKit_FreeDisplayModeData(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
if (display->driverdata != NULL) {
|
||||||
[data->uiscreen release];
|
CFRelease(display->driverdata);
|
||||||
SDL_free(data);
|
|
||||||
display->driverdata = NULL;
|
display->driverdata = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
extern int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window,
|
extern int UIKit_GL_MakeCurrent(_THIS, SDL_Window * window,
|
||||||
SDL_GLContext context);
|
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 void UIKit_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||||
extern SDL_GLContext UIKit_GL_CreateContext(_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_DeleteContext(_THIS, SDL_GLContext context);
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
#if SDL_VIDEO_DRIVER_UIKIT
|
#if SDL_VIDEO_DRIVER_UIKIT
|
||||||
|
|
||||||
#include "SDL_uikitopengles.h"
|
#include "SDL_uikitopengles.h"
|
||||||
#include "SDL_uikitopenglview.h"
|
#import "SDL_uikitopenglview.h"
|
||||||
#include "SDL_uikitappdelegate.h"
|
|
||||||
#include "SDL_uikitmodes.h"
|
#include "SDL_uikitmodes.h"
|
||||||
#include "SDL_uikitwindow.h"
|
#include "SDL_uikitwindow.h"
|
||||||
|
#include "SDL_uikitevents.h"
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
#include "../../events/SDL_keyboard_c.h"
|
#include "../../events/SDL_keyboard_c.h"
|
||||||
#include "../../events/SDL_mouse_c.h"
|
#include "../../events/SDL_mouse_c.h"
|
||||||
|
@ -40,148 +40,189 @@ void *
|
||||||
UIKit_GL_GetProcAddress(_THIS, const char *proc)
|
UIKit_GL_GetProcAddress(_THIS, const char *proc)
|
||||||
{
|
{
|
||||||
/* Look through all SO's for the proc symbol. Here's why:
|
/* 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 iPhone Simulator.
|
* -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.
|
* -We don't know that the path won't change in the future. */
|
||||||
*/
|
|
||||||
return dlsym(RTLD_DEFAULT, proc);
|
return dlsym(RTLD_DEFAULT, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
note that SDL_GL_Delete context makes it current without passing the window
|
note that SDL_GL_DeleteContext 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 {
|
||||||
|
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;
|
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
|
int
|
||||||
UIKit_GL_LoadLibrary(_THIS, const char *path)
|
UIKit_GL_LoadLibrary(_THIS, const char *path)
|
||||||
{
|
{
|
||||||
/*
|
/* We shouldn't pass a path to this function, since we've already loaded the
|
||||||
shouldn't be passing a path into this function
|
* library. */
|
||||||
why? Because we've already loaded the library
|
|
||||||
and because the SDK forbids loading an external SO
|
|
||||||
*/
|
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
return SDL_SetError("iPhone GL Load Library just here for compatibility");
|
return SDL_SetError("iOS GL Load Library just here for compatibility");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
|
void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
SDLEAGLContext *context = (__bridge SDLEAGLContext *) SDL_GL_GetCurrentContext();
|
||||||
|
|
||||||
#if SDL_POWER_UIKIT
|
#if SDL_POWER_UIKIT
|
||||||
/* Check once a frame to see if we should turn off the battery monitor. */
|
/* Check once a frame to see if we should turn off the battery monitor. */
|
||||||
SDL_UIKit_UpdateBatteryMonitoring();
|
SDL_UIKit_UpdateBatteryMonitoring();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
[context.sdlView swapBuffers];
|
||||||
|
|
||||||
if (nil == data->view) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[data->view swapBuffers];
|
|
||||||
|
|
||||||
/* You need to pump events in order for the OS to make changes visible.
|
/* 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
|
* We don't pump events here because we don't want iOS application events
|
||||||
(low memory, terminate, etc.) to happen inside low level rendering.
|
* (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_uikitopenglview *view;
|
||||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
||||||
SDL_DisplayData *displaydata = display->driverdata;
|
EAGLSharegroup *sharegroup = nil;
|
||||||
SDL_DisplayModeData *displaymodedata = display->current_mode.driverdata;
|
CGFloat scale = 1.0;
|
||||||
UIWindow *uiwindow = data->uiwindow;
|
|
||||||
EAGLSharegroup *share_group = nil;
|
|
||||||
|
|
||||||
if (_this->gl_config.share_with_current_context) {
|
if (_this->gl_config.share_with_current_context) {
|
||||||
SDL_uikitopenglview *view = (SDL_uikitopenglview *) SDL_GL_GetCurrentContext();
|
EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
|
||||||
share_group = [view.context sharegroup];
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* construct our view, passing in SDL's OpenGL configuration data */
|
/* construct our view, passing in SDL's OpenGL configuration data */
|
||||||
CGRect frame;
|
view = [[SDL_uikitopenglview alloc] initWithFrame:frame
|
||||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
scale:scale
|
||||||
frame = [displaydata->uiscreen bounds];
|
retainBacking:_this->gl_config.retained_backing
|
||||||
} else {
|
rBits:_this->gl_config.red_size
|
||||||
frame = [displaydata->uiscreen applicationFrame];
|
gBits:_this->gl_config.green_size
|
||||||
}
|
bBits:_this->gl_config.blue_size
|
||||||
view = [[SDL_uikitopenglview alloc] initWithFrame: frame
|
aBits:_this->gl_config.alpha_size
|
||||||
scale: displaymodedata->scale
|
depthBits:_this->gl_config.depth_size
|
||||||
retainBacking: _this->gl_config.retained_backing
|
stencilBits:_this->gl_config.stencil_size
|
||||||
rBits: _this->gl_config.red_size
|
sRGB:_this->gl_config.framebuffer_srgb_capable
|
||||||
gBits: _this->gl_config.green_size
|
majorVersion:_this->gl_config.major_version
|
||||||
bBits: _this->gl_config.blue_size
|
shareGroup:sharegroup];
|
||||||
aBits: _this->gl_config.alpha_size
|
|
||||||
depthBits: _this->gl_config.depth_size
|
|
||||||
stencilBits: _this->gl_config.stencil_size
|
|
||||||
majorVersion: _this->gl_config.major_version
|
|
||||||
shareGroup: share_group];
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->view = view;
|
SDLEAGLContext *context = view.context;
|
||||||
view->viewcontroller = data->viewcontroller;
|
if (UIKit_GL_MakeCurrent(_this, window, (__bridge SDL_GLContext) context) < 0) {
|
||||||
if (view->viewcontroller != nil) {
|
UIKit_GL_DeleteContext(_this, (SDL_GLContext) CFBridgingRetain(context));
|
||||||
[view->viewcontroller setView:view];
|
|
||||||
[view->viewcontroller retain];
|
|
||||||
}
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAGLContext *context = view.context;
|
|
||||||
if (UIKit_GL_MakeCurrent(_this, window, context) < 0) {
|
|
||||||
UIKit_GL_DeleteContext(_this, context);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make this window the current mouse focus for touch input */
|
/* We return a +1'd context. The window's driverdata owns the view (via
|
||||||
if (displaydata->uiscreen == [UIScreen mainScreen]) {
|
* MakeCurrent.) */
|
||||||
SDL_SetMouseFocus(window);
|
return (SDL_GLContext) CFBridgingRetain(context);
|
||||||
SDL_SetKeyboardFocus(window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
void
|
||||||
|
UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||||
{
|
{
|
||||||
SDL_Window *window;
|
@autoreleasepool {
|
||||||
|
/* Transfer ownership the +1'd context to ARC. */
|
||||||
|
SDLEAGLContext *eaglcontext = (SDLEAGLContext *) CFBridgingRelease(context);
|
||||||
|
|
||||||
/* Find the view associated with this context */
|
/* Detach the context's view from its window. */
|
||||||
for (window = _this->windows; window; window = window->next) {
|
[eaglcontext.sdlView setSDLWindow:NULL];
|
||||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
|
||||||
SDL_uikitopenglview *view = data->view;
|
|
||||||
if (view.context == context) {
|
|
||||||
/* the delegate has retained the view, this will release him */
|
|
||||||
if (view->viewcontroller) {
|
|
||||||
UIWindow *uiwindow = (UIWindow *)view.superview;
|
|
||||||
if (uiwindow.rootViewController == view->viewcontroller) {
|
|
||||||
uiwindow.rootViewController = nil;
|
|
||||||
}
|
}
|
||||||
[view->viewcontroller setView:nil];
|
}
|
||||||
[view->viewcontroller release];
|
|
||||||
}
|
|
||||||
[view removeFromSuperview];
|
|
||||||
|
|
||||||
/* FIXME: This doesn't actually call view dealloc - what is holding a reference to it? */
|
Uint32
|
||||||
[view release];
|
SDL_iPhoneGetViewRenderbuffer(SDL_Window * window)
|
||||||
return;
|
{
|
||||||
|
if (!window) {
|
||||||
|
SDL_SetError("Invalid window");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
return glview.drawableRenderbuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* View not found... delete the context anyway? */
|
SDL_SetError("Window does not have an attached OpenGL view");
|
||||||
[(EAGLContext *)context release];
|
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;
|
||||||
|
UIView *view = data.viewcontroller.view;
|
||||||
|
if ([view isKindOfClass:[SDL_uikitopenglview class]]) {
|
||||||
|
SDL_uikitopenglview *glview = (SDL_uikitopenglview *) view;
|
||||||
|
return glview.drawableFramebuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetError("Window does not have an attached OpenGL view");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||||
|
|
|
@ -21,44 +21,22 @@
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <OpenGLES/EAGL.h>
|
#import <OpenGLES/EAGL.h>
|
||||||
#import <OpenGLES/ES1/gl.h>
|
#import <OpenGLES/ES2/gl.h>
|
||||||
#import <OpenGLES/ES1/glext.h>
|
|
||||||
#import "SDL_uikitview.h"
|
#import "SDL_uikitview.h"
|
||||||
/*
|
#include "SDL_uikitvideo.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
|
@class SDL_uikitopenglview;
|
||||||
/* The pixel dimensions of the backbuffer */
|
|
||||||
GLint backingWidth;
|
|
||||||
GLint backingHeight;
|
|
||||||
|
|
||||||
EAGLContext *context;
|
@interface SDLEAGLContext : EAGLContext
|
||||||
|
|
||||||
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
|
@property (nonatomic, weak) SDL_uikitopenglview *sdlView;
|
||||||
GLuint viewRenderbuffer, viewFramebuffer;
|
|
||||||
|
|
||||||
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
|
@end
|
||||||
GLuint depthRenderbuffer;
|
|
||||||
|
|
||||||
/* format of depthRenderbuffer */
|
@interface SDL_uikitopenglview : SDL_uikitview
|
||||||
GLenum depthBufferFormat;
|
|
||||||
|
|
||||||
id displayLink;
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
int animationInterval;
|
|
||||||
void (*animationCallback)(void*);
|
|
||||||
void *animationCallbackParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic, retain, readonly) EAGLContext *context;
|
|
||||||
|
|
||||||
- (void)swapBuffers;
|
|
||||||
- (void)setCurrentContext;
|
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)frame
|
|
||||||
scale:(CGFloat)scale
|
scale:(CGFloat)scale
|
||||||
retainBacking:(BOOL)retained
|
retainBacking:(BOOL)retained
|
||||||
rBits:(int)rBits
|
rBits:(int)rBits
|
||||||
|
@ -67,20 +45,24 @@
|
||||||
aBits:(int)aBits
|
aBits:(int)aBits
|
||||||
depthBits:(int)depthBits
|
depthBits:(int)depthBits
|
||||||
stencilBits:(int)stencilBits
|
stencilBits:(int)stencilBits
|
||||||
|
sRGB:(BOOL)sRGB
|
||||||
majorVersion:(int)majorVersion
|
majorVersion:(int)majorVersion
|
||||||
shareGroup:(EAGLSharegroup*)shareGroup;
|
shareGroup:(EAGLSharegroup*)shareGroup;
|
||||||
|
|
||||||
|
@property (nonatomic, readonly, strong) SDLEAGLContext *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)updateFrame;
|
||||||
|
|
||||||
- (void)setAnimationCallback:(int)interval
|
|
||||||
callback:(void (*)(void*))callback
|
|
||||||
callbackParam:(void*)callbackParam;
|
|
||||||
|
|
||||||
- (void)startAnimation;
|
|
||||||
- (void)stopAnimation;
|
|
||||||
|
|
||||||
- (void)doLoop:(CADisplayLink*)sender;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -22,22 +22,36 @@
|
||||||
|
|
||||||
#if SDL_VIDEO_DRIVER_UIKIT
|
#if SDL_VIDEO_DRIVER_UIKIT
|
||||||
|
|
||||||
#include <QuartzCore/QuartzCore.h>
|
|
||||||
#include <OpenGLES/EAGLDrawable.h>
|
#include <OpenGLES/EAGLDrawable.h>
|
||||||
#include "SDL_uikitopenglview.h"
|
#include <OpenGLES/ES2/glext.h>
|
||||||
#include "SDL_uikitmessagebox.h"
|
#import "SDL_uikitopenglview.h"
|
||||||
|
#include "SDL_uikitwindow.h"
|
||||||
|
|
||||||
|
@implementation SDLEAGLContext
|
||||||
|
|
||||||
@implementation SDL_uikitopenglview
|
@end
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
/* format of depthRenderbuffer */
|
||||||
|
GLenum depthBufferFormat;
|
||||||
|
}
|
||||||
|
|
||||||
@synthesize context;
|
@synthesize context;
|
||||||
|
@synthesize backingWidth;
|
||||||
|
@synthesize backingHeight;
|
||||||
|
|
||||||
+ (Class)layerClass
|
+ (Class)layerClass
|
||||||
{
|
{
|
||||||
return [CAEAGLLayer class];
|
return [CAEAGLLayer class];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
scale:(CGFloat)scale
|
scale:(CGFloat)scale
|
||||||
retainBacking:(BOOL)retained
|
retainBacking:(BOOL)retained
|
||||||
rBits:(int)rBits
|
rBits:(int)rBits
|
||||||
|
@ -46,146 +60,152 @@
|
||||||
aBits:(int)aBits
|
aBits:(int)aBits
|
||||||
depthBits:(int)depthBits
|
depthBits:(int)depthBits
|
||||||
stencilBits:(int)stencilBits
|
stencilBits:(int)stencilBits
|
||||||
|
sRGB:(BOOL)sRGB
|
||||||
majorVersion:(int)majorVersion
|
majorVersion:(int)majorVersion
|
||||||
shareGroup:(EAGLSharegroup*)shareGroup
|
shareGroup:(EAGLSharegroup*)shareGroup
|
||||||
{
|
{
|
||||||
depthBufferFormat = 0;
|
|
||||||
|
|
||||||
if ((self = [super initWithFrame:frame])) {
|
if ((self = [super initWithFrame:frame])) {
|
||||||
const BOOL useStencilBuffer = (stencilBits != 0);
|
const BOOL useStencilBuffer = (stencilBits != 0);
|
||||||
const BOOL useDepthBuffer = (depthBits != 0);
|
const BOOL useDepthBuffer = (depthBits != 0);
|
||||||
NSString *colorFormat = nil;
|
NSString *colorFormat = nil;
|
||||||
|
|
||||||
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
|
||||||
versions, and this allows us to handle future OpenGL ES versions.
|
* versions, and this allows us to handle future OpenGL ES versions. */
|
||||||
*/
|
|
||||||
EAGLRenderingAPI api = majorVersion;
|
EAGLRenderingAPI api = majorVersion;
|
||||||
|
|
||||||
if (rBits == 8 && gBits == 8 && bBits == 8) {
|
context = [[SDLEAGLContext alloc] initWithAPI:api sharegroup:shareGroup];
|
||||||
/* if user specifically requests rbg888 or some color format higher than 16bpp */
|
|
||||||
colorFormat = kEAGLColorFormatRGBA8;
|
|
||||||
} else {
|
|
||||||
/* default case (faster) */
|
|
||||||
colorFormat = kEAGLColorFormatRGB565;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the layer */
|
|
||||||
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]) {
|
if (!context || ![EAGLContext setCurrentContext:context]) {
|
||||||
[self release];
|
|
||||||
SDL_SetError("OpenGL ES %d not supported", majorVersion);
|
SDL_SetError("OpenGL ES %d not supported", majorVersion);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.sdlView = self;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
/* default case (potentially faster) */
|
||||||
|
colorFormat = kEAGLColorFormatRGB565;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
|
||||||
|
|
||||||
|
eaglLayer.opaque = YES;
|
||||||
|
eaglLayer.drawableProperties = @{
|
||||||
|
kEAGLDrawablePropertyRetainedBacking:@(retained),
|
||||||
|
kEAGLDrawablePropertyColorFormat:colorFormat
|
||||||
|
};
|
||||||
|
|
||||||
/* Set the appropriate scale (for retina display support) */
|
/* Set the appropriate scale (for retina display support) */
|
||||||
self.contentScaleFactor = scale;
|
self.contentScaleFactor = scale;
|
||||||
|
|
||||||
/* create the buffers */
|
/* Create the color Renderbuffer Object */
|
||||||
glGenFramebuffersOES(1, &viewFramebuffer);
|
glGenRenderbuffers(1, &viewRenderbuffer);
|
||||||
glGenRenderbuffersOES(1, &viewRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||||
|
|
||||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
|
if (![context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]) {
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
SDL_SetError("Failed to create OpenGL ES drawable");
|
||||||
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
|
return nil;
|
||||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
|
}
|
||||||
|
|
||||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
|
/* Create the Framebuffer Object */
|
||||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
|
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 ((useDepthBuffer) || (useStencilBuffer)) {
|
||||||
if (useStencilBuffer) {
|
if (useStencilBuffer) {
|
||||||
/* Apparently you need to pack stencil and depth into one buffer. */
|
/* Apparently you need to pack stencil and depth into one buffer. */
|
||||||
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
|
depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
|
||||||
} else if (useDepthBuffer) {
|
} else if (useDepthBuffer) {
|
||||||
/* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
|
/* iOS only uses 32-bit float (exposed as fixed point 24-bit)
|
||||||
|
* depth buffers. */
|
||||||
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
|
depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenRenderbuffersOES(1, &depthRenderbuffer);
|
glGenRenderbuffers(1, &depthRenderbuffer);
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
|
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||||
if (useDepthBuffer) {
|
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) {
|
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) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
return NO;
|
SDL_SetError("Failed creating OpenGL ES framebuffer");
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||||
/* end create buffers */
|
|
||||||
|
|
||||||
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
|
[self setDebugLabels];
|
||||||
self.autoresizesSubviews = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (GLuint)drawableRenderbuffer
|
||||||
|
{
|
||||||
|
return viewRenderbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (GLuint)drawableFramebuffer
|
||||||
|
{
|
||||||
|
return viewFramebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateFrame
|
- (void)updateFrame
|
||||||
{
|
{
|
||||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
|
GLint prevRenderbuffer = 0;
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
|
glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer);
|
||||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, 0);
|
|
||||||
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
|
|
||||||
|
|
||||||
glGenRenderbuffersOES(1, &viewRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
|
||||||
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
|
|
||||||
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
|
|
||||||
|
|
||||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
||||||
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
||||||
|
|
||||||
if (depthRenderbuffer != 0) {
|
if (depthRenderbuffer != 0) {
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
|
||||||
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
|
glRenderbufferStorage(GL_RENDERBUFFER, depthBufferFormat, backingWidth, backingHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, prevRenderbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAnimationCallback:(int)interval
|
- (void)setDebugLabels
|
||||||
callback:(void (*)(void*))callback
|
|
||||||
callbackParam:(void*)callbackParam
|
|
||||||
{
|
{
|
||||||
[self stopAnimation];
|
if (viewFramebuffer != 0) {
|
||||||
|
glLabelObjectEXT(GL_FRAMEBUFFER, viewFramebuffer, 0, "context FBO");
|
||||||
|
}
|
||||||
|
|
||||||
animationInterval = interval;
|
if (viewRenderbuffer != 0) {
|
||||||
animationCallback = callback;
|
glLabelObjectEXT(GL_RENDERBUFFER, viewRenderbuffer, 0, "context color buffer");
|
||||||
animationCallbackParam = callbackParam;
|
}
|
||||||
|
|
||||||
if (animationCallback)
|
if (depthRenderbuffer != 0) {
|
||||||
[self startAnimation];
|
if (depthBufferFormat == GL_DEPTH24_STENCIL8_OES) {
|
||||||
}
|
glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth-stencil buffer");
|
||||||
|
} else {
|
||||||
- (void)startAnimation
|
glLabelObjectEXT(GL_RENDERBUFFER, depthRenderbuffer, 0, "context depth buffer");
|
||||||
{
|
}
|
||||||
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(doLoop:)];
|
|
||||||
[displayLink setFrameInterval:animationInterval];
|
|
||||||
[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()) {
|
|
||||||
animationCallback(animationCallbackParam);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,44 +214,60 @@
|
||||||
[EAGLContext setCurrentContext:context];
|
[EAGLContext setCurrentContext:context];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)swapBuffers
|
- (void)swapBuffers
|
||||||
{
|
{
|
||||||
/* viewRenderbuffer should always be bound here. Code that binds something
|
/* viewRenderbuffer should always be bound here. Code that binds something
|
||||||
else is responsible for rebinding viewRenderbuffer, to reduce
|
* else is responsible for rebinding viewRenderbuffer, to reduce duplicate
|
||||||
duplicate state changes. */
|
* state changes. */
|
||||||
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
|
[context presentRenderbuffer:GL_RENDERBUFFER];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (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];
|
[EAGLContext setCurrentContext:context];
|
||||||
|
}
|
||||||
|
|
||||||
[self updateFrame];
|
[self updateFrame];
|
||||||
|
|
||||||
|
if (prevContext != context) {
|
||||||
|
[EAGLContext setCurrentContext:prevContext];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)destroyFramebuffer
|
- (void)destroyFramebuffer
|
||||||
{
|
{
|
||||||
glDeleteFramebuffersOES(1, &viewFramebuffer);
|
if (viewFramebuffer != 0) {
|
||||||
|
glDeleteFramebuffers(1, &viewFramebuffer);
|
||||||
viewFramebuffer = 0;
|
viewFramebuffer = 0;
|
||||||
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
|
}
|
||||||
viewRenderbuffer = 0;
|
|
||||||
|
|
||||||
if (depthRenderbuffer) {
|
if (viewRenderbuffer != 0) {
|
||||||
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
|
glDeleteRenderbuffers(1, &viewRenderbuffer);
|
||||||
|
viewRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depthRenderbuffer != 0) {
|
||||||
|
glDeleteRenderbuffers(1, &depthRenderbuffer);
|
||||||
depthRenderbuffer = 0;
|
depthRenderbuffer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
[self destroyFramebuffer];
|
|
||||||
if ([EAGLContext currentContext] == context) {
|
if ([EAGLContext currentContext] == context) {
|
||||||
|
[self destroyFramebuffer];
|
||||||
[EAGLContext setCurrentContext:nil];
|
[EAGLContext setCurrentContext:nil];
|
||||||
}
|
}
|
||||||
[context release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -25,20 +25,8 @@
|
||||||
|
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
|
|
||||||
#ifndef __IPHONE_6_0
|
BOOL UIKit_IsSystemVersionAtLeast(double version);
|
||||||
/* 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 */
|
CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
|
||||||
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 */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _SDL_uikitvideo_h */
|
#endif /* _SDL_uikitvideo_h */
|
||||||
|
|
||||||
|
|
|
@ -75,15 +75,15 @@ UIKit_CreateDevice(int devindex)
|
||||||
device->SetDisplayMode = UIKit_SetDisplayMode;
|
device->SetDisplayMode = UIKit_SetDisplayMode;
|
||||||
device->PumpEvents = UIKit_PumpEvents;
|
device->PumpEvents = UIKit_PumpEvents;
|
||||||
device->CreateWindow = UIKit_CreateWindow;
|
device->CreateWindow = UIKit_CreateWindow;
|
||||||
|
device->SetWindowTitle = UIKit_SetWindowTitle;
|
||||||
device->ShowWindow = UIKit_ShowWindow;
|
device->ShowWindow = UIKit_ShowWindow;
|
||||||
device->HideWindow = UIKit_HideWindow;
|
device->HideWindow = UIKit_HideWindow;
|
||||||
device->RaiseWindow = UIKit_RaiseWindow;
|
device->RaiseWindow = UIKit_RaiseWindow;
|
||||||
|
device->SetWindowBordered = UIKit_SetWindowBordered;
|
||||||
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
|
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
|
||||||
device->DestroyWindow = UIKit_DestroyWindow;
|
device->DestroyWindow = UIKit_DestroyWindow;
|
||||||
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
|
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
|
||||||
|
|
||||||
/* !!! FIXME: implement SetWindowBordered */
|
|
||||||
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
#if SDL_IPHONE_KEYBOARD
|
||||||
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
|
device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
|
||||||
device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
|
device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
|
||||||
|
@ -94,6 +94,7 @@ UIKit_CreateDevice(int devindex)
|
||||||
|
|
||||||
/* OpenGL (ES) functions */
|
/* OpenGL (ES) functions */
|
||||||
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
|
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
|
||||||
|
device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
|
||||||
device->GL_SwapWindow = UIKit_GL_SwapWindow;
|
device->GL_SwapWindow = UIKit_GL_SwapWindow;
|
||||||
device->GL_CreateContext = UIKit_GL_CreateContext;
|
device->GL_CreateContext = UIKit_GL_CreateContext;
|
||||||
device->GL_DeleteContext = UIKit_GL_DeleteContext;
|
device->GL_DeleteContext = UIKit_GL_DeleteContext;
|
||||||
|
@ -129,6 +130,25 @@ UIKit_VideoQuit(_THIS)
|
||||||
UIKit_QuitModes(_this);
|
UIKit_QuitModes(_this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
UIKit_IsSystemVersionAtLeast(double version)
|
||||||
|
{
|
||||||
|
return [[UIDevice currentDevice].systemVersion doubleValue] >= version;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
* iOS log support.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,59 +20,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import "SDL_uikitviewcontroller.h"
|
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
|
||||||
#include "SDL_touch.h"
|
#include "SDL_touch.h"
|
||||||
|
|
||||||
#define IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
@interface SDL_uikitview : UIView
|
||||||
|
|
||||||
#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
- (instancetype)initWithFrame:(CGRect)frame;
|
||||||
#define MAX_SIMULTANEOUS_TOUCHES 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
- (void)setSDLWindow:(SDL_Window *)window;
|
||||||
@interface SDL_uikitview : UIView<UITextFieldDelegate> {
|
|
||||||
#else
|
|
||||||
@interface SDL_uikitview : UIView {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_TouchID touchId;
|
|
||||||
UITouch *leftFingerDown;
|
|
||||||
#ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
|
||||||
UITouch *finger[MAX_SIMULTANEOUS_TOUCHES];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize;
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||||
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
|
||||||
- (void)showKeyboard;
|
|
||||||
- (void)hideKeyboard;
|
|
||||||
- (void)initializeKeyboard;
|
|
||||||
@property (readonly) BOOL keyboardVisible;
|
|
||||||
@property (nonatomic,assign) SDL_Rect textInputRect;
|
|
||||||
@property (nonatomic,assign) int keyboardHeight;
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -24,438 +24,167 @@
|
||||||
|
|
||||||
#include "SDL_uikitview.h"
|
#include "SDL_uikitview.h"
|
||||||
|
|
||||||
#include "../../events/SDL_keyboard_c.h"
|
|
||||||
#include "../../events/SDL_mouse_c.h"
|
#include "../../events/SDL_mouse_c.h"
|
||||||
#include "../../events/SDL_touch_c.h"
|
#include "../../events/SDL_touch_c.h"
|
||||||
|
#include "../../events/SDL_events_c.h"
|
||||||
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
#import "SDL_uikitappdelegate.h"
|
||||||
#include "keyinfotable.h"
|
#import "SDL_uikitmodes.h"
|
||||||
#endif
|
#import "SDL_uikitwindow.h"
|
||||||
#include "SDL_uikitappdelegate.h"
|
|
||||||
#include "SDL_uikitmodes.h"
|
|
||||||
#include "SDL_uikitwindow.h"
|
|
||||||
|
|
||||||
void _uikit_keyboard_init() ;
|
@implementation SDL_uikitview {
|
||||||
|
SDL_Window *sdlwindow;
|
||||||
|
|
||||||
@implementation SDL_uikitview
|
SDL_TouchID touchId;
|
||||||
|
UITouch * __weak firstFingerDown;
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
[super dealloc];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)frame
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame: frame];
|
if ((self = [super initWithFrame:frame])) {
|
||||||
|
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||||
#if SDL_IPHONE_KEYBOARD
|
self.autoresizesSubviews = YES;
|
||||||
[self initializeKeyboard];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
self.multipleTouchEnabled = YES;
|
self.multipleTouchEnabled = YES;
|
||||||
|
|
||||||
touchId = 1;
|
touchId = 1;
|
||||||
SDL_AddTouch(touchId, "");
|
SDL_AddTouch(touchId, "");
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSDLWindow:(SDL_Window *)window
|
||||||
|
{
|
||||||
|
SDL_WindowData *data = nil;
|
||||||
|
|
||||||
|
if (window == sdlwindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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. */
|
||||||
|
if (data.views.count > 0) {
|
||||||
|
view = data.views[data.views.count - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
data.viewcontroller.view = view;
|
||||||
|
|
||||||
|
if (data.uiwindow.rootViewController != data.viewcontroller) {
|
||||||
|
data.uiwindow.rootViewController = data.viewcontroller;
|
||||||
|
} else if (view) {
|
||||||
|
[data.uiwindow addSubview:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
[data.uiwindow layoutIfNeeded];
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (data.uiwindow.rootViewController != data.viewcontroller) {
|
||||||
|
/* The root view controller handles rotation and the status bar.
|
||||||
|
* Assigning it also adds the controller's view to the window. */
|
||||||
|
data.uiwindow.rootViewController = data.viewcontroller;
|
||||||
|
} else {
|
||||||
|
[data.uiwindow addSubview:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
|
||||||
{
|
{
|
||||||
CGPoint point = [touch locationInView: self];
|
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) {
|
if (normalize) {
|
||||||
CGRect bounds = [self bounds];
|
CGRect bounds = self.bounds;
|
||||||
point.x /= bounds.size.width;
|
point.x /= bounds.size.width;
|
||||||
point.y /= bounds.size.height;
|
point.y /= bounds.size.height;
|
||||||
} else {
|
|
||||||
point.x *= displaymodedata->scale;
|
|
||||||
point.y *= displaymodedata->scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
for (UITouch *touch in touches) {
|
||||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
if (!firstFingerDown) {
|
||||||
|
|
||||||
while (touch) {
|
|
||||||
if (!leftFingerDown) {
|
|
||||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||||
|
|
||||||
/* send moved event */
|
/* send mouse moved event */
|
||||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||||
|
|
||||||
/* send mouse down event */
|
/* send mouse down event */
|
||||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
|
||||||
|
|
||||||
leftFingerDown = touch;
|
firstFingerDown = touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
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_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||||
SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
|
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
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
for (UITouch *touch in touches) {
|
||||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
if (touch == firstFingerDown) {
|
||||||
|
|
||||||
while(touch) {
|
|
||||||
if (touch == leftFingerDown) {
|
|
||||||
/* send mouse up */
|
/* send mouse up */
|
||||||
SDL_SendMouseButton(self->viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||||
leftFingerDown = nil;
|
firstFingerDown = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
|
||||||
SDL_SendTouch(touchId, (long)touch,
|
|
||||||
SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
|
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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
/*
|
[self touchesEnded:touches withEvent:event];
|
||||||
this can happen if the user puts more than 5 touches on the screen
|
|
||||||
at once, or perhaps in other circumstances. Usually (it seems)
|
|
||||||
all active touches are canceled.
|
|
||||||
*/
|
|
||||||
[self touchesEnded: touches withEvent: event];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
NSEnumerator *enumerator = [touches objectEnumerator];
|
for (UITouch *touch in touches) {
|
||||||
UITouch *touch = (UITouch*)[enumerator nextObject];
|
if (touch == firstFingerDown) {
|
||||||
|
|
||||||
while (touch) {
|
|
||||||
if (touch == leftFingerDown) {
|
|
||||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
|
||||||
|
|
||||||
/* send moved event */
|
/* send moved event */
|
||||||
SDL_SendMouseMotion(self->viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
|
||||||
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
|
SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
|
||||||
SDL_SendTouchMotion(touchId, (long)touch,
|
|
||||||
locationInView.x, locationInView.y, 1.0f);
|
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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
---- Keyboard related functionality below this line ----
|
|
||||||
*/
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
|
||||||
|
|
||||||
@synthesize textInputRect = textInputRect;
|
|
||||||
@synthesize keyboardHeight = keyboardHeight;
|
|
||||||
|
|
||||||
/* Is the iPhone virtual keyboard visible onscreen? */
|
|
||||||
- (BOOL)keyboardVisible
|
|
||||||
{
|
|
||||||
return keyboardVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set ourselves up as a UITextFieldDelegate */
|
|
||||||
- (void)initializeKeyboard
|
|
||||||
{
|
|
||||||
textField = [[UITextField alloc] initWithFrame: CGRectZero];
|
|
||||||
textField.delegate = self;
|
|
||||||
/* placeholder so there is something to delete! */
|
|
||||||
textField.text = @" ";
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
/* add the UITextField (hidden) to our view */
|
|
||||||
[self addSubview: textField];
|
|
||||||
[textField release];
|
|
||||||
|
|
||||||
_uikit_keyboard_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reveal onscreen virtual keyboard */
|
|
||||||
- (void)showKeyboard
|
|
||||||
{
|
|
||||||
keyboardVisible = YES;
|
|
||||||
[textField becomeFirstResponder];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* hide onscreen virtual keyboard */
|
|
||||||
- (void)hideKeyboard
|
|
||||||
{
|
|
||||||
keyboardVisible = NO;
|
|
||||||
[textField resignFirstResponder];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UITextFieldDelegate method. Invoked when user types something. */
|
|
||||||
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
|
||||||
{
|
|
||||||
if ([string length] == 0) {
|
|
||||||
/* it wants to replace text with nothing, ie a delete */
|
|
||||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE);
|
|
||||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* go through all the characters in the string we've been sent
|
|
||||||
and convert them to key presses */
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < [string length]; i++) {
|
|
||||||
|
|
||||||
unichar c = [string characterAtIndex: i];
|
|
||||||
|
|
||||||
Uint16 mod = 0;
|
|
||||||
SDL_Scancode code;
|
|
||||||
|
|
||||||
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([string UTF8String]);
|
|
||||||
}
|
|
||||||
return NO; /* don't allow the edit! (keep placeholder text there) */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Terminates the editing session */
|
|
||||||
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
|
|
||||||
{
|
|
||||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
|
|
||||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
|
|
||||||
SDL_StopTextInput();
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* iPhone keyboard addition functions */
|
|
||||||
#if SDL_IPHONE_KEYBOARD
|
|
||||||
|
|
||||||
static SDL_uikitview * getWindowView(SDL_Window * window)
|
|
||||||
{
|
|
||||||
if (window == NULL) {
|
|
||||||
SDL_SetError("Window does not exist");
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
|
||||||
SDL_uikitview *view = data != NULL ? data->view : nil;
|
|
||||||
|
|
||||||
if (view == nil) {
|
|
||||||
SDL_SetError("Window has no view");
|
|
||||||
}
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_bool UIKit_HasScreenKeyboardSupport(_THIS)
|
|
||||||
{
|
|
||||||
return SDL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
|
|
||||||
{
|
|
||||||
SDL_uikitview *view = getWindowView(window);
|
|
||||||
if (view != nil) {
|
|
||||||
[view showKeyboard];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
|
|
||||||
{
|
|
||||||
SDL_uikitview *view = getWindowView(window);
|
|
||||||
if (view != nil) {
|
|
||||||
[view hideKeyboard];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
|
|
||||||
{
|
|
||||||
SDL_uikitview *view = getWindowView(window);
|
|
||||||
if (view == nil) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return view.keyboardVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _uikit_keyboard_update() {
|
|
||||||
SDL_Window *window = SDL_GetFocusWindow();
|
|
||||||
if (!window) { return; }
|
|
||||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
|
||||||
if (!data) { return; }
|
|
||||||
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);
|
|
||||||
int bottom = (r.y + r.h);
|
|
||||||
int kbottom = sh - height;
|
|
||||||
if (kbottom < bottom) {
|
|
||||||
offsety = kbottom-bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
|
|
||||||
if (ui_orient == UIInterfaceOrientationLandscapeLeft) {
|
|
||||||
int tmp = offsetx; offsetx = offsety; offsety = tmp;
|
|
||||||
}
|
|
||||||
if (ui_orient == UIInterfaceOrientationLandscapeRight) {
|
|
||||||
offsety = -offsety;
|
|
||||||
int tmp = offsetx; offsetx = offsety; offsety = tmp;
|
|
||||||
}
|
|
||||||
if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) {
|
|
||||||
offsety = -offsety;
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetx /= scale;
|
|
||||||
offsety /= scale;
|
|
||||||
|
|
||||||
view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _uikit_keyboard_set_height(int height) {
|
|
||||||
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
|
|
||||||
if (view == nil) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
view.keyboardHeight = height;
|
|
||||||
_uikit_keyboard_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _uikit_keyboard_init() {
|
|
||||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
|
||||||
NSOperationQueue *queue = [NSOperationQueue mainQueue];
|
|
||||||
[center addObserverForName:UIKeyboardWillShowNotification
|
|
||||||
object:nil
|
|
||||||
queue:queue
|
|
||||||
usingBlock:^(NSNotification *notification) {
|
|
||||||
int height = 0;
|
|
||||||
CGSize keyboardSize = [[[notification userInfo] objectForKey: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);
|
|
||||||
}
|
|
||||||
];
|
|
||||||
[center addObserverForName:UIKeyboardDidHideNotification
|
|
||||||
object:nil
|
|
||||||
queue:queue
|
|
||||||
usingBlock:^(NSNotification *notification) {
|
|
||||||
_uikit_keyboard_set_height(0);
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
|
|
||||||
{
|
|
||||||
if (!rect) {
|
|
||||||
SDL_InvalidParamError("rect");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
|
|
||||||
if (view == nil) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
view.textInputRect = *rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SDL_IPHONE_KEYBOARD */
|
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -23,18 +23,56 @@
|
||||||
|
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
|
|
||||||
@interface SDL_uikitviewcontroller : UIViewController {
|
#include "SDL_touch.h"
|
||||||
@private
|
|
||||||
SDL_Window *window;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (readwrite) SDL_Window *window;
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
@interface SDL_uikitviewcontroller : UIViewController <UITextFieldDelegate>
|
||||||
|
#else
|
||||||
|
@interface SDL_uikitviewcontroller : UIViewController
|
||||||
|
#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;
|
||||||
|
|
||||||
- (id)initWithSDLWindow:(SDL_Window *)_window;
|
|
||||||
- (void)loadView;
|
- (void)loadView;
|
||||||
- (void)viewDidLayoutSubviews;
|
- (void)viewDidLayoutSubviews;
|
||||||
- (NSUInteger)supportedInterfaceOrientations;
|
- (NSUInteger)supportedInterfaceOrientations;
|
||||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient;
|
||||||
- (BOOL)prefersStatusBarHidden;
|
- (BOOL)prefersStatusBarHidden;
|
||||||
|
- (UIStatusBarStyle)preferredStatusBarStyle;
|
||||||
|
|
||||||
|
#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
|
@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
|
||||||
|
|
|
@ -28,108 +28,389 @@
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
|
|
||||||
#include "SDL_uikitviewcontroller.h"
|
#import "SDL_uikitviewcontroller.h"
|
||||||
|
#import "SDL_uikitmessagebox.h"
|
||||||
#include "SDL_uikitvideo.h"
|
#include "SDL_uikitvideo.h"
|
||||||
#include "SDL_uikitmodes.h"
|
#include "SDL_uikitmodes.h"
|
||||||
#include "SDL_uikitwindow.h"
|
#include "SDL_uikitwindow.h"
|
||||||
|
|
||||||
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
#include "keyinfotable.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
@implementation SDL_uikitviewcontroller
|
@implementation SDL_uikitviewcontroller {
|
||||||
|
CADisplayLink *displayLink;
|
||||||
|
int animationInterval;
|
||||||
|
void (*animationCallback)(void*);
|
||||||
|
void *animationCallbackParam;
|
||||||
|
|
||||||
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
UITextField *textField;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@synthesize window;
|
@synthesize window;
|
||||||
|
|
||||||
- (id)initWithSDLWindow:(SDL_Window *)_window
|
- (instancetype)initWithSDLWindow:(SDL_Window *)_window
|
||||||
{
|
{
|
||||||
self = [self init];
|
if (self = [super initWithNibName:nil bundle:nil]) {
|
||||||
if (self == nil) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
self.window = _window;
|
self.window = _window;
|
||||||
|
|
||||||
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
[self initKeyboard];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
[self deinitKeyboard];
|
||||||
|
#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:)];
|
||||||
|
[displayLink setFrameInterval:animationInterval];
|
||||||
|
[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()) {
|
||||||
|
animationCallback(animationCallbackParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)loadView
|
- (void)loadView
|
||||||
{
|
{
|
||||||
/* do nothing. */
|
/* Do nothing. */
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidLayoutSubviews
|
- (void)viewDidLayoutSubviews
|
||||||
{
|
{
|
||||||
if (self->window->flags & SDL_WINDOW_RESIZABLE) {
|
const CGSize size = self.view.bounds.size;
|
||||||
SDL_WindowData *data = self->window->driverdata;
|
int w = (int) size.width;
|
||||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(self->window);
|
int h = (int) size.height;
|
||||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
|
||||||
const CGSize size = data->view.bounds.size;
|
|
||||||
int w, h;
|
|
||||||
|
|
||||||
w = (int)(size.width * displaymodedata->scale);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||||
h = (int)(size.height * displaymodedata->scale);
|
|
||||||
|
|
||||||
SDL_SendWindowEvent(self->window, SDL_WINDOWEVENT_RESIZED, w, h);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)supportedInterfaceOrientations
|
- (NSUInteger)supportedInterfaceOrientations
|
||||||
{
|
{
|
||||||
NSUInteger orientationMask = 0;
|
return UIKit_GetSupportedOrientations(window);
|
||||||
|
|
||||||
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 ([orientations containsObject:@"LandscapeLeft"]) {
|
|
||||||
orientationMask |= UIInterfaceOrientationMaskLandscapeLeft;
|
|
||||||
}
|
|
||||||
if ([orientations containsObject:@"LandscapeRight"]) {
|
|
||||||
orientationMask |= UIInterfaceOrientationMaskLandscapeRight;
|
|
||||||
}
|
|
||||||
if ([orientations containsObject:@"Portrait"]) {
|
|
||||||
orientationMask |= UIInterfaceOrientationMaskPortrait;
|
|
||||||
}
|
|
||||||
if ([orientations containsObject:@"PortraitUpsideDown"]) {
|
|
||||||
orientationMask |= UIInterfaceOrientationMaskPortraitUpsideDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (self->window->flags & SDL_WINDOW_RESIZABLE) {
|
|
||||||
orientationMask = UIInterfaceOrientationMaskAll; /* any orientation is okay. */
|
|
||||||
} else {
|
|
||||||
if (self->window->w >= self->window->h) {
|
|
||||||
orientationMask |= UIInterfaceOrientationMaskLandscape;
|
|
||||||
}
|
|
||||||
if (self->window->h >= self->window->w) {
|
|
||||||
orientationMask |= (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient
|
||||||
{
|
{
|
||||||
NSUInteger orientationMask = [self supportedInterfaceOrientations];
|
return ([self supportedInterfaceOrientations] & (1 << orient)) != 0;
|
||||||
return (orientationMask & (1 << orient));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)prefersStatusBarHidden
|
- (BOOL)prefersStatusBarHidden
|
||||||
{
|
{
|
||||||
if (self->window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
|
||||||
return YES;
|
}
|
||||||
} else {
|
|
||||||
return NO;
|
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||||
|
{
|
||||||
|
/* We assume most SDL apps don't have a bright white background. */
|
||||||
|
return UIStatusBarStyleLightContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
---- Keyboard related functionality below this line ----
|
||||||
|
*/
|
||||||
|
#if SDL_IPHONE_KEYBOARD
|
||||||
|
|
||||||
|
@synthesize textInputRect;
|
||||||
|
@synthesize keyboardHeight;
|
||||||
|
@synthesize keyboardVisible;
|
||||||
|
|
||||||
|
/* Set ourselves up as a UITextFieldDelegate */
|
||||||
|
- (void)initKeyboard
|
||||||
|
{
|
||||||
|
textField = [[UITextField alloc] initWithFrame:CGRectZero];
|
||||||
|
textField.delegate = self;
|
||||||
|
/* placeholder so there is something to delete! */
|
||||||
|
textField.text = @" ";
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
[center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
|
||||||
|
[center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setView:(UIView *)view
|
||||||
|
{
|
||||||
|
[super setView:view];
|
||||||
|
|
||||||
|
[view addSubview:textField];
|
||||||
|
|
||||||
|
if (keyboardVisible) {
|
||||||
|
[self showKeyboard];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)deinitKeyboard
|
||||||
|
{
|
||||||
|
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||||
|
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
|
||||||
|
[center removeObserver:self name:UIKeyboardWillHideNotification 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
|
||||||
|
{
|
||||||
|
CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue];
|
||||||
|
UIView *view = self.view;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
/* The keyboard rect is in the coordinate space of the screen, but we want
|
||||||
|
* its height in the view's coordinate space. */
|
||||||
|
#ifdef __IPHONE_8_0
|
||||||
|
if ([view respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) {
|
||||||
|
UIScreen *screen = view.window.screen;
|
||||||
|
kbrect = [view convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace];
|
||||||
|
height = kbrect.size.height;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* In iOS 7 and below, the screen's coordinate space is never rotated. */
|
||||||
|
if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
|
||||||
|
height = kbrect.size.width;
|
||||||
|
} else {
|
||||||
|
height = kbrect.size.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self setKeyboardHeight:height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyboardWillHide:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
[self setKeyboardHeight:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateKeyboard
|
||||||
|
{
|
||||||
|
SDL_Rect textrect = self.textInputRect;
|
||||||
|
CGAffineTransform t = self.view.transform;
|
||||||
|
CGPoint offset = CGPointMake(0.0, 0.0);
|
||||||
|
|
||||||
|
if (self.keyboardHeight) {
|
||||||
|
int rectbottom = textrect.y + textrect.h;
|
||||||
|
int kbottom = self.view.bounds.size.height - self.keyboardHeight;
|
||||||
|
if (kbottom < rectbottom) {
|
||||||
|
offset.y = kbottom - rectbottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the offset into the this view transform's coordinate space. */
|
||||||
|
t.tx = 0.0;
|
||||||
|
t.ty = 0.0;
|
||||||
|
offset = CGPointApplyAffineTransform(offset, t);
|
||||||
|
|
||||||
|
t.tx = offset.x;
|
||||||
|
t.ty = offset.y;
|
||||||
|
|
||||||
|
/* Move the view by applying the updated transform. */
|
||||||
|
self.view.transform = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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) {
|
||||||
|
/* it wants to replace text with nothing, ie a delete */
|
||||||
|
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE);
|
||||||
|
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE);
|
||||||
|
} else {
|
||||||
|
/* 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 = [string characterAtIndex:i];
|
||||||
|
Uint16 mod = 0;
|
||||||
|
SDL_Scancode code;
|
||||||
|
|
||||||
|
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([string UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO; /* don't allow the edit! (keep placeholder text there) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminates the editing session */
|
||||||
|
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
|
||||||
|
{
|
||||||
|
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
|
||||||
|
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
|
||||||
|
SDL_StopTextInput();
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@end
|
@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.isKeyboardVisible;
|
||||||
|
}
|
||||||
|
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 */
|
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -23,28 +23,33 @@
|
||||||
|
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
#import "SDL_uikitvideo.h"
|
#import "SDL_uikitvideo.h"
|
||||||
#import "SDL_uikitopenglview.h"
|
#import "SDL_uikitview.h"
|
||||||
#import "SDL_uikitviewcontroller.h"
|
#import "SDL_uikitviewcontroller.h"
|
||||||
|
|
||||||
typedef struct SDL_WindowData SDL_WindowData;
|
|
||||||
|
|
||||||
extern int UIKit_CreateWindow(_THIS, SDL_Window * window);
|
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_ShowWindow(_THIS, SDL_Window * window);
|
||||||
extern void UIKit_HideWindow(_THIS, SDL_Window * window);
|
extern void UIKit_HideWindow(_THIS, SDL_Window * window);
|
||||||
extern void UIKit_RaiseWindow(_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_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
|
||||||
extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
|
extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
|
||||||
extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
|
extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
|
||||||
struct SDL_SysWMinfo * info);
|
struct SDL_SysWMinfo * info);
|
||||||
|
|
||||||
|
extern NSUInteger UIKit_GetSupportedOrientations(SDL_Window * window);
|
||||||
|
|
||||||
@class UIWindow;
|
@class UIWindow;
|
||||||
|
|
||||||
struct SDL_WindowData
|
@interface SDL_WindowData : NSObject
|
||||||
{
|
|
||||||
UIWindow *uiwindow;
|
@property (nonatomic, strong) UIWindow *uiwindow;
|
||||||
SDL_uikitopenglview *view;
|
@property (nonatomic, strong) SDL_uikitviewcontroller *viewcontroller;
|
||||||
SDL_uikitviewcontroller *viewcontroller;
|
|
||||||
};
|
/* Array of SDL_uikitviews owned by this window. */
|
||||||
|
@property (nonatomic, copy) NSMutableArray *views;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
#endif /* _SDL_uikitwindow_h */
|
#endif /* _SDL_uikitwindow_h */
|
||||||
|
|
||||||
|
|
|
@ -37,89 +37,110 @@
|
||||||
#include "SDL_uikitwindow.h"
|
#include "SDL_uikitwindow.h"
|
||||||
#import "SDL_uikitappdelegate.h"
|
#import "SDL_uikitappdelegate.h"
|
||||||
|
|
||||||
#import "SDL_uikitopenglview.h"
|
#import "SDL_uikitview.h"
|
||||||
|
|
||||||
#include <Foundation/Foundation.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)
|
static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
|
||||||
{
|
{
|
||||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
SDL_DisplayData *displaydata = (__bridge SDL_DisplayData *) display->driverdata;
|
||||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
SDL_uikitview *view;
|
||||||
SDL_WindowData *data;
|
|
||||||
|
|
||||||
/* Allocate the window data */
|
CGRect frame = UIKit_ComputeViewFrame(window, displaydata.uiscreen);
|
||||||
data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
|
int width = (int) frame.size.width;
|
||||||
|
int height = (int) frame.size.height;
|
||||||
|
|
||||||
|
SDL_WindowData *data = [[SDL_WindowData alloc] init];
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
data->uiwindow = uiwindow;
|
|
||||||
data->viewcontroller = nil;
|
|
||||||
data->view = nil;
|
|
||||||
|
|
||||||
/* Fill in the SDL window with the window data */
|
window->driverdata = (void *) CFBridgingRetain(data);
|
||||||
{
|
|
||||||
window->x = 0;
|
|
||||||
window->y = 0;
|
|
||||||
|
|
||||||
CGRect bounds;
|
data.uiwindow = uiwindow;
|
||||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
|
||||||
bounds = [displaydata->uiscreen bounds];
|
|
||||||
} else {
|
|
||||||
bounds = [displaydata->uiscreen applicationFrame];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get frame dimensions in pixels */
|
|
||||||
int width = (int)(bounds.size.width * displaymodedata->scale);
|
|
||||||
int height = (int)(bounds.size.height * displaymodedata->scale);
|
|
||||||
|
|
||||||
/* Make sure the width/height are oriented correctly */
|
|
||||||
if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
|
|
||||||
int temp = width;
|
|
||||||
width = height;
|
|
||||||
height = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->w = width;
|
|
||||||
window->h = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->driverdata = data;
|
|
||||||
|
|
||||||
/* only one window on iOS, always shown */
|
/* only one window on iOS, always shown */
|
||||||
window->flags &= ~SDL_WINDOW_HIDDEN;
|
window->flags &= ~SDL_WINDOW_HIDDEN;
|
||||||
|
|
||||||
/* SDL_WINDOW_BORDERLESS controls whether status bar is hidden.
|
if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
||||||
* 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]) {
|
|
||||||
window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
|
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
|
|
||||||
if ([UIApplication sharedApplication].statusBarHidden) {
|
|
||||||
window->flags |= SDL_WINDOW_BORDERLESS;
|
|
||||||
} else {
|
} else {
|
||||||
window->flags &= ~SDL_WINDOW_BORDERLESS;
|
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizable */
|
||||||
}
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
|
|
||||||
window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
|
window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
|
||||||
window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
|
window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The View Controller will handle rotating the view when the
|
if (displaydata.uiscreen == [UIScreen mainScreen]) {
|
||||||
* device orientation changes. This will trigger resize events, if
|
NSUInteger orients = UIKit_GetSupportedOrientations(window);
|
||||||
* appropriate.
|
BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0;
|
||||||
*/
|
BOOL supportsPortrait = (orients & (UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown)) != 0;
|
||||||
SDL_uikitviewcontroller *controller;
|
|
||||||
controller = [SDL_uikitviewcontroller alloc];
|
/* Make sure the width/height are oriented correctly */
|
||||||
data->viewcontroller = [controller initWithSDLWindow:window];
|
if ((width > height && !supportsLandscape) || (height > width && !supportsPortrait)) {
|
||||||
[data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */
|
int temp = width;
|
||||||
|
width = height;
|
||||||
|
height = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -127,10 +148,10 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
|
||||||
int
|
int
|
||||||
UIKit_CreateWindow(_THIS, SDL_Window *window)
|
UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||||
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
|
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
|
||||||
const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
|
const CGSize origsize = data.uiscreen.currentMode.size;
|
||||||
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 currently puts this window at the start of display's linked list. We rely on this. */
|
||||||
SDL_assert(_this->windows == window);
|
SDL_assert(_this->windows == window);
|
||||||
|
@ -142,8 +163,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||||
|
|
||||||
/* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
|
/* 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
|
* user, so it's in standby), try to force the display to a resolution
|
||||||
* that most closely matches the desired window size.
|
* that most closely matches the desired window size. */
|
||||||
*/
|
|
||||||
if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
|
if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
|
||||||
if (display->num_display_modes == 0) {
|
if (display->num_display_modes == 0) {
|
||||||
_this->GetDisplayModes(_this, display);
|
_this->GetDisplayModes(_this, display);
|
||||||
|
@ -153,79 +173,79 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
|
||||||
const SDL_DisplayMode *bestmode = NULL;
|
const SDL_DisplayMode *bestmode = NULL;
|
||||||
for (i = display->num_display_modes; i >= 0; i--) {
|
for (i = display->num_display_modes; i >= 0; i--) {
|
||||||
const SDL_DisplayMode *mode = &display->display_modes[i];
|
const SDL_DisplayMode *mode = &display->display_modes[i];
|
||||||
if ((mode->w >= window->w) && (mode->h >= window->h))
|
if ((mode->w >= window->w) && (mode->h >= window->h)) {
|
||||||
bestmode = mode;
|
bestmode = mode;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bestmode) {
|
if (bestmode) {
|
||||||
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
|
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)bestmode->driverdata;
|
||||||
[data->uiscreen setCurrentMode:modedata->uiscreenmode];
|
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
|
||||||
|
|
||||||
/* desktop_mode doesn't change here (the higher level will
|
/* desktop_mode doesn't change here (the higher level will
|
||||||
* use it to set all the screens back to their defaults
|
* use it to set all the screens back to their defaults
|
||||||
* upon window destruction, SDL_Quit(), etc.
|
* upon window destruction, SDL_Quit(), etc. */
|
||||||
*/
|
|
||||||
display->current_mode = *bestmode;
|
display->current_mode = *bestmode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->uiscreen == [UIScreen mainScreen]) {
|
if (data.uiscreen == [UIScreen mainScreen]) {
|
||||||
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
NSUInteger orientations = UIKit_GetSupportedOrientations(window);
|
||||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
UIApplication *app = [UIApplication sharedApplication];
|
||||||
} else {
|
|
||||||
[UIApplication sharedApplication].statusBarHidden = NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
|
||||||
if (window->w > window->h) {
|
app.statusBarHidden = YES;
|
||||||
if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
|
} else {
|
||||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
|
app.statusBarHidden = NO;
|
||||||
}
|
|
||||||
} else if (window->w < window->h) {
|
|
||||||
if (UIKit_IsDisplayLandscape(data->uiscreen)) {
|
|
||||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore the size user requested, and make a fullscreen window */
|
/* ignore the size user requested, and make a fullscreen window */
|
||||||
/* !!! FIXME: can we have a smaller view? */
|
/* !!! FIXME: can we have a smaller view? */
|
||||||
UIWindow *uiwindow = [UIWindow alloc];
|
UIWindow *uiwindow = [[SDL_uikitwindow alloc] initWithFrame:data.uiscreen.bounds];
|
||||||
uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
|
|
||||||
|
|
||||||
/* put the window on an external display if appropriate. This implicitly
|
/* put the window on an external display if appropriate. */
|
||||||
* does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
|
if (data.uiscreen != [UIScreen mainScreen]) {
|
||||||
* main display, where we land by default, as that would eat the
|
[uiwindow setScreen:data.uiscreen];
|
||||||
* status bar real estate.
|
|
||||||
*/
|
|
||||||
if (external) {
|
|
||||||
[uiwindow setScreen:data->uiscreen];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
|
||||||
[uiwindow release];
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UIKit_SetWindowTitle(_THIS, SDL_Window * window)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
|
if (window->title) {
|
||||||
|
data.viewcontroller.title = @(window->title);
|
||||||
|
} else {
|
||||||
|
data.viewcontroller.title = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UIKit_ShowWindow(_THIS, SDL_Window * window)
|
UIKit_ShowWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
@autoreleasepool {
|
||||||
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
[uiwindow makeKeyAndVisible];
|
[data.uiwindow makeKeyAndVisible];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UIKit_HideWindow(_THIS, SDL_Window * window)
|
UIKit_HideWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
@autoreleasepool {
|
||||||
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
uiwindow.hidden = YES;
|
data.uiwindow.hidden = YES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -234,66 +254,59 @@ UIKit_RaiseWindow(_THIS, SDL_Window * window)
|
||||||
/* We don't currently offer a concept of "raising" the SDL window, since
|
/* We don't currently offer a concept of "raising" the SDL window, since
|
||||||
* we only allow one per display, in the iOS fashion.
|
* we only allow one per display, in the iOS fashion.
|
||||||
* However, we use this entry point to rebind the context to the view
|
* However, we use this entry point to rebind the context to the view
|
||||||
* during OnWindowRestored processing.
|
* during OnWindowRestored processing. */
|
||||||
*/
|
|
||||||
_this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
|
_this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
|
SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
|
||||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
|
||||||
|
|
||||||
if (fullscreen) {
|
if (data.uiwindow.screen == [UIScreen mainScreen]) {
|
||||||
|
if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) {
|
||||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||||
} else {
|
} else {
|
||||||
[UIApplication sharedApplication].statusBarHidden = NO;
|
[UIApplication sharedApplication].statusBarHidden = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGRect bounds;
|
/* iOS 7+ won't update the status bar until we tell it to. */
|
||||||
if (fullscreen) {
|
if ([viewcontroller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
|
||||||
bounds = [displaydata->uiscreen bounds];
|
[viewcontroller setNeedsStatusBarAppearanceUpdate];
|
||||||
} else {
|
}
|
||||||
bounds = [displaydata->uiscreen applicationFrame];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get frame dimensions in pixels */
|
/* Update the view's frame to account for the status bar change. */
|
||||||
int width = (int)(bounds.size.width * displaymodedata->scale);
|
viewcontroller.view.frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
|
||||||
int height = (int)(bounds.size.height * displaymodedata->scale);
|
[viewcontroller.view setNeedsLayout];
|
||||||
|
[viewcontroller.view layoutIfNeeded];
|
||||||
|
}
|
||||||
|
|
||||||
/* We can pick either width or height here and we'll rotate the
|
void
|
||||||
screen to match, so we pick the closest to what we wanted.
|
UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
||||||
*/
|
{
|
||||||
if (window->w >= window->h) {
|
@autoreleasepool {
|
||||||
if (width > height) {
|
UIKit_UpdateWindowBorder(_this, window);
|
||||||
window->w = width;
|
|
||||||
window->h = height;
|
|
||||||
} else {
|
|
||||||
window->w = height;
|
|
||||||
window->h = width;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (width > height) {
|
|
||||||
window->w = height;
|
|
||||||
window->h = width;
|
|
||||||
} else {
|
|
||||||
window->w = width;
|
|
||||||
window->h = height;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
UIKit_UpdateWindowBorder(_this, window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
@autoreleasepool {
|
||||||
|
if (window->driverdata != NULL) {
|
||||||
if (data) {
|
SDL_WindowData *data = (SDL_WindowData *) CFBridgingRelease(window->driverdata);
|
||||||
[data->viewcontroller release];
|
[data.viewcontroller stopAnimation];
|
||||||
[data->uiwindow release];
|
}
|
||||||
SDL_free(data);
|
|
||||||
}
|
}
|
||||||
window->driverdata = NULL;
|
window->driverdata = NULL;
|
||||||
}
|
}
|
||||||
|
@ -301,29 +314,82 @@ UIKit_DestroyWindow(_THIS, SDL_Window * window)
|
||||||
SDL_bool
|
SDL_bool
|
||||||
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||||
{
|
{
|
||||||
UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
|
@autoreleasepool {
|
||||||
|
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
|
||||||
|
|
||||||
if (info->version.major <= SDL_MAJOR_VERSION) {
|
if (info->version.major <= SDL_MAJOR_VERSION) {
|
||||||
info->subsystem = SDL_SYSWM_UIKIT;
|
info->subsystem = SDL_SYSWM_UIKIT;
|
||||||
info->info.uikit.window = uiwindow;
|
info->info.uikit.window = data.uiwindow;
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
} else {
|
} else {
|
||||||
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
SDL_SetError("Application not compiled with SDL %d.%d\n",
|
||||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSUInteger
|
||||||
|
UIKit_GetSupportedOrientations(SDL_Window * window)
|
||||||
|
{
|
||||||
|
const char *hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
|
||||||
|
NSUInteger orientationMask = 0;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
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 the phone, so answering calls is in the natural orientation */
|
||||||
|
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
|
||||||
|
orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return orientationMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
|
SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
|
if (!window || !window->driverdata) {
|
||||||
|
return SDL_SetError("Invalid window");
|
||||||
if (!data || !data->view) {
|
}
|
||||||
return SDL_SetError("Invalid window or view not set");
|
|
||||||
|
@autoreleasepool {
|
||||||
|
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
|
||||||
|
[data.viewcontroller setAnimationCallback:interval
|
||||||
|
callback:callback
|
||||||
|
callbackParam:callbackParam];
|
||||||
}
|
}
|
||||||
|
|
||||||
[data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue