ecere/drivers/Android: Tweaks to run with latest Android SDK/NDK on Nexus 9
[sdk] / ecere / src / gui / drivers / AndroidInterface.ec
index 613f4d2..8bfbea1 100644 (file)
@@ -10,6 +10,7 @@ import "Condition"
 #include <locale.h>
 #include <pthread.h>
 #include <unistd.h>
+#include <sys/prctl.h>
 
 #include <android/configuration.h>
 #include <android/looper.h>
@@ -25,14 +26,14 @@ import "Condition"
 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "ecere-app", __VA_ARGS__))
 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "ecere-app", __VA_ARGS__))
 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "ecere-app", __VA_ARGS__))
-#ifdef _DEBUG
+#ifndef _DEBUG
 #define LOGV(...)  ((void)0)
 #else
 #define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
 #endif
 
 // *** NATIVE APP GLUE ********
-enum LooperID : byte { main = 1, input = 2, user = 3 };
+enum LooperID { main = 1, input = 2, user = 3 };
 enum AppCommand : byte
 {
    error = 0, inputChanged, initWindow, termWindow, windowResized, windowRedrawNeeded,
@@ -128,12 +129,12 @@ private:
          AInputEvent* event = null;
          if(AInputQueue_getEvent(inputQueue, &event) >= 0)
          {
-            int handled = 0;
+            //int handled = 0;
             LOGV("New input event: type=%d\n", AInputEvent_getType(event));
             if(AInputQueue_preDispatchEvent(inputQueue, event))
                return;
-            handled = onInputEvent(event);
-            AInputQueue_finishEvent(inputQueue, event, handled);
+            /*handled = */onInputEvent(event);
+            //AInputQueue_finishEvent(inputQueue, event, handled);
          }
          else
             LOGE("Failure reading next input event: %s\n", strerror(errno));
@@ -150,7 +151,9 @@ private:
    void free_saved_state()
    {
       mutex.Wait();
-      free(savedState);
+      if(savedState)
+         free(savedState);
+      savedState = 0;
       savedStateSize = 0;
       mutex.Release();
    }
@@ -197,7 +200,7 @@ private:
 
    void pre_exec_cmd(AppCommand cmd)
    {
-      PrintLn("pre_exec_cmd: ", (int)cmd);
+      //PrintLn("pre_exec_cmd: ", cmd);
       switch(cmd)
       {
          case inputChanged:
@@ -240,7 +243,7 @@ private:
 
    void post_exec_cmd(AppCommand cmd)
    {
-      PrintLn("post_exec_cmd: ", (int)cmd);
+      //PrintLn("post_exec_cmd: ", cmd);
       switch(cmd)
       {
          case termWindow:
@@ -312,7 +315,9 @@ private:
 
    void setSavedState(void * state, uint size)
    {
-      free(savedState);
+      if(savedState)
+         free(savedState);
+      savedState = null;
       if(state)
       {
          savedState = malloc(size);
@@ -323,7 +328,7 @@ private:
          savedStateSize = 0;
    }
 
-   void Create()
+   public void Create()
    {
       int msgpipe[2];
       if(pipe(msgpipe))
@@ -344,25 +349,25 @@ private:
 static void onDestroy(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("Destroy: %p\n", activity);
+   LOGI("Destroy: %p\n", activity);
    app.cleanup();
    app.Wait();
    delete androidActivity;
-   delete __currentModule;
-   LOGV("THE END.");
+   delete __androidCurrentModule;
+   LOGI("THE END.");
 }
 
 static void onStart(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("Start: %p\n", activity);
+   LOGI("Start: %p\n", activity);
    app.set_activity_state(start);
 }
 
 static void onResume(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("Resume: %p\n", activity);
+   LOGI("Resume: %p\n", activity);
    app.set_activity_state(resume);
 }
 
@@ -370,7 +375,7 @@ static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
    void* savedState = null;
-   LOGV("SaveInstanceState: %p\n", activity);
+   LOGI("SaveInstanceState: %p\n", activity);
    app.mutex.Wait();
    app.stateSaved = false;
    app.write_cmd(saveState);
@@ -390,63 +395,63 @@ static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
 static void onPause(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("Pause: %p\n", activity);
+   LOGI("Pause: %p\n", activity);
    app.set_activity_state(pause);
 }
 
 static void onStop(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("Stop: %p\n", activity);
+   LOGI("Stop: %p\n", activity);
    app.set_activity_state(stop);
 }
 
 static void onConfigurationChanged(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("ConfigurationChanged: %p\n", activity);
+   LOGI("ConfigurationChanged: %p\n", activity);
    app.write_cmd(configChanged);
 }
 
 static void onLowMemory(ANativeActivity* activity)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("LowMemory: %p\n", activity);
+   LOGI("LowMemory: %p\n", activity);
    app.write_cmd(lowMemory);
 }
 
 static void onWindowFocusChanged(ANativeActivity* activity, int focused)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
+   LOGI("WindowFocusChanged: %p -- %d\n", activity, focused);
    app.write_cmd(focused ? gainedFocus : lostFocus);
 }
 
 static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
+   LOGI("NativeWindowCreated: %p -- %p\n", activity, window);
    app.set_window(window);
 }
 
 static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
+   LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
    app.set_window(null);
 }
 
 static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
+   LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
    app.set_input(queue);
 }
 
 static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
-   LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
+   LOGI("InputQueueDestroyed: %p -- %p\n", activity, queue);
    app.inputQueue = null;
    app.set_input(null);
 }
@@ -470,8 +475,12 @@ default dllexport void ANativeActivity_onCreate(ANativeActivity* activity, void*
    guiApp = null;
    desktopW = 0; desktopH = 0;
    clipBoardData = null;
+   __thisModule = null;
+   __androidCurrentModule = null;
 
-   LOGV("Creating: %p\n", activity);
+   prctl(PR_SET_DUMPABLE, 1);
+
+   LOGI("Creating: %p\n", activity);
 
    //(*activity->vm)->AttachCurrentThread(activity->vm, &env, 0);
    clazz = (*env)->GetObjectClass(env, activity->clazz);
@@ -484,16 +493,19 @@ default dllexport void ANativeActivity_onCreate(ANativeActivity* activity, void*
    androidArgv[0] = moduleName;
 
    // Create a base Application class
-   __thisModule = __currentModule = __ecere_COM_Initialize(true, 1, androidArgv);
+   __androidCurrentModule = __ecere_COM_Initialize(true, 1, androidArgv);
    // Load up Ecere
-   eModule_Load(__currentModule, "ecere", publicAccess);
+   eModule_Load(__androidCurrentModule, "ecere", publicAccess);
+
 
+   /*
    if(activity->internalDataPath) PrintLn("internalDataPath is ", activity->internalDataPath);
    if(activity->externalDataPath) PrintLn("externalDataPath is ", activity->externalDataPath);
    {
       char tmp[256];
       PrintLn("cwd is ", GetWorkingDir(tmp, sizeof(tmp)));
    }
+   */
 
    ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN|AWINDOW_FLAG_KEEP_SCREEN_ON, 0 );
    app = AndroidActivity { activity = activity, moduleName = moduleName };
@@ -535,11 +547,12 @@ extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDo
 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
 private:
 
-static Module __currentModule;
+static Module __androidCurrentModule;
 static char * androidArgv[1];
 
 static int desktopW, desktopH;
 static char * clipBoardData;
+static int mouseX, mouseY;
 
 class AndroidInterface : Interface
 {
@@ -563,12 +576,30 @@ class AndroidInterface : Interface
    bool ProcessInput(bool processAll)
    {
       bool eventAvailable = false;
-      if(androidActivity.ident >= 0)
+
+      if(androidActivity.ident < 0)
+         androidActivity.ident = (LooperID)ALooper_pollAll(0, null, &androidActivity.events, (void**)&androidActivity.source);
+
+      if(gotInit && androidActivity.window)
       {
-         //PrintLn("androidActivity.ident >= 0");
-         // Process this event.
-         if(androidActivity.source)
-            androidActivity.source.process(androidActivity.source.userData);
+         int w = ANativeWindow_getWidth(androidActivity.window);
+         int h = ANativeWindow_getHeight(androidActivity.window);
+         if(desktopW != w || desktopH != h)
+         {
+            guiApp.SetDesktopPosition(0, 0, w, h, true);
+            desktopW = w;
+            desktopH = h;
+            guiApp.desktop.Update(null);
+         }
+      }
+
+      while(androidActivity.ident >= 0)
+      {
+         AndroidPollSource source = androidActivity.source;
+
+         androidActivity.source = null;
+         if(source)
+            source.process(source.userData);
 
          // If a sensor has data, process it now.
          /*
@@ -582,25 +613,25 @@ class AndroidInterface : Interface
             }
          }
          */
-         // eventAvailable = true;
+
+         eventAvailable = true;
          if(androidActivity.destroyRequested)
          {
             guiApp.desktop.Destroy(0);
             eventAvailable = true;
+            androidActivity.ident = (LooperID)-1;
          }
+         else if(processAll)
+            androidActivity.ident = (LooperID)ALooper_pollAll(0, null, &androidActivity.events, (void**)&androidActivity.source);
+         else
+            androidActivity.ident = (LooperID)-1;
       }
-      androidActivity.ident = 0;
-      if(androidActivity.animating)
-         guiApp.desktop.Update(null);
-
-      if(!eventAvailable)
-         return false;
-      return true;
+      return eventAvailable;
    }
 
    void Wait()
    {
-      androidActivity.ident = (LooperID)ALooper_pollAll(androidActivity.animating ? 0 : -1, null, &androidActivity.events, (void**)&androidActivity.source);
+      androidActivity.ident = (LooperID)ALooper_pollAll((int)(1000/18.2f), null, &androidActivity.events, (void**)&androidActivity.source);
       // guiApp.WaitEvent();
    }
 
@@ -614,11 +645,11 @@ class AndroidInterface : Interface
 
    }
 
-   char ** GraphicsDrivers(int * numDrivers)
+   const char ** GraphicsDrivers(int * numDrivers)
    {
-      static char *graphicsDrivers[] = { "OpenGL" };
+      static const char *graphicsDrivers[] = { "OpenGL" };
       *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
-      return (char **)graphicsDrivers;
+      return (const char **)graphicsDrivers;
    }
 
    void GetCurrentMode(bool * fullScreen, int * resolution, int * colorDepth, int * refreshRate)
@@ -651,7 +682,7 @@ class AndroidInterface : Interface
 
    // -- Window manipulation ---
 
-   void SetRootWindowCaption(Window window, char * name)
+   void SetRootWindowCaption(Window window, const char * name)
    {
 
    }
@@ -729,14 +760,14 @@ class AndroidInterface : Interface
 
    void GetMousePosition(int *x, int *y)
    {
-      int rootWindow, childWindow;
-      int mx, my;
-      unsigned int state;
+      *x = mouseX;
+      *y = mouseY;
    }
 
    void SetMousePosition(int x, int y)
    {
-
+      mouseX = x;
+      mouseY = y;
    }
 
    void SetMouseRange(Window window, Box box)
@@ -749,7 +780,7 @@ class AndroidInterface : Interface
 
    // -- Mouse cursor ---
 
-   void SetMouseCursor(int cursor)
+   void SetMouseCursor(Window window, int cursor)
    {
       if(cursor == -1)
       {
@@ -766,7 +797,7 @@ class AndroidInterface : Interface
       if(window && window.windowData)
       {
       }
-   }  
+   }
 
    void ClearClipboard()
    {
@@ -780,7 +811,7 @@ class AndroidInterface : Interface
    {
       bool result = false;
       if((clipBoard.text = new0 byte[size]))
-         result = true;   
+         result = true;
       return result;
    }
 
@@ -845,14 +876,14 @@ class AndroidInterface : Interface
 
    bool GetKeyState(Key key)
    {
-      int keyState = 0;
+      bool keyState = false;
       return keyState;
    }
 
    void SetTimerResolution(uint hertz)
    {
       // timerDelay = hertz ? (1000000 / hertz) : MAXINT;
-   }  
+   }
 
    bool SetIcon(Window window, BitmapResource resource)
    {
@@ -877,8 +908,156 @@ struct SavedState
 
 static AndroidActivity androidActivity;
 
+default const char * AndroidInterface_GetLibLocation(Application a)
+{
+   static char loc[MAX_LOCATION];
+   // sprintf(loc, "/data/data/com.ecere.%s/lib/lib", a.argv[0]);
+   sprintf(loc, "/data/app/com.ecere.%s-1/lib/arm64/lib", a.argv[0]);
+   return loc;
+}
+
 static bool gotInit;
 
+default float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
+        int32_t axis, size_t pointer_index);
+
+
+static define AMETA_META_ON       = 0x00010000;
+static define AMETA_META_LEFT_ON  = 0x00020000;
+static define AMETA_META_RIGHT_ON = 0x00040000;
+
+static Key keyCodeTable[] =
+{
+    0, //AKEYCODE_UNKNOWN         = 0,
+    0, //AKEYCODE_SOFT_LEFT       = 1,
+    0, //AKEYCODE_SOFT_RIGHT      = 2,
+    0, //AKEYCODE_HOME            = 3,
+    0, //AKEYCODE_BACK            = 4,
+    0, //AKEYCODE_CALL            = 5,
+    0, //AKEYCODE_ENDCALL         = 6,
+    k0, //AKEYCODE_0               = 7,
+    k1, //AKEYCODE_1               = 8,
+    k2, //AKEYCODE_2               = 9,
+    k3, //AKEYCODE_3               = 10,
+    k4, //AKEYCODE_4               = 11,
+    k5, //AKEYCODE_5               = 12,
+    k6, //AKEYCODE_6               = 13,
+    k7, //AKEYCODE_7               = 14,
+    k8, //AKEYCODE_8               = 15,
+    k9, //AKEYCODE_9               = 16,
+    keyPadStar, //AKEYCODE_STAR            = 17,
+    Key { k3, shift = true }, //AKEYCODE_POUND           = 18,
+    up, //AKEYCODE_DPAD_UP         = 19,
+    down, //AKEYCODE_DPAD_DOWN       = 20,
+    left, //AKEYCODE_DPAD_LEFT       = 21,
+    right, //AKEYCODE_DPAD_RIGHT      = 22,
+    keyPad5, //AKEYCODE_DPAD_CENTER     = 23,
+    0, //AKEYCODE_VOLUME_UP       = 24,
+    0, //AKEYCODE_VOLUME_DOWN     = 25,
+    0, //AKEYCODE_POWER           = 26,
+    0, //AKEYCODE_CAMERA          = 27,
+    0, //AKEYCODE_CLEAR           = 28,
+    a, //AKEYCODE_A               = 29,
+    b, //AKEYCODE_B               = 30,
+    c, //AKEYCODE_C               = 31,
+    d, //AKEYCODE_D               = 32,
+    e, //AKEYCODE_E               = 33,
+    f, //AKEYCODE_F               = 34,
+    g, //AKEYCODE_G               = 35,
+    h, //AKEYCODE_H               = 36,
+    i, //AKEYCODE_I               = 37,
+    j, //AKEYCODE_J               = 38,
+    k, //AKEYCODE_K               = 39,
+    l, //AKEYCODE_L               = 40,
+    m, //AKEYCODE_M               = 41,
+    n, //AKEYCODE_N               = 42,
+    o, //AKEYCODE_O               = 43,
+    p, //AKEYCODE_P               = 44,
+    q, //AKEYCODE_Q               = 45,
+    r, //AKEYCODE_R               = 46,
+    s, //AKEYCODE_S               = 47,
+    t, //AKEYCODE_T               = 48,
+    u, //AKEYCODE_U               = 49,
+    v, //AKEYCODE_V               = 50,
+    w, //AKEYCODE_W               = 51,
+    x, //AKEYCODE_X               = 52,
+    y, //AKEYCODE_Y               = 53,
+    z, //AKEYCODE_Z               = 54,
+    comma, //AKEYCODE_COMMA           = 55,
+    period, //AKEYCODE_PERIOD          = 56,
+    leftAlt, //AKEYCODE_ALT_LEFT        = 57,
+    rightAlt, //AKEYCODE_ALT_RIGHT       = 58,
+    leftShift, //AKEYCODE_SHIFT_LEFT      = 59,
+    rightShift, //AKEYCODE_SHIFT_RIGHT     = 60,
+    tab, //AKEYCODE_TAB             = 61,
+    space, //AKEYCODE_SPACE           = 62,
+    0, //AKEYCODE_SYM             = 63,
+    0, //AKEYCODE_EXPLORER        = 64,
+    0, //AKEYCODE_ENVELOPE        = 65,
+    enter, //AKEYCODE_ENTER           = 66,
+    backSpace, //AKEYCODE_DEL             = 67,
+    backQuote, //AKEYCODE_GRAVE           = 68,
+    minus, //AKEYCODE_MINUS           = 69,
+    plus, //AKEYCODE_EQUALS          = 70,
+    leftBracket, //AKEYCODE_LEFT_BRACKET    = 71,
+    rightBracket, //AKEYCODE_RIGHT_BRACKET   = 72,
+    backSlash, //AKEYCODE_BACKSLASH       = 73,
+    semicolon, //AKEYCODE_SEMICOLON       = 74,
+    quote, //AKEYCODE_APOSTROPHE      = 75,
+    slash, //AKEYCODE_SLASH           = 76,
+    Key { k2, shift = true }, //AKEYCODE_AT              = 77,
+    0, //AKEYCODE_NUM             = 78,      // Interpreted as an Alt
+    0, //AKEYCODE_HEADSETHOOK     = 79,
+    0, //AKEYCODE_FOCUS           = 80,   // *Camera* focus
+    keyPadPlus, //AKEYCODE_PLUS            = 81,
+    0, //AKEYCODE_MENU            = 82,
+    0, //AKEYCODE_NOTIFICATION    = 83,
+    0, //AKEYCODE_SEARCH          = 84,
+    0, //AKEYCODE_MEDIA_PLAY_PAUSE= 85,
+    0, //AKEYCODE_MEDIA_STOP      = 86,
+    0, //AKEYCODE_MEDIA_NEXT      = 87,
+    0, //AKEYCODE_MEDIA_PREVIOUS  = 88,
+    0, //AKEYCODE_MEDIA_REWIND    = 89,
+    0, //AKEYCODE_MEDIA_FAST_FORWARD = 90,
+    0, //AKEYCODE_MUTE            = 91,
+    0, //AKEYCODE_PAGE_UP         = 92,
+    0, //AKEYCODE_PAGE_DOWN       = 93,
+    0, //AKEYCODE_PICTSYMBOLS     = 94,
+    0, //AKEYCODE_SWITCH_CHARSET  = 95,
+    0, //AKEYCODE_BUTTON_A        = 96,
+    0, //AKEYCODE_BUTTON_B        = 97,
+    0, //AKEYCODE_BUTTON_C        = 98,
+    0, //AKEYCODE_BUTTON_X        = 99,
+    0, //AKEYCODE_BUTTON_Y        = 100,
+    0, //AKEYCODE_BUTTON_Z        = 101,
+    0, //AKEYCODE_BUTTON_L1       = 102,
+    0, //AKEYCODE_BUTTON_R1       = 103,
+    0, //AKEYCODE_BUTTON_L2       = 104,
+    0, //AKEYCODE_BUTTON_R2       = 105,
+    0, //AKEYCODE_BUTTON_THUMBL   = 106,
+    0, //AKEYCODE_BUTTON_THUMBR   = 107,
+    0, //AKEYCODE_BUTTON_START    = 108,
+    0, //AKEYCODE_BUTTON_SELECT   = 109,
+    0, //AKEYCODE_BUTTON_MODE     = 110,
+    escape, //AKEYCODE_BUTTON_ESCAPE = 111,
+    del, //AKEYCODE_BUTTON_ESCAPE    = 112,
+    leftControl, // = 113
+    rightControl, // = 114
+    capsLock, // = 115
+    scrollLock, // = 116
+    0, // = 117      KEYCODE_META_LEFT
+    0, // = 118      KEYCODE_META_RIGHT
+    0, // = 119      KEYCODE_FUNCTION
+    printScreen, // = 120      KEYCODE_SYSRQ
+    pauseBreak, // = 121
+    home, // = 122
+    end, // = 123
+    insert // = 124
+};
+
+// Why don't we have this in the NDK :(
+// default int32_t AKeyEvent_getUnichar(const AInputEvent* key_event);
+
 class AndroidActivity : AndroidAppGlue
 {
    AndroidPollSource source;
@@ -889,7 +1068,6 @@ class AndroidActivity : AndroidAppGlue
    const ASensor* accelerometerSensor;
    ASensorEventQueue* sensorEventQueue;
    */
-   bool animating;
    SavedState state;
 
    int onInputEvent(AInputEvent* event)
@@ -899,26 +1077,49 @@ class AndroidActivity : AndroidAppGlue
       if(type == AINPUT_EVENT_TYPE_MOTION)
       {
          uint actionAndIndex = AMotionEvent_getAction(event);
+         //uint source = AInputEvent_getSource(event);
          uint action = actionAndIndex & AMOTION_EVENT_ACTION_MASK;
-         uint index  = (actionAndIndex & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-         uint flags = AMotionEvent_getFlags(event);
+         //uint index  = (actionAndIndex & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+         //uint flags = AMotionEvent_getFlags(event);
          uint meta = AMotionEvent_getMetaState(event);
-         uint edge = AMotionEvent_getEdgeFlags(event);
-         int64 downTime = AMotionEvent_getDownTime(event);     // nanotime
-         int64 eventTime = AMotionEvent_getDownTime(event);
+         //uint edge = AMotionEvent_getEdgeFlags(event);
+         //int64 downTime = AMotionEvent_getDownTime(event);     // nanotime
+         //int64 eventTime = AMotionEvent_getDownTime(event);
+         //float axis;
          Modifiers keyFlags = 0;
          int x = (int)AMotionEvent_getX(event, 0);
          int y = (int)AMotionEvent_getY(event, 0);
+         bool shift = (meta & AMETA_SHIFT_ON) ? true : false;
+         bool alt = (meta & AMETA_ALT_ON) ? true : false;
+         //bool sym = (meta & AMETA_SYM_ON) ? true : false;
+
+         keyFlags.shift = shift;
+         keyFlags.alt = alt;
+
+         //PrintLn("Got a motion input event: ", action);
+         /*
+         if(action == 8) //AMOTION_EVENT_ACTION_SCROLL)
+            axis = AMotionEvent_getAxisValue(event, 9, index); //AMOTION_EVENT_AXIS_VSCROLL);
+         */
 
+         AInputQueue_finishEvent(inputQueue, event, 1);
          switch(action)
          {
+            /*
+            case 8: //AMOTION_EVENT_ACTION_SCROLL:
+               window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, (axis < 0) ? wheelUp : wheelDown, 0);
+               break;
+               */
             case AMOTION_EVENT_ACTION_DOWN:
+               mouseX = x, mouseY = y;
                window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown, x, y, &keyFlags, false, true);
                break;
             case AMOTION_EVENT_ACTION_UP:
+               mouseX = x, mouseY = y;
                window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x, y, &keyFlags, false, true);
                break;
             case AMOTION_EVENT_ACTION_MOVE:
+               mouseX = x, mouseY = y;
                window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, true);
                break;
             case AMOTION_EVENT_ACTION_CANCEL: break;
@@ -926,17 +1127,49 @@ class AndroidActivity : AndroidAppGlue
             case AMOTION_EVENT_ACTION_POINTER_DOWN: break;
             case AMOTION_EVENT_ACTION_POINTER_UP: break;
          }
-
-         animating = true;
          return 1;
       }
       else if(type == AINPUT_EVENT_TYPE_KEY)
       {
          uint action = AKeyEvent_getAction(event);
-         uint flags = AKeyEvent_getFlags(event);
+         //uint flags = AKeyEvent_getFlags(event);
          uint keyCode = AKeyEvent_getKeyCode(event);
          uint meta = AKeyEvent_getMetaState(event);
+         Key key = keyCodeTable[keyCode];
+         bool shift = (meta & AMETA_SHIFT_ON) ? true : false;
+         bool alt = (meta & AMETA_ALT_ON || meta & AMETA_ALT_LEFT_ON || meta & AMETA_ALT_RIGHT_ON) ? true : false;
+         //bool metaMeta = (meta & AMETA_META_ON || meta & AMETA_META_LEFT_ON || meta & AMETA_META_RIGHT_ON) ? true : false;
+         //bool sym = (meta & AMETA_SYM_ON) ? true : false;
+         //unichar ch = AKeyEvent_getUnichar(event);
+         unichar ch = 0;
+
+         key.shift = shift;
+         key.alt = alt;
+
+         AInputQueue_finishEvent(inputQueue, event, 1);
+
+         // PrintLn("Got a key: action = ", action, ", flags = ", flags, ", keyCode = ", keyCode, ", meta = ", meta, ": key = ", (int)key);
+
+         if(key)
+         {
+            if(action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_MULTIPLE)
+            {
+               /*if(key == wheelDown || key == wheelUp)
+                  window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, key, ch);
+               else*/
+               {
+                  char c = Interface::TranslateKey(key.code, shift);
+                  if(c > 0) ch = c;
+                  window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, key, ch);
+               }
+            }
+            else if(action == AKEY_EVENT_ACTION_UP)
+               window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, ch);
+         }
+         return 1;
       }
