1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.content.browser; 6 7 import android.view.MotionEvent; 8 import android.view.MotionEvent.PointerCoords; 9 import android.view.MotionEvent.PointerProperties; 10 11 import org.chromium.base.CalledByNative; 12 import org.chromium.base.JNINamespace; 13 14 /** 15 * Provides a Java-side implementation for injecting synthetic touch events. 16 */ 17 @JNINamespace("content") 18 public class TouchEventSynthesizer { 19 private static final int MAX_NUM_POINTERS = 16; 20 21 private static final int ACTION_START = 0; 22 private static final int ACTION_MOVE = 1; 23 private static final int ACTION_CANCEL = 2; 24 private static final int ACTION_END = 3; 25 26 private final ContentViewCore mContentViewCore; 27 private final PointerProperties[] mPointerProperties; 28 private final PointerCoords[] mPointerCoords; 29 private long mDownTimeInMs; 30 TouchEventSynthesizer(ContentViewCore contentViewCore)31 TouchEventSynthesizer(ContentViewCore contentViewCore) { 32 mContentViewCore = contentViewCore; 33 mPointerProperties = new PointerProperties[MAX_NUM_POINTERS]; 34 mPointerCoords = new PointerCoords[MAX_NUM_POINTERS]; 35 } 36 37 @CalledByNative setPointer(int index, int x, int y, int id)38 void setPointer(int index, int x, int y, int id) { 39 assert (0 <= index && index < MAX_NUM_POINTERS); 40 41 // Convert coordinates from density independent pixels to density dependent pixels. 42 float scaleFactor = mContentViewCore.getRenderCoordinates().getDeviceScaleFactor(); 43 44 PointerCoords coords = new PointerCoords(); 45 coords.x = scaleFactor * x; 46 coords.y = scaleFactor * y; 47 coords.pressure = 1.0f; 48 mPointerCoords[index] = coords; 49 50 PointerProperties properties = new PointerProperties(); 51 properties.id = id; 52 mPointerProperties[index] = properties; 53 } 54 55 @CalledByNative inject(int action, int pointerCount, long timeInMs)56 void inject(int action, int pointerCount, long timeInMs) { 57 switch (action) { 58 case ACTION_START: { 59 mDownTimeInMs = timeInMs; 60 MotionEvent event = MotionEvent.obtain( 61 mDownTimeInMs, timeInMs, MotionEvent.ACTION_DOWN, 1, 62 mPointerProperties, mPointerCoords, 63 0, 0, 1, 1, 0, 0, 0, 0); 64 mContentViewCore.onTouchEvent(event); 65 event.recycle(); 66 67 if (pointerCount > 1) { 68 event = MotionEvent.obtain( 69 mDownTimeInMs, timeInMs, 70 MotionEvent.ACTION_POINTER_DOWN, pointerCount, 71 mPointerProperties, mPointerCoords, 72 0, 0, 1, 1, 0, 0, 0, 0); 73 mContentViewCore.onTouchEvent(event); 74 event.recycle(); 75 } 76 break; 77 } 78 case ACTION_MOVE: { 79 MotionEvent event = MotionEvent.obtain(mDownTimeInMs, timeInMs, 80 MotionEvent.ACTION_MOVE, 81 pointerCount, mPointerProperties, mPointerCoords, 82 0, 0, 1, 1, 0, 0, 0, 0); 83 mContentViewCore.onTouchEvent(event); 84 event.recycle(); 85 break; 86 } 87 case ACTION_CANCEL: { 88 MotionEvent event = MotionEvent.obtain( 89 mDownTimeInMs, timeInMs, MotionEvent.ACTION_CANCEL, 1, 90 mPointerProperties, mPointerCoords, 91 0, 0, 1, 1, 0, 0, 0, 0); 92 mContentViewCore.onTouchEvent(event); 93 event.recycle(); 94 break; 95 } 96 case ACTION_END: { 97 if (pointerCount > 1) { 98 MotionEvent event = MotionEvent.obtain( 99 mDownTimeInMs, timeInMs, MotionEvent.ACTION_POINTER_UP, 100 pointerCount, mPointerProperties, mPointerCoords, 101 0, 0, 1, 1, 0, 0, 0, 0); 102 mContentViewCore.onTouchEvent(event); 103 event.recycle(); 104 } 105 106 MotionEvent event = MotionEvent.obtain( 107 mDownTimeInMs, timeInMs, MotionEvent.ACTION_UP, 1, 108 mPointerProperties, mPointerCoords, 109 0, 0, 1, 1, 0, 0, 0, 0); 110 mContentViewCore.onTouchEvent(event); 111 event.recycle(); 112 break; 113 } 114 } 115 } 116 } 117