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 # Impements the services of `mnit:app` using the API from the Android ndk
26 #include <android/log.h>
27 #include <android_native_app_glue.h>
29 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__))
31 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__))
33 #define LOGI(...) (void)0
40 #define GL_GLEXT_PROTOTYPES 1
41 #include <GLES/glext.h>
44 extern EGLDisplay mnit_display;
45 extern EGLSurface mnit_surface;
46 extern EGLContext mnit_context;
47 extern EGLConfig mnit_config;
48 extern int32_t mnit_width;
49 extern int32_t mnit_height;
50 extern float mnit_zoom;
52 //int mnit_orientation_changed;
55 /* Handle inputs from the Android platform and sort them before
56 sending them in the Nit App */
57 static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) {
58 App nit_app = app->userData;
59 LOGI("handle input %i", (int)pthread_self());
60 if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
62 return App_extern_input_key(nit_app, event);
64 else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
66 return App_extern_input_motion(nit_app, event);
74 extern class InnerAndroidMotionEvent in "C" `{AInputEvent *`}
76 private fun pointers_count: Int is extern `{
77 return AMotionEvent_getPointerCount(recv
);
79 private fun just_went_down: Bool is extern `{
80 return (AMotionEvent_getAction(recv
) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN;
82 private fun edge: Int is extern `{
83 return AMotionEvent_getEdgeFlags(recv
);
85 private fun index_down_pointer: Int is extern `{
86 int a
= AMotionEvent_getAction(recv
);
87 if ((a
& AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN)
88 return (a
& AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
92 private fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `}
95 extern class AMotionEventAction `{ int32_t `}
96 protected fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `}
97 fun is_down
: Bool do return action
== 0
98 fun is_up
: Bool do return action
== 1
99 fun is_move
: Bool do return action
== 2
100 fun is_cancel
: Bool do return action
== 3
101 fun is_outside
: Bool do return action
== 4
102 fun is_pointer_down
: Bool do return action
== 5
103 fun is_pointer_up
: Bool do return action
== 6
106 interface AndroidInputEvent
110 class AndroidMotionEvent
111 super AndroidInputEvent
114 private init(ie
: InnerAndroidMotionEvent) do inner_event
= ie
115 private var inner_event
: InnerAndroidMotionEvent
117 private var pointers_cache
: nullable Array[AndroidPointerEvent] = null
118 fun pointers
: Array[AndroidPointerEvent]
120 if pointers_cache
!= null then
121 return pointers_cache
.as(not null)
123 var pointers
= new Array[AndroidPointerEvent]
124 var pointers_count
= inner_event
.pointers_count
125 for i
in [0 .. pointers_count
[do
126 var pointer_event
= new AndroidPointerEvent(self, i
)
127 pointers
.add
(pointer_event
)
129 pointers_cache
= pointers
134 redef fun just_went_down
: Bool do return inner_event
.just_went_down
135 fun edge
: Int do return inner_event
.edge
137 redef fun down_pointer
: nullable AndroidPointerEvent
139 var i
= inner_event
.index_down_pointer
148 class AndroidPointerEvent
150 super AndroidInputEvent
152 protected var motion_event
: AndroidMotionEvent
153 protected var pointer_id
: Int
155 redef fun x
: Float do return extern_x
(motion_event
.inner_event
, pointer_id
)
156 private fun extern_x
(motion_event
: InnerAndroidMotionEvent, pointer_id
: Int): Float is extern `{
157 return ((int) AMotionEvent_getX(motion_event, pointer_id) * mnit_zoom);
160 redef fun y
: Float do return extern_y
(motion_event
.inner_event
, pointer_id
)
161 private fun extern_y
(motion_event
: InnerAndroidMotionEvent, pointer_id
: Int): Float is extern `{
162 return ((int) AMotionEvent_getY(motion_event, pointer_id) * mnit_zoom);
165 fun pressure
: Float do return extern_pressure
(motion_event
.inner_event
, pointer_id
)
166 private fun extern_pressure
(motion_event
: InnerAndroidMotionEvent, pointer_id
: Int): Float is extern `{
167 return AMotionEvent_getPressure(motion_event, pointer_id);
172 var action
= motion_event
.inner_event
.action
173 return action
.is_down
or action
.is_move
176 redef fun depressed
do return not pressed
179 extern class AndroidKeyEvent in "C" `{AInputEvent *`}
181 super AndroidInputEvent
183 fun action: Int is extern `{
184 return AKeyEvent_getAction(recv
);
186 redef fun is_down: Bool do return action == 0
187 redef fun is_up: Bool do return action == 1
189 fun key_code: Int is extern `{
190 return AKeyEvent_getKeyCode(recv
);
193 fun key_char: Char is extern `{
194 int code
= AKeyEvent_getKeyCode(recv
);
195 if (code
>= AKEYCODE_0 && code
<= AKEYCODE_9)
196 return '0'+code-AKEYCODE_0
;
197 if (code
>= AKEYCODE_A && code
<= AKEYCODE_Z)
198 return 'a'+code-AKEYCODE_A
;
202 fun is_back_key: Bool do return key_code == 4
203 fun is_menu_key: Bool do return key_code == 82
204 fun is_search_key: Bool do return key_code == 84
208 redef type IE: AndroidInputEvent
209 redef type D: Opengles1Display
211 redef fun init_window
213 set_as_input_handler native_app_glue
214 display = new Opengles1Display
219 private fun set_as_input_handler(app_glue: NativeAppGlue) import extern_input_key, extern_input_motion `{
220 app_glue-
>onInputEvent
= mnit_handle_input
;
223 redef fun full_frame do if not paused then super
225 # these are used as a callback from native to type incoming events
226 private fun extern_input_key(event: AndroidKeyEvent): Bool
230 private fun extern_input_motion(event: InnerAndroidMotionEvent): Bool
232 var ie = new AndroidMotionEvent(event)
233 var handled = input(ie)
236 for pe in ie.pointers do
244 redef fun generate_input do poll_looper 0