+      else
+         AInputQueue_finishEvent(inputQueue, event, 0);
       return 0;
    }
 
@@ -952,7 +1185,6 @@ class AndroidActivity : AndroidAppGlue
             {
                int w, h;
                gotInit = true;
-               PrintLn("onAppCmd: initWindow");
                ANativeWindow_setBuffersGeometry(window, 0, 0, 0); //format);
                w = ANativeWindow_getWidth(window);
                h = ANativeWindow_getHeight(window);
@@ -971,11 +1203,11 @@ class AndroidActivity : AndroidAppGlue
             }
             break;
          case termWindow:
-            animating = false;
             guiApp.desktop.UnloadGraphics(false);
             break;
          case gainedFocus:
-            androidActivity.animating = true;
+            guiApp.desktop.Update(null);
+            guiApp.SetAppFocus(true);
             /*
             if(accelerometerSensor)
             {
@@ -989,9 +1221,13 @@ class AndroidActivity : AndroidAppGlue
             if(accelerometerSensor)
                ASensorEventQueue_disableSensor(sensorEventQueue, accelerometerSensor);
             */
-            animating = false;
+            guiApp.SetAppFocus(false);
             guiApp.desktop.Update(null);
             break;
+         case configChanged:
+            if(window)
+               guiApp.desktop.UpdateDisplay();
+            break;
       }
    }
 
