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