ecere/gui/Window;AndroidInterface: Initial multi-touch support multiTouch
authorJerome St-Louis <jerome@ecere.com>
Wed, 15 Jul 2015 16:06:38 +0000 (12:06 -0400)
committerJerome St-Louis <jerome@ecere.com>
Thu, 15 Oct 2015 00:28:40 +0000 (20:28 -0400)
ecere/src/gui/Window.ec
ecere/src/gui/drivers/AndroidInterface.ec

index 85dcdaa..581e4dc 100644 (file)
@@ -491,6 +491,15 @@ private class HotKeySlot : struct
    Key key;
 };
 
+public struct TouchPointerInfo
+{
+   int id;
+   int x, y;
+   float size, pressure;
+};
+
+public enum TouchPointerEvent { move, up, down, pointerUp, pointerDown };
+
 public class Window
 {
 private:
@@ -4060,6 +4069,59 @@ private:
       reEntrancy = false;
    }
 
+   public bool MultiTouchMessage(TouchPointerEvent event, Array<TouchPointerInfo> infos, Modifiers * mods, bool consequential, bool activate)
+   {
+      bool result = true;
+      if(infos.count)
+      {
+         Window w = null;
+         while(result && w != this)
+         {
+            // TODO: How to handle this?
+            int x = infos[0].x;
+            int y = infos[0].y;
+            Window msgWindow = GetAtPosition(x,y, false, true, w);
+            Window window;
+            delete w;
+            w = msgWindow;
+            if(w) incref w;
+            window = (w && !w.disabled) ? w : null;
+
+            if(consequential) mods->isSideEffect = true;
+            if(!result || (window && window.destroyed)) window = null;
+
+            if(window)
+            {
+               if(window.OnMultiTouch && !window.disabled)
+               {
+                  Array<TouchPointerInfo> in { size = infos.size };
+                  memcpy(in.array, infos.array, sizeof(TouchPointerInfo) * infos.size);
+
+                  for(i : in)
+                  {
+                     i.x -= (window.absPosition.x + window.clientStart.x);
+                     i.y -= (window.absPosition.y + window.clientStart.y);
+
+                     i.x = Max(Min(i.x, 32767),-32768);
+                     i.y = Max(Min(i.y, 32767),-32768);
+                  }
+
+                  incref window;
+                  if(!window.OnMultiTouch(event, in, *mods))
+                     result = false;
+
+                  delete in;
+                  delete window;
+               }
+            }
+            if(!result || !w || !w.clickThrough)
+               break;
+         }
+         delete w;
+      }
+      return result;
+   }
+
    public bool MouseMessage(uint method, int x, int y, Modifiers * mods, bool consequential, bool activate)
    {
       bool result = true;
@@ -7985,6 +8047,7 @@ public:
    virtual bool OnMiddleButtonDown(int x, int y, Modifiers mods);
    virtual bool OnMiddleButtonUp(int x, int y, Modifiers mods);
    virtual bool OnMiddleDoubleClick(int x, int y, Modifiers mods);
+   virtual bool OnMultiTouch(TouchPointerEvent event, Array<TouchPointerInfo> infos, Modifiers mods);
    virtual void OnMouseCaptureLost(void);
    virtual void OnHScroll(ScrollBarAction action, int position, Key key);
    virtual void OnVScroll(ScrollBarAction action, int position, Key key);
@@ -10134,6 +10197,18 @@ class WindowControllerInterface : ControllableWindow
       return result;
    }
 
