Document android app lifecycle; kill app when window is closed, until pausing/restori...
[freeglut] / src / android / fg_main_android.c
index 1ad6b38..52700fe 100644 (file)
@@ -133,6 +133,7 @@ static unsigned char key_ascii(struct android_app* app, AInputEvent* event) {
   int ascii = (*env)->CallIntMethod(env, keyEvent, KeyEvent_getUnicodeChar, AKeyEvent_getMetaState(event));
 
   /* LOGI("getUnicodeChar(%d) = %d ('%c')", AKeyEvent_getKeyCode(event), ascii, ascii); */
+  (*vm)->DetachCurrentThread(vm);
 
   return ascii;
 }
@@ -302,42 +303,75 @@ int32_t handle_input(struct android_app* app, AInputEvent* event) {
  */
 void handle_cmd(struct android_app* app, int32_t cmd) {
   switch (cmd) {
-  case APP_CMD_SAVE_STATE:
-    /* The system has asked us to save our current state.  Do so. */
-    LOGI("handle_cmd: APP_CMD_SAVE_STATE");
+  /* App life cycle, in that order: */
+  case APP_CMD_START:
+    LOGI("handle_cmd: APP_CMD_START");
+    break;
+  case APP_CMD_RESUME:
+    LOGI("handle_cmd: APP_CMD_RESUME");
+    /* If coming back from a pause: */
+    /* - Recreate window context and surface */
+    /* - Call user-defined hook to restore resources (textures...) */
+    /* - Unpause GLUT callbacks */
     break;
-  case APP_CMD_INIT_WINDOW:
+  case APP_CMD_INIT_WINDOW: /* surfaceCreated */
     /* The window is being shown, get it ready. */
     LOGI("handle_cmd: APP_CMD_INIT_WINDOW");
     fgDisplay.pDisplay.single_window->Window.Handle = app->window;
     /* glPlatformOpenWindow was waiting for Handle to be defined and
        will now return from fgPlatformProcessSingleEvent() */
     break;
-  case APP_CMD_TERM_WINDOW:
-    /* The window is being hidden or closed, clean it up. */
-    LOGI("handle_cmd: APP_CMD_TERM_WINDOW");
-    fgDestroyWindow(fgDisplay.pDisplay.single_window);
-    break;
-  case APP_CMD_DESTROY:
-    /* Not reached because GLUT exit()s when last window is closed */
-    LOGI("handle_cmd: APP_CMD_DESTROY");
-    break;
   case APP_CMD_GAINED_FOCUS:
     LOGI("handle_cmd: APP_CMD_GAINED_FOCUS");
     break;
+  case APP_CMD_WINDOW_RESIZED:
+    LOGI("handle_cmd: APP_CMD_WINDOW_RESIZED");
+    if (fgDisplay.pDisplay.single_window->Window.pContext.egl.Surface != EGL_NO_SURFACE)
+      /* Make ProcessSingleEvent detect the new size, only available
+        after the next SwapBuffer */
+      glutPostRedisplay();
+    break;
+
+  case APP_CMD_SAVE_STATE: /* onSaveInstanceState */
+    /* The system has asked us to save our current state, when it
+       pauses the application without destroying it right after. */
+    /* app->savedState = ... */
+    /* app->savedStateSize = ... */
+    LOGI("handle_cmd: APP_CMD_SAVE_STATE");
+    break;
+  case APP_CMD_PAUSE:
+    LOGI("handle_cmd: APP_CMD_PAUSE");
+    /* - Pause GLUT callbacks */
+    break;
   case APP_CMD_LOST_FOCUS:
     LOGI("handle_cmd: APP_CMD_LOST_FOCUS");
     break;
+  case APP_CMD_TERM_WINDOW: /* surfaceDestroyed */
+    /* The application is being hidden, but may be restored */
+    /* TODO: Pausing/resuming windows not ready yet, so killing it now */
+    fgDestroyWindow(fgDisplay.pDisplay.single_window);
+    fgDisplay.pDisplay.single_window = NULL;
+    LOGI("handle_cmd: APP_CMD_TERM_WINDOW");
+    break;
+  case APP_CMD_STOP:
+    LOGI("handle_cmd: APP_CMD_STOP");
+    break;
+  case APP_CMD_DESTROY: /* Activity.onDestroy */
+    LOGI("handle_cmd: APP_CMD_DESTROY");
+    /* User closed the application for good, let's kill the window */
+    if (fgDisplay.pDisplay.single_window != NULL) {
+      fgDestroyWindow(fgDisplay.pDisplay.single_window);
+      fgDisplay.pDisplay.single_window = NULL;
+    }
+    /* glue has already set android_app->destroyRequested=1 */
+    break;
+
   case APP_CMD_CONFIG_CHANGED:
     /* Handle rotation / orientation change */
     LOGI("handle_cmd: APP_CMD_CONFIG_CHANGED");
     break;
-  case APP_CMD_WINDOW_RESIZED:
-    LOGI("handle_cmd: APP_CMD_WINDOW_RESIZED");
-    if (fgDisplay.pDisplay.single_window->Window.pContext.egl.Surface != EGL_NO_SURFACE)
-      /* Make ProcessSingleEvent detect the new size, only available
-        after the next SwapBuffer */
-      glutPostRedisplay();
+  case APP_CMD_LOW_MEMORY:
+    LOGI("handle_cmd: APP_CMD_LOW_MEMORY");
     break;
   default:
     LOGI("handle_cmd: unhandled cmd=%d", cmd);
@@ -346,9 +380,6 @@ void handle_cmd(struct android_app* app, int32_t cmd) {
 
 void fgPlatformProcessSingleEvent ( void )
 {
-  static int32_t last_width = -1;
-  static int32_t last_height = -1;
-
   /* When the screen is resized, the window handle still points to the
      old window until the next SwapBuffer, while it's crucial to set
      the size (onShape) correctly before the next onDisplay callback.
@@ -362,9 +393,9 @@ void fgPlatformProcessSingleEvent ( void )
   if (window != NULL && window->Window.Handle != NULL) {
     int32_t width = ANativeWindow_getWidth(window->Window.Handle);
     int32_t height = ANativeWindow_getHeight(window->Window.Handle);
-    if (width != last_width || height != last_height) {
-      last_width = width;
-      last_height = height;
+    if (width != window->State.pWState.LastWidth || height != window->State.pWState.LastHeight) {
+      window->State.pWState.LastWidth = width;
+      window->State.pWState.LastHeight = height;
       LOGI("width=%d, height=%d", width, height);
       if( FETCH_WCB( *window, Reshape ) )
        INVOKE_WCB( *window, Reshape, ( width, height ) );
@@ -393,7 +424,7 @@ void fgPlatformProcessSingleEvent ( void )
 
 void fgPlatformMainLoopPreliminaryWork ( void )
 {
-  printf("fgPlatformMainLoopPreliminaryWork\n");
+  LOGI("fgPlatformMainLoopPreliminaryWork\n");
 
   key_init();