/* * Handle Key Inputs */ static int32_t handle_key_input(AInputEvent *event) { if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) { switch (AKeyEvent_getKeyCode(event)) { case AKEYCODE_BACK: { cocos2d::EventKeyboard event(cocos2d::EventKeyboard::KeyCode::KEY_BACKSPACE, false); cocos2d::EventDispatcher::getInstance()->dispatchEvent(&event); } return 1; case AKEYCODE_MENU: { cocos2d::EventKeyboard event(cocos2d::EventKeyboard::KeyCode::KEY_MENU, false); cocos2d::EventDispatcher::getInstance()->dispatchEvent(&event); } return 1; default: break; } } return 0; }
int Engine::handleInput(AInputEvent* event) { if( !event ) return 0; //We only handle motion events (touchscreen) and key (button/key) events int32_t eventType = AInputEvent_getType(event); if (eventType == AINPUT_EVENT_TYPE_MOTION) { int32_t actionUnmasked = AMotionEvent_getAction(event); int32_t action = (actionUnmasked & AMOTION_EVENT_ACTION_MASK); static int l_siIgnoreTime = 0; bool l_bTouch = false; if(AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN || AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE ) { l_bTouch = true; } if( cGameApp::m_sbGamePause ) l_siIgnoreTime = 1; if( g_pAndroidTestApp && !cGameApp::m_sbGamePause && l_siIgnoreTime == 0 ) { if(g_pAndroidTestApp->m_sbDoMultiTouch) { int numEvents = AMotionEvent_getPointerCount(event); for (int index=0; index<numEvents; index++) { int id = AMotionEvent_getPointerId(event, index); float l_fPosX = AMotionEvent_getX(event, index); float l_fPosY = AMotionEvent_getY(event, index); float l_fpressure = AMotionEvent_getPressure(event, index); float l_fSize =AMotionEvent_getSize(event, index); g_pAndroidTestApp->m_spMultiTouchPoints->Touch(l_bTouch,(int)l_fPosX,(int)l_fPosY,id); g_pAndroidTestApp->TouchSignalProcess(l_fPosX,l_fPosY,l_bTouch); } g_pAndroidTestApp->m_spMultiTouchPoints->Update(0); } else { int32_t iX = AMotionEvent_getX(event, 0); int32_t iY = AMotionEvent_getY(event, 0); g_pAndroidTestApp->TouchSignalProcess(iX,iY,l_bTouch); } } if( l_siIgnoreTime > 0 ) { if( l_bTouch == false ) l_siIgnoreTime = 0; } //int32_t action = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction((const AInputEvent*)event); // A tap on the screen takes us out of autopause into gameplay mode if // we were paused. No other touch processing is done. if (action == AMOTION_EVENT_ACTION_DOWN) { setGameplayMode(true); g_pAndroidTestApp->m_spMultiTouchPoints->Init(); } //, return 1; } else if (eventType == AINPUT_EVENT_TYPE_KEY) { int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int32_t action = AKeyEvent_getAction((const AInputEvent*)event); // if we are in gameplay mode, we eat the back button and move into // pause mode. If we are already in pause mode, we allow the back // button to be handled by the OS, which means we'll be shut down if ((code == AKEYCODE_BACK) && mGameplayMode) { setGameplayMode(false); return 1; } std::string l_strDebugInfo = "Code:"; l_strDebugInfo += ValueToString(code); l_strDebugInfo += "___Action"; l_strDebugInfo += ValueToString(action); cGameApp::OutputDebugInfoString(l_strDebugInfo); bool l_bVaildKey = false; bool l_bKeyDown = action==0?true:false; if((code >= AKEYCODE_A && code <= AKEYCODE_Z)) {//windows 65-90 code -= AKEYCODE_A; code += 65; l_bVaildKey = true; } else if((code >= AKEYCODE_0 && code <= AKEYCODE_9)) {//windows 45-97 code -= AKEYCODE_0; code += 45; l_bVaildKey = true; } if( l_bVaildKey ) { if( l_bKeyDown ) { g_pAndroidTestApp->KeyDown((char)code); } else { g_pAndroidTestApp->KeyUp((char)code); } } } return 0; }
int32_t _glfwPlatformProcInputEvent( struct android_app* app, AInputEvent *event ) { // Motion events if ( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) { int action = AKeyEvent_getAction(event); int count = AMotionEvent_getPointerCount(event); switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); _glfwInputMouseClick(GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); } break; case AMOTION_EVENT_ACTION_UP: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); _glfwInputMouseClick(GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); } break; case AMOTION_EVENT_ACTION_MOVE: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); }else if(count == 2){ int old_x1 = (int) _glfwInput.MousePosX; int old_y1 = (int) _glfwInput.MousePosY; int old_x2 = (int) _glfwInput.MousePosX2; int old_y2 = (int) _glfwInput.MousePosY2; int new_x1 = (int) AMotionEvent_getX(event, 0); int new_y1 = (int) AMotionEvent_getY(event, 0); int new_x2 = (int) AMotionEvent_getX(event, 1); int new_y2 = (int) AMotionEvent_getY(event, 1); if(old_x1 == new_x1 && old_y1 == new_y1) { } else if(old_x2 == new_x2 && old_y2 == new_y2) { } else { if(abs((new_x2 - new_x1) * (new_y2 - new_y1)) > abs((old_x2 - old_x1) * (old_y2 - old_y1))){ _glfwInput.WheelPos++; }else{ _glfwInput.WheelPos--; } if(_glfwWin.mouseWheelCallback) _glfwWin.mouseWheelCallback(_glfwInput.WheelPos); } } _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); _glfwInput.MousePosX2 = AMotionEvent_getX(event, 1); _glfwInput.MousePosY2 = AMotionEvent_getY(event, 1); break; } return 1; } return 0; }
for (int index = 0; index < pointer_count; index++) { const f32 xx = AMotionEvent_getX(event, index); const f32 yy = AMotionEvent_getY(event, index); const s32 id = AMotionEvent_getPointerId(event, index); _queue.push_touch_event((s16)xx, (s16)yy, (u8)id); } break; } return 1; } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { const s32 keycode = AKeyEvent_getKeyCode(event); const s32 keyaction = AKeyEvent_getAction(event); if (keycode == AKEYCODE_BACK) { _queue.push_keyboard_event(KeyboardButton::ESCAPE , keyaction == AKEY_EVENT_ACTION_DOWN ? true : false ); } return 1; } return 0; } static s32 on_input_event(struct android_app* app, AInputEvent* event)
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent) { CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData; s32 status = 0; switch ( AInputEvent_getType(androidEvent) ) { case AINPUT_EVENT_TYPE_MOTION: { SEvent event; event.EventType = EET_TOUCH_INPUT_EVENT; s32 eventAction = AMotionEvent_getAction(androidEvent); s32 eventType = eventAction & AMOTION_EVENT_ACTION_MASK; #if 0 // Useful for debugging. We might have to pass some of those infos on at some point. // but preferably device independent (so iphone can use same irrlicht flags). int32_t flags = AMotionEvent_getFlags(androidEvent); os::Printer::log("flags: ", core::stringc(flags).c_str(), ELL_DEBUG); int32_t metaState = AMotionEvent_getMetaState(androidEvent); os::Printer::log("metaState: ", core::stringc(metaState).c_str(), ELL_DEBUG); int32_t edgeFlags = AMotionEvent_getEdgeFlags(androidEvent); os::Printer::log("edgeFlags: ", core::stringc(flags).c_str(), ELL_DEBUG); #endif bool touchReceived = true; switch (eventType) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: event.TouchInput.Event = ETIE_PRESSED_DOWN; break; case AMOTION_EVENT_ACTION_MOVE: event.TouchInput.Event = ETIE_MOVED; break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_CANCEL: event.TouchInput.Event = ETIE_LEFT_UP; break; default: touchReceived = false; break; } if (touchReceived) { // Process all touches for move action. if (event.TouchInput.Event == ETIE_MOVED) { s32 pointerCount = AMotionEvent_getPointerCount(androidEvent); for (s32 i = 0; i < pointerCount; ++i) { event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i); event.TouchInput.X = AMotionEvent_getX(androidEvent, i); event.TouchInput.Y = AMotionEvent_getY(androidEvent, i); device->postEventFromUser(event); } } else // Process one touch for other actions. { s32 pointerIndex = (eventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex); event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex); event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex); device->postEventFromUser(event); } status = 1; } } break; case AINPUT_EVENT_TYPE_KEY: { SEvent event; event.EventType = EET_KEY_INPUT_EVENT; int32_t keyCode = AKeyEvent_getKeyCode(androidEvent); // os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG); int32_t keyAction = AKeyEvent_getAction(androidEvent); int32_t keyMetaState = AKeyEvent_getMetaState(androidEvent); if ( keyCode >= 0 && (u32)keyCode < device->KeyMap.size() ) event.KeyInput.Key = device->KeyMap[keyCode]; else event.KeyInput.Key = KEY_UNKNOWN; event.KeyInput.SystemKeyCode = (u32)keyCode; if ( keyAction == AKEY_EVENT_ACTION_DOWN ) event.KeyInput.PressedDown = true; else if ( keyAction == AKEY_EVENT_ACTION_UP ) event.KeyInput.PressedDown = false; else if ( keyAction == AKEY_EVENT_ACTION_MULTIPLE ) { // TODO: Multiple duplicate key events have occurred in a row, // or a complex string is being delivered. The repeat_count // property of the key event contains the number of times the // given key code should be executed. // I guess this might necessary for more complicated i18n key input, // but don't see yet how to handle this correctly. } /* no use for meta keys so far. if ( keyMetaState & AMETA_ALT_ON || keyMetaState & AMETA_ALT_LEFT_ON || keyMetaState & AMETA_ALT_RIGHT_ON ) ; // what is a sym? if ( keyMetaState & AMETA_SYM_ON ) ; */ if ( keyMetaState & AMETA_SHIFT_ON || keyMetaState & AMETA_SHIFT_LEFT_ON || keyMetaState & AMETA_SHIFT_RIGHT_ON ) event.KeyInput.Shift = true; else event.KeyInput.Shift = false; event.KeyInput.Control = false; // Having memory allocations + going through JNI for each key-press is pretty bad (slow). // So we do it only for those keys which are likely text-characters and avoid it for all other keys. // So it's fast for keys like game controller input and special keys. And text keys are typically // only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much. if ( event.KeyInput.Key > 0 ) { // TODO: // Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or // trying to use the activity->env. My best guess is that the event-handling happens in an own thread. // It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that // (we could attach & detach each time, but that would probably be slow) // Also - it has to be each time as it get's invalid when the application mode changes. if ( device->Initialized && device->Android && device->Android->activity && device->Android->activity->vm ) { JavaVMAttachArgs attachArgs; attachArgs.version = JNI_VERSION_1_6; attachArgs.name = 0; attachArgs.group = NULL; // Not a big problem calling it each time - it's a no-op when the thread already is attached. // And we have to do that as someone else can have detached the thread in the meantime. jint result = device->Android->activity->vm->AttachCurrentThread(&device->JNIEnvAttachedToVM, &attachArgs); if(result == JNI_ERR) { os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING); device->JNIEnvAttachedToVM = 0; } if ( device->JNIEnvAttachedToVM ) { jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode); event.KeyInput.Char = keyEventWrapper->getUnicodeChar(keyMetaState); delete keyEventWrapper; } } if ( event.KeyInput.Key == KEY_BACK ) { event.KeyInput.Char = 0x08; // same key-code as on other operating systems. Otherwise we have to handle too much system specific stuff in the editbox. } //os::Printer::log("char-code: ", core::stringc((int)event.KeyInput.Char).c_str(), ELL_DEBUG); } else { // os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG); event.KeyInput.Char = 0; } device->postEventFromUser(event); } break; default: break; } return status; }
int32_t CPUT_OGL::cput_handle_input(struct android_app* app, AInputEvent* event) { int n; MySample *pSample = (MySample *)app->userData; int lEventType = AInputEvent_getType(event); static float drag_center_x = 0.0f, drag_center_y = 0.0f; static float dist_squared = 0.0f; static bool isPanning = false; switch (lEventType) { case AINPUT_EVENT_TYPE_MOTION: { ndk_helper::GESTURE_STATE doubleTapState = pSample->mDoubletapDetector.Detect(event); ndk_helper::GESTURE_STATE dragState = pSample->mDragDetector.Detect(event); ndk_helper::GESTURE_STATE pinchState = pSample->mPinchDetector.Detect(event); if( doubleTapState == ndk_helper::GESTURE_STATE_ACTION ) { LOGI("DOUBLE TAP RECEIVED"); } else { //Handle drag state if( dragState & ndk_helper::GESTURE_STATE_START ) { if (isPanning == false) { //LOGI("GESTURE_STATE_START - drag"); ndk_helper::Vec2 v; float x, y; pSample->mDragDetector.GetPointer( v ); v.Value(x, y); //LOGI(" TOUCH POINT: %f, %f", x, y); pSample->CPUTHandleMouseEvent(x, y, 0.0f, CPUT_MOUSE_LEFT_DOWN); } } else if( dragState & ndk_helper::GESTURE_STATE_MOVE ) { if (isPanning == false) { //LOGI("GESTURE_STATE_MOVE - drag"); ndk_helper::Vec2 v; float x, y; pSample->mDragDetector.GetPointer( v ); v.Value(x, y); pSample->CPUTHandleMouseEvent(x, y, 0.0f, CPUT_MOUSE_LEFT_DOWN); } } else if( dragState & ndk_helper::GESTURE_STATE_END ) { pSample->CPUTHandleMouseEvent(0.0f, 0.0f, 0.0f, CPUT_MOUSE_NONE ); pSample->HandleKeyboardEvent(KEY_A, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_D, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_E, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_W, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_S, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_Q, CPUT_KEY_UP); isPanning = false; //LOGI("GESTURE_STATE_END - drag"); } //Handle pinch state if( pinchState & ndk_helper::GESTURE_STATE_START ) { if (isPanning == false) { //LOGI("GESTURE_STATE_START - pinch"); //Start new pinch ndk_helper::Vec2 v1; ndk_helper::Vec2 v2; float x1, y1, x2, y2; pSample->mPinchDetector.GetPointers( v1, v2 ); v1.Value(x1, y1); v2.Value(x2, y2); drag_center_x = (x1 + x2) / 2.0f; drag_center_y = (y1 + y2) / 2.0f; dist_squared = ((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)); } } else if( pinchState & ndk_helper::GESTURE_STATE_MOVE ) { isPanning = true; CPUTKey key = (CPUTKey)0; CPUTKeyState state = (CPUTKeyState)0; //LOGI("GESTURE_STATE_MOVE - pinch"); ndk_helper::Vec2 v1; ndk_helper::Vec2 v2; float x1, y1, x2, y2; float new_center_x, new_center_y; float new_dist_squared; float delta_x, delta_y; pSample->mPinchDetector.GetPointers( v1, v2 ); v1.Value(x1, y1); v2.Value(x2, y2); new_center_x = (x1 + x2) / 2.0f; new_center_y = (y1 + y2) / 2.0f; new_dist_squared = ((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)); delta_x = drag_center_x - new_center_x; delta_y = drag_center_y - new_center_y; // // For each direction of movement, the opposite direction is cancelled (KEY_UP) // // Handle pinch and zoom actions if (abs(new_dist_squared - dist_squared) > 1000.0f) { if (new_dist_squared < dist_squared) { pSample->HandleKeyboardEvent(KEY_S, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_W, CPUT_KEY_DOWN); } else { pSample->HandleKeyboardEvent(KEY_W, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_S, CPUT_KEY_DOWN); } } else { pSample->HandleKeyboardEvent(KEY_W, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_S, CPUT_KEY_UP); } // handle left and right drag if (delta_x >= 2.0f) { pSample->HandleKeyboardEvent(KEY_A, CPUT_KEY_DOWN); pSample->HandleKeyboardEvent(KEY_D, CPUT_KEY_UP); } else if (delta_x <= -2.0f) { pSample->HandleKeyboardEvent(KEY_D, CPUT_KEY_DOWN); pSample->HandleKeyboardEvent(KEY_A, CPUT_KEY_UP); } else if (delta_x < 2.0 && delta_x > -2.0) { pSample->HandleKeyboardEvent(KEY_A, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_D, CPUT_KEY_UP); } // handle up and down drag if (delta_y >= 2.0f) { pSample->HandleKeyboardEvent(KEY_Q, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_E, CPUT_KEY_DOWN); } else if (delta_y <= -2.0f) { pSample->HandleKeyboardEvent(KEY_E, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_Q, CPUT_KEY_DOWN); } else if (delta_y < 2.0 && delta_y > -2.0) { pSample->HandleKeyboardEvent(KEY_E, CPUT_KEY_UP); pSample->HandleKeyboardEvent(KEY_Q, CPUT_KEY_UP); } // current values become old values for next frame dist_squared = new_dist_squared; drag_center_x = new_center_x; drag_center_y = new_center_y; } } } case AINPUT_EVENT_TYPE_KEY: { int aKey = AKeyEvent_getKeyCode(event); CPUTKey cputKey = ConvertToCPUTKey(aKey); int aAction = AKeyEvent_getAction(event); CPUTKeyState cputKeyState = ConvertToCPUTKeyState(aAction); pSample->CPUTHandleKeyboardEvent(cputKey, cputKeyState); return 1; } default: return 0; } return 0; }
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { engine* e = (engine*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { int32_t key = AKeyEvent_getKeyCode(event); int32_t key_action = AKeyEvent_getAction(event); if (key == AKEYCODE_BACK) { LOGD( "engine_handle_input", "AKEYCODE_BACK"); if (key_action == AKEY_EVENT_ACTION_UP) { LOGD("engine_handle_input", "AKEY_EVENT_ACTION_UP"); } return 1; // <-- prevent default handler } if (key == AKEYCODE_MENU) { LOGD( "engine_handle_input", "AKEYCODE_MENU"); if (key_action == AKEY_EVENT_ACTION_UP) { LOGD("engine_handle_input", "AKEY_EVENT_ACTION_UP"); } return 1; // <-- prevent default handler } /* if (key == AKEYCODE_HOME) { LOGD( "engine_handle_input", "AKEYCODE_HOME"); if (key_action == AKEY_EVENT_ACTION_UP) { LOGD("engine_handle_input", "AKEY_EVENT_ACTION_UP"); } return 1; // <-- prevent default handler } if (key == AKEYCODE_VOLUME_UP) { LOGD( "engine_handle_input", "AKEYCODE_VOLUME_UP"); if (key_action == AKEY_EVENT_ACTION_UP) { LOGD("engine_handle_input", "AKEY_EVENT_ACTION_UP"); } return 1; // <-- prevent default handler } if (key == AKEYCODE_VOLUME_DOWN) { LOGD( "engine_handle_input", "AKEYCODE_VOLUME_DOWN"); if (key_action == AKEY_EVENT_ACTION_UP) { LOGD("engine_handle_input", "AKEY_EVENT_ACTION_UP"); } return 1; // <-- prevent default handler }*/ } int index = 0; int touch_max = 5; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { if (touch_enabled) { int p; int action = AKeyEvent_getAction(event); switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: LOGDw("engine_handle_input", "AMOTION_EVENT_ACTION_DOWN"); touch_branching(AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0)); e->animating = 1; break; case AMOTION_EVENT_ACTION_POINTER_DOWN: LOGDw( "engine_handle_input", "AMOTION_EVENT_ACTION_POINTER_DOWN"); /* Bits in the action code that represent a pointer index, used with * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer * index where the data for the pointer going up or down can be found. */ // AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00, // マルチタッチバグを解決するため、こうやれば一番いい。 size_t pointer_index_mask = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; trigger_note(AMotionEvent_getX(event, pointer_index_mask), AMotionEvent_getY(event, pointer_index_mask)); set_parts_active(); LOGD("engine_handle_input", "pointer_index_mask: %d", pointer_index_mask); break; } return 1; } } return 0; }
int WindowImplAndroid::processEvent(int fd, int events, void* data) { ActivityStates* states = getActivity(NULL); Lock lock(states->mutex); AInputEvent* _event = NULL; if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0) { if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) return 1; int handled = 0; int32_t type = AInputEvent_getType(_event); if (type == AINPUT_EVENT_TYPE_KEY) { int32_t action = AKeyEvent_getAction(_event); int32_t key = AKeyEvent_getKeyCode(_event); if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) && key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN) { handled = processKeyEvent(_event, states); } } else if (type == AINPUT_EVENT_TYPE_MOTION) { int32_t action = AMotionEvent_getAction(_event); switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_SCROLL: { handled = processScrollEvent(_event, states); break; } // todo: should hover_move indeed trigger the event? // case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: { handled = processMotionEvent(_event, states); break; } // todo: investigate AMOTION_EVENT_OUTSIDE case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_DOWN: { handled = processPointerEvent(true, _event, states); break; } case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: { handled = processPointerEvent(false, _event, states); break; } } } AInputQueue_finishEvent(states->inputQueue, _event, handled); } return 1; }
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engineState* engine = (struct engineState*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int source = AInputEvent_getSource(event); if (source == AINPUT_SOURCE_TOUCHSCREEN) { float x = AMotionEvent_getX(event, 0); float y = AMotionEvent_getY(event, 0); engine->instance->getAndroidInputSystem()->handleTouchInput(x, y); return 1; } if (source == AINPUT_SOURCE_JOYSTICK) { float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0); float y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0); int devId = AInputEvent_getDeviceId(event); LOG_INFO("dev: " << devId << " pos: " << x << ":" << y); } return 0; } if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { int32_t source = AInputEvent_getSource(event); int32_t code = AKeyEvent_getKeyCode(event); int32_t action = AKeyEvent_getAction(event); LOG_INFO("Code: " << code << " Action: " << action); engine::input::KeyCode keycode = engine::input::KEY_VOID; switch (code) { case 96: keycode = engine::input::BUTTON_A; break; case 99: keycode = engine::input::BUTTON_X; break; case 100: keycode = engine::input::BUTTON_Y; break; case 97: keycode = engine::input::BUTTON_B; break; } if (action == 1) engine->instance->getInputSystem()->keyUp(keycode); else engine->instance->getInputSystem()->keyDown(keycode); return 1; } return 0; }
//callback extern int32_t __android_handle_input(struct android_app* app, AInputEvent* event){ /* Input source */ int nSourceId = AInputEvent_getSource( event ); //not supported device? if (!(nSourceId == AINPUT_SOURCE_TOUCHPAD || nSourceId == AINPUT_SOURCE_KEYBOARD || nSourceId == AINPUT_SOURCE_TOUCHSCREEN)) return 0; //keyboard if(nSourceId == AINPUT_SOURCE_KEYBOARD) { if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { //keybord down //get key code unsigned int keyAction = AKeyEvent_getAction(event); // if( keyDown && keyAction == AKEY_EVENT_ACTION_DOWN ) { keyDown(app->userData,AKeyEvent_getKeyCode(event)); } else if( keyUp && keyAction == AKEY_EVENT_ACTION_UP ) { keyUp(app->userData,AKeyEvent_getKeyCode(event)); } else { return 0; } return 1; } return 0; } //action unsigned int unmaskAction = AMotionEvent_getAction(event); //base action unsigned int action = unmaskAction & AMOTION_EVENT_ACTION_MASK; //pointer action unsigned int actionPointerIndex = (unmaskAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK); actionPointerIndex >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; if (action == AMOTION_EVENT_ACTION_DOWN) { //all down if(fingerDown){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerDown(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_POINTER_DOWN ) { //one down if(fingerDown){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); if( pointerFingerId==actionPointerIndex ) { fingerDown(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } } else if (action == AMOTION_EVENT_ACTION_UP) { //up all if(fingerUp){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerUp(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) { //up one if(fingerUp){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); if( pointerFingerId==actionPointerIndex ) { fingerUp(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } } else if (action == AMOTION_EVENT_ACTION_MOVE) { //move if(fingerMove){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerMove(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_CANCEL) { } else { return 0; } return 1; }
bool NvGamepadAndroid::processEvent(AInputEvent* event, uint32_t& changedMask) { int32_t eventType = AInputEvent_getType(event); // Hack - pad 0 only for now... State& state = mStates[0]; if (eventType == AINPUT_EVENT_TYPE_MOTION) { if (AINPUT_SOURCE_JOYSTICK == AInputEvent_getSource(event)) { state.mThumbLX = MapCenteredAxis(event, AMOTION_EVENT_AXIS_X); state.mThumbLY = MapCenteredAxis(event, AMOTION_EVENT_AXIS_Y); state.mThumbRX = MapCenteredAxis(event, AMOTION_EVENT_AXIS_Z); state.mThumbRY = MapCenteredAxis(event, AMOTION_EVENT_AXIS_RZ); ProcessDPAD(event, state); // need to map bot pairs of axes as of Android L { float lTrigger = MapAxis(event, AMOTION_EVENT_AXIS_LTRIGGER); float brake = MapAxis(event, AMOTION_EVENT_AXIS_BRAKE); state.mLeftTrigger = (lTrigger > brake) ? lTrigger : brake; } { float gas = MapAxis(event, AMOTION_EVENT_AXIS_GAS); float rTrigger = MapAxis(event, AMOTION_EVENT_AXIS_RTRIGGER); state.mRightTrigger = (rTrigger > gas) ? rTrigger : gas; } state.mTimestamp++; changedMask |= 1; return true; } } else if (eventType == AINPUT_EVENT_TYPE_KEY) { int32_t source = AInputEvent_getSource(event); int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int32_t action = AKeyEvent_getAction((const AInputEvent*)event); bool down = (action == AKEY_EVENT_ACTION_UP) ? false : true; uint32_t button = 0; switch (code) { case AKEYCODE_BUTTON_THUMBL: button = BUTTON_LEFT_THUMB; break; case AKEYCODE_BUTTON_THUMBR: button = BUTTON_RIGHT_THUMB; break; case AKEYCODE_DPAD_UP: button = BUTTON_DPAD_UP; break; case AKEYCODE_DPAD_DOWN: button = BUTTON_DPAD_DOWN; break; case AKEYCODE_DPAD_LEFT: button = BUTTON_DPAD_LEFT; break; case AKEYCODE_DPAD_RIGHT: button = BUTTON_DPAD_RIGHT; break; case AKEYCODE_DPAD_CENTER: button = BUTTON_CENTER; break; case AKEYCODE_BUTTON_L1: button = BUTTON_LEFT_SHOULDER; break; case AKEYCODE_BUTTON_R1: button = BUTTON_RIGHT_SHOULDER; break; case AKEYCODE_BUTTON_START: button = BUTTON_START; break; case AKEYCODE_BUTTON_A: button = BUTTON_A; break; case AKEYCODE_BUTTON_B: button = BUTTON_B; break; case AKEYCODE_BUTTON_X: button = BUTTON_X; break; case AKEYCODE_BUTTON_Y: button = BUTTON_Y; break; case AKEYCODE_MEDIA_PLAY_PAUSE: button = BUTTON_PLAY_PAUSE; break; default: #ifdef _DEBUG __android_log_print(ANDROID_LOG_VERBOSE, "NvGamepad", "unknown button 0x%0x", code); #endif return false; }; if (button) { if (UpdateButtonMask(down, state.mButtons, button)) { changedMask |= 1; state.mTimestamp++; } return true; } } return false; }
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* engine = (struct engine*)app->userData; int pointers = AMotionEvent_getPointerCount(event); if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int pointers = AMotionEvent_getPointerCount(event); switch(pointers) { case 1: //rotation if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_DOWN ) { X1 = AMotionEvent_getX(event, 0); Y1 = AMotionEvent_getY(event, 0); return 1; } else if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_UP) { // Do nothing } else if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_MOVE ) { float dx = AMotionEvent_getX(event, 0) - X1; float dy = AMotionEvent_getY(event, 0) - Y1; touchRotate(-dx,-dy); X1 = AMotionEvent_getX(event, 0); Y1 = AMotionEvent_getY(event, 0); } break; case 2: //pinch/zoom (multitouch) if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_DOWN ) { X1 = AMotionEvent_getX(event, 0); Y1 = AMotionEvent_getY(event, 0); X2 = AMotionEvent_getX(event, 1); Y2 = AMotionEvent_getY(event, 1); double dx = abs((double) (X2 - X1)); double dy = abs((double) (Y2 - Y1)); S = (float) sqrt((dx * dx) + (dy * dy)); } else if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_MOVE ) { float x1 = 0.0F; float y1 = 0.0F; float x2 = 0.0F; float y2 = 0.0F; // some unknown device throws an exception here x1 = AMotionEvent_getX(event, 0); y1 = AMotionEvent_getY(event, 0); x2 = AMotionEvent_getX(event, 1); y2 = AMotionEvent_getY(event, 1); double dx = abs((double) (x2 - x1)); double dy = abs((double) (y2 - y1)); float s = (float) sqrt((dx * dx) + (dy * dy)); touchScale(4.0f * (S - s)); //LOGI("S-s: %f",S-s); X1 = x1; Y1 = y1; X2 = x2; Y2 = y2; S = s; } break; case 3: //3 finger tap to switch shaders //LOGI("action: %i%",AKeyEvent_getAction(event)); if(AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_UP || AKeyEvent_getAction(event) == AMOTION_EVENT_ACTION_POINTER_UP ) { LOGI("3 finger tap UP"); ShaderToUse ++; if(ShaderToUse>2) ShaderToUse=0; } } } return 0; }
/** * Process the next input event. */ int32_t Engine::handleInput(AInputEvent* event) { if (mCallbacks && mGamepad->pollGamepads(event, mPadChangedMask)) return true; else if (NULL==mCallbacks) return false; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { bool handled = false; int32_t pointerCount = AMotionEvent_getPointerCount(event); int32_t action = amotion_getActionMasked(event); int32_t pointerIndex = amotion_getActionIndex(event); float x=0, y=0; NvPointerEvent p[20]; // !!!!!TBD should use linkedlist or app-member struct or something? TODO NvInputDeviceType::Enum dev = NvInputDeviceType::TOUCH; // loop over pointercount and copy data // !!!!TBD TODO, might need to ensure that p[0] is always the data from the first-finger-touched ID... for (int i=0; i<pointerCount; i++) { x = AMotionEvent_getX(event, i); y = AMotionEvent_getY(event, i); p[i].m_x = x; p[i].m_y = y; p[i].m_id = AMotionEvent_getPointerId(event, i); // then figure out tool/device enum... int32_t tool = AMotionEvent_getToolType(event, i); if (tool==AMOTION_EVENT_TOOL_TYPE_STYLUS || tool==AMOTION_EVENT_TOOL_TYPE_ERASER)//!!!!TBD TODO dev = NvInputDeviceType::STYLUS; else if (tool==AMOTION_EVENT_TOOL_TYPE_MOUSE) dev = NvInputDeviceType::MOUSE; else dev = NvInputDeviceType::TOUCH; // else we assume == FINGER... if unknown, treat as FINGER. TODO. p[i].m_device = dev; } mState.x = x; mState.y = y; NvPointerActionType::Enum pact; switch(action) { case AMOTION_EVENT_ACTION_DOWN: pact = NvPointerActionType::DOWN; break; case AMOTION_EVENT_ACTION_POINTER_DOWN: pact = NvPointerActionType::EXTRA_DOWN; break; case AMOTION_EVENT_ACTION_UP: pact = NvPointerActionType::UP; break; case AMOTION_EVENT_ACTION_POINTER_UP: pact = NvPointerActionType::EXTRA_UP; break; case AMOTION_EVENT_ACTION_MOVE: pact = NvPointerActionType::MOTION; break; case AMOTION_EVENT_ACTION_CANCEL: pact = NvPointerActionType::UP; pointerCount = 0; // clear. break; } const int64_t timestamp = AMotionEvent_getEventTime((const AInputEvent*)event); handled = mCallbacks->pointerInput(dev, pact, 0, pointerCount, p, timestamp); // return code handling... if (pact==NvPointerActionType::UP) return 1; return handled ? 1 : 0; } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { bool handled = false; int32_t source = AInputEvent_getSource(event); int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int32_t action = AKeyEvent_getAction((const AInputEvent*)event); bool down = (action != AKEY_EVENT_ACTION_UP) ? true : false; if (mCallbacks) { handled = mCallbacks->keyInput(code, down ? NvKeyActionType::DOWN : NvKeyActionType::UP); if (!handled && down) { uint8_t c = mapAndroidCodeToChar(code); if (c) handled = mCallbacks->characterInput(c); } } return handled ? 1 : 0; } return 0; }
/***************************************************************************** Global code *****************************************************************************/ static int32_t handle_input(struct android_app* app, AInputEvent* event) { PVRShellInit* init = (PVRShellInit*) app->userData; if(init) { switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: // Handle keyboard events { switch(AKeyEvent_getAction(event)) { case AKEY_EVENT_ACTION_DOWN: { switch(AKeyEvent_getKeyCode(event)) { case AKEYCODE_Q: init->KeyPressed(PVRShellKeyNameQUIT); break; case AKEYCODE_BACK: init->KeyPressed(PVRShellKeyNameQUIT); break; case AKEYCODE_DPAD_CENTER: init->KeyPressed(PVRShellKeyNameSELECT); break; case AKEYCODE_SPACE: init->KeyPressed(PVRShellKeyNameACTION1); break; case AKEYCODE_SHIFT_LEFT: init->KeyPressed(PVRShellKeyNameACTION2); break; case AKEYCODE_DPAD_UP: init->KeyPressed(init->m_eKeyMapUP); break; case AKEYCODE_DPAD_DOWN: init->KeyPressed(init->m_eKeyMapDOWN); break; case AKEYCODE_DPAD_LEFT: init->KeyPressed(init->m_eKeyMapLEFT); break; case AKEYCODE_DPAD_RIGHT: init->KeyPressed(init->m_eKeyMapRIGHT); break; case AKEYCODE_S: init->KeyPressed(PVRShellKeyNameScreenshot);break; default: break; } } return 1; default: break; } return 1; } case AINPUT_EVENT_TYPE_MOTION: // Handle touch events { switch(AMotionEvent_getAction(event)) { case AMOTION_EVENT_ACTION_DOWN: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchBegan(vec2TouchPosition); } break; } case AMOTION_EVENT_ACTION_MOVE: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchMoved(vec2TouchPosition); } break; } case AMOTION_EVENT_ACTION_UP: { PVRShell *pShell = init->m_pShell; if(pShell) { float vec2TouchPosition[2] = { AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth), AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight) }; init->TouchEnded(vec2TouchPosition); } break; } } return 1; } } } return 1; }
/** * Process the next input event. */ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* engine = (struct engine*)app->userData; const int32_t input_type = AInputEvent_getType(event); if (input_type == AINPUT_EVENT_TYPE_MOTION) { engine->has_focus = 1; const float x = AMotionEvent_getX(event, 0); const float y = AMotionEvent_getY(event, 0); const int32_t actionAndPtr = AMotionEvent_getAction(event); const int32_t action = AMOTION_EVENT_ACTION_MASK & actionAndPtr; // const int32_t ptrindex = (AMOTION_EVENT_ACTION_POINTER_INDEX_MASK & actionAndPtr) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; const size_t num_ptrs = AMotionEvent_getPointerCount(event); switch(action) { case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: UnpressAll(); break; case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: UnpressAll(); if(num_ptrs <=2) { const int button = (num_ptrs==1) ? 0 : 2; pangolin::process::Mouse(button, 0, x, y); } break; case AMOTION_EVENT_ACTION_MOVE: if(num_ptrs == 3) { const double dx = x - process::last_x; const double dy = y - process::last_y; process::last_x = x; process::last_y = y; pangolin::process::Scroll(dx,dy); }else{ pangolin::process::MouseMotion(x,y); } break; default: break; } return 1; }else if(AINPUT_EVENT_TYPE_KEY) { static bool shift = false; const int32_t action = AKeyEvent_getAction(event); const int32_t keycode = AKeyEvent_getKeyCode(event); if(keycode == AKEYCODE_SHIFT_LEFT) { shift = (action == AKEY_EVENT_ACTION_DOWN); return 1; } unsigned char key = PangolinKeyFromAndroidKeycode(keycode, shift); if(action == AKEY_EVENT_ACTION_DOWN) { pangolin::process::Keyboard(key, pangolin::process::last_x,pangolin::process::last_y); }else{ pangolin::process::KeyboardUp(key, pangolin::process::last_x,pangolin::process::last_y); } } return 1; }
, pointerId , xx , yy , 0.0f ); } } break; } return 1; } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { const int32_t keyCode = AKeyEvent_getKeyCode(event); const int32_t keyAction = AKeyEvent_getAction(event); if (keyCode == AKEYCODE_BACK) { deviceEventQueue.pushButtonEvent(InputDeviceType::KEYBOARD , 0 , KeyboardButton::ESCAPE , keyaction == AKEY_EVENT_ACTION_DOWN ? true : false ); } return 1; } return 0; }
/***************************************************************************** Global code *****************************************************************************/ static int32_t handle_input(struct android_app* app, AInputEvent* event) { //PVRShellInit* init = (PVRShellInit*) app->userData; // if(init) // { switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: // Handle keyboard events { switch(AKeyEvent_getAction(event)) { case AKEY_EVENT_ACTION_DOWN: { switch(AKeyEvent_getKeyCode(event)) { // case AKEYCODE_Q: init->KeyPressed(PVRShellKeyNameQUIT); break; // case AKEYCODE_DPAD_CENTER: init->KeyPressed(PVRShellKeyNameSELECT); break; // case AKEYCODE_SPACE: init->KeyPressed(PVRShellKeyNameACTION1); break; // case AKEYCODE_SHIFT_LEFT: init->KeyPressed(PVRShellKeyNameACTION2); break; // case AKEYCODE_DPAD_UP: init->KeyPressed(init->m_eKeyMapUP); break; // case AKEYCODE_DPAD_DOWN: init->KeyPressed(init->m_eKeyMapDOWN); break; // case AKEYCODE_DPAD_LEFT: init->KeyPressed(init->m_eKeyMapLEFT); break; // case AKEYCODE_DPAD_RIGHT: init->KeyPressed(init->m_eKeyMapRIGHT); break; // case AKEYCODE_S: init->KeyPressed(PVRShellKeyNameScreenshot);break; default: break; } } return 1; default: break; } return 1; } case AINPUT_EVENT_TYPE_MOTION: // Handle touch events { switch(AMotionEvent_getAction(event)) { case AMOTION_EVENT_ACTION_DOWN: // init->m_bTouching = true; case AMOTION_EVENT_ACTION_MOVE: { // PVRShell *pShell = init->m_pShell; // // if(pShell) // { // init->m_vec2PointerLocation[0] = AMotionEvent_getX(event, 0) / pShell->PVRShellGet(prefWidth); // init->m_vec2PointerLocation[1] = AMotionEvent_getY(event, 0) / pShell->PVRShellGet(prefHeight); // return 1; // } break; } case AMOTION_EVENT_ACTION_UP: /* init->m_bTouching = false;*/ return 1; } return 1; } } // } return 1; }
/* * IN_Android_OnInputEvent */ static int32_t IN_Android_OnInputEvent( struct android_app *app, AInputEvent *event ) { int32_t type = AInputEvent_getType( event ); int64_t time; if( type == AINPUT_EVENT_TYPE_KEY ) { int32_t keycode = AKeyEvent_getKeyCode( event ); int key; if( keycode >= ( sizeof( s_android_scantokey ) / sizeof( s_android_scantokey[0] ) ) ) return 0; if( ( keycode >= AKEYCODE_DPAD_UP ) && ( keycode <= AKEYCODE_DPAD_RIGHT ) && ( AInputEvent_getSource( event ) == AINPUT_SOURCE_KEYBOARD ) ) { key = keycode + ( K_UPARROW - AKEYCODE_DPAD_UP ); } else { key = s_android_scantokey[keycode]; } if( !key ) return 0; time = AKeyEvent_getEventTime( event ) / ( ( int64_t )1000000 ); switch( AKeyEvent_getAction( event ) ) { case AKEY_EVENT_ACTION_DOWN: case AKEY_EVENT_ACTION_MULTIPLE: if( ( key == K_ESCAPE ) && IN_Android_HideSoftKeyboard() ) // Instead of broken AInputQueue_preDispatchEvent. return 1; Key_Event( key, true, time ); if( Key_IsDown( K_LCTRL ) || Key_IsDown( K_RCTRL ) ) { if( key == 'v' ) Key_CharEvent( KC_CTRLV, KC_CTRLV ); else if( key == 'c' ) Key_CharEvent( KC_CTRLC, KC_CTRLC ); else Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) ); } else { Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) ); } break; case AKEY_EVENT_ACTION_UP: Key_Event( key, false, time ); break; } return 1; } if( type == AINPUT_EVENT_TYPE_MOTION ) { int32_t action = AMotionEvent_getAction( event ); int32_t source = AInputEvent_getSource( event ); int x, y; time = AMotionEvent_getEventTime( event ) / ( ( int64_t )1000000 ); switch( source ) { case AINPUT_SOURCE_TOUCHSCREEN: { touchevent_t type; size_t i, pointerCount = 0, p; switch( action & AMOTION_EVENT_ACTION_MASK ) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: type = TOUCH_DOWN; pointerCount = 1; break; case AMOTION_EVENT_ACTION_POINTER_UP: type = TOUCH_UP; pointerCount = 1; break; case AMOTION_EVENT_ACTION_MOVE: type = TOUCH_MOVE; pointerCount = AMotionEvent_getPointerCount( event ); break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_OUTSIDE: type = TOUCH_UP; pointerCount = AMotionEvent_getPointerCount( event ); break; } p = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; for( i = 0; i < pointerCount; ++i, ++p ) { if( IN_Android_EventToWindowCoordinates( event, p, &x, &y ) ) CL_TouchEvent( AMotionEvent_getPointerId( event, p ), type, x, y, time ); } } break; case AINPUT_SOURCE_JOYSTICK: { float hatXValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_X, 0 ); float hatYValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_Y, 0 ); int hatX = 0, hatY = 0; static int oldHatX = 0, oldHatY = 0; bool leftTrigger, rightTrigger; static bool oldLeftTrigger = false, oldRightTrigger = false; in_android_thumbsticks[0] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_X, 0 ); in_android_thumbsticks[1] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Y, 0 ); in_android_thumbsticks[2] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Z, 0 ); in_android_thumbsticks[3] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RZ, 0 ); hatX = ( hatXValue > 0.5f ) - ( hatXValue < -0.5f ); hatY = ( hatYValue > 0.5f ) - ( hatYValue < -0.5f ); if( hatX != oldHatX ) { if( oldHatX ) Key_Event( K_DPAD_LEFT + ( oldHatX > 0 ), false, time ); if( hatX ) Key_Event( K_DPAD_LEFT + ( hatX > 0 ), true, time ); oldHatX = hatX; } if( hatY != oldHatY ) { if( oldHatY ) Key_Event( K_DPAD_UP + ( oldHatY > 0 ), false, time ); if( hatY ) Key_Event( K_DPAD_UP + ( hatY > 0 ), true, time ); oldHatY = hatY; } leftTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_BRAKE, 0 ) > ( 30.0f / 255.0f ) ) || ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_LTRIGGER, 0 ) > ( 30.0f / 255.0f ) ); rightTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_GAS, 0 ) > ( 30.0f / 255.0f ) ) || ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RTRIGGER, 0 ) > ( 30.0f / 255.0f ) ); if( leftTrigger != oldLeftTrigger ) { Key_Event( K_LTRIGGER, leftTrigger, time ); oldLeftTrigger = leftTrigger; } if( rightTrigger != oldRightTrigger ) { Key_Event( K_RTRIGGER, rightTrigger, time ); oldRightTrigger = rightTrigger; } } break; case AINPUT_SOURCE_MOUSE: { switch( action & AMOTION_EVENT_ACTION_MASK ) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_UP: { static int32_t oldButtonState = 0; int32_t buttonState = AMotionEvent_getButtonState( event ); int32_t buttonsDown = buttonState & ~oldButtonState, buttonsUp = oldButtonState & ~buttonState; int32_t buttonsChanged = buttonsDown | buttonsUp; int button; oldButtonState = buttonState; for( button = 0; buttonsChanged >> button; button++ ) { if( buttonsChanged & ( 1 << button ) ) Key_MouseEvent( K_MOUSE1 + button, ( buttonsDown & ( 1 << button ) ) ? true : false, time ); } } break; case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: if( IN_Android_EventToWindowCoordinates( event, 0, &x, &y ) ) CL_MouseSet( x, y, false ); break; case AMOTION_EVENT_ACTION_SCROLL: { float scroll = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_VSCROLL, 0 ); if( scroll > 0.0f ) { Key_Event( K_MWHEELUP, true, time ); Key_Event( K_MWHEELUP, false, time ); } else if( scroll < 0.0f ) { Key_Event( K_MWHEELDOWN, true, time ); Key_Event( K_MWHEELDOWN, false, time ); } } break; } } break; } return 1; }
int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AKeyEvent_getAction(_event); int32_t key = AKeyEvent_getKeyCode(_event); int32_t metakey = AKeyEvent_getMetaState(_event); Event event; event.key.code = androidKeyToSF(key); event.key.alt = metakey & AMETA_ALT_ON; event.key.control = false; event.key.shift = metakey & AMETA_SHIFT_ON; switch (action) { case AKEY_EVENT_ACTION_DOWN: event.type = Event::KeyPressed; forwardEvent(event); return 1; case AKEY_EVENT_ACTION_UP: event.type = Event::KeyReleased; forwardEvent(event); if (int unicode = getUnicode(_event)) { event.type = Event::TextEntered; event.text.unicode = unicode; forwardEvent(event); } return 1; case AKEY_EVENT_ACTION_MULTIPLE: // Since complex inputs don't get separate key down/up events // both have to be faked at once event.type = Event::KeyPressed; forwardEvent(event); event.type = Event::KeyReleased; forwardEvent(event); // This requires some special treatment, since this might represent // a repetition of key presses or a complete sequence if (key == AKEYCODE_UNKNOWN) { // This is a unique sequence, which is not yet exposed in the NDK // http://code.google.com/p/android/issues/detail?id=33998 return 0; } else if (int unicode = getUnicode(_event)) // This is a repeated sequence { event.type = Event::TextEntered; event.text.unicode = unicode; int32_t repeats = AKeyEvent_getRepeatCount(_event); for (int32_t i = 0; i < repeats; ++i) forwardEvent(event); return 1; } break; } return 0; }
int Engine::handleInput(AInputEvent* event) { //We only handle motion events (touchscreen) and key (button/key) events int32_t eventType = AInputEvent_getType(event); if (eventType == AINPUT_EVENT_TYPE_MOTION) { int32_t edgeFlags = AMotionEvent_getEdgeFlags(event); if(edgeFlags == AMOTION_EVENT_EDGE_FLAG_NONE) { //The current motion event (touch) is within screen bounds int32_t action = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction((const AInputEvent*)event); int32_t iX = AMotionEvent_getX(event, 0); int32_t iY = AMotionEvent_getY(event, 0); if (checkUIHandledMotion(iX, iY, action)) return 0; if (AMOTION_EVENT_ACTION_UP == action) { mGlobeApp->pauseAnim(false); mLastX = mEgl.getWidth() / 2; mLastY = mEgl.getHeight() / 2; } else if (AMOTION_EVENT_ACTION_DOWN == action) { mGlobeApp->pauseAnim(true); mLastX = iX; mLastY = iY; } else if (AMOTION_EVENT_ACTION_MOVE == action) { // Empirical value (how many degrees to rotate when dragging finger on screen so // it looks like finger is "anchored" const static float DEGS_PER_PIXEL_DRAG = 0.25f; float fRotX = (float)(iY - mLastY) * DEGS_PER_PIXEL_DRAG; float fRotY = (float)(iX - mLastX) * DEGS_PER_PIXEL_DRAG; mGlobeApp->addRotation(fRotX, fRotY); mGlobeApp->positionCamera(); mLastX = iX; mLastY = iY; } return 1; } else // if(edgeFlags == AMOTION_EVENT_EDGE_FLAG_NONE) { //The current motion event (touch) has reached an edge. //We process it the same way as if we were touching and we had lifted //the finger off the screen mGlobeApp->pauseAnim(false); mLastX = mEgl.getWidth() / 2; mLastY = mEgl.getHeight() / 2; return 1; } } else if (eventType == AINPUT_EVENT_TYPE_KEY) { int32_t action = AKeyEvent_getAction((const AInputEvent*)event); int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int returnCode = 1; // pass to the on-screen UI, which will return what our "handled" code should be // or will return false to us, which indicates that the UI is allowing default // behavior for the key if (checkUIHandledKey(code, action, returnCode)) return returnCode; } return 0; }
static int32_t _onInputEvent(struct android_app* app, AInputEvent* event) { if (!event || !::g_defaultWindow.get()) { return 1; } int32_t source = AInputEvent_getSource(event); if (source == AINPUT_SOURCE_MOUSE) { int32_t x = (int32_t)AMotionEvent_getX(event, 0); int32_t y = (int32_t)AMotionEvent_getY(event, 0); g_defaultWindow->getMouseInput().setLocation(glm::ivec2(x, y)); int32_t buttonState = AMotionEvent_getButtonState(event); g_defaultWindow->getMouseInput().setButton(VKTS_MOUSE_BUTTON_LEFT, buttonState & AMOTION_EVENT_BUTTON_PRIMARY); g_defaultWindow->getMouseInput().setButton(VKTS_MOUSE_BUTTON_RIGHT, buttonState & AMOTION_EVENT_BUTTON_SECONDARY); g_defaultWindow->getMouseInput().setButton(VKTS_MOUSE_BUTTON_MIDDLE, buttonState & AMOTION_EVENT_BUTTON_TERTIARY); int32_t vscroll = (int32_t)AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_VSCROLL, 0); g_defaultWindow->getMouseInput().setMouseWheel(vscroll); return 1; } else if (source == AINPUT_SOURCE_KEYBOARD) { VkBool32 pressed = (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN); int32_t scanCode = AKeyEvent_getScanCode(event); int32_t key = vkts::_visualTranslateKey(scanCode); if (pressed && key == VKTS_KEY_ESCAPE) { g_app->destroyRequested = 1; } else if (key != VKTS_KEY_UNKNOWN) { g_defaultWindow->getKeyInput().setKey(key, pressed); } return 1; } else if (source == AINPUT_SOURCE_JOYSTICK) { int32_t pointerIndex = (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; if (pointerIndex >= 0 && pointerIndex < VKTS_MAX_GAMEPADS) { for (int32_t axis = AMOTION_EVENT_AXIS_X; axis <= AMOTION_EVENT_AXIS_RTRIGGER; axis++) { int32_t axisIndex = -1; float axisValue = AMotionEvent_getAxisValue(event, axis, pointerIndex); switch (axis) { case AMOTION_EVENT_AXIS_X: axisIndex = VKTS_GAMEPAD_LEFT_STICK_X; break; case AMOTION_EVENT_AXIS_Y: axisIndex = VKTS_GAMEPAD_LEFT_STICK_Y; axisValue = -axisValue; break; case AMOTION_EVENT_AXIS_Z: axisIndex = VKTS_GAMEPAD_RIGHT_STICK_X; break; case AMOTION_EVENT_AXIS_RZ: axisIndex = VKTS_GAMEPAD_RIGHT_STICK_Y; axisValue = -axisValue; break; case AMOTION_EVENT_AXIS_LTRIGGER: axisIndex = VKTS_GAMEPAD_LEFT_TRIGGER; break; case AMOTION_EVENT_AXIS_RTRIGGER: axisIndex = VKTS_GAMEPAD_RIGHT_TRIGGER; break; case AMOTION_EVENT_AXIS_HAT_X: { VkBool32 buttonPressed = axisValue < 0.0f ? VK_TRUE : VK_FALSE; g_defaultWindow->getGamepadInput(pointerIndex).setButton(VKTS_GAMEPAD_DPAD_LEFT, buttonPressed); buttonPressed = axisValue > 0.0f ? VK_TRUE : VK_FALSE; g_defaultWindow->getGamepadInput(pointerIndex).setButton(VKTS_GAMEPAD_DPAD_RIGHT, buttonPressed); } break; case AMOTION_EVENT_AXIS_HAT_Y: { VkBool32 buttonPressed = axisValue > 0.0f ? VK_TRUE : VK_FALSE; g_defaultWindow->getGamepadInput(pointerIndex).setButton(VKTS_GAMEPAD_DPAD_DOWN, buttonPressed); buttonPressed = axisValue < 0.0f ? VK_TRUE : VK_FALSE; g_defaultWindow->getGamepadInput(pointerIndex).setButton(VKTS_GAMEPAD_DPAD_UP, buttonPressed); } break; } if (axisIndex == -1) { continue; } g_defaultWindow->getGamepadInput(pointerIndex).setAxis(axisIndex, axisValue); } } return 1; }
if (debug_enable) snprintf(msg, sizeof(msg), "Pad %d : x = %.2f, y = %.2f, src %d.\n", state_id, x, y, source); } else if (type_event == AINPUT_EVENT_TYPE_KEY) { if (debug_enable) snprintf(msg, sizeof(msg), "Pad %d : %d, ac = %d, src = %d.\n", state_id, keycode, action, source); /* Hack - we have to decrease the unpacked value by 1 * because we 'added' 1 to each entry in the LUT - * RETRO_DEVICE_ID_JOYPAD_B is 0 */ uint8_t unpacked = (keycode_lut[keycode] >> ((state_id+1) << 3)) - 1; uint64_t input_state = (1ULL << unpacked); int action = AKeyEvent_getAction(event); uint64_t *key = NULL; if(input_state < (1ULL << RARCH_FIRST_META_KEY)) key = &state[state_id]; else if(input_state) key = &g_extern.lifecycle_state; if(key != NULL) { if (action == AKEY_EVENT_ACTION_UP) *key &= ~(input_state); else if (action == AKEY_EVENT_ACTION_DOWN) *key |= input_state; }
bool EngineCore::inputEvent(AInputEvent* event) { bool handled = false; bool doubleTapHandled = false; bool dragHandled = false; bool pinchHandled = false; switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: handled = inputKeyEvent(AKeyEvent_getAction(event), AKeyEvent_getKeyCode(event)); break; case AINPUT_EVENT_TYPE_MOTION: { ndk_helper::GESTURE_STATE doubleTapState = mDoubleTapDetector.Detect(event); ndk_helper::GESTURE_STATE dragState = mDragDetector.Detect(event); ndk_helper::GESTURE_STATE pinchState = mPinchDetector.Detect(event); if (doubleTapState == ndk_helper::GESTURE_STATE_ACTION) { doubleTapHandled = handleDoubleTap(); } else { if (dragState & ndk_helper::GESTURE_STATE_START) { ndk_helper::Vec2 v; mDragDetector.GetPointer(v); float x, y; v.Value(x, y); dragHandled = handleDrag(GESTURE_DRAG_START, x, y); } else if (dragState & ndk_helper::GESTURE_STATE_MOVE) { ndk_helper::Vec2 v; mDragDetector.GetPointer(v); float x, y; v.Value(x, y); dragHandled = handleDrag(GESTURE_DRAG_MOVE, x, y); } else if (dragState & ndk_helper::GESTURE_STATE_END) { dragHandled = handleDrag(GESTURE_DRAG_END, 0, 0); } if (pinchState & ndk_helper::GESTURE_STATE_START) { ndk_helper::Vec2 v1; ndk_helper::Vec2 v2; mPinchDetector.GetPointers(v1, v2); float x1, y1, x2, y2; v1.Value(x1, y1); v2.Value(x2, y2); pinchHandled = handlePinch(GESTURE_PINCH_START, x1, y1, x2, y2); } else if (pinchState & ndk_helper::GESTURE_STATE_MOVE) { ndk_helper::Vec2 v1; ndk_helper::Vec2 v2; mPinchDetector.GetPointers(v1, v2); float x1, y1, x2, y2; v1.Value(x1, y1); v2.Value(x2, y2); pinchHandled = handlePinch(GESTURE_PINCH_MOVE, x1, y1, x2, y2); } } if (!doubleTapHandled && !dragHandled && !pinchHandled) handled = inputMotionEvent(AMotionEvent_getAction(event)); break; } default: ALOGW("Unknown input event"); break; } return doubleTapHandled || dragHandled || pinchHandled || handled; }
void StWindowImpl::onAndroidInput(const AInputEvent* theEvent, bool& theIsProcessed) { const int anEventType = AInputEvent_getType(theEvent); switch(anEventType) { case AINPUT_EVENT_TYPE_KEY: { StVirtKey aVKeySt = ST_VK_NULL; int32_t aKeySym = AKeyEvent_getKeyCode(theEvent); if(aKeySym < ST_ANDROID2ST_VK_SIZE) { aVKeySt = (StVirtKey )ST_ANDROID2ST_VK[aKeySym]; } if(aVKeySt == ST_VK_NULL) { return; } myStEvent.Key.Time = getEventTime(); //AKeyEvent_getEventTime(theEvent); myStEvent.Key.VKey = aVKeySt; myStEvent.Key.Char = 0; const int32_t aKeyAction = AKeyEvent_getAction(theEvent); if(aKeyAction == AKEY_EVENT_ACTION_DOWN) { postKeyDown(myStEvent); } else if(aKeyAction == AKEY_EVENT_ACTION_UP) { postKeyUp(myStEvent); }// else if(aKeyAction == AKEY_EVENT_ACTION_MULTIPLE) {} return; } case AINPUT_EVENT_TYPE_MOTION: { theIsProcessed = true; const int32_t aSource = AInputEvent_getSource(theEvent); const int32_t anActionPak = AMotionEvent_getAction(theEvent); const int32_t anAction = anActionPak & AMOTION_EVENT_ACTION_MASK; const size_t anActionPntIndex = anActionPak & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK; //const StRectI_t& aWinRect = attribs.IsFullScreen ? myRectFull : myRectNorm; const StRectI_t& aWinRect = myRectNorm; const float aWinSizeX = aWinRect.width(); const float aWinSizeY = aWinRect.height(); // at least single point is defined StPointD_t aPos0(double(AMotionEvent_getX(theEvent, 0)) / double(aWinSizeX), double(AMotionEvent_getY(theEvent, 0)) / double(aWinSizeY)); myStEvent.Type = stEvent_None; myStEvent.Base.Time = getEventTime(); /// int64_t AMotionEvent_getEventTime(theEvent); switch(aSource) { case AINPUT_SOURCE_TOUCHSCREEN: case AINPUT_SOURCE_TOUCHPAD: { const size_t aNbTouches = AMotionEvent_getPointerCount(theEvent); myStEvent.Touch.NbTouches = std::min(aNbTouches, (size_t )ST_MAX_TOUCHES); bool isUp = anAction == AMOTION_EVENT_ACTION_UP || anAction == AMOTION_EVENT_ACTION_POINTER_UP; if(isUp) { myStEvent.Touch.NbTouches = std::max(myStEvent.Touch.NbTouches - 1, 0); } for(size_t aTouchIter = 0; aTouchIter < ST_MAX_TOUCHES; ++aTouchIter) { StTouch& aTouch = myStEvent.Touch.Touches[aTouchIter]; aTouch = StTouch::Empty(); if(aTouchIter == anActionPntIndex && isUp) { continue; } if(aTouchIter >= aNbTouches) { continue; } aTouch.Id = AMotionEvent_getPointerId(theEvent, aTouchIter); aTouch.DeviceId = AInputEvent_getDeviceId(theEvent); aTouch.OnScreen = aSource == AINPUT_SOURCE_TOUCHSCREEN; const float aPosX = AMotionEvent_getX(theEvent, aTouchIter); const float aPosY = AMotionEvent_getY(theEvent, aTouchIter); aTouch.PointX = (aPosX - float(aWinRect.left())) / aWinSizeX; aTouch.PointY = (aPosY - float(aWinRect.top())) / aWinSizeY; } switch(anAction) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: { myStEvent.Type = stEvent_TouchDown; doTouch(myStEvent.Touch); if(aNbTouches == 1) { // simulate mouse click myMousePt = aPos0; myIsPreciseCursor = false; myStEvent.Type = stEvent_MouseDown; myStEvent.Button.Button = ST_MOUSE_LEFT; myStEvent.Button.Buttons = 0; myStEvent.Button.PointX = myMousePt.x(); myStEvent.Button.PointY = myMousePt.y(); signals.onMouseDown->emit(myStEvent.Button); } else if(aNbTouches == 2) { // emit special event to cancel previously simulated click myStEvent.Type = stEvent_MouseCancel; myStEvent.Button.Button = ST_MOUSE_LEFT; myStEvent.Button.Buttons = 0; myStEvent.Button.PointX = myMousePt.x(); myStEvent.Button.PointY = myMousePt.y(); signals.onMouseUp->emit(myStEvent.Button); } break; } case AMOTION_EVENT_ACTION_MOVE: { myStEvent.Type = stEvent_TouchMove; if(aNbTouches == 1) { // simulate mouse move myMousePt = aPos0; myIsPreciseCursor = false; } doTouch(myStEvent.Touch); break; } case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: { myStEvent.Type = stEvent_TouchUp; doTouch(myStEvent.Touch); if(aNbTouches == 1) { // simulate mouse unclick myMousePt = aPos0; myIsPreciseCursor = false; myStEvent.Type = stEvent_MouseUp; myStEvent.Button.Button = ST_MOUSE_LEFT; myStEvent.Button.Buttons = 0; myStEvent.Button.PointX = myMousePt.x(); myStEvent.Button.PointY = myMousePt.y(); signals.onMouseUp->emit(myStEvent.Button); } break; } case AMOTION_EVENT_ACTION_CANCEL: { myStEvent.Type = stEvent_TouchCancel; doTouch(myStEvent.Touch); break; } } return; } } myMousePt = aPos0; myIsPreciseCursor = aSource == AINPUT_SOURCE_MOUSE; // || AINPUT_SOURCE_STYLUS StVirtButton aMouseBtn = ST_MOUSE_LEFT; myStEvent.Button.Button = aMouseBtn; myStEvent.Button.Buttons = 0; myStEvent.Button.PointX = myMousePt.x(); myStEvent.Button.PointY = myMousePt.y(); if(anAction == AMOTION_EVENT_ACTION_DOWN) { myStEvent.Type = stEvent_MouseDown; signals.onMouseDown->emit(myStEvent.Button); } else if(anAction == AMOTION_EVENT_ACTION_UP) { myStEvent.Type = stEvent_MouseUp; signals.onMouseUp->emit(myStEvent.Button); } return; } } }
bool CAndroidKey::onKeyboardEvent(AInputEvent *event) { if (event == NULL) return false; int32_t flags = AKeyEvent_getFlags(event); int32_t state = AKeyEvent_getMetaState(event); int32_t action = AKeyEvent_getAction(event); int32_t repeat = AKeyEvent_getRepeatCount(event); int32_t keycode = AKeyEvent_getKeyCode(event); int32_t deviceId = AInputEvent_getDeviceId(event); CJNIKeyCharacterMap map = CJNIKeyCharacterMap::load(deviceId); uint16_t unicode = map.get(keycode, state); // Check if we got some special key uint16_t sym = XBMCK_UNKNOWN; for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++) { if (keycode == keyMap[index].nativeKey) { sym = keyMap[index].xbmcKey; break; } } if (m_handleMediaKeys) { for (unsigned int index = 0; index < sizeof(MediakeyMap) / sizeof(KeyMap); index++) { if (keycode == MediakeyMap[index].nativeKey) { sym = MediakeyMap[index].xbmcKey; break; } } } // check if this is a key we don't want to handle if (sym == XBMCK_LAST || sym == XBMCK_UNKNOWN) { CXBMCApp::android_printf("CAndroidKey: key ignored (code: %d)", keycode); return false; } uint16_t modifiers = 0; if (state & AMETA_ALT_LEFT_ON) modifiers |= XBMCKMOD_LALT; if (state & AMETA_ALT_RIGHT_ON) modifiers |= XBMCKMOD_RALT; if (state & AMETA_SHIFT_LEFT_ON) modifiers |= XBMCKMOD_LSHIFT; if (state & AMETA_SHIFT_RIGHT_ON) modifiers |= XBMCKMOD_RSHIFT; if (state & AMETA_CTRL_LEFT_ON) modifiers |= XBMCKMOD_LCTRL; if (state & AMETA_CTRL_RIGHT_ON) modifiers |= XBMCKMOD_RCTRL; /* TODO: if (state & AMETA_SYM_ON) modifiers |= 0x000?;*/ switch (action) { case AKEY_EVENT_ACTION_DOWN: #if 1 CXBMCApp::android_printf("CAndroidKey: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, false); return true; case AKEY_EVENT_ACTION_UP: #if 1 CXBMCApp::android_printf("CAndroidKey: key up (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, true); return true; case AKEY_EVENT_ACTION_MULTIPLE: #if 1 CXBMCApp::android_printf("CAndroidKey: key multiple (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif break; default: #if 1 CXBMCApp::android_printf("CAndroidKey: unknown key (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif break; } return false; }
/** * Process the next input event. */ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* engine = (struct engine*)app->userData; switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_MOTION: { int32_t action = AMotionEvent_getAction(event ); int pointer = ( action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK ) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int p = AMotionEvent_getPointerCount( event ); #ifdef DEBUG_TOUCH_INPUT LOGI( "pointer (full action)%04x (pointer)%d (number points)%d", action, pointer, p ); #endif { int n; for( n = 0; n < engine->nPoints; n++ ) { engine->points[n].flags.new_event = 0; if( engine->points[n].flags.end_event ) { int m; for( m = n; m < (engine->nPoints-1); m++ ) { if( engine->input_point_map[m+1] == m+1 ) engine->input_point_map[m] = m; else { if( engine->input_point_map[m+1] < n ) engine->input_point_map[m] = engine->input_point_map[m+1]; else engine->input_point_map[m] = engine->input_point_map[m+1] - 1; } engine->points[m] = engine->points[m+1]; } engine->nPoints--; n--; } } } switch( action & AMOTION_EVENT_ACTION_MASK ) { case AMOTION_EVENT_ACTION_DOWN: // primary pointer down. //if( engine->nPoints ) //{ // LOGI( "Pointer Event Down (pointer0) and there's already pointers..." ); //} engine->points[0].x = AMotionEvent_getX( event, pointer ); engine->points[0].y = AMotionEvent_getY( event, pointer ); engine->points[0].flags.new_event = 1; engine->points[0].flags.end_event = 0; engine->nPoints++; engine->input_point_map[0] = 0; break; case AMOTION_EVENT_ACTION_UP: // primary pointer up. engine->points[0].flags.new_event = 0; engine->points[0].flags.end_event = 1; break; case AMOTION_EVENT_ACTION_MOVE: { int n; for( n = 0; n < p; n++ ) { // points may have come in as 'new' in the wrong order, // reference the input point map to fill in the correct point location int actual = engine->input_point_map[n]; engine->points[actual].x = AMotionEvent_getX( event, n ); engine->points[actual].y = AMotionEvent_getY( event, n ); engine->points[actual].flags.new_event = 0; engine->points[actual].flags.end_event = 0; } } break; case AMOTION_EVENT_ACTION_POINTER_DOWN: // the new pointer might not be the last one, so we insert it. // at the end, before dispatch, new points are moved to the end // and mapping begins. this code should not reference the map if( pointer < engine->nPoints ) { int c; #ifdef DEBUG_TOUCH_INPUT LOGI( "insert point new. %d", engine->nPoints-1 ); #endif for( c = engine->nPoints; c >= pointer; c-- ) { #ifdef DEBUG_TOUCH_INPUT LOGI( "Set %d to %d", c, engine->input_point_map[c-1] ); #endif engine->input_point_map[c] = engine->input_point_map[c-1]; // save still in the same target... } #ifdef DEBUG_TOUCH_INPUT LOGI( "Set %d to %d", pointer, engine->nPoints ); #endif engine->input_point_map[pointer] = engine->nPoints; // and the new one maps to the last. // now just save in last and don't swap twice. engine->points[engine->nPoints].x = AMotionEvent_getX( event, pointer ); engine->points[engine->nPoints].y = AMotionEvent_getY( event, pointer ); pointer = engine->nPoints; } else { engine->points[pointer].x = AMotionEvent_getX( event, pointer ); engine->points[pointer].y = AMotionEvent_getY( event, pointer ); engine->input_point_map[pointer] = pointer; } // primary pointer down. engine->points[pointer].flags.new_event = 1; engine->points[pointer].flags.end_event = 0; // always initialize the engine->nPoints++; break; case AMOTION_EVENT_ACTION_POINTER_UP: { // a up pointer may be remapped already, set the actual entry for the point int actual = engine->input_point_map[pointer]; int n; engine->points[actual].flags.new_event = 0; engine->points[actual].flags.end_event = 1; #ifdef DEBUG_TOUCH_INPUT LOGI( "Set point %d (map %d) to ended", pointer, actual ); #endif // any release event will reset the other input points appropriately(?) for( n = 0; n < engine->nPoints; n++ ) { int other; if( engine->input_point_map[n] != n ) { int m; #ifdef DEBUG_TOUCH_INPUT LOGI( "reorder to natural input order" ); #endif memcpy( engine->tmp_points, engine->points, engine->nPoints * sizeof( struct input_point ) ); // m is the point currently mapped to this position. // data from engine[n] and engine[m] need to swap for( m = 0; m < engine->nPoints; m++ ) { engine->points[m] = engine->tmp_points[other = engine->input_point_map[m]]; engine->input_point_map[m] = m; #ifdef DEBUG_TOUCH_INPUT LOGI( "move point %d to %d", other, m ); #endif } break; } } } break; default: #ifdef DEBUG_TOUCH_INPUT LOGI( "Motion Event ignored..." ); #endif break; } { int n; #ifdef DEBUG_TOUCH_INPUT for( n = 0; n < engine->nPoints; n++ ) { LOGI( "Point : %d %d %g %g %d %d", n, engine->input_point_map[n], engine->points[n].x , engine->points[n].y, engine->points[n].flags.new_event, engine->points[n].flags.end_event ); } #endif } BagVidlibPureglSendTouchEvents( engine->nPoints, engine->points ); //engine->state.animating = 1; //engine->state.x = AMotionEvent_getX(event, 0); //engine->state.y = AMotionEvent_getY(event, 0); return 1; } case AINPUT_EVENT_TYPE_KEY: { int32_t key_val = AKeyEvent_getKeyCode(event); //int32_t key_char = AKeyEvent_getKeyChar(event); int32_t key_mods = AKeyEvent_getMetaState( event ); int32_t key_pressed = AKeyEvent_getAction( event ); int realmod = 0; //lprintf( "key char is %d (%c)", key_char, key_char ); if( ( key_mods & 0x3000 ) == 0x3000 ) realmod |= KEY_MOD_CTRL; if( ( key_mods & 0x12 ) == 0x12 ) realmod |= KEY_MOD_ALT; if( ( key_mods & 0x41 ) == 0x41 ) realmod |= KEY_MOD_SHIFT; key_mods = realmod; #ifdef DEBUG_KEY_INPUT LOGI("Received key event: %d %d %d\n", key_pressed, key_val, key_mods ); #endif { engine->key_text = AndroidGetKeyText( event ); lprintf( "Event translates to %d(%04x)%c", engine->key_text, engine->key_text ,engine->key_text ); } if( key_val ) { int used; if( key_pressed == AKEY_EVENT_ACTION_MULTIPLE ) { int count = AKeyEvent_getRepeatCount( event ); int n; for( n = 0; n < count; n++ ) { used = BagVidlibPureglSendKeyEvents( 1, key_val, key_mods ); used = BagVidlibPureglSendKeyEvents( 0, key_val, key_mods ); } } else used = BagVidlibPureglSendKeyEvents( (key_pressed==AKEY_EVENT_ACTION_DOWN)?1:0, key_val, key_mods ); return used; } break; } default: LOGI( "Unhandled Motion Event ignored..." ); break; } return 0; }
void title_handle_key_evt (struct android_app* app, AInputEvent* event) { Context* context = (Context*) app->userData; int32_t key_code, i; if (AKeyEvent_getAction(event) != AKEY_EVENT_ACTION_UP) { return; } key_code = AKeyEvent_getKeyCode(event); switch (context->title->state) { case TITLE_STATE_LOAD_PROFILE: if (key_code == AKEY_CODE_BACK) { title_transition(context, TITLE_STATE_MAIN); } break; case TITLE_STATE_NEW_PROFILE: if (key_code == AKEY_CODE_BACK) { title_transition(context, TITLE_STATE_MAIN); } else if ( key_code >= AKEY_CODE_A && key_code <= AKEY_CODE_Z && ( context->title->profile_name == NULL || strlen(context->title->profile_name) <= PROFILE_MAX_LEN ) ) { char c = key_code - AKEY_CODE_A + 'A'; if (context->title->profile_name == NULL) { context->title->profile_name = (char*) malloc((PROFILE_MAX_LEN + 1) * sizeof(char)); context->title->profile_line = (Line*) malloc(sizeof(Line)); context->title->profile_line->v_bufs = (vertex_buffer**) malloc(PROFILE_MAX_LEN * sizeof(vertex_buffer*)); context->title->profile_line->x = 0; context->title->profile_line->y = SCREEN_TOP + GLYPH_SIZE + LINE_GAP; context->title->profile_line->len = 0; context->title->profile_name[0] = c; context->title->profile_name[1] = '\0'; } else { context->title->profile_name[ context->title->profile_line->len ] = c; context->title->profile_name[ context->title->profile_line->len+1 ] = '\0'; } write_char(context->glyphs, context->title->profile_line, c); } else if (key_code == AKEY_CODE_DEL) { if (context->title->profile_name == NULL) { return; } if (context->title->lines[1] != NULL) { del_line(context->glyphs, context->title->lines[1]); } if (strlen(context->title->profile_name) == 1) { free(context->title->profile_name); context->title->profile_name = NULL; del_line(context->glyphs, context->title->profile_line); } else { del_char(context->glyphs, context->title->profile_line); context->title->profile_name[ context->title->profile_line->len ] = '\0'; } } else if (key_code == AKEY_CODE_ENTER) { int valid = 1; int idx = 0; for (i = 0; i < MAX_PROFILES; i++) { if (context->profiles[i] == NULL) { break; } if ( strcasecmp( context->profiles[i]->name , context->title->profile_name ) == 0 ) { valid = 0; } idx++; } if (!valid) { context->title->lines[1] = write_line( context->glyphs , 0 , SCREEN_TOP + (GLYPH_SIZE + LINE_GAP) * 3 , "Name in use" ); } else { context->profiles[i] = new_profile( context->app , context->title->profile_name , 0 , 0 ); context->profile = context->profiles[idx]; title_transition(context, TITLE_STATE_MAIN); } } break; } }
/** * Process the next input event. */ int32_t handle_input(struct android_app* app, AInputEvent* event) { SFG_Window* window = fgStructure.CurrentWindow; /* FIXME: in Android, when key is repeated, down and up events happen most often at the exact same time. This makes it impossible to animate based on key press time. */ /* e.g. down/up/wait/down/up rather than down/wait/down/wait/up */ if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { /* LOGI("action: %d", AKeyEvent_getAction(event)); */ /* LOGI("keycode: %d", code); */ int32_t code = AKeyEvent_getKeyCode(event); if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) { int32_t keypress = 0; unsigned char ascii = 0; if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) { INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY)); return EVENT_HANDLED; } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) { INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY)); return EVENT_HANDLED; } } else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) { int32_t keypress = 0; unsigned char ascii = 0; if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) { INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY)); return EVENT_HANDLED; } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) { INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY)); return EVENT_HANDLED; } } } if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int32_t action = AMotionEvent_getAction(event); float x = AMotionEvent_getX(event, 0); float y = AMotionEvent_getY(event, 0); LOGI("motion %.01f,%.01f action=%d", x, y, AMotionEvent_getAction(event)); /* Virtual arrows PAD */ // Don't interfere with existing mouse move event if (!touchscreen.in_mmotion) { struct vpad_state prev_vpad = touchscreen.vpad; touchscreen.vpad.left = touchscreen.vpad.right = touchscreen.vpad.up = touchscreen.vpad.down = false; int32_t width = ANativeWindow_getWidth(window->Window.Handle); int32_t height = ANativeWindow_getHeight(window->Window.Handle); if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) { if ((x > 0 && x < 100) && (y > (height - 100) && y < height)) touchscreen.vpad.left = true; if ((x > 200 && x < 300) && (y > (height - 100) && y < height)) touchscreen.vpad.right = true; if ((x > 100 && x < 200) && (y > (height - 100) && y < height)) touchscreen.vpad.down = true; if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100))) touchscreen.vpad.up = true; } if (action == AMOTION_EVENT_ACTION_DOWN && (touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up)) touchscreen.vpad.on = true; if (action == AMOTION_EVENT_ACTION_UP) touchscreen.vpad.on = false; if (prev_vpad.left != touchscreen.vpad.left || prev_vpad.right != touchscreen.vpad.right || prev_vpad.up != touchscreen.vpad.up || prev_vpad.down != touchscreen.vpad.down || prev_vpad.on != touchscreen.vpad.on) { if (FETCH_WCB(*window, Special)) { if (prev_vpad.left == false && touchscreen.vpad.left == true) INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y)); else if (prev_vpad.right == false && touchscreen.vpad.right == true) INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y)); else if (prev_vpad.up == false && touchscreen.vpad.up == true) INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y)); else if (prev_vpad.down == false && touchscreen.vpad.down == true) INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y)); } if (FETCH_WCB(*window, SpecialUp)) { if (prev_vpad.left == true && touchscreen.vpad.left == false) INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y)); if (prev_vpad.right == true && touchscreen.vpad.right == false) INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y)); if (prev_vpad.up == true && touchscreen.vpad.up == false) INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y)); if (prev_vpad.down == true && touchscreen.vpad.down == false) INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y)); } return EVENT_HANDLED; } } /* Normal mouse events */ if (!touchscreen.vpad.on) { window->State.MouseX = x; window->State.MouseY = y; LOGI("Changed mouse position: %d,%d", x, y); if (action == AMOTION_EVENT_ACTION_DOWN && FETCH_WCB(*window, Mouse)) { touchscreen.in_mmotion = true; INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_DOWN, x, y)); } else if (action == AMOTION_EVENT_ACTION_UP && FETCH_WCB(*window, Mouse)) { touchscreen.in_mmotion = false; INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_UP, x, y)); } else if (action == AMOTION_EVENT_ACTION_MOVE && FETCH_WCB(*window, Motion)) { INVOKE_WCB(*window, Motion, (x, y)); } } return EVENT_HANDLED; } /* Let Android handle other events (e.g. Back and Menu buttons) */ return EVENT_NOT_HANDLED; }
/** * Process the next input event. */ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* engine = (struct engine*)app->userData; if (!engine->os) return 0; switch(AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: { int ac = AKeyEvent_getAction(event); switch(ac) { case AKEY_EVENT_ACTION_DOWN: { int32_t code = AKeyEvent_getKeyCode(event); if (code==AKEYCODE_BACK) { //AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled); if (engine->os) engine->os->main_loop_request_quit(); return 1; } } break; case AKEY_EVENT_ACTION_UP: { } break; } } break; case AINPUT_EVENT_TYPE_MOTION: { Vector<OS_Android::TouchPos> touchvec; int pc = AMotionEvent_getPointerCount(event); touchvec.resize(pc); for(int i=0;i<pc;i++) { touchvec[i].pos.x=AMotionEvent_getX(event,i); touchvec[i].pos.y=AMotionEvent_getY(event,i); touchvec[i].id=AMotionEvent_getPointerId(event,i); } //System.out.printf("gaction: %d\n",event.getAction()); int pidx=(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)>>8; switch(AMotionEvent_getAction(event)&AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: { engine->os->process_touch(0,0,touchvec); //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY()); } break; case AMOTION_EVENT_ACTION_MOVE: { engine->os->process_touch(1,0,touchvec); //for(int i=0;i<event.getPointerCount();i++) { // System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i)); //} } break; case AMOTION_EVENT_ACTION_POINTER_UP: { engine->os->process_touch(4,pidx,touchvec); //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); } break; case AMOTION_EVENT_ACTION_POINTER_DOWN: { engine->os->process_touch(3,pidx,touchvec); //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); } break; case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_UP: { engine->os->process_touch(2,0,touchvec); //for(int i=0;i<event.getPointerCount();i++) { // System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i)); //} } break; } return 1; } break; } return 0; }
/** * Process the next input event. */ static int32_t engine_handle_input( struct android_app* app, AInputEvent* event ) { JNIEnv *jni; (*jVM)->AttachCurrentThread(jVM, &jni, NULL); struct ENGINE* engine = (struct ENGINE*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY){ int device = AInputEvent_getDeviceId(event); int action = AKeyEvent_getAction(event); int keyCode = AKeyEvent_getKeyCode(event); if(jni && g_pActivity){ if((*jni)->ExceptionCheck(jni)) { (*jni)->ExceptionDescribe(jni); (*jni)->ExceptionClear(jni); } (*jni)->CallIntMethod(jni, g_pActivity, javaOnNDKKey, device, keyCode, action, AKeyEvent_getMetaState(event)); if (!(keyCode == AKEYCODE_MENU || keyCode == AKEYCODE_BACK || keyCode == AKEYCODE_BUTTON_THUMBR || keyCode == AKEYCODE_VOLUME_UP || keyCode == AKEYCODE_VOLUME_DOWN || keyCode == AKEYCODE_BUTTON_SELECT)) { return 1; } } } else if( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) { int device = AInputEvent_getDeviceId( event ); int nSourceId = AInputEvent_getSource( event ); int nPointerCount = AMotionEvent_getPointerCount( event ); int n; jboolean newTouch = JNI_TRUE; for( n = 0 ; n < nPointerCount ; ++n ) { int nPointerId = AMotionEvent_getPointerId( event, n ); int nAction = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction( event ); int nRawAction = AMotionEvent_getAction( event ); struct TOUCHSTATE *touchstate = 0; if( nSourceId == AINPUT_SOURCE_TOUCHPAD ) { touchstate = engine->touchstate_pad; } else { touchstate = engine->touchstate_screen; } if( nAction == AMOTION_EVENT_ACTION_POINTER_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_UP ) { int nPointerIndex = (AMotionEvent_getAction( event ) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; nPointerId = AMotionEvent_getPointerId( event, nPointerIndex ); } if( nAction == AMOTION_EVENT_ACTION_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_DOWN ) { touchstate[nPointerId].down = 1; } else if( nAction == AMOTION_EVENT_ACTION_UP || nAction == AMOTION_EVENT_ACTION_POINTER_UP || nAction == AMOTION_EVENT_ACTION_CANCEL ) { touchstate[nPointerId].down = 0; } if (touchstate[nPointerId].down == 1) { touchstate[nPointerId].x = AMotionEvent_getX( event, n ); touchstate[nPointerId].y = AMotionEvent_getY( event, n ); } if( jni && g_pActivity && isXperiaPlay) { // (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y, newTouch); (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y); } newTouch = JNI_FALSE; }