lib/android: intro motion down_time
[nit.git] / lib / android / input_events.nit
index 48c2d72..5ee9d87 100644 (file)
@@ -17,8 +17,8 @@
 # Pointer and hardware key events
 module input_events
 
-import mnit_input
-import android
+import mnit::input
+import android::game
 
 in "C header" `{
        #include <android/log.h>
@@ -54,29 +54,35 @@ in "C" `{
 private extern class NativeAndroidMotionEvent `{AInputEvent *`}
 
        fun pointers_count: Int `{
-               return AMotionEvent_getPointerCount(recv);
-       `}
-
-       fun just_went_down: Bool `{
-               return (AMotionEvent_getAction(recv) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN;
+               return AMotionEvent_getPointerCount(self);
        `}
 
        fun edge: Int `{
-               return AMotionEvent_getEdgeFlags(recv);
+               return AMotionEvent_getEdgeFlags(self);
        `}
 
+       # Get the non-primary pointer id that just went down (returns -1 or > 0)
        fun index_down_pointer: Int `{
-               int a = AMotionEvent_getAction(recv);
+               int a = AMotionEvent_getAction(self);
                if ((a & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN)
                        return (a & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
                else return -1;
        `}
 
-       fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `}
+       fun action: AMotionEventAction `{ return AMotionEvent_getAction(self); `}
+
+       fun native_down_time: Int `{ return AMotionEvent_getDownTime(self); `}
 end
 
 private extern class AMotionEventAction `{ int32_t `}
-       fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `}
+       fun action: Int `{ return self & AMOTION_EVENT_ACTION_MASK; `}
+
+       # Pointer index concerned by this action
+       #
+       # Require: `is_pointer_down or is_pointer_up`
+       fun pointer_index: Int `{
+               return (self & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+       `}
 
        fun is_down: Bool do return action == 0
        fun is_up: Bool do return action == 1
@@ -99,26 +105,24 @@ class AndroidMotionEvent
 
        private var native: NativeAndroidMotionEvent
 
-       private var pointers_cache: nullable Array[AndroidPointerEvent] = null
-
        # Pointers (or fingers) composing this motion event