+   bool OnMultiTouch(TouchPointerEvent event, Array<TouchPointerInfo> infos, Modifiers mods)
+   {
+      bool result = controller.OnMultiTouch ? ((bool(*)(Window, WindowController, TouchPointerEvent event, Array<TouchPointerInfo> infos, Modifiers))(void *)controller.OnMultiTouch)((Window)controller.controlled, controller, event, infos, mods) : true;
+      if(result)
+      {
+         bool(* onMultiTouch)(Window, TouchPointerEvent, Array<TouchPointerInfo>, Modifiers) = (void *)controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMultiTouch];
+         if(onMultiTouch)
+            onMultiTouch(controller.window, event, infos, mods);
+      }
+      return result;
+   }
+
    void OnResize(int width, int height)
    {
       if(controller.OnResize)
@@ -10249,6 +10324,7 @@ public:
    virtual bool V::OnMiddleButtonDown(WindowController controller, int x, int y, Modifiers mods);
    virtual bool V::OnMiddleButtonUp(WindowController controller, int x, int y, Modifiers mods);
    virtual bool V::OnMiddleDoubleClick(WindowController controller, int x, int y, Modifiers mods);
+   virtual bool V::OnMultiTouch(WindowController controller, TouchPointerEvent event, Array<TouchPointerInfo> infos, Modifiers mods);
    virtual void V::OnResize(WindowController controller, int width, int height);
    virtual void V::OnRedraw(WindowController controller, Surface surface);
    virtual bool V::OnCreate(WindowController controller);
index bfa009d..c623415 100644 (file)
@@ -440,6 +440,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
 {
    AndroidAppGlue app = (AndroidAppGlue)activity->instance;
    LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
+   app.window = null;
    app.set_window(null);
 }
 
@@ -512,7 +513,7 @@ default dllexport void ANativeActivity_onCreate(ANativeActivity* activity, void*
    ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN|AWINDOW_FLAG_KEEP_SCREEN_ON, 0 );
    app = AndroidActivity { activity = activity, moduleName = moduleName };
    incref app;
-   app.setSavedState(savedState, savedStateSize);
+   app.setSavedState(savedState, (uint)savedStateSize);
    activity->callbacks->onDestroy = onDestroy;
    activity->callbacks->onStart = onStart;
    activity->callbacks->onResume = onResume;
@@ -1060,6 +1061,22 @@ static Key keyCodeTable[] =
 // Why don't we have this in the NDK :(
 // default int32_t AKeyEvent_getUnichar(const AInputEvent* key_event);
 
+static Array<TouchPointerInfo> buildPointerInfo(AInputEvent * event)
+{
+   uint count = (uint)AMotionEvent_getPointerCount(event);
+   Array<TouchPointerInfo> infos { size = count };
+   int i;
+   for(i = 0; i < count; i++)
+   {
+      infos[i].x = (int)AMotionEvent_getX(event, i);
+      infos[i].y = (int)AMotionEvent_getY(event, i);
+      infos[i].id = (int)AMotionEvent_getPointerId(event, i);
+      infos[i].pressure = AMotionEvent_getPressure(event, i);
+      infos[i].size = AMotionEvent_getSize(event, i);
+   }
+   return infos;
+}
+
 class AndroidActivity : AndroidAppGlue
 {
    AndroidPollSource source;
@@ -1124,20 +1141,48 @@ class AndroidActivity : AndroidAppGlue
                mouseX = x, mouseY = y;
                if(result)
                   window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown, x, y, &keyFlags, false, true);
+               if(result)
+               {
+                  Array<TouchPointerInfo> infos = buildPointerInfo(event);
+                  window.MultiTouchMessage(down, infos, &keyFlags, false, true);
+                  delete infos;
+               }
                break;
             }
             case AMOTION_EVENT_ACTION_UP:
                mouseX = x, mouseY = y;
-               window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x, y, &keyFlags, false, true);
+               if(window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x, y, &keyFlags, false, true))
+               {
+                  Array<TouchPointerInfo> infos = buildPointerInfo(event);
+                  window.MultiTouchMessage(up, infos, &keyFlags, false, true);
+                  delete infos;
+               }
                break;
             case AMOTION_EVENT_ACTION_MOVE:
                mouseX = x, mouseY = y;
-               window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, true);
+               if(window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, true))
+               {
+                  Array<TouchPointerInfo> infos = buildPointerInfo(event);
+                  window.MultiTouchMessage(move, infos, &keyFlags, false, true);
+                  delete infos;
+               }
                break;
             case AMOTION_EVENT_ACTION_CANCEL: break;
             case AMOTION_EVENT_ACTION_OUTSIDE: break;
-            case AMOTION_EVENT_ACTION_POINTER_DOWN: break;
-            case AMOTION_EVENT_ACTION_POINTER_UP: break;
+            case AMOTION_EVENT_ACTION_POINTER_DOWN:
+            {
+               Array<TouchPointerInfo> infos = buildPointerInfo(event);
+               window.MultiTouchMessage(pointerDown, infos, &keyFlags, false, true);
+               delete infos;
+               break;
+            }
+            case AMOTION_EVENT_ACTION_POINTER_UP:
+            {
+               Array<TouchPointerInfo> infos = buildPointerInfo(event);
+               window.MultiTouchMessage(pointerUp, infos, &keyFlags, false, true);
+               delete infos;
+               break;
+            }
          }
          return 1;
       }