static bool CookEvent_Motion(AInputEvent *event, CookedEventCallback callback) { int src = AInputEvent_getSource(event); int action = AMotionEvent_getAction(event); int actionMasked = action & AMOTION_EVENT_ACTION_MASK; int ptrIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; struct CookedEvent ev; memset(&ev, 0, sizeof(ev)); if (actionMasked == AMOTION_EVENT_ACTION_DOWN || actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) { ev.type = COOKED_EVENT_TYPE_POINTER_DOWN; } else if (actionMasked == AMOTION_EVENT_ACTION_UP || actionMasked == AMOTION_EVENT_ACTION_POINTER_UP) { ev.type = COOKED_EVENT_TYPE_POINTER_UP; } else { ev.type = COOKED_EVENT_TYPE_POINTER_MOVE; } ev.motionPointerId = AMotionEvent_getPointerId(event, ptrIndex); ev.motionIsOnScreen = (src == AINPUT_SOURCE_TOUCHSCREEN); ev.motionX = AMotionEvent_getX(event, ptrIndex); ev.motionY = AMotionEvent_getY(event, ptrIndex); if (ev.motionIsOnScreen) { // use screen size as the motion range ev.motionMinX = 0.0f; ev.motionMaxX = SceneManager::GetInstance()->GetScreenWidth(); ev.motionMinY = 0.0f; ev.motionMaxY = SceneManager::GetInstance()->GetScreenHeight(); } else { // look up motion range for this device _look_up_motion_range((int) AInputEvent_getDeviceId(event), (int)AInputEvent_getSource(event), &ev.motionMinX, &ev.motionMaxX, &ev.motionMinY, &ev.motionMaxY); } // deliver event callback(&ev); // deliver motion info about other pointers (for multi-touch) int ptrCount = AMotionEvent_getPointerCount(event); for (int i = 0; i < ptrCount; i++) { ev.type = COOKED_EVENT_TYPE_POINTER_MOVE; ev.motionX = AMotionEvent_getX(event, i); ev.motionY = AMotionEvent_getY(event, i); ev.motionPointerId = AMotionEvent_getPointerId(event, i); callback(&ev); } // If this is a touch-nav event, return false to indicate that we haven't handled it. // This will trigger translation of swipes to DPAD keys, which is what we want. // Otherwise, we say that we've handled it. return (src != SOURCE_TOUCH_NAVIGATION); }
int32_t Engine::onMotionEvent(android_app* app, AInputEvent* event) { if (!this->loaded) return 0; if (!this->focused) return 0; size_t pointerCount = AMotionEvent_getPointerCount(event); this->updateUptime(); for (size_t i = 0; i < pointerCount; i++) { size_t pointerId = AMotionEvent_getPointerId(event, i); size_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; size_t pointerIndex = i; if (action == AMOTION_EVENT_ACTION_POINTER_DOWN || action == AMOTION_EVENT_ACTION_POINTER_UP) { pointerIndex = (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; pointerId = AMotionEvent_getPointerId(event, pointerIndex); } this->touchEventParamCache[0] = pointerId; this->touchEventParamCache[1] = action; this->touchEventParamCache[2] = AMotionEvent_getX(event, pointerIndex); this->touchEventParamCache[3] = AMotionEvent_getY(event, pointerIndex); this->touchEventParamCache[4] = this->uptime.time; this->touchEventParamCache[5] = this->uptime.millitm; this->touchEventParamCache[6] = AInputEvent_getDeviceId(event); this->touchEventParamCache[7] = AInputEvent_getSource(event); if (callSqFunction_Bool_Floats(this->sqvm, EMO_NAMESPACE, EMO_FUNC_MOTIONEVENT, this->touchEventParamCache, MOTION_EVENT_PARAMS_SIZE, false)) { return 1; } }
static int32_t input_eventcallback(struct android_app* app, AInputEvent* event) { int32_t type = AInputEvent_getType(event); AndroidApplication* a = (AndroidApplication*)app->userData; switch (type) { case AINPUT_EVENT_TYPE_MOTION: switch (AInputEvent_getSource(event)) { case AINPUT_SOURCE_TOUCHSCREEN: return a->eventManager()->processTouchEvent(event); break; } break; case AINPUT_EVENT_TYPE_KEY: Log::debug("EVENT INPUT OK"); switch(AKeyEvent_getKeyCode(event)) { case AKEYCODE_BACK: return 1; break; } return 0; break; } }
bool CookEvent(AInputEvent *event, CookedEventCallback callback) { int type = AInputEvent_getType(event); int src = AInputEvent_getSource(event); bool isJoy = (type == AINPUT_EVENT_TYPE_MOTION) && (src & AINPUT_SOURCE_CLASS_MASK) == SOURCE_CLASS_JOYSTICK; if (!_init_done) { _init(); _init_done = true; } if (isJoy) { return CookEvent_Joy(event, callback); } else if (type == AINPUT_EVENT_TYPE_KEY) { bool handled = _process_keys(false, event, callback); if (AKeyEvent_getKeyCode(event) == AKEYCODE_BACK && 0 == AKeyEvent_getAction(event)) { // back key was pressed struct CookedEvent ev; memset(&ev, 0, sizeof(ev)); ev.type = COOKED_EVENT_TYPE_BACK; return callback(&ev); } // Note: if you want to handle other keys, add code here. For now we only // handle DPAD keys as indicated in _process_keys. return handled; } else if (type == AINPUT_EVENT_TYPE_MOTION) { return CookEvent_Motion(event, callback); } return false; }
int32_t EventLoop::processInputEvent(AInputEvent* pEvent) { Pegas_log_info_loop("EventLoop::processInputEvent [pEvent: %d]", pEvent); int32_t lEventType = AInputEvent_getType(pEvent); Pegas_log_debug_loop("lEventType = %d [%X]", lEventType, lEventType); int32_t lEventSource = AInputEvent_getSource(pEvent); Pegas_log_debug_loop("lEventSource = %d [%X]", lEventSource, lEventSource); switch (lEventType) { case AINPUT_EVENT_TYPE_MOTION: switch (lEventSource) { case AINPUT_SOURCE_TOUCHSCREEN: return mInputHandler->onTouchEvent(pEvent); case AINPUT_SOURCE_TRACKBALL: return mInputHandler->onTrackballEvent(pEvent); } break; case AINPUT_EVENT_TYPE_KEY: return mInputHandler->onKeyboardEvent(pEvent); } return 0; }
int32_t CEventLoop::processInput(AInputEvent* event) { int32_t rtn = 0; int32_t type = AInputEvent_getType(event); int32_t source = AInputEvent_getSource(event); // handle joystick input if (IS_FROM_SOURCE(source, AINPUT_SOURCE_GAMEPAD) || IS_FROM_SOURCE(source, AINPUT_SOURCE_JOYSTICK)) { if (m_inputHandler->onJoyStickEvent(event)) return true; } switch(type) { case AINPUT_EVENT_TYPE_KEY: rtn = m_inputHandler->onKeyboardEvent(event); break; case AINPUT_EVENT_TYPE_MOTION: if (IS_FROM_SOURCE(source, AINPUT_SOURCE_TOUCHSCREEN)) rtn = m_inputHandler->onTouchEvent(event); else if (IS_FROM_SOURCE(source, AINPUT_SOURCE_MOUSE)) rtn = m_inputHandler->onMouseEvent(event); break; } return rtn; }
void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int id = AMotionEvent_getPointerId(_event, index); float x = AMotionEvent_getX(_event, index); float y = AMotionEvent_getY(_event, index); Event event; if (isDown) { if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonPressed; event.mouseButton.button = static_cast<Mouse::Button>(id); event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = true; } else if (device == AINPUT_SOURCE_TOUCHSCREEN) { event.type = Event::TouchBegan; event.touch.finger = id; event.touch.x = x; event.touch.y = y; states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } } else { if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonReleased; event.mouseButton.button = static_cast<Mouse::Button>(id); event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = false; } else if (device == AINPUT_SOURCE_TOUCHSCREEN) { event.type = Event::TouchEnded; event.touch.finger = id; event.touch.x = x; event.touch.y = y; states->touchEvents.erase(id); } } forwardEvent(event); }
bool CAndroidJoyStick::onJoyStickKeyEvent(AInputEvent *event) { if (event == NULL) return false; int32_t keycode = AKeyEvent_getKeyCode(event); // watch this check, others might be different. // AML IR Controller is AINPUT_SOURCE_GAMEPAD | AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD // Gamestick Controller == AINPUT_SOURCE_GAMEPAD | AINPUT_SOURCE_KEYBOARD // NVidiaShield Controller == AINPUT_SOURCE_GAMEPAD | AINPUT_SOURCE_KEYBOARD // we want to reject AML IR Controller. if (AInputEvent_getSource(event) == (AINPUT_SOURCE_GAMEPAD | AINPUT_SOURCE_KEYBOARD)) { // GamePad events are AINPUT_EVENT_TYPE_KEY events, // trap them here and revector valid ones as JoyButtons // so we get keymap handling. for (size_t i = 0; i < sizeof(ButtonMap) / sizeof(KeyMap); i++) { if (keycode == ButtonMap[i].nativeKey) { uint32_t holdtime = 0; uint8_t button = ButtonMap[i].xbmcID; int32_t action = AKeyEvent_getAction(event); int32_t device = AInputEvent_getDeviceId(event); if ((action == AKEY_EVENT_ACTION_UP)) { // ProcessJoystickEvent does not understand up, ignore it. m_prev_holdtime = m_prev_device = m_prev_button = 0; return false; } else { if (m_prev_holdtime && device == m_prev_device && button == m_prev_button) { holdtime = CTimeUtils::GetFrameTime() - m_prev_holdtime; } else { m_prev_holdtime = CTimeUtils::GetFrameTime(); m_prev_device = device; m_prev_button = button; } } XBMC_JoyButton(device, button, holdtime, action == AKEY_EVENT_ACTION_UP); return true; } } } return false; }
int WindowImplAndroid::getUnicode(AInputEvent* event) { // Retrieve activity states ActivityStates* states = getActivity(NULL); Lock lock(states->mutex); // Initializes JNI jint lResult; jint lFlags = 0; JavaVM* lJavaVM = states->activity->vm; JNIEnv* lJNIEnv = states->activity->env; JavaVMAttachArgs lJavaVMAttachArgs; lJavaVMAttachArgs.version = JNI_VERSION_1_6; lJavaVMAttachArgs.name = "NativeThread"; lJavaVMAttachArgs.group = NULL; lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs); if (lResult == JNI_ERR) err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl; // Retrieve key data from the input event jlong downTime = AKeyEvent_getDownTime(event); jlong eventTime = AKeyEvent_getEventTime(event); jint action = AKeyEvent_getAction(event); jint code = AKeyEvent_getKeyCode(event); jint repeat = AKeyEvent_getRepeatCount(event); // not sure! jint metaState = AKeyEvent_getMetaState(event); jint deviceId = AInputEvent_getDeviceId(event); jint scancode = AKeyEvent_getScanCode(event); jint flags = AKeyEvent_getFlags(event); jint source = AInputEvent_getSource(event); // Construct a KeyEvent object from the event data jclass ClassKeyEvent = lJNIEnv->FindClass("android/view/KeyEvent"); jmethodID KeyEventConstructor = lJNIEnv->GetMethodID(ClassKeyEvent, "<init>", "(JJIIIIIIII)V"); jobject ObjectKeyEvent = lJNIEnv->NewObject(ClassKeyEvent, KeyEventConstructor, downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source); // Call its getUnicodeChar() method to get the Unicode value jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I"); int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState); lJNIEnv->DeleteLocalRef(ClassKeyEvent); lJNIEnv->DeleteLocalRef(ObjectKeyEvent); // Detach this thread from the JVM lJavaVM->DetachCurrentThread(); return unicode; }
int processInputEvent(AInputEvent* event) { int eventType = AInputEvent_getType(event); switch (eventType) { case AINPUT_EVENT_TYPE_MOTION: switch (AInputEvent_getSource(event)) { case AINPUT_SOURCE_TOUCHSCREEN: return onTouchEvent(event); break; } break; } return 0; }
int32_t EventLoop::processInputEvent(AInputEvent* event) { int32_t eventType = AInputEvent_getType(event); int32_t eventSource = AInputEvent_getSource(event); switch(eventType) { case AINPUT_EVENT_TYPE_MOTION: return m_inputHandler->onTouchEvent(event); case AINPUT_EVENT_TYPE_KEY: return m_inputHandler->onKeyEvent(event); } return 0; }
static void _log_event(AInputEvent *event) { if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { LOGD("DEBUG: Key event: action=%d, keycode=%d, meta=0x%x, source=%d", AKeyEvent_getAction(event), AKeyEvent_getKeyCode(event), AKeyEvent_getMetaState(event), (int)(AInputEvent_getSource(event))); } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { LOGD("DEBUG: Motion event: deviceid=%d, pointerid=%d, sourceid=%d, action=%d, keycode=%d" "x,y=%f,%f, raw x,y=%f,%f, source=%d", (int)AInputEvent_getDeviceId(event), (int)AMotionEvent_getPointerId(event, 0), (int)AInputEvent_getSource(event), (int)AKeyEvent_getAction(event), (int)AKeyEvent_getKeyCode(event), (float)AMotionEvent_getX(event,0), (float)AMotionEvent_getY(event,0), (float)AMotionEvent_getRawX(event,0), (float)AMotionEvent_getRawY(event,0), (int)(AInputEvent_getSource(event))); } else { LOGD("DEBUG: other type of event, %d", AInputEvent_getType(event)); } }
/** * 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( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) { engine->render = 1; int nPointerCount = AMotionEvent_getPointerCount( event ); int nSourceId = AInputEvent_getSource( event ); int n; for( n = 0 ; n < nPointerCount ; ++n ) { int nPointerId = AMotionEvent_getPointerId( event, n ); int nAction = AMOTION_EVENT_ACTION_MASK & 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 ); } }
static int32_t custom_handle_input(struct android_app* _application, AInputEvent* _event) { if( AInputEvent_getType(_event) == AINPUT_EVENT_TYPE_MOTION ) { i32 pointerCount = AMotionEvent_getPointerCount(_event); i32 sourceId = AInputEvent_getSource(_event); for(ui32 i = 0 ; i < pointerCount ; ++i) { i32 pointerId = AMotionEvent_getPointerId(_event, i); i32 action = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction(_event); i32 rawAction = AMotionEvent_getAction(_event); if(sourceId == AINPUT_SOURCE_TOUCHPAD) { } else { } f32 pointX = AMotionEvent_getX(_event, 0); f32 pointY = AMotionEvent_getY(_event, 0); if(action == AMOTION_EVENT_ACTION_POINTER_DOWN || action == AMOTION_EVENT_ACTION_POINTER_UP) { i32 pointerIndex = (AMotionEvent_getAction(_event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; pointerId = AMotionEvent_getPointerId(_event, pointerIndex); } if(action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_POINTER_DOWN) { IInputContext::NativeCallTapRecognizerPressed(glm::ivec2(pointX, pointY)); } else if( action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_POINTER_UP || action == AMOTION_EVENT_ACTION_CANCEL ) { IInputContext::NativeCallTapRecognizerReleased(glm::ivec2(pointX, pointY)); } else if(action == AMOTION_EVENT_ACTION_MOVE) { IInputContext::NativeCallTapRecognizerMoved(glm::ivec2(pointX, pointY)); } }
int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); Event event; if (device == AINPUT_SOURCE_MOUSE) event.type = Event::MouseMoved; else if (device & AINPUT_SOURCE_TOUCHSCREEN) event.type = Event::TouchMoved; int pointerCount = AMotionEvent_getPointerCount(_event); for (int p = 0; p < pointerCount; p++) { int id = AMotionEvent_getPointerId(_event, p); float x = AMotionEvent_getX(_event, p); float y = AMotionEvent_getY(_event, p); if (device == AINPUT_SOURCE_MOUSE) { event.mouseMove.x = x; event.mouseMove.y = y; states->mousePosition = Vector2i(event.mouseMove.x, event.mouseMove.y); } else if (device & AINPUT_SOURCE_TOUCHSCREEN) { if (states->touchEvents[id].x == x && states->touchEvents[id].y == y) continue; event.touch.finger = id; event.touch.x = x; event.touch.y = y; states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } forwardEvent(event); } return 1; }
int32_t touch(bool down, int32_t action, AInputEvent* event) { auto& windowRef = Engine::getMainWindow(); const int32_t device = AInputEvent_getSource(event); if (device & AINPUT_SOURCE_TOUCHSCREEN) { const int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; const int id = AMotionEvent_getPointerId(event, index); if (id < 10) { const float x = AMotionEvent_getX(event, index); const float y = AMotionEvent_getY(event, index); auto state = ActivityState::get(); if (down) { state->lastTouchPosition[id] = glm::vec2(x, y); windowRef.getEventHandler()->touchPressed(id, x, y); } else { state->lastTouchPosition[id] = glm::vec2(-1.f, -1.f); windowRef.getEventHandler()->touchReleased(id, x, y); } for (int info = 0; info < 4; ++info) { const float i = AMotionEvent_getAxisValue(event, ns_touchAxes[info], index); if (i > JOP_AXIS_TOLERANCE) windowRef.getEventHandler()->touchInfo(id, Input::getJopTouchInfo(ns_touchAxes[info]), i); } return 1; } } return 0; }
int32_t VulkanExampleBase::handleAppInput(struct android_app* app, AInputEvent* event) { VulkanExampleBase* vulkanExample = (VulkanExampleBase*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { if (AInputEvent_getSource(event) == AINPUT_SOURCE_JOYSTICK) { vulkanExample->gamePadState.axes.x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0); vulkanExample->gamePadState.axes.y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0); vulkanExample->gamePadState.axes.z = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, 0); vulkanExample->gamePadState.axes.rz = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, 0); } else { // todo : touch input } return 1; } return 0; }
int32_t scroll(AInputEvent* event) { auto& windowRef = Engine::getMainWindow(); const int32_t device = AInputEvent_getSource(event); const float x = AMotionEvent_getX(event, 0); const float y = AMotionEvent_getY(event, 0); if (device & AINPUT_SOURCE_TOUCHSCREEN) windowRef.getEventHandler()->touchScrolled(x, y); else if (device & AINPUT_SOURCE_MOUSE) windowRef.getEventHandler()->mouseScrolled(x, y); else return 0; return 1; }
int32_t CEventLoop::processInput(AInputEvent* event) { int32_t type = AInputEvent_getType(event); switch (type) { case AINPUT_EVENT_TYPE_MOTION: switch (AInputEvent_getSource(event)) { case AINPUT_SOURCE_TOUCHSCREEN: return m_inputHandler->onTouchEvent(event); case AINPUT_SOURCE_MOUSE: return m_inputHandler->onMouseEvent(event); } break; case AINPUT_EVENT_TYPE_KEY: return m_inputHandler->onKeyboardEvent(event); } return 0; }
bool OuyaInputView::dispatchKeyEvent(AInputEvent* keyEvent) { int64_t downTime = AKeyEvent_getDownTime(keyEvent); int64_t eventTime = AKeyEvent_getEventTime(keyEvent); int32_t action = AKeyEvent_getAction(keyEvent); int32_t code = AKeyEvent_getKeyCode(keyEvent); int32_t repeat = AKeyEvent_getRepeatCount(keyEvent); int32_t metaState = AKeyEvent_getMetaState(keyEvent); int32_t deviceId = AInputEvent_getDeviceId(keyEvent); int32_t scancode = AKeyEvent_getScanCode(keyEvent); int32_t flags = AKeyEvent_getFlags(keyEvent); int32_t source = AInputEvent_getSource(keyEvent); #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "downTime=%lld eventTime=%lld action=%d code=%d repeat=%d metaState=%d deviceId=%d scancode=%d flags=%d source=%d", downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source); #endif return javaDispatchKeyEvent(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source); }
int32_t AndroidEventLoop::ProcessInputEvent(AInputEvent* pEvent) { int32_t eventType = AInputEvent_getType(pEvent); switch (eventType) { case AINPUT_EVENT_TYPE_MOTION: switch (AInputEvent_getSource(pEvent)) { case AINPUT_SOURCE_TOUCHSCREEN: return Global::pContext->pInputService->onTouchEvent(pEvent); break; } break; case AINPUT_EVENT_TYPE_KEY: switch (AKeyEvent_getKeyCode(pEvent)) { case AKEYCODE_BACK: return Global::pContext->pInputService->onKeyBack(); break; } break; } 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; }
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; }
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; } } }
static void android_input_poll(void *data) { (void)data; RARCH_PERFORMANCE_INIT(input_poll); RARCH_PERFORMANCE_START(input_poll); bool debug_enable = g_settings.input.debug_enable; struct android_app* android_app = (struct android_app*)g_android; uint64_t *lifecycle_state = &g_extern.lifecycle_state; *lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS)); // Read all pending events. while (AInputQueue_hasEvents(android_app->inputQueue) > 0) { AInputEvent* event = NULL; if (AInputQueue_getEvent(android_app->inputQueue, &event) < 0) break; bool long_msg_enable = false; int32_t handled = 1; int action = 0; char msg[128]; msg[0] = 0; int source = AInputEvent_getSource(event); int id = AInputEvent_getDeviceId(event); if (id == zeus_second_id) id = zeus_id; int keycode = AKeyEvent_getKeyCode(event); int type_event = AInputEvent_getType(event); int state_id = -1; if (source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD)) state_id = 0; // touch overlay is always player 1 else { for (unsigned i = 0; i < pads_connected; i++) if (state_device_ids[i] == id) state_id = i; } if (state_id < 0) { state_id = pads_connected; state_device_ids[pads_connected++] = id; input_autodetect_setup(android_app, msg, sizeof(msg), state_id, id, source); long_msg_enable = true; } if (keycode == AKEYCODE_BACK ) { int meta = AKeyEvent_getMetaState(event); if (!(meta & AMETA_ALT_ON)) { *lifecycle_state |= (1ULL << RARCH_QUIT_KEY); AInputQueue_finishEvent(android_app->inputQueue, event, handled); break; } } if (type_event == AINPUT_EVENT_TYPE_MOTION) { float x = 0.0f; float y = 0.0f; action = AMotionEvent_getAction(event); size_t motion_pointer = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; action &= AMOTION_EVENT_ACTION_MASK; if (source & ~(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE)) { if (g_settings.input.dpad_emulation[state_id] != DPAD_EMULATION_NONE) { uint64_t *state_cur = &state[state_id]; x = AMotionEvent_getX(event, motion_pointer); y = AMotionEvent_getY(event, motion_pointer); *state_cur &= ~((1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)); *state_cur |= PRESSED_LEFT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; *state_cur |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; *state_cur |= PRESSED_UP(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; *state_cur |= PRESSED_DOWN(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; } } else { bool keyup = (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL || action == AMOTION_EVENT_ACTION_POINTER_UP) || (source == AINPUT_SOURCE_MOUSE && action != AMOTION_EVENT_ACTION_DOWN); if (keyup && motion_pointer < MAX_TOUCH) { memmove(pointer + motion_pointer, pointer + motion_pointer + 1, (MAX_TOUCH - motion_pointer - 1) * sizeof(struct input_pointer)); if (pointer_count > 0) pointer_count--; } else { int pointer_max = min(AMotionEvent_getPointerCount(event), MAX_TOUCH); for (motion_pointer = 0; motion_pointer < pointer_max; motion_pointer++) { x = AMotionEvent_getX(event, motion_pointer); y = AMotionEvent_getY(event, motion_pointer); input_translate_coord_viewport(x, y, &pointer[motion_pointer].x, &pointer[motion_pointer].y, &pointer[motion_pointer].full_x, &pointer[motion_pointer].full_y); pointer_count = max(pointer_count, motion_pointer + 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)
/* * 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; }
static void android_input_poll(void *data) { (void)data; RARCH_PERFORMANCE_INIT(input_poll); RARCH_PERFORMANCE_START(input_poll); struct android_app* android_app = g_android.app; g_extern.lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS)); // Read all pending events. while(AInputQueue_hasEvents(android_app->inputQueue)) { AInputEvent* event = NULL; AInputQueue_getEvent(android_app->inputQueue, &event); if (AInputQueue_preDispatchEvent(android_app->inputQueue, event)) continue; int32_t handled = 1; int source = AInputEvent_getSource(event); int id = AInputEvent_getDeviceId(event); int type_event = AInputEvent_getType(event); int state_id = state_device_ids[id]; if(state_id == -1) state_id = state_device_ids[id] = pads_connected++; int action = 0; #ifdef RARCH_INPUT_DEBUG char msg[128]; #endif if(type_event == AINPUT_EVENT_TYPE_MOTION) { action = AMotionEvent_getAction(event); int8_t motion_action = action & AMOTION_EVENT_ACTION_MASK; size_t motion_pointer = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; float x = AMotionEvent_getX(event, motion_pointer); float y = AMotionEvent_getY(event, motion_pointer); if(source & ~(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE)) { state[state_id] &= ~((1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)); state[state_id] |= PRESSED_LEFT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; state[state_id] |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; state[state_id] |= PRESSED_UP(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; state[state_id] |= PRESSED_DOWN(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; } else { bool mouse_is_not_dirty = (source == AINPUT_SOURCE_MOUSE && action != AMOTION_EVENT_ACTION_DOWN); bool pointer_is_not_dirty = (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL || action == AMOTION_EVENT_ACTION_POINTER_UP); pointer_dirty = !(mouse_is_not_dirty || pointer_is_not_dirty); if (pointer_dirty) input_translate_coord_viewport(x, y, &pointer_x, &pointer_y); } #ifdef RARCH_INPUT_DEBUG snprintf(msg, sizeof(msg), "Pad %d : x = %.2f, y = %.2f, src %d.\n", state_id, x, y, source); #endif } else {
bool CAndroidKey::onKeyboardEvent(AInputEvent *event) { if (event == NULL) return false; bool ret = true; 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 source = AInputEvent_getSource(event); int32_t deviceId = AInputEvent_getDeviceId(event); uint16_t unicode = 0; CJNIKeyCharacterMap map = CJNIKeyCharacterMap::load(deviceId); if (map) 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 (sym == XBMCK_UNKNOWN && m_handleMediaKeys) { for (unsigned int index = 0; index < sizeof(MediakeyMap) / sizeof(KeyMap); index++) { if (keycode == MediakeyMap[index].nativeKey) { sym = MediakeyMap[index].xbmcKey; break; } } } if (sym == XBMCK_UNKNOWN && m_handleSearchKeys) { for (unsigned int index = 0; index < sizeof(SearchkeyMap) / sizeof(KeyMap); index++) { if (keycode == SearchkeyMap[index].nativeKey) { sym = SearchkeyMap[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 implement /* if (state & AMETA_SYM_ON) modifiers |= 0x000?;*/ switch (action) { case AKEY_EVENT_ACTION_DOWN: #if 1 CXBMCApp::android_printf("CAndroidKey: key down (dev:%d; src:%d; code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", deviceId, source, 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); break; case AKEY_EVENT_ACTION_UP: #if 1 CXBMCApp::android_printf("CAndroidKey: key up (dev:%d; src:%d; code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", deviceId, source, 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); break; case AKEY_EVENT_ACTION_MULTIPLE: #if 1 CXBMCApp::android_printf("CAndroidKey: key multiple (dev:%d; src:%d; code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", deviceId, source, keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif return false; break; default: #if 1 CXBMCApp::android_printf("CAndroidKey: unknown key (dev:%d; src:%d; code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", deviceId, source, keycode, repeat, flags, (state & AMETA_ALT_ON) ? "yes" : "no", (state & AMETA_SHIFT_ON) ? "yes" : "no", (state & AMETA_SYM_ON) ? "yes" : "no"); #endif return false; break; } return ret; }
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; }
bool OuyaInputView::dispatchGenericMotionEvent(AInputEvent* motionEvent) { int64_t downTime = AMotionEvent_getDownTime(motionEvent); int64_t eventTime = AMotionEvent_getEventTime(motionEvent); int32_t action = AMotionEvent_getAction(motionEvent); int32_t metaState = AMotionEvent_getMetaState(motionEvent); int32_t pointerCount = AMotionEvent_getPointerCount(motionEvent); int32_t buttonState = AMotionEvent_getButtonState(motionEvent); float xPrecision = AMotionEvent_getXPrecision(motionEvent); float yPrecision = AMotionEvent_getYPrecision(motionEvent); int32_t deviceId = AInputEvent_getDeviceId(motionEvent); int32_t edgeFlags = AMotionEvent_getEdgeFlags(motionEvent); int32_t flags = AMotionEvent_getFlags(motionEvent); int32_t source = AInputEvent_getSource(motionEvent); int* pointerPropertiesId = new int[pointerCount]; int* pointerPropertiesToolType = new int[pointerCount]; float* pointerCoordsOrientation = new float[pointerCount]; float* pointerCoordsPressure = new float[pointerCount]; float* pointerCoordsSize = new float[pointerCount]; float* pointerCoordsToolMajor = new float[pointerCount]; float* pointerCoordsToolMinor = new float[pointerCount]; float* pointerCoordsTouchMajor = new float[pointerCount]; float* pointerCoordsTouchMinor = new float[pointerCount]; float* pointerCoordsX = new float[pointerCount]; float* pointerCoordsY = new float[pointerCount]; std::vector<int> listAxisIndices; std::vector<float> listAxisValues; if (pointerCount > 0) { #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "pointerCount=%d deviceId=%d source=%d", pointerCount, deviceId, source); #endif // MotionEvent.PointerProperties long long pointerId = AMotionEvent_getPointerId(motionEvent, 0); int32_t toolType = AMotionEvent_getToolType(motionEvent, 0); #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "PointerProperties pointerId=%lld toolType-%d", pointerId, toolType); #endif pointerPropertiesId[0] = pointerId; pointerPropertiesToolType[0] = toolType; // MotionEvent.PointerCoords float orientation = AMotionEvent_getOrientation(motionEvent, pointerId); float pressure = AMotionEvent_getPressure(motionEvent, pointerId); float size = AMotionEvent_getSize(motionEvent, pointerId); float toolMajor = AMotionEvent_getTouchMajor(motionEvent, pointerId); float toolMinor = AMotionEvent_getToolMinor(motionEvent, pointerId); float touchMajor = AMotionEvent_getTouchMajor(motionEvent, pointerId); float touchMinor = AMotionEvent_getTouchMinor(motionEvent, pointerId); float x = AMotionEvent_getX(motionEvent, pointerId); float y = AMotionEvent_getY(motionEvent, pointerId); #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "PointerCoords orientation=%f pressure=%f size=%f toolMajor=%f toolMinor=%f touchMajor=%f touchMinor=%f x=%f y=%f", orientation, pressure, size, toolMajor, toolMinor, touchMajor, touchMinor, x, y); #endif pointerCoordsOrientation[0] = orientation; pointerCoordsPressure[0] = pressure; pointerCoordsSize[0] = size; pointerCoordsToolMajor[0] = toolMajor; pointerCoordsToolMinor[0] = toolMinor; pointerCoordsTouchMajor[0] = touchMajor; pointerCoordsTouchMinor[0] = touchMinor; pointerCoordsX[0] = x; pointerCoordsY[0] = y; for (int32_t axis = 0; axis < 50; ++axis) // 50 is based on the AXIS_value range I saw in the documentation { float val = AMotionEvent_getAxisValue(motionEvent, axis, pointerId); if (val != 0.0f) { #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "axis=%d val=%f", axis, val); #endif listAxisIndices.push_back(axis); listAxisValues.push_back(val); } } } int axisCount = listAxisIndices.size(); int* axisIndexes = new int[axisCount]; float* axisValues = new float[axisCount]; for (int index = 0; index < axisCount; ++index) { axisIndexes[index] = listAxisIndices[index]; axisValues[index] = listAxisValues[index]; } listAxisIndices.clear(); listAxisValues.clear(); bool handled = javaDispatchGenericMotionEvent( downTime, eventTime, action, pointerCount, metaState, buttonState, xPrecision, yPrecision, deviceId, edgeFlags, source, flags, pointerPropertiesId, pointerPropertiesToolType, pointerCoordsOrientation, pointerCoordsPressure, pointerCoordsSize, pointerCoordsToolMajor, pointerCoordsToolMinor, pointerCoordsTouchMajor, pointerCoordsTouchMinor, pointerCoordsX, pointerCoordsY, axisCount, axisIndexes, axisValues); delete pointerPropertiesId; delete pointerPropertiesToolType; delete pointerCoordsOrientation; delete pointerCoordsPressure; delete pointerCoordsSize; delete pointerCoordsToolMajor; delete pointerCoordsToolMinor; delete pointerCoordsTouchMajor; delete pointerCoordsTouchMinor; delete pointerCoordsX; delete pointerCoordsY; delete axisIndexes; delete axisValues; return handled; }