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; }