From f559d818c6652f55a2f63e9d391b29d88d160a38 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexis=20Laferri=C3=A8re?= Date: Thu, 18 Dec 2014 20:06:37 -0500 Subject: [PATCH] android: extract Android input events from `mnit_android` MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Alexis Laferrière --- lib/android/input_events.nit | 207 ++++++++++++++++++++++++++++++++++++++ lib/mnit_android/android_app.nit | 188 ++-------------------------------- 2 files changed, 213 insertions(+), 182 deletions(-) create mode 100644 lib/android/input_events.nit diff --git a/lib/android/input_events.nit b/lib/android/input_events.nit new file mode 100644 index 0000000..df23070 --- /dev/null +++ b/lib/android/input_events.nit @@ -0,0 +1,207 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2012-2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Pointer and hardware key events +module input_events + +import mnit_input +import android + +in "C header" `{ + #include + #include + + #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__)) + #ifdef DEBUG + #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__)) + #else + #define LOGI(...) (void)0 + #endif +`} + +in "C" `{ + /* Handle inputs from the Android platform and sort them before + sending them in the Nit App */ + static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) { + App nit_app = app->userData; + LOGI("handle input %i", (int)pthread_self()); + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { + LOGI("key"); + return App_extern_input_key(nit_app, event); + } + else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { + LOGI("motion"); + return App_extern_input_motion(nit_app, event); + } + + return 0; + } +`} + + +extern class InnerAndroidMotionEvent in "C" `{AInputEvent *`} + super Pointer + private fun pointers_count: Int is extern `{ + return AMotionEvent_getPointerCount(recv); + `} + private fun just_went_down: Bool is extern `{ + return (AMotionEvent_getAction(recv) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN; + `} + private fun edge: Int is extern `{ + return AMotionEvent_getEdgeFlags(recv); + `} + private fun index_down_pointer: Int is extern `{ + int a = AMotionEvent_getAction(recv); + 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; + `} + + private fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `} +end + +extern class AMotionEventAction `{ int32_t `} + protected fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `} + fun is_down: Bool do return action == 0 + fun is_up: Bool do return action == 1 + fun is_move: Bool do return action == 2 + fun is_cancel: Bool do return action == 3 + fun is_outside: Bool do return action == 4 + fun is_pointer_down: Bool do return action == 5 + fun is_pointer_up: Bool do return action == 6 +end + +interface AndroidInputEvent + super InputEvent +end + +class AndroidMotionEvent + super AndroidInputEvent + super MotionEvent + + private init(ie: InnerAndroidMotionEvent) do inner_event = ie + private var inner_event: InnerAndroidMotionEvent + + private var pointers_cache: nullable Array[AndroidPointerEvent] = null + 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 = inner_event.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 + end + end + + redef fun just_went_down: Bool do return inner_event.just_went_down + fun edge: Int do return inner_event.edge + + redef fun down_pointer: nullable AndroidPointerEvent + do + var i = inner_event.index_down_pointer + if i > 0 then + return pointers[i] + else + return null + end + end +end + +class AndroidPointerEvent + super PointerEvent + super AndroidInputEvent + + protected var motion_event: AndroidMotionEvent + protected var pointer_id: Int + + redef fun x: Float do return extern_x(motion_event.inner_event, pointer_id) + private fun extern_x(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ + return AMotionEvent_getX(motion_event, pointer_id); + `} + + redef fun y: Float do return extern_y(motion_event.inner_event, pointer_id) + private fun extern_y(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ + return AMotionEvent_getY(motion_event, pointer_id); + `} + + fun pressure: Float do return extern_pressure(motion_event.inner_event, pointer_id) + private fun extern_pressure(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ + return AMotionEvent_getPressure(motion_event, pointer_id); + `} + + redef fun pressed + do + var action = motion_event.inner_event.action + return action.is_down or action.is_move + end + + redef fun depressed do return not pressed +end + +extern class AndroidKeyEvent in "C" `{AInputEvent *`} + super KeyEvent + super AndroidInputEvent + + fun action: Int is extern `{ + return AKeyEvent_getAction(recv); + `} + redef fun is_down: Bool do return action == 0 + redef fun is_up: Bool do return action == 1 + + fun key_code: Int is extern `{ + return AKeyEvent_getKeyCode(recv); + `} + + redef fun to_c `{ + int code = AKeyEvent_getKeyCode(recv); + if (code >= AKEYCODE_0 && code <= AKEYCODE_9) + return '0'+code-AKEYCODE_0; + if (code >= AKEYCODE_A && code <= AKEYCODE_Z) + return 'a'+code-AKEYCODE_A; + return 0; + `} + + fun is_back_key: Bool do return key_code == 4 + fun is_menu_key: Bool do return key_code == 82 + fun is_search_key: Bool do return key_code == 84 + + fun is_volume_up: Bool do return key_code == 24 + fun is_volume_down: Bool do return key_code == 25 +end + +redef class App + + redef fun init_window + do + set_as_input_handler native_app_glue + super + end + + private fun set_as_input_handler(app_glue: NativeAppGlue) import extern_input_key, extern_input_motion `{ + app_glue->onInputEvent = mnit_handle_input; + `} + + # these are used as a callback from native to type incoming events + private fun extern_input_key(event: AndroidKeyEvent): Bool is abstract + + private fun extern_input_motion(event: InnerAndroidMotionEvent): Bool is abstract +end diff --git a/lib/mnit_android/android_app.nit b/lib/mnit_android/android_app.nit index 87afb4a..00c3244 100644 --- a/lib/mnit_android/android_app.nit +++ b/lib/mnit_android/android_app.nit @@ -25,27 +25,10 @@ end import mnit import android import mnit::opengles1 - -in "C header" `{ - #include - #include - #include - #include - - #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__)) - #ifdef DEBUG - #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__)) - #else - #define LOGI(...) (void)0 - #endif -`} +intrude import ::android::input_events in "C" `{ #include - #include - #define GL_GLEXT_PROTOTYPES 1 - #include - #include extern EGLDisplay mnit_display; extern EGLSurface mnit_surface; @@ -57,185 +40,28 @@ in "C" `{ //int mnit_orientation_changed; float mnit_zoom; - - /* Handle inputs from the Android platform and sort them before - sending them in the Nit App */ - static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) { - App nit_app = app->userData; - LOGI("handle input %i", (int)pthread_self()); - if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { - LOGI("key"); - return App_extern_input_key(nit_app, event); - } - else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { - LOGI("motion"); - return App_extern_input_motion(nit_app, event); - } - - return 0; - } `} - -extern class InnerAndroidMotionEvent in "C" `{AInputEvent *`} - super Pointer - private fun pointers_count: Int is extern `{ - return AMotionEvent_getPointerCount(recv); - `} - private fun just_went_down: Bool is extern `{ - return (AMotionEvent_getAction(recv) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN; - `} - private fun edge: Int is extern `{ - return AMotionEvent_getEdgeFlags(recv); - `} - private fun index_down_pointer: Int is extern `{ - int a = AMotionEvent_getAction(recv); - 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; - `} - - private fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `} -end - -extern class AMotionEventAction `{ int32_t `} - protected fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `} - fun is_down: Bool do return action == 0 - fun is_up: Bool do return action == 1 - fun is_move: Bool do return action == 2 - fun is_cancel: Bool do return action == 3 - fun is_outside: Bool do return action == 4 - fun is_pointer_down: Bool do return action == 5 - fun is_pointer_up: Bool do return action == 6 -end - -interface AndroidInputEvent - super InputEvent -end - -class AndroidMotionEvent - super AndroidInputEvent - super MotionEvent - - private init(ie: InnerAndroidMotionEvent) do inner_event = ie - private var inner_event: InnerAndroidMotionEvent - - private var pointers_cache: nullable Array[AndroidPointerEvent] = null - 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 = inner_event.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 - end - end - - redef fun just_went_down: Bool do return inner_event.just_went_down - fun edge: Int do return inner_event.edge - - redef fun down_pointer: nullable AndroidPointerEvent - do - var i = inner_event.index_down_pointer - if i > 0 then - return pointers[i] - else - return null - end - end -end - -class AndroidPointerEvent - super PointerEvent - super AndroidInputEvent - - protected var motion_event: AndroidMotionEvent - protected var pointer_id: Int - - redef fun x: Float do return extern_x(motion_event.inner_event, pointer_id) - private fun extern_x(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return ((int) AMotionEvent_getX(motion_event, pointer_id)); - `} - - redef fun y: Float do return extern_y(motion_event.inner_event, pointer_id) - private fun extern_y(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return ((int) AMotionEvent_getY(motion_event, pointer_id)); - `} - - fun pressure: Float do return extern_pressure(motion_event.inner_event, pointer_id) - private fun extern_pressure(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return AMotionEvent_getPressure(motion_event, pointer_id); - `} - - redef fun pressed - do - var action = motion_event.inner_event.action - return action.is_down or action.is_move - end - - redef fun depressed do return not pressed -end - -extern class AndroidKeyEvent in "C" `{AInputEvent *`} - super KeyEvent - super AndroidInputEvent - - fun action: Int is extern `{ - return AKeyEvent_getAction(recv); - `} - redef fun is_down: Bool do return action == 0 - redef fun is_up: Bool do return action == 1 - - fun key_code: Int is extern `{ - return AKeyEvent_getKeyCode(recv); - `} - - redef fun to_c `{ - int code = AKeyEvent_getKeyCode(recv); - if (code >= AKEYCODE_0 && code <= AKEYCODE_9) - return '0'+code-AKEYCODE_0; - if (code >= AKEYCODE_A && code <= AKEYCODE_Z) - return 'a'+code-AKEYCODE_A; - return 0; - `} - - fun is_back_key: Bool do return key_code == 4 - fun is_menu_key: Bool do return key_code == 82 - fun is_search_key: Bool do return key_code == 84 - - fun is_volume_up: Bool do return key_code == 24 - fun is_volume_down: Bool do return key_code == 25 -end - redef class App redef type D: Opengles1Display redef fun init_window do - set_as_input_handler native_app_glue display = new Opengles1Display super end - private fun set_as_input_handler(app_glue: NativeAppGlue) import extern_input_key, extern_input_motion `{ - app_glue->onInputEvent = mnit_handle_input; - `} - redef fun full_frame do if not paused then super - # these are used as a callback from native to type incoming events - private fun extern_input_key(event: AndroidKeyEvent): Bool + redef fun generate_input do poll_looper 0 + + redef fun extern_input_key(event) do return input(event) end - private fun extern_input_motion(event: InnerAndroidMotionEvent): Bool + + redef fun extern_input_motion(event) do var ie = new AndroidMotionEvent(event) var handled = input(ie) @@ -248,6 +74,4 @@ redef class App return handled end - - redef fun generate_input do poll_looper 0 end -- 1.7.9.5