I am in general agreement that there should be a real callback for
this. As you said, there has been a movement to event driven systems
for awhile now. As issues like battery life become more important to
end users, I believe the pressure for event systems will continue to
increase.
As for your patch, I’m thinking we might be able to improve upon this
so it is more optional, more extensible, and less platform specific. I
think we should introduce a new/general SDL function that lets you set
a function pointer to handle callback events. (This is akin to
SDL_mixer’s callback system.) On platforms that support callbacks, if
the function pointer is set, it will invoke the user’s function,
otherwise it is a no-op.
(All typed in mail, so code is unverified.)
void SDL_SetEventCallback( void
(sdl_event_callback_function)(SDL_Event event, void* userdata),
void* userdata);
I haven’t looked at the old iOS/SDL patch for handling events, but I
assume there is already special information packed into SDL_event so
you could get this through PollEvent. So I propose to reuse those
SDL_events for the callback. The callback will pass through an
SDL_event so you can identify which specific event is happening (e.g.
background, resume, low memory). I hope we might be able to also pass
any special OS specific data in this structure just in case, otherwise
we might want an additional void* parameter for this. The userdata
parameter is for users to pass through any special information they
need to get back from the callback so they don’t need global
variables. (This is a pet-peev of mine about SDL_mixer’s callbacks.)
void MyEventCallbackHandler(SDL_Event* event, void* userdata)
{
// Look at the SDL_Event to figure out what kind of event this is and handle it
if(MyIsSuspendEvent(event))
{
// Do what I need to do to save my info and prepare for suspend
}
else if(MyIsResumeEvent(event))
{
}
else if(MyIsLowMemoryEvent(event))
{
}
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
// ? yada yada yada
SDL_SetEventCallback(MyEventCallbackHandler, NULL);
return 0;
}
Then for example, in the iOS implementation of SDL:
-
(void)applicationWillTerminate:(UIApplication *)application
{
// Note: SDL will need some global/static variable to save the
function pointer that user registered and another for the user data.
// This will be in the SDL core and not the platform specific implementation.
if(NULL != s_userSDLEventCallbackPtr)
{
// We need to create the SDL_event with the proper stuff to passthrough.
// Can we do this on the stack, or do we need to do this on the heap?
// If on the heap, we need to free the memory after the callback
SDL_Event event;
// Fill the event for this event type (terminate)
// ?// Invoke the callback s_userSDLEventCallbackPtr(&event, s_userSDLEventCallbackUserData); // free the event if it was done on the heap
}
}
The nice thing about this is that it can be useful on more platforms
(e.g. Android, Mac, etc.) while at the same time allows users to
opt-into it instead of throwing a compile error. (I will argue that
though handling these is a good idea, not everybody actually needs to
handle it directly at this level so forcing it may not be correct.)
Thinking way, way ahead into the future, one possibility is that this
could be used to optionally use SDL as an event driven system instead
of the current polling architecture. So for example in Cocoa, we start
adding the callback check to all the event handlers such as mouse,
keyboard, touch, etc. and invoke the callback if defined and not be
restricted to just ‘special’ system events like iOS style
backgrounding. We might need one more API function to let users
specify which mode they want to run SDL in for these.
-EricOn 3/31/12, Brian Barnes wrote:
I created a patch.
http://www.klinksoftware.com/download/iOSCallback.zip
This contains 3 files. The patch itself, and the two changed .m files if
anybody wants to just apply it that way (both in video/uikit). This was
done off the trunk from about a day ago (I doubt these files have changed.)This ASSUMES you are compiling a static library, which right now is your
only option, and it requires that these functions exist. The functions are:void SDL_iOSEvent_WillTerminate(void);
void SDL_iOSEvent_DidReceiveMemoryWarning(void);
void SDL_iOSEvent_WillResignActive(void);
void SDL_iOSEvent_DidBecomeActive(void);
void SDL_iOSEvent_DidEnterBackground(void);
void SDL_iOSEvent_WillEnterForeground(void);Currently, I get a crash every 3rd or so time. I will be tracking this;
it’s obviously some threaded or race condition, and I have some ideals. For
now, I’m assuming it’s my code.I left in there the call that adds a minimize/maximize event onto the event
stack. I ignore these on iOS, so somebody else will have to fight over
include/not-include.NOTE: I REMOVED a pump events from swap buffer. ANY pump events outside of
event polling code is going to be asking for trouble. So using this
REQUIRES that you pump events yourself (or poll events, whatever.) This is
something you should probably be doing anyway. There could be more, and it
could be the source of my crash, but I won’t know until I can investigate
further.The patch itself (don’t use this, use the one in the zip):
diff -r 6bb657898f55 src/video/uikit/SDL_uikitappdelegate.m
— a/src/video/uikit/SDL_uikitappdelegate.m Tue Feb 28 21:58:36 2012 -0500
+++ b/src/video/uikit/SDL_uikitappdelegate.m Sat Mar 31 12:54:02 2012 -0400
@@ -36,6 +36,15 @@
#undef main
#endif+// these events must be defined in the client code
+// this assumes a static library
+extern void SDL_iOSEvent_WillTerminate(void);
+extern void SDL_iOSEvent_DidReceiveMemoryWarning(void);
+extern void SDL_iOSEvent_WillResignActive(void);
+extern void SDL_iOSEvent_DidBecomeActive(void);
+extern void SDL_iOSEvent_DidEnterBackground(void);
+extern void SDL_iOSEvent_WillEnterForeground(void);
+
extern int SDL_main(int argc, char *argv[]);
static int forward_argc;
static char **forward_argv;
@@ -123,16 +132,16 @@
- (void)applicationWillTerminate:(UIApplication *)application
{- SDL_SendQuit();
/* hack to prevent automatic termination. See SDL_uikitevents.m for
details */
- longjmp(*(jump_env()), 1);
- SDL_iOSEvent_WillTerminate();
+}± (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
+{
- SDL_iOSEvent_DidReceiveMemoryWarning();
}
- (void) applicationWillResignActive:(UIApplication*)application
{- //NSLog(@"%@", NSStringFromSelector(_cmd));
- // Send every window on every screen a MINIMIZED event.
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return;
@@ -143,13 +152,14 @@
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
- SDL_iOSEvent_WillResignActive();
}
- (void) applicationDidBecomeActive:(UIApplication*)application
{- //NSLog(@"%@", NSStringFromSelector(_cmd));
- // Send every window on every screen a RESTORED event.
- SDL_iOSEvent_DidBecomeActive();
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return;
@@ -162,6 +172,16 @@
}
}± (void) applicationDidEnterBackground:(UIApplication*)application
+{
- SDL_iOSEvent_DidEnterBackground();
+}± (void) applicationWillEnterForeground:(UIApplication*)application
+{
- SDL_iOSEvent_WillEnterForeground();
+}@end
#endif /* SDL_VIDEO_DRIVER_UIKIT */
diff -r 6bb657898f55 src/video/uikit/SDL_uikitopengles.m
— a/src/video/uikit/SDL_uikitopengles.m Tue Feb 28 21:58:36 2012 -0500
+++ b/src/video/uikit/SDL_uikitopengles.m Sat Mar 31 12:54:02 2012 -0400
@@ -95,7 +95,7 @@
[data->uiwindow makeKeyAndVisible];/* we need to let the event cycle run, or the OS won't update the
OpenGL view! */
- SDL_PumpEvents();
+// SDL_PumpEvents();}
[>] Brian
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
–
Beginning iPhone Games Development
http://playcontrol.net/iphonegamebook/