android: make code 're-entrant' - i.e. NativeActivity can restart the program without...
[freeglut] / src / android / fg_main_android.c
index 3f973f2..1e30b10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_main_android.c
+ * fg_main_android.c
  *
  * The Android-specific windows message processing methods.
  *
@@ -28,6 +28,7 @@
 
 #include <GL/freeglut.h>
 #include "fg_internal.h"
+#include "fg_main.h"
 
 #include <android/log.h>
 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT", __VA_ARGS__))
@@ -132,14 +133,13 @@ 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;
 }
 
 /*
- * Handle a window configuration change. When no reshape
- * callback is hooked, the viewport size is updated to
- * match the new window size.
+ * Request a window resize
  */
 void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
 {
@@ -167,7 +167,13 @@ unsigned long fgPlatformSystemTime ( void )
  */
 void fgPlatformSleepForEvents( long msec )
 {
-  /* fprintf(stderr, "fgPlatformSleepForEvents: STUB\n"); */
+    /* Android's NativeActivity relies on a Looper/ALooper object to
+       notify about events.  The Looper object is plugged on two
+       internal pipe(2)s to detect system and input events.  Sadly you
+       can only ask the Looper for an event, not just ask whether
+       there is a pending event (and process it later).  Consequently,
+       short of redesigning NativeActivity, we cannot
+       SleepForEvents. */
 }
 
 /**
@@ -217,13 +223,13 @@ int32_t handle_input(struct android_app* app, AInputEvent* event) {
     LOGI("motion %.01f,%.01f action=%d", x, y, AMotionEvent_getAction(event));
     
     /* Virtual arrows PAD */
-    // Don't interfere with existing mouse move event
+    /* Don't interfere with existing mouse move event */
     if (!touchscreen.in_mmotion) {
       struct vpad_state prev_vpad = touchscreen.vpad;
       touchscreen.vpad.left = touchscreen.vpad.right
        = touchscreen.vpad.up = touchscreen.vpad.down = false;
 
-      int32_t width = ANativeWindow_getWidth(window->Window.Handle);
+      /* int32_t width = ANativeWindow_getWidth(window->Window.Handle); */
       int32_t height = ANativeWindow_getHeight(window->Window.Handle);
       if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) {
        if ((x > 0 && x < 100) && (y > (height - 100) && y < height))
@@ -273,7 +279,7 @@ int32_t handle_input(struct android_app* app, AInputEvent* event) {
     if (!touchscreen.vpad.on) {
       window->State.MouseX = x;
       window->State.MouseY = y;
-      LOGI("Changed mouse position: %d,%d", x, y);
+      LOGI("Changed mouse position: %f,%f", x, y);
       if (action == AMOTION_EVENT_ACTION_DOWN && FETCH_WCB(*window, Mouse)) {
        touchscreen.in_mmotion = true;
        INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_DOWN, x, y));
@@ -312,10 +318,11 @@ void handle_cmd(struct android_app* app, int32_t cmd) {
     /* The window is being hidden or closed, clean it up. */
     LOGI("handle_cmd: APP_CMD_TERM_WINDOW");
     fgDestroyWindow(fgDisplay.pDisplay.single_window);
+    fgDisplay.pDisplay.single_window = NULL;
     break;
   case APP_CMD_DESTROY:
-    /* Not reached because GLUT exit()s when last window is closed */
     LOGI("handle_cmd: APP_CMD_DESTROY");
+    /* glue has already set android_app->destroyRequested=1 */
     break;
   case APP_CMD_GAINED_FOCUS:
     LOGI("handle_cmd: APP_CMD_GAINED_FOCUS");
@@ -341,9 +348,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.
@@ -357,9 +361,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 ) );
@@ -388,7 +392,7 @@ void fgPlatformProcessSingleEvent ( void )
 
 void fgPlatformMainLoopPreliminaryWork ( void )
 {
-  printf("fgPlatformMainLoopPreliminaryWork\n");
+  LOGI("fgPlatformMainLoopPreliminaryWork\n");
 
   key_init();
 
@@ -396,8 +400,3 @@ void fgPlatformMainLoopPreliminaryWork ( void )
   /* JNI entry points need to be bundled even when linking statically */
   app_dummy();
 }
-
-void fgPlatformDeinitialiseInputDevices ( void )
-{
-  fprintf(stderr, "fgPlatformDeinitialiseInputDevices: STUB\n");
-}