-       fun pointers: Array[AndroidPointerEvent]
-       do
-               if pointers_cache != null then
-                       return pointers_cache.as(not null)
-               else
-                       var pointers = new Array[AndroidPointerEvent]
-                       var pointers_count = native.pointers_count
-                       for i in [0 .. pointers_count [do
-                               var pointer_event = new AndroidPointerEvent(self, i)
-                               pointers.add(pointer_event)
-                       end
-                       pointers_cache = pointers
-                       return pointers
+       var pointers: Array[AndroidPointerEvent] is lazy do
+               return [for i in native.pointers_count.times do new AndroidPointerEvent(self, i)]
+       end
+
+       # The pointer (or finger) causing this event
+       var acting_pointer: AndroidPointerEvent is lazy do
+               var action = native.action
+               var index = 0
+
+               if action.is_pointer_down or action.is_pointer_up then
+                       index = native.action.pointer_index
                end
+
+               return new AndroidPointerEvent(self, index)
        end
 
-       redef fun just_went_down: Bool do return native.just_went_down
+       redef fun just_went_down do return native.action.is_down or native.action.is_pointer_down
 
        # Was the top edge of the screen intersected by this event?
        fun touch_to_edge: Bool do return native.edge == 1
@@ -134,13 +138,24 @@ class AndroidMotionEvent
 
        redef fun down_pointer: nullable AndroidPointerEvent
        do
+               if just_went_down then
+                       # The primary pointer went down
+                       return pointers[0]
+               end
+
                var i = native.index_down_pointer
                if i > 0 then
+                       # A secondary pointer went down
                        return pointers[i]
                else
                        return null
                end
        end
+
+       # Time when the user originally pressed down to start a stream of position events
+       #
+       # The return value is in the `java.lang.System.nanoTime()` time base.
+       fun down_time: Int do return native.native_down_time
 end
 
 # A pointer event
@@ -150,34 +165,46 @@ class AndroidPointerEvent
 
        private var motion_event: AndroidMotionEvent
 
-       private var pointer_id: Int
+       private var pointer_index: Int
 
-       redef fun x: Float do return native_x(motion_event.native, pointer_id)
+       redef fun x do return native_x(motion_event.native, pointer_index)
 
-       private fun native_x(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{
-               return AMotionEvent_getX(motion_event, pointer_id);
+       private fun native_x(motion_event: NativeAndroidMotionEvent, pointer_index: Int): Float `{
+               return AMotionEvent_getX(motion_event, pointer_index);
        `}
 
-       redef fun y: Float do return native_y(motion_event.native, pointer_id)
+       redef fun y do return native_y(motion_event.native, pointer_index)
 
-       private fun native_y(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{
-               return AMotionEvent_getY(motion_event, pointer_id);
+       private fun native_y(motion_event: NativeAndroidMotionEvent, pointer_index: Int): Float `{
+               return AMotionEvent_getY(motion_event, pointer_index);
        `}
 
        # Pressure applied by this pointer
-       fun pressure: Float do return native_pressure(motion_event.native, pointer_id)
+       fun pressure: Float do return native_pressure(motion_event.native, pointer_index)
 
-       private fun native_pressure(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{
-               return AMotionEvent_getPressure(motion_event, pointer_id);
+       private fun native_pressure(motion_event: NativeAndroidMotionEvent, pointer_index: Int): Float `{
+               return AMotionEvent_getPressure(motion_event, pointer_index);
        `}
 
        redef fun pressed
        do
                var action = motion_event.native.action
-               return action.is_down or action.is_move
+               return action.is_down or action.is_move or action.is_pointer_down
        end
 
-       redef fun depressed do return not pressed
+       redef fun is_move do return motion_event.acting_pointer == self and
+               motion_event.native.action.is_move
+
+       # Does this pointer just began touching the screen?
+       fun just_went_down: Bool do return motion_event.acting_pointer == self and
+               motion_event.just_went_down
+
+       # Unique id of this pointer since the beginning of the gesture
+       fun pointer_id: Int do return native_pointer_id(motion_event.native, pointer_index)
+
+       private fun native_pointer_id(motion_event: NativeAndroidMotionEvent, pointer_index: Int): Int `{
+               return AMotionEvent_getPointerId(motion_event, pointer_index);
+       `}
 end
 
 # An hardware key event
@@ -185,16 +212,23 @@ extern class AndroidKeyEvent `{AInputEvent *`}
        super KeyEvent
        super AndroidInputEvent
 
-       private fun action: Int `{ return AKeyEvent_getAction(recv); `}
+       private fun action: Int `{ return AKeyEvent_getAction(self); `}
 
-       redef fun is_down: Bool do return action == 0
-       redef fun is_up: Bool do return action == 1
+       redef fun is_down do return action == 0
+       redef fun is_up do return action == 1
 
        # Hardware code of the key raising this event
-       fun key_code: Int `{ return AKeyEvent_getKeyCode(recv); `}
+       fun key_code: Int `{ return AKeyEvent_getKeyCode(self); `}
 
-       redef fun to_c `{
-               int code = AKeyEvent_getKeyCode(recv);
+       redef fun to_c
+       do
+               var i = native_to_c
+               if i == 0 then return null
+               return i.code_point
+       end
+
+       private fun native_to_c: Int `{
+               int code = AKeyEvent_getKeyCode(self);
                if (code >= AKEYCODE_0 && code <= AKEYCODE_9)
                        return '0'+code-AKEYCODE_0;
                if (code >= AKEYCODE_A && code <= AKEYCODE_Z)
@@ -202,6 +236,8 @@ extern class AndroidKeyEvent `{AInputEvent *`}
                return 0;
        `}
 
+       redef fun name do return key_code.to_s
+
        # Was this event raised by the back key?
        fun is_back_key: Bool do return key_code == 4