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.
|
||||
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
|
||||
==============================================================================
|
||||
|
|
|
@ -78,17 +78,26 @@ public class SDLActivity extends Activity {
|
|||
}
|
||||
|
||||
// Events
|
||||
/*protected void onPause() {
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.v("SDL", "onPause()");
|
||||
super.onPause();
|
||||
// Don't call SDLActivity.nativePause(); here, it will be called by SDLSurface::surfaceDestroyed
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.v("SDL", "onResume()");
|
||||
super.onResume();
|
||||
// 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
|
||||
protected void onDestroy() {
|
||||
|
@ -180,6 +189,7 @@ public class SDLActivity extends Activity {
|
|||
|
||||
// C functions we call
|
||||
public static native void nativeInit();
|
||||
public static native void nativeLowMemory();
|
||||
public static native void nativeQuit();
|
||||
public static native void nativePause();
|
||||
public static native void nativeResume();
|
||||
|
@ -600,8 +610,6 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||
public void onDraw(Canvas canvas) {}
|
||||
|
||||
|
||||
|
||||
|
||||
// Key events
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
|
|
|
@ -61,6 +61,32 @@ typedef enum
|
|||
/* Application events */
|
||||
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 */
|
||||
SDL_WINDOWEVENT = 0x200, /**< Window state change */
|
||||
SDL_SYSWMEVENT, /**< System specific event */
|
||||
|
@ -427,6 +453,14 @@ typedef struct SDL_QuitEvent
|
|||
Uint32 timestamp;
|
||||
} 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.*)
|
||||
|
|
|
@ -181,12 +181,20 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
|
|||
bHasNewData = true;
|
||||
}
|
||||
|
||||
// Low memory
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||
}
|
||||
|
||||
// Quit
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
// Inject a SDL_QUIT event
|
||||
SDL_SendQuit();
|
||||
SDL_SendAppEvent(SDL_APP_TERMINATING);
|
||||
}
|
||||
|
||||
// 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_MINIMIZED, 0, 0);
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
|
||||
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
|
||||
}
|
||||
|
||||
// Resume
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
|
||||
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) {
|
||||
/* 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
|
||||
|
@ -616,7 +632,9 @@ static int Android_JNI_FileOpen(SDL_RWops* ctx)
|
|||
|
||||
if (false) {
|
||||
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 */
|
||||
ctx->hidden.androidio.assetFileDescriptorRef = NULL;
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ SDL_StopEventLoop(void)
|
|||
SDL_event_watchers = tmp->next;
|
||||
SDL_free(tmp);
|
||||
}
|
||||
SDL_EventOK = NULL;
|
||||
}
|
||||
|
||||
/* This function (and associated calls) may be called more than once */
|
||||
|
@ -133,8 +134,7 @@ SDL_StartEventLoop(void)
|
|||
}
|
||||
#endif /* !SDL_THREADS_DISABLED */
|
||||
|
||||
/* No filter to start with, process most event types */
|
||||
SDL_EventOK = NULL;
|
||||
/* Process most event types */
|
||||
SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
|
||||
SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||
|
@ -365,7 +365,9 @@ int
|
|||
SDL_PushEvent(SDL_Event * event)
|
||||
{
|
||||
SDL_EventWatcher *curr;
|
||||
|
||||
event->common.timestamp = SDL_GetTicks();
|
||||
|
||||
if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -516,8 +518,20 @@ SDL_RegisterEvents(int numevents)
|
|||
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
|
||||
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@ extern int SDL_StartEventLoop(void);
|
|||
extern void SDL_StopEventLoop(void);
|
||||
extern void SDL_QuitInterrupt(void);
|
||||
|
||||
extern int SDL_SendAppEvent(SDL_EventType eventType);
|
||||
extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
|
||||
|
||||
extern int SDL_QuitInit(void);
|
||||
|
|
|
@ -114,15 +114,7 @@ SDL_QuitQuit(void)
|
|||
int
|
||||
SDL_SendQuit(void)
|
||||
{
|
||||
int posted;
|
||||
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
return SDL_SendAppEvent(SDL_QUIT);
|
||||
}
|
||||
|
||||
/* 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
|
||||
{
|
||||
SDL_SendQuit();
|
||||
/* hack to prevent automatic termination. See SDL_uikitevents.m for details */
|
||||
longjmp(*(jump_env()), 1);
|
||||
SDL_SendAppEvent(SDL_APP_TERMINATING);
|
||||
}
|
||||
|
||||
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
|
||||
{
|
||||
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||
}
|
||||
|
||||
- (void) applicationWillResignActive:(UIApplication*)application
|
||||
{
|
||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
||||
|
||||
// Send every window on every screen a MINIMIZED event.
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this) {
|
||||
SDL_Window *window;
|
||||
for (window = _this->windows; window != nil; window = window->next) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_LOST, 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
|
||||
{
|
||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
||||
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
|
||||
|
||||
// Send every window on every screen a RESTORED event.
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this) {
|
||||
SDL_Window *window;
|
||||
for (window = _this->windows; window != nil; window = window->next) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (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];
|
||||
|
||||
/* we need to let the event cycle run, or the OS won't update the OpenGL view! */
|
||||
SDL_PumpEvents();
|
||||
/* You need to pump events in order for the OS to make changes visible.
|
||||
We don't pump events here because we don't want iOS application events
|
||||
(low memory, terminate, etc.) to happen inside low level rendering.
|
||||
*/
|
||||
}
|
||||
|
||||
SDL_GLContext UIKit_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue