// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.content.browser; import android.util.Log; import android.view.MotionEvent; import org.chromium.base.CalledByNative; // This class converts android MotionEvent into an array of touch points so // that they can be forwarded to the renderer process. class TouchPoint { public static final int CONVERSION_ERROR = -1; // Type of motion event to send to the native side. The values originate from their // webkit WebInputEvent counterparts, and are set via initializeConstants(). static int TOUCH_EVENT_TYPE_START; static int TOUCH_EVENT_TYPE_MOVE; static int TOUCH_EVENT_TYPE_END; static int TOUCH_EVENT_TYPE_CANCEL; // Type of motion event to send to the native side. The values originate from their // webkit WebTouchPoint counterparts, and are set via initializeConstants(). private static int TOUCH_POINT_STATE_UNDEFINED; private static int TOUCH_POINT_STATE_RELEASED; private static int TOUCH_POINT_STATE_PRESSED; private static int TOUCH_POINT_STATE_MOVED; private static int TOUCH_POINT_STATE_STATIONARY; private static int TOUCH_POINT_STATE_CANCELLED; private final int mState; private final int mId; private final float mX; private final float mY; private final float mSize; private final float mPressure; TouchPoint(int state, int id, float x, float y, float size, float pressure) { mState = state; mId = id; mX = x; mY = y; mSize = size; mPressure = pressure; } // The following methods are called by native to parse the java TouchPoint // object it has received. @SuppressWarnings("unused") @CalledByNative public int getState() { return mState; } @SuppressWarnings("unused") @CalledByNative public int getId() { return mId; } @SuppressWarnings("unused") @CalledByNative public int getX() { return (int) mX; } @SuppressWarnings("unused") @CalledByNative public int getY() { return (int) mY; } @SuppressWarnings("unused") @CalledByNative public double getSize() { return mSize; } @SuppressWarnings("unused") @CalledByNative public double getPressure() { return mPressure; } // Converts a MotionEvent into an array of touch points. // Returns the WebTouchEvent::Type for the MotionEvent and -1 for failure. public static int createTouchPoints(MotionEvent event, TouchPoint[] pts) { int type; int defaultState; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: type = TOUCH_EVENT_TYPE_START; defaultState = TOUCH_POINT_STATE_PRESSED; break; case MotionEvent.ACTION_MOVE: type = TOUCH_EVENT_TYPE_MOVE; defaultState = TOUCH_POINT_STATE_MOVED; break; case MotionEvent.ACTION_UP: type = TOUCH_EVENT_TYPE_END; defaultState = TOUCH_POINT_STATE_RELEASED; break; case MotionEvent.ACTION_CANCEL: type = TOUCH_EVENT_TYPE_CANCEL; defaultState = TOUCH_POINT_STATE_CANCELLED; break; case MotionEvent.ACTION_POINTER_DOWN: // fall through. case MotionEvent.ACTION_POINTER_UP: type = TOUCH_EVENT_TYPE_MOVE; defaultState = TOUCH_POINT_STATE_STATIONARY; break; default: Log.e("Chromium", "Unknown motion event action: " + event.getActionMasked()); return CONVERSION_ERROR; } for (int i = 0; i < pts.length; ++i) { int state = defaultState; if (defaultState == TOUCH_POINT_STATE_STATIONARY && event.getActionIndex() == i) { // An additional pointer has started or ended. Map this pointer state as // required, and all other pointers as "stationary". state = event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN ? TOUCH_POINT_STATE_PRESSED : TOUCH_POINT_STATE_RELEASED; } pts[i] = new TouchPoint(state, event.getPointerId(i), event.getX(i), event.getY(i), event.getSize(i), event.getPressure(i)); } return type; } // This method is called by native to initialize all the constants from // their counterparts in WebInputEvent and WebTouchPoint. @SuppressWarnings("unused") @CalledByNative private static void initializeConstants( int touchTypeStart, int touchTypeMove, int touchTypeEnd, int touchTypeCancel, int touchPointUndefined, int touchPointReleased, int touchPointPressed, int touchPointMoved, int touchPointStationary, int touchPointCancelled) { TOUCH_EVENT_TYPE_START = touchTypeStart; TOUCH_EVENT_TYPE_MOVE = touchTypeMove; TOUCH_EVENT_TYPE_END = touchTypeEnd; TOUCH_EVENT_TYPE_CANCEL = touchTypeCancel; TOUCH_POINT_STATE_UNDEFINED = touchPointUndefined; TOUCH_POINT_STATE_RELEASED = touchPointReleased; TOUCH_POINT_STATE_PRESSED = touchPointPressed; TOUCH_POINT_STATE_MOVED = touchPointMoved; TOUCH_POINT_STATE_STATIONARY = touchPointStationary; TOUCH_POINT_STATE_CANCELLED = touchPointCancelled; } /** * Initialize the constants to distinct values if they have not been initialized. * During pure-Java testing, initializeConstants() may not be called by native code. * Unit tests should call this method before using the values. */ static void initializeConstantsForTesting() { if (TOUCH_EVENT_TYPE_START == TOUCH_EVENT_TYPE_MOVE) { initializeConstants(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); } } }