//--------------------------------------------------------------------------------
// 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;
}
Example #2
0
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();
}
    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;
    }
	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;
	}