Added mobile application events, with implementations for iOS and Android
This commit is contained in:
parent
2ff60371f5
commit
2ac8624930
9 changed files with 182 additions and 44 deletions
63
README.iOS
63
README.iOS
|
@ -54,6 +54,69 @@ Here is a more manual method:
|
||||||
4. Remove the ApplicationDelegate.h and ApplicationDelegate.m files -- SDL for iPhone provides its own UIApplicationDelegate. Remove MainWindow.xib -- SDL for iPhone produces its user interface programmatically.
|
4. Remove the ApplicationDelegate.h and ApplicationDelegate.m files -- SDL for iPhone provides its own UIApplicationDelegate. Remove MainWindow.xib -- SDL for iPhone produces its user interface programmatically.
|
||||||
5. Delete the contents of main.m and program your app as a regular SDL program instead. You may replace main.m with your own main.c, but you must tell XCode not to use the project prefix file, as it includes Objective-C code.
|
5. Delete the contents of main.m and program your app as a regular SDL program instead. You may replace main.m with your own main.c, but you must tell XCode not to use the project prefix file, as it includes Objective-C code.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
Notes -- Application events
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
On iOS the application goes through a fixed life cycle and you will get
|
||||||
|
notifications of state changes via application events. When these events
|
||||||
|
are delivered you must handle them in an event callback because the OS may
|
||||||
|
not give you any processing time after the events are delivered.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
int HandleAppEvents(void *userdata, SDL_Event *event)
|
||||||
|
{
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case SDL_APP_TERMINATING:
|
||||||
|
/* Terminate the app.
|
||||||
|
Shut everything down before returning from this function.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
case SDL_APP_LOWMEMORY:
|
||||||
|
/* You will get this when your app is paused and iOS wants more memory.
|
||||||
|
Release as much memory as possible.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
case SDL_APP_WILLENTERBACKGROUND:
|
||||||
|
/* Prepare your app to go into the background. Stop loops, etc.
|
||||||
|
This gets called when the user hits the home button, or gets a call.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
case SDL_APP_DIDENTERBACKGROUND:
|
||||||
|
/* This will get called if the user accepted whatever sent your app to the background.
|
||||||
|
If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.
|
||||||
|
When you get this, you have 5 seconds to save all your state or the app will be terminated.
|
||||||
|
Your app is NOT active at this point.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
case SDL_APP_WILLENTERFOREGROUND:
|
||||||
|
/* This call happens when your app is coming back to the foreground.
|
||||||
|
Restore all your state here.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
case SDL_APP_DIDENTERFOREGROUND:
|
||||||
|
/* Restart your loops here.
|
||||||
|
Your app is interactive and getting CPU again.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
/* No special processing, add it to the event queue */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
SDL_SetEventFilter(HandleAppEvents, NULL);
|
||||||
|
|
||||||
|
... run your main loop
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
Notes -- Accelerometer as Joystick
|
Notes -- Accelerometer as Joystick
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
|
@ -78,17 +78,26 @@ public class SDLActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
/*protected void onPause() {
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
Log.v("SDL", "onPause()");
|
Log.v("SDL", "onPause()");
|
||||||
super.onPause();
|
super.onPause();
|
||||||
// Don't call SDLActivity.nativePause(); here, it will be called by SDLSurface::surfaceDestroyed
|
// Don't call SDLActivity.nativePause(); here, it will be called by SDLSurface::surfaceDestroyed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
Log.v("SDL", "onResume()");
|
Log.v("SDL", "onResume()");
|
||||||
super.onResume();
|
super.onResume();
|
||||||
// Don't call SDLActivity.nativeResume(); here, it will be called via SDLSurface::surfaceChanged->SDLActivity::startApp
|
// Don't call SDLActivity.nativeResume(); here, it will be called via SDLSurface::surfaceChanged->SDLActivity::startApp
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLowMemory() {
|
||||||
|
Log.v("SDL", "onLowMemory()");
|
||||||
|
super.onLowMemory();
|
||||||
|
SDLActivity.nativeLowMemory();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
|
@ -180,6 +189,7 @@ public class SDLActivity extends Activity {
|
||||||
|
|
||||||
// C functions we call
|
// C functions we call
|
||||||
public static native void nativeInit();
|
public static native void nativeInit();
|
||||||
|
public static native void nativeLowMemory();
|
||||||
public static native void nativeQuit();
|
public static native void nativeQuit();
|
||||||
public static native void nativePause();
|
public static native void nativePause();
|
||||||
public static native void nativeResume();
|
public static native void nativeResume();
|
||||||
|
@ -600,8 +610,6 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||||
public void onDraw(Canvas canvas) {}
|
public void onDraw(Canvas canvas) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Key events
|
// Key events
|
||||||
@Override
|
@Override
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||||
|
|
|
@ -61,6 +61,32 @@ typedef enum
|
||||||
/* Application events */
|
/* Application events */
|
||||||
SDL_QUIT = 0x100, /**< User-requested quit */
|
SDL_QUIT = 0x100, /**< User-requested quit */
|
||||||
|
|
||||||
|
/* These application events have special meaning on iOS, see README.iOS for details */
|
||||||
|
SDL_APP_TERMINATING, /**< The application is being terminated by the OS
|
||||||
|
Called on iOS in applicationWillTerminate()
|
||||||
|
Called on Android in onDestroy()
|
||||||
|
*/
|
||||||
|
SDL_APP_LOWMEMORY, /**< The application is low on memory, free memory if possible.
|
||||||
|
Called on iOS in applicationDidReceiveMemoryWarning()
|
||||||
|
Called on Android in onLowMemory()
|
||||||
|
*/
|
||||||
|
SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
|
||||||
|
Called on iOS in applicationWillResignActive()
|
||||||
|
Called on Android in onPause()
|
||||||
|
*/
|
||||||
|
SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
|
||||||
|
Called on iOS in applicationDidEnterBackground()
|
||||||
|
Called on Android in onPause()
|
||||||
|
*/
|
||||||
|
SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
|
||||||
|
Called on iOS in applicationWillEnterForeground()
|
||||||
|
Called on Android in onResume()
|
||||||
|
*/
|
||||||
|
SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
|
||||||
|
Called on iOS in applicationDidBecomeActive()
|
||||||
|
Called on Android in onResume()
|
||||||
|
*/
|
||||||
|
|
||||||
/* Window events */
|
/* Window events */
|
||||||
SDL_WINDOWEVENT = 0x200, /**< Window state change */
|
SDL_WINDOWEVENT = 0x200, /**< Window state change */
|
||||||
SDL_SYSWMEVENT, /**< System specific event */
|
SDL_SYSWMEVENT, /**< System specific event */
|
||||||
|
@ -427,6 +453,14 @@ typedef struct SDL_QuitEvent
|
||||||
Uint32 timestamp;
|
Uint32 timestamp;
|
||||||
} SDL_QuitEvent;
|
} SDL_QuitEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief OS Specific event
|
||||||
|
*/
|
||||||
|
typedef struct SDL_OSEvent
|
||||||
|
{
|
||||||
|
Uint32 type; /**< ::SDL_QUIT */
|
||||||
|
Uint32 timestamp;
|
||||||
|
} SDL_OSEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A user-defined event type (event.user.*)
|
* \brief A user-defined event type (event.user.*)
|
||||||
|
|
|
@ -181,12 +181,20 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
|
||||||
bHasNewData = true;
|
bHasNewData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Low memory
|
||||||
|
extern "C" void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
|
||||||
|
JNIEnv* env, jclass cls)
|
||||||
|
{
|
||||||
|
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
// Quit
|
// Quit
|
||||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||||
JNIEnv* env, jclass cls)
|
JNIEnv* env, jclass cls)
|
||||||
{
|
{
|
||||||
// Inject a SDL_QUIT event
|
// Inject a SDL_QUIT event
|
||||||
SDL_SendQuit();
|
SDL_SendQuit();
|
||||||
|
SDL_SendAppEvent(SDL_APP_TERMINATING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause
|
// Pause
|
||||||
|
@ -199,12 +207,20 @@ extern "C" void Java_org_libsdl_app_SDLActivity_nativePause(
|
||||||
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
||||||
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
|
||||||
|
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||||
|
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resume
|
// Resume
|
||||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
|
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
|
||||||
JNIEnv* env, jclass cls)
|
JNIEnv* env, jclass cls)
|
||||||
{
|
{
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
|
||||||
|
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
|
||||||
|
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
||||||
|
|
||||||
if (Android_Window) {
|
if (Android_Window) {
|
||||||
/* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
|
/* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
|
||||||
* We can't restore the GL Context here because it needs to be done on the SDL main thread
|
* We can't restore the GL Context here because it needs to be done on the SDL main thread
|
||||||
|
@ -616,7 +632,9 @@ static int Android_JNI_FileOpen(SDL_RWops* ctx)
|
||||||
|
|
||||||
if (false) {
|
if (false) {
|
||||||
fallback:
|
fallback:
|
||||||
__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
|
// Disabled log message because of spam on the Nexus 7
|
||||||
|
//__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
|
||||||
|
|
||||||
/* Try the old method using InputStream */
|
/* Try the old method using InputStream */
|
||||||
ctx->hidden.androidio.assetFileDescriptorRef = NULL;
|
ctx->hidden.androidio.assetFileDescriptorRef = NULL;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ SDL_StopEventLoop(void)
|
||||||
SDL_event_watchers = tmp->next;
|
SDL_event_watchers = tmp->next;
|
||||||
SDL_free(tmp);
|
SDL_free(tmp);
|
||||||
}
|
}
|
||||||
|
SDL_EventOK = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function (and associated calls) may be called more than once */
|
/* This function (and associated calls) may be called more than once */
|
||||||
|
@ -133,8 +134,7 @@ SDL_StartEventLoop(void)
|
||||||
}
|
}
|
||||||
#endif /* !SDL_THREADS_DISABLED */
|
#endif /* !SDL_THREADS_DISABLED */
|
||||||
|
|
||||||
/* No filter to start with, process most event types */
|
/* Process most event types */
|
||||||
SDL_EventOK = NULL;
|
|
||||||
SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
|
SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
|
||||||
SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
|
SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
|
||||||
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||||
|
@ -365,7 +365,9 @@ int
|
||||||
SDL_PushEvent(SDL_Event * event)
|
SDL_PushEvent(SDL_Event * event)
|
||||||
{
|
{
|
||||||
SDL_EventWatcher *curr;
|
SDL_EventWatcher *curr;
|
||||||
|
|
||||||
event->common.timestamp = SDL_GetTicks();
|
event->common.timestamp = SDL_GetTicks();
|
||||||
|
|
||||||
if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
|
if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -516,8 +518,20 @@ SDL_RegisterEvents(int numevents)
|
||||||
return event_base;
|
return event_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a generic event handler.
|
int
|
||||||
*/
|
SDL_SendAppEvent(SDL_EventType eventType)
|
||||||
|
{
|
||||||
|
int posted;
|
||||||
|
|
||||||
|
posted = 0;
|
||||||
|
if (SDL_GetEventState(eventType) == SDL_ENABLE) {
|
||||||
|
SDL_Event event;
|
||||||
|
event.type = eventType;
|
||||||
|
posted = (SDL_PushEvent(&event) > 0);
|
||||||
|
}
|
||||||
|
return (posted);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
|
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,7 @@ extern int SDL_StartEventLoop(void);
|
||||||
extern void SDL_StopEventLoop(void);
|
extern void SDL_StopEventLoop(void);
|
||||||
extern void SDL_QuitInterrupt(void);
|
extern void SDL_QuitInterrupt(void);
|
||||||
|
|
||||||
|
extern int SDL_SendAppEvent(SDL_EventType eventType);
|
||||||
extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
|
extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
|
||||||
|
|
||||||
extern int SDL_QuitInit(void);
|
extern int SDL_QuitInit(void);
|
||||||
|
|
|
@ -114,15 +114,7 @@ SDL_QuitQuit(void)
|
||||||
int
|
int
|
||||||
SDL_SendQuit(void)
|
SDL_SendQuit(void)
|
||||||
{
|
{
|
||||||
int posted;
|
return SDL_SendAppEvent(SDL_QUIT);
|
||||||
|
|
||||||
posted = 0;
|
|
||||||
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
|
|
||||||
SDL_Event event;
|
|
||||||
event.type = SDL_QUIT;
|
|
||||||
posted = (SDL_PushEvent(&event) > 0);
|
|
||||||
}
|
|
||||||
return (posted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -228,43 +228,49 @@ static void SDL_IdleTimerDisabledChanged(const char *name, const char *oldValue,
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(UIApplication *)application
|
- (void)applicationWillTerminate:(UIApplication *)application
|
||||||
{
|
{
|
||||||
SDL_SendQuit();
|
SDL_SendAppEvent(SDL_APP_TERMINATING);
|
||||||
/* hack to prevent automatic termination. See SDL_uikitevents.m for details */
|
}
|
||||||
longjmp(*(jump_env()), 1);
|
|
||||||
|
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
|
||||||
|
{
|
||||||
|
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationWillResignActive:(UIApplication*)application
|
- (void) applicationWillResignActive:(UIApplication*)application
|
||||||
{
|
{
|
||||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
|
||||||
|
|
||||||
// Send every window on every screen a MINIMIZED event.
|
|
||||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||||
if (!_this) {
|
if (_this) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
for (window = _this->windows; window != nil; window = window->next) {
|
for (window = _this->windows; window != nil; window = window->next) {
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) applicationDidEnterBackground:(UIApplication*)application
|
||||||
|
{
|
||||||
|
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) applicationWillEnterForeground:(UIApplication*)application
|
||||||
|
{
|
||||||
|
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) applicationDidBecomeActive:(UIApplication*)application
|
- (void) applicationDidBecomeActive:(UIApplication*)application
|
||||||
{
|
{
|
||||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
||||||
|
|
||||||
// Send every window on every screen a RESTORED event.
|
|
||||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||||
if (!_this) {
|
if (_this) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
for (window = _this->windows; window != nil; window = window->next) {
|
for (window = _this->windows; window != nil; window = window->next) {
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
||||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (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
|
||||||
|
|
|
@ -91,8 +91,10 @@ void UIKit_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||||
}
|
}
|
||||||
[data->view swapBuffers];
|
[data->view swapBuffers];
|
||||||
|
|
||||||
/* we need to let the event cycle run, or the OS won't update the OpenGL view! */
|
/* You need to pump events in order for the OS to make changes visible.
|
||||||
SDL_PumpEvents();
|
We don't pump events here because we don't want iOS application events
|
||||||
|
(low memory, terminate, etc.) to happen inside low level rendering.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue