// Copyright 2013 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.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
/**
* Provides a Java-side implementation for injecting synthetic touch events.
*/
@JNINamespace("content")
public class TouchEventSynthesizer {
private static final int MAX_NUM_POINTERS = 16;
private static final int ACTION_START = 0;
private static final int ACTION_MOVE = 1;
private static final int ACTION_CANCEL = 2;
private static final int ACTION_END = 3;
private final ContentViewCore mContentViewCore;
private final PointerProperties[] mPointerProperties;
private final PointerCoords[] mPointerCoords;
private long mDownTimeInMs;
TouchEventSynthesizer(ContentViewCore contentViewCore) {
mContentViewCore = contentViewCore;
mPointerProperties = new PointerProperties[MAX_NUM_POINTERS];
mPointerCoords = new PointerCoords[MAX_NUM_POINTERS];
}
@CalledByNative
void setPointer(int index, int x, int y, int id) {
assert (0 <= index && index < MAX_NUM_POINTERS);
// Convert coordinates from density independent pixels to density dependent pixels.
float scaleFactor = mContentViewCore.getRenderCoordinates().getDeviceScaleFactor();
PointerCoords coords = new PointerCoords();
coords.x = scaleFactor * x;
coords.y = scaleFactor * y;
coords.pressure = 1.0f;
mPointerCoords[index] = coords;
PointerProperties properties = new PointerProperties();
properties.id = id;
mPointerProperties[index] = properties;
}
@CalledByNative
void inject(int action, int pointerCount, long timeInMs) {
switch (action) {
case ACTION_START: {
mDownTimeInMs = timeInMs;
MotionEvent event = MotionEvent.obtain(
mDownTimeInMs, timeInMs, MotionEvent.ACTION_DOWN, 1,
mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
if (pointerCount > 1) {
event = MotionEvent.obtain(
mDownTimeInMs, timeInMs,
MotionEvent.ACTION_POINTER_DOWN, pointerCount,
mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
}
break;
}
case ACTION_MOVE: {
MotionEvent event = MotionEvent.obtain(mDownTimeInMs, timeInMs,
MotionEvent.ACTION_MOVE,
pointerCount, mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
break;
}
case ACTION_CANCEL: {
MotionEvent event = MotionEvent.obtain(
mDownTimeInMs, timeInMs, MotionEvent.ACTION_CANCEL, 1,
mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
break;
}
case ACTION_END: {
if (pointerCount > 1) {
MotionEvent event = MotionEvent.obtain(
mDownTimeInMs, timeInMs, MotionEvent.ACTION_POINTER_UP,
pointerCount, mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
}
MotionEvent event = MotionEvent.obtain(
mDownTimeInMs, timeInMs, MotionEvent.ACTION_UP, 1,
mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mContentViewCore.onTouchEvent(event);
event.recycle();
break;
}
}
}
}