1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Pointer and hardware key events
24 #include <android/log.h>
25 #include <android_native_app_glue.h>
27 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__))
29 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__))
31 #define LOGI(...) (void)0
36 /* Handle inputs from the Android platform and sort them before
37 sending them in the Nit App */
38 static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) {
39 App nit_app = app->userData;
40 LOGI("handle input %i", (int)pthread_self());
41 if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
43 return App_native_input_key(nit_app, event);
45 else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
47 return App_native_input_motion(nit_app, event);
54 private extern class NativeAndroidMotionEvent `{AInputEvent *`}
56 fun pointers_count: Int `{
57 return AMotionEvent_getPointerCount(self);
60 # Did this motion event just started?
61 fun just_went_down: Bool `{
62 return (AMotionEvent_getAction(self) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN;
66 return AMotionEvent_getEdgeFlags(self);
69 # Get the non-primary pointer id that just went down (returns -1 or > 0)
70 fun index_down_pointer: Int `{
71 int a
= AMotionEvent_getAction(self);
72 if ((a
& AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN)
73 return (a
& AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
77 fun action: AMotionEventAction `{ return AMotionEvent_getAction(self); `}
80 private extern class AMotionEventAction `{ int32_t `}
81 fun action: Int `{ return self & AMOTION_EVENT_ACTION_MASK; `}
83 # Pointer index concerned by this action
85 # Require: `is_pointer_down or is_pointer_up`
86 fun pointer_index
: Int `{
87 return (self & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
90 fun is_down
: Bool do return action
== 0
91 fun is_up
: Bool do return action
== 1
92 fun is_move
: Bool do return action
== 2
93 fun is_cancel
: Bool do return action
== 3
94 fun is_outside
: Bool do return action
== 4
95 fun is_pointer_down
: Bool do return action
== 5
96 fun is_pointer_up
: Bool do return action
== 6
99 # An input event on Android
100 interface AndroidInputEvent
104 # A motion event concerning a single or more `pointers`
105 class AndroidMotionEvent
106 super AndroidInputEvent
109 private var native
: NativeAndroidMotionEvent
111 # Pointers (or fingers) composing this motion event
112 var pointers
: Array[AndroidPointerEvent] is lazy
do
113 return [for i
in native
.pointers_count
.times
do new AndroidPointerEvent(self, i
)]
116 # The pointer (or finger) causing this event
117 var acting_pointer
: AndroidPointerEvent is lazy
do
118 var action
= native
.action
121 if action
.is_pointer_down
or action
.is_pointer_up
then
122 index
= native
.action
.pointer_index
125 return new AndroidPointerEvent(self, index
)
128 redef fun just_went_down
do return native
.just_went_down
130 # Was the top edge of the screen intersected by this event?
131 fun touch_to_edge
: Bool do return native
.edge
== 1
133 # Was the bottom edge of the screen intersected by this event?
134 fun touch_bottom_edge
: Bool do return native
.edge
== 2
136 # Was the left edge of the screen intersected by this event?
137 fun touch_left_edge
: Bool do return native
.edge
== 4
139 # Was the right edge of the screen intersected by this event?
140 fun touch_right_edge
: Bool do return native
.edge
== 8
142 redef fun down_pointer
: nullable AndroidPointerEvent
144 if just_went_down
then
145 # The primary pointer went down
149 var i
= native
.index_down_pointer
151 # A secondary pointer went down
160 class AndroidPointerEvent
162 super AndroidInputEvent
164 private var motion_event
: AndroidMotionEvent
166 private var pointer_index
: Int
168 redef fun x
do return native_x
(motion_event
.native
, pointer_index
)
170 private fun native_x
(motion_event
: NativeAndroidMotionEvent, pointer_index
: Int): Float `{
171 return AMotionEvent_getX(motion_event, pointer_index);
174 redef fun y
do return native_y
(motion_event
.native
, pointer_index
)
176 private fun native_y
(motion_event
: NativeAndroidMotionEvent, pointer_index
: Int): Float `{
177 return AMotionEvent_getY(motion_event, pointer_index);
180 # Pressure applied by this pointer
181 fun pressure
: Float do return native_pressure
(motion_event
.native
, pointer_index
)
183 private fun native_pressure
(motion_event
: NativeAndroidMotionEvent, pointer_index
: Int): Float `{
184 return AMotionEvent_getPressure(motion_event, pointer_index);
189 var action
= motion_event
.native
.action
190 return action
.is_down
or action
.is_move
or action
.is_pointer_down
193 # Is this a move event?
194 fun is_move
: Bool do return motion_event
.acting_pointer
== self and
195 motion_event
.native
.action
.is_move
197 redef fun depressed
do return not pressed
199 # Does this pointer just began touching the screen?
200 fun just_went_down
: Bool
202 return motion_event
.down_pointer
== self
205 # Unique id of this pointer since the beginning of the gesture
206 fun pointer_id
: Int do return native_pointer_id
(motion_event
.native
, pointer_index
)
208 private fun native_pointer_id
(motion_event
: NativeAndroidMotionEvent, pointer_index
: Int): Int `{
209 return AMotionEvent_getPointerId(motion_event, pointer_index);
213 # An hardware key event
214 extern class AndroidKeyEvent `{AInputEvent *`}
216 super AndroidInputEvent
218 private fun action: Int `{ return AKeyEvent_getAction(self); `}
220 redef fun is_down
do return action
== 0
221 redef fun is_up
do return action
== 1
223 # Hardware code of the key raising this event
224 fun key_code
: Int `{ return AKeyEvent_getKeyCode(self); `}
227 int code
= AKeyEvent_getKeyCode(self);
228 if (code
>= AKEYCODE_0 && code
<= AKEYCODE_9)
229 return '0'+code-AKEYCODE_0
;
230 if (code
>= AKEYCODE_A && code
<= AKEYCODE_Z)
231 return 'a'+code-AKEYCODE_A
;
235 redef fun name do return key_code.to_s
237 # Was this event raised by the back key?
238 fun is_back_key: Bool do return key_code == 4
240 # Was this event raised by the menu key?
241 fun is_menu_key: Bool do return key_code == 82
243 # Was this event raised by the search key?
244 fun is_search_key: Bool do return key_code == 84
246 # Was this event raised by the volume up key?
247 fun is_volume_up: Bool do return key_code == 24
249 # Was this event raised by the volume down key?
250 fun is_volume_down: Bool do return key_code == 25
255 redef fun init_window
257 set_as_input_handler native_app_glue
261 private fun set_as_input_handler(app_glue: NativeAppGlue)
262 import native_input_key, native_input_motion `{
263 app_glue-
>onInputEvent
= mnit_handle_input
;
266 # these are used as a callback from native to type incoming events
267 private fun native_input_key(event: AndroidKeyEvent): Bool is abstract
269 private fun native_input_motion(event: NativeAndroidMotionEvent): Bool is abstract