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