@@ -1009,21 +1245,21 @@ class AndroidActivity : AndroidAppGlue
 
       {
          Module app;
-          
+
          // Evolve the Application class into a GuiApplication
-         eInstance_Evolve((Instance *)&__currentModule, class(GuiApplication));
-         __thisModule = __currentModule;
+         eInstance_Evolve((Instance *)&__androidCurrentModule, class(GuiApplication));
 
          // Wait for the initWindow command:
          guiApp.interfaceDriver = class(AndroidInterface);
          while(!gotInit)
          {
-            guiApp.Wait();
-            guiApp.ProcessInput(true);
+            // Can't call the GuiApplication here, because GuiApplication::Initialize() has not been called yet
+            guiApp.interfaceDriver.Wait();
+            guiApp.interfaceDriver.ProcessInput(true);
          }
 
          // Invoke __ecereDll_Load() in lib[our package name].so
-         app = eModule_Load(__currentModule, moduleName, publicAccess);
+         app = eModule_Load(__androidCurrentModule, moduleName, publicAccess);
          if(app)
          {
             Class c;
@@ -1031,21 +1267,30 @@ class AndroidActivity : AndroidAppGlue
             for(c = app.classes.first; c && !eClass_IsDerived(c, class(GuiApplication)); c = c.next);
             if(!c) c = class(GuiApplication);
 
+            guiApp.lockMutex.Release();   // TOCHECK: Seems the evolve is losing our mutex lock here ?
+
             // Evolve the Application into it
-            eInstance_Evolve((Instance *)&__currentModule, c);
-            __thisModule = __currentModule;
+            eInstance_Evolve((Instance *)&__androidCurrentModule, c);
+            guiApp = (GuiApplication)__androidCurrentModule;
+
+            {
+               const String skin = guiApp.skin;
+               *&guiApp.currentSkin = null;
+               guiApp.SelectSkin(skin);
+            }
 
+            guiApp.lockMutex.Wait();
 
             // Call Main()
-            __currentModule._vTbl[12](__currentModule);
+            ((void (*)(void *))(void *)__androidCurrentModule._vTbl[12])(__androidCurrentModule);
          }
 
          if(!destroyRequested)
             ANativeActivity_finish(activity);
          while(!destroyRequested)
          {
-            guiApp.Wait();
-            guiApp.ProcessInput(true);
+            guiApp.interfaceDriver.Wait();
+            guiApp.interfaceDriver.ProcessInput(true);
          }
       }
    }