//-------------------------------------------------------------------------------- // DoubletapDetector //-------------------------------------------------------------------------------- GESTURE_STATE DoubletapDetector::Detect(const AInputEvent* motion_event) { if (AMotionEvent_getPointerCount(motion_event) > 1) { // Only support single double tap return false; } bool tap_detected = tap_detector_.Detect(motion_event); int32_t action = AMotionEvent_getAction(motion_event); unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; switch (flags) { case AMOTION_EVENT_ACTION_DOWN: { int64_t eventTime = AMotionEvent_getEventTime(motion_event); if (eventTime - last_tap_time_ <= DOUBLE_TAP_TIMEOUT) { float x = AMotionEvent_getX(motion_event, 0) - last_tap_x_; float y = AMotionEvent_getY(motion_event, 0) - last_tap_y_; if (x * x + y * y < DOUBLE_TAP_SLOP * DOUBLE_TAP_SLOP * dp_factor_) { LOGI("DoubletapDetector: Doubletap detected"); return GESTURE_STATE_ACTION; } } break; } case AMOTION_EVENT_ACTION_UP: if (tap_detected) { last_tap_time_ = AMotionEvent_getEventTime(motion_event); last_tap_x_ = AMotionEvent_getX(motion_event, 0); last_tap_y_ = AMotionEvent_getY(motion_event, 0); } break; } return GESTURE_STATE_NONE; }
bool CAndroidTouch::onTouchEvent(AInputEvent* event) { CXBMCApp::android_printf("%s", __PRETTY_FUNCTION__); if (event == NULL) return false; size_t numPointers = AMotionEvent_getPointerCount(event); if (numPointers <= 0) { CXBMCApp::android_printf(" => aborting touch event because there are no active pointers"); return false; } if (numPointers > TOUCH_MAX_POINTERS) numPointers = TOUCH_MAX_POINTERS; int32_t eventAction = AMotionEvent_getAction(event); int8_t touchAction = eventAction & AMOTION_EVENT_ACTION_MASK; size_t touchPointer = eventAction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; CTouchInput::TouchEvent touchEvent = CTouchInput::TouchEventAbort; switch (touchAction) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: touchEvent = CTouchInput::TouchEventDown; break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: touchEvent = CTouchInput::TouchEventUp; break; case AMOTION_EVENT_ACTION_MOVE: touchEvent = CTouchInput::TouchEventMove; break; case AMOTION_EVENT_ACTION_OUTSIDE: case AMOTION_EVENT_ACTION_CANCEL: default: break; } float x = AMotionEvent_getX(event, touchPointer); float y = AMotionEvent_getY(event, touchPointer); float size = m_dpi / 16.0f; int64_t time = AMotionEvent_getEventTime(event); // first update all touch pointers for (unsigned int pointer = 0; pointer < numPointers; pointer++) CTouchInput::Get().Update(pointer, AMotionEvent_getX(event, pointer), AMotionEvent_getY(event, pointer), AMotionEvent_getEventTime(event), m_dpi / 16.0f); // now send the event return CTouchInput::Get().Handle(touchEvent, x, y, time, touchPointer, size); }
//-------------------------------------------------------------------------------- // TapDetector //-------------------------------------------------------------------------------- GESTURE_STATE TapDetector::Detect(const AInputEvent* motion_event) { if (AMotionEvent_getPointerCount(motion_event) > 1) { // Only support single touch return false; } int32_t action = AMotionEvent_getAction(motion_event); unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; switch (flags) { case AMOTION_EVENT_ACTION_DOWN: down_pointer_id_ = AMotionEvent_getPointerId(motion_event, 0); down_x_ = AMotionEvent_getX(motion_event, 0); down_y_ = AMotionEvent_getY(motion_event, 0); break; case AMOTION_EVENT_ACTION_UP: { int64_t eventTime = AMotionEvent_getEventTime(motion_event); int64_t downTime = AMotionEvent_getDownTime(motion_event); if (eventTime - downTime <= TAP_TIMEOUT) { if (down_pointer_id_ == AMotionEvent_getPointerId(motion_event, 0)) { float x = AMotionEvent_getX(motion_event, 0) - down_x_; float y = AMotionEvent_getY(motion_event, 0) - down_y_; if (x * x + y * y < TOUCH_SLOP * TOUCH_SLOP * dp_factor_) { LOGI("TapDetector: Tap detected"); return GESTURE_STATE_ACTION; } } } break; } } return GESTURE_STATE_NONE; }
Pointer get_pointer_event(AInputEvent* event, int32_t index) { const Vec2i& point = rainbow::graphics::convert_to_flipped_view(Vec2i( AMotionEvent_getX(event, index), AMotionEvent_getY(event, index))); return Pointer(AMotionEvent_getPointerId(event, index), point.x, point.y, AMotionEvent_getEventTime(event)); }
static void computeValues(AInputEvent* event, tMotionEvent* evt, GLint index) { evt->packetCount=0; evt->eventArray[0].x = AMotionEvent_getX(event, index); evt->eventArray[0].y = AMotionEvent_getY(event, index); evt->eventArray[0].time = AMotionEvent_getEventTime(event); evt->eventArray[0].pointerIndex = index; evt->packetCount++; }
void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states) { // Prepare the java virtual machine 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 everything we need to create this MotionEvent in java jlong downTime = AMotionEvent_getDownTime(_event); jlong eventTime = AMotionEvent_getEventTime(_event); jint action = AMotionEvent_getAction(_event); jfloat x = AMotionEvent_getX(_event, 0); jfloat y = AMotionEvent_getY(_event, 0); jfloat pressure = AMotionEvent_getPressure(_event, 0); jfloat size = AMotionEvent_getSize(_event, 0); jint metaState = AMotionEvent_getMetaState(_event); jfloat xPrecision = AMotionEvent_getXPrecision(_event); jfloat yPrecision = AMotionEvent_getYPrecision(_event); jint deviceId = AInputEvent_getDeviceId(_event); jint edgeFlags = AMotionEvent_getEdgeFlags(_event); // Create the MotionEvent object in java trough its static constructor obtain() jclass ClassMotionEvent = lJNIEnv->FindClass("android/view/MotionEvent"); jmethodID StaticMethodObtain = lJNIEnv->GetStaticMethodID(ClassMotionEvent, "obtain", "(JJIFFFFIFFII)Landroid/view/MotionEvent;"); jobject ObjectMotionEvent = lJNIEnv->CallStaticObjectMethod(ClassMotionEvent, StaticMethodObtain, downTime, eventTime, action, x, y, pressure, size, metaState, xPrecision, yPrecision, deviceId, edgeFlags); // Call its getAxisValue() method to get the delta value of our wheel move event jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F"); jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001); // Create and send our mouse wheel event Event event; event.type = Event::MouseWheelMoved; event.mouseWheel.delta = static_cast<double>(delta); event.mouseWheel.x = AMotionEvent_getX(_event, 0); event.mouseWheel.y = AMotionEvent_getY(_event, 0); forwardEvent(event); // Dettach this thread from the JVM lJavaVM->DetachCurrentThread(); }
void FillEventData(UIEvent &uiEvent, int32 phase, AInputEvent* event, int32 index) { uiEvent.phase = phase; uiEvent.physPoint.x = AMotionEvent_getX(event, index); uiEvent.physPoint.y = AMotionEvent_getY(event, index); uiEvent.point.x = uiEvent.physPoint.x; uiEvent.point.y = uiEvent.physPoint.y; uiEvent.timestamp = AMotionEvent_getEventTime(event); }
static void computeMoveValues(AInputEvent* event, tMotionEvent* evt) { short index; evt->packetCount = 0; for (index=0; index<AMotionEvent_getPointerCount(event); ++index) { evt->eventArray[index].x = AMotionEvent_getX(event, AMotionEvent_getPointerId(event, index)); evt->eventArray[index].y = AMotionEvent_getY(event, AMotionEvent_getPointerId(event, index)); evt->eventArray[index].time = AMotionEvent_getEventTime(event); evt->eventArray[index].pointerIndex = AMotionEvent_getPointerId(event, index); evt->packetCount++; } }
bool InputService::onTouchEvent(AInputEvent* pEvent) { #ifdef INPUTSERVICE_LOG_EVENTS packt_Log_debug("AMotionEvent_getAction=%d", AMotionEvent_getAction(pEvent)); packt_Log_debug("AMotionEvent_getFlags=%d", AMotionEvent_getFlags(pEvent)); packt_Log_debug("AMotionEvent_getMetaState=%d", AMotionEvent_getMetaState(pEvent)); packt_Log_debug("AMotionEvent_getEdgeFlags=%d", AMotionEvent_getEdgeFlags(pEvent)); packt_Log_debug("AMotionEvent_getDownTime=%lld", AMotionEvent_getDownTime(pEvent)); packt_Log_debug("AMotionEvent_getEventTime=%lld", AMotionEvent_getEventTime(pEvent)); packt_Log_debug("AMotionEvent_getXOffset=%f", AMotionEvent_getXOffset(pEvent)); packt_Log_debug("AMotionEvent_getYOffset=%f", AMotionEvent_getYOffset(pEvent)); packt_Log_debug("AMotionEvent_getXPrecision=%f", AMotionEvent_getXPrecision(pEvent)); packt_Log_debug("AMotionEvent_getYPrecision=%f", AMotionEvent_getYPrecision(pEvent)); packt_Log_debug("AMotionEvent_getPointerCount=%d", AMotionEvent_getPointerCount(pEvent)); packt_Log_debug("AMotionEvent_getRawX=%f", AMotionEvent_getRawX(pEvent, 0)); packt_Log_debug("AMotionEvent_getRawY=%f", AMotionEvent_getRawY(pEvent, 0)); packt_Log_debug("AMotionEvent_getX=%f", AMotionEvent_getX(pEvent, 0)); packt_Log_debug("AMotionEvent_getY=%f", AMotionEvent_getY(pEvent, 0)); packt_Log_debug("AMotionEvent_getPressure=%f", AMotionEvent_getPressure(pEvent, 0)); packt_Log_debug("AMotionEvent_getSize=%f", AMotionEvent_getSize(pEvent, 0)); packt_Log_debug("AMotionEvent_getOrientation=%f", AMotionEvent_getOrientation(pEvent, 0)); packt_Log_debug("AMotionEvent_getTouchMajor=%f", AMotionEvent_getTouchMajor(pEvent, 0)); packt_Log_debug("AMotionEvent_getTouchMinor=%f", AMotionEvent_getTouchMinor(pEvent, 0)); #endif const float TOUCH_MAX_RANGE = 65.0f; // In pixels. if (mRefPoint != NULL) { if (AMotionEvent_getAction(pEvent) == AMOTION_EVENT_ACTION_MOVE) { // Needs a conversion to proper coordinates // (origin at bottom/left). Only lMoveY needs it. float lMoveX = AMotionEvent_getX(pEvent, 0) - mRefPoint->mPosX; float lMoveY = mHeight - AMotionEvent_getY(pEvent, 0) - mRefPoint->mPosY; float lMoveRange = sqrt((lMoveX * lMoveX) + (lMoveY * lMoveY)); if (lMoveRange > TOUCH_MAX_RANGE) { float lCropFactor = TOUCH_MAX_RANGE / lMoveRange; lMoveX *= lCropFactor; lMoveY *= lCropFactor; } mHorizontal = lMoveX / TOUCH_MAX_RANGE; mVertical = lMoveY / TOUCH_MAX_RANGE; } else { mHorizontal = 0.0f; mVertical = 0.0f; } } return true; }
/** * @brief * Call this to process the next motion input event */ void AndroidMouseDevice::OnMotionInputEvent(const struct AInputEvent &cAMotionInputEvent) { // Get the number of pointers of data contained in this event const size_t nAndroidPointerCount = AMotionEvent_getPointerCount(&cAMotionInputEvent); if (nAndroidPointerCount) { // Get the current X and Y coordinate of this event for the given pointer index m_fMousePositionX = AMotionEvent_getX(&cAMotionInputEvent, 0); m_fMousePositionY = AMotionEvent_getY(&cAMotionInputEvent, 0); m_fMousePressure = AMotionEvent_getPressure(&cAMotionInputEvent, 0); // Get the combined motion event action code and the action code const int32_t nAndroidCombinedAction = AMotionEvent_getAction(&cAMotionInputEvent); const int32_t nAndroidAction = (nAndroidCombinedAction & AMOTION_EVENT_ACTION_MASK); // Touch end? if (nAndroidAction == AMOTION_EVENT_ACTION_UP) { // Jap, touch end, previous mouse position = current mouse position m_fPreviousMousePositionX = m_fMousePositionX; m_fPreviousMousePositionY = m_fMousePositionY; m_fPreviousMousePressure = m_fMousePressure; // Mouse moved during the current touch? If no, this is handled as a left mouse button click as well. if (!m_bMouseMoved && !m_bLeftMouseButton) { // Check if input device is valid if (m_pDevice) { // Get mouse device Mouse *pMouse = static_cast<Mouse*>(m_pDevice); // Update button if (pMouse->Left.IsPressed() != true) pMouse->Left.SetPressed(true); } } // The left mouse button is now no longer down m_bLeftMouseButton = false; } else { // Touch start? if (nAndroidAction == AMOTION_EVENT_ACTION_DOWN) { // Jap, touch start, previous mouse position = current mouse position m_fPreviousMousePositionX = m_fMousePositionX; m_fPreviousMousePositionY = m_fMousePositionY; m_fPreviousMousePressure = m_fMousePressure; // The mouse was not yet moved m_bMouseMoved = false; // The left mouse button is not pressed m_bLeftMouseButton = false; } // As long as the mouse was not yet moved, a "left mouse button is hold down" can still be generated if (!m_bMouseMoved && !m_bLeftMouseButton) { // Get the past time since the touch has been started (in nanoseconds) const int64_t nPastTime = AMotionEvent_getEventTime(&cAMotionInputEvent) - AMotionEvent_getDownTime(&cAMotionInputEvent); // If the mouse has not been moved for half a second, we go into "left mouse button is hold down"-mode if (nPastTime > 500*1000*1000) { // The left mouse button is now down m_bLeftMouseButton = true; } } } } }
bool InputService::onTrackballEvent(AInputEvent* pEvent) { #ifdef INPUTSERVICE_LOG_EVENTS packt_Log_debug("AMotionEvent_getAction=%d", AMotionEvent_getAction(pEvent)); packt_Log_debug("AMotionEvent_getFlags=%d", AMotionEvent_getFlags(pEvent)); packt_Log_debug("AMotionEvent_getMetaState=%d", AMotionEvent_getMetaState(pEvent)); packt_Log_debug("AMotionEvent_getEdgeFlags=%d", AMotionEvent_getEdgeFlags(pEvent)); packt_Log_debug("AMotionEvent_getDownTime=%lld", AMotionEvent_getDownTime(pEvent)); packt_Log_debug("AMotionEvent_getEventTime=%lld", AMotionEvent_getEventTime(pEvent)); packt_Log_debug("AMotionEvent_getXOffset=%f", AMotionEvent_getXOffset(pEvent)); packt_Log_debug("AMotionEvent_getYOffset=%f", AMotionEvent_getYOffset(pEvent)); packt_Log_debug("AMotionEvent_getXPrecision=%f", AMotionEvent_getXPrecision(pEvent)); packt_Log_debug("AMotionEvent_getYPrecision=%f", AMotionEvent_getYPrecision(pEvent)); packt_Log_debug("AMotionEvent_getPointerCount=%d", AMotionEvent_getPointerCount(pEvent)); packt_Log_debug("AMotionEvent_getRawX=%f", AMotionEvent_getRawX(pEvent, 0)); packt_Log_debug("AMotionEvent_getRawY=%f", AMotionEvent_getRawY(pEvent, 0)); packt_Log_debug("AMotionEvent_getX=%f", AMotionEvent_getX(pEvent, 0)); packt_Log_debug("AMotionEvent_getY=%f", AMotionEvent_getY(pEvent, 0)); packt_Log_debug("AMotionEvent_getPressure=%f", AMotionEvent_getPressure(pEvent, 0)); packt_Log_debug("AMotionEvent_getSize=%f", AMotionEvent_getSize(pEvent, 0)); packt_Log_debug("AMotionEvent_getOrientation=%f", AMotionEvent_getOrientation(pEvent, 0)); packt_Log_debug("AMotionEvent_getTouchMajor=%f", AMotionEvent_getTouchMajor(pEvent, 0)); packt_Log_debug("AMotionEvent_getTouchMinor=%f", AMotionEvent_getTouchMinor(pEvent, 0)); #endif const float ORTHOGONAL_MOVE = 1.0f; const float DIAGONAL_MOVE = 0.707f; const float THRESHOLD = (1/100.0f); if (AMotionEvent_getAction(pEvent) == AMOTION_EVENT_ACTION_MOVE) { float lDirectionX = AMotionEvent_getX(pEvent, 0); float lDirectionY = AMotionEvent_getY(pEvent, 0); float lHorizontal, lVertical; if (lDirectionX < -THRESHOLD) { if (lDirectionY < -THRESHOLD) { lHorizontal = -DIAGONAL_MOVE; lVertical = DIAGONAL_MOVE; } else if (lDirectionY > THRESHOLD) { lHorizontal = -DIAGONAL_MOVE; lVertical = -DIAGONAL_MOVE; } else { lHorizontal = -ORTHOGONAL_MOVE; lVertical = 0.0f; } } else if (lDirectionX > THRESHOLD) { if (lDirectionY < -THRESHOLD) { lHorizontal = DIAGONAL_MOVE; lVertical = DIAGONAL_MOVE; } else if (lDirectionY > THRESHOLD) { lHorizontal = DIAGONAL_MOVE; lVertical = -DIAGONAL_MOVE; } else { lHorizontal = ORTHOGONAL_MOVE; lVertical = 0.0f; } } else if (lDirectionY < -THRESHOLD) { lHorizontal = 0.0f; lVertical = ORTHOGONAL_MOVE; } else if (lDirectionY > THRESHOLD) { lHorizontal = 0.0f; lVertical = -ORTHOGONAL_MOVE; } // Ends movement if there is a counter movement. if ((lHorizontal < 0.0f) && (mHorizontal > 0.0f)) { mHorizontal = 0.0f; } else if ((lHorizontal > 0.0f) && (mHorizontal < 0.0f)) { mHorizontal = 0.0f; } else { mHorizontal = lHorizontal; } if ((lVertical < 0.0f) && (mVertical > 0.0f)) { mVertical = 0.0f; } else if ((lVertical > 0.0f) && (mVertical < 0.0f)) { mVertical = 0.0f; } else { mVertical = lVertical; } } else { mHorizontal = 0.0f; mVertical = 0.0f; } return true; }
/* * 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; }
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; }
/** * 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; }