1 // Copyright (c) 2012 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 #include "content/browser/android/touch_point.h" 6 7 #include "base/debug/debugger.h" 8 #include "base/logging.h" 9 #include "base/time/time.h" 10 11 #include "jni/TouchPoint_jni.h" 12 13 using WebKit::WebTouchEvent; 14 using WebKit::WebTouchPoint; 15 16 namespace { 17 18 void MaybeAddTouchPoint(JNIEnv* env, 19 jobject pt, 20 float dpi_scale, 21 WebKit::WebTouchEvent& event) { 22 WebTouchPoint::State state = static_cast<WebTouchPoint::State>( 23 Java_TouchPoint_getState(env, pt)); 24 if (state == WebTouchPoint::StateUndefined) 25 return; 26 27 // When generating a cancel event from an event of a different type, the 28 // touch points are out of sync, so we ensure the points are marked as 29 // canceled as well. 30 if (event.type == WebTouchEvent::TouchCancel) 31 state = WebTouchPoint::StateCancelled; 32 33 // Record the current number of points in the WebTouchEvent 34 const int idx = event.touchesLength; 35 DCHECK_LT(idx, WebKit::WebTouchEvent::touchesLengthCap); 36 37 WebTouchPoint wtp; 38 wtp.id = Java_TouchPoint_getId(env, pt); 39 wtp.state = state; 40 wtp.position.x = Java_TouchPoint_getX(env, pt) / dpi_scale; 41 wtp.position.y = Java_TouchPoint_getY(env, pt) / dpi_scale; 42 // TODO(joth): Raw event co-ordinates. 43 wtp.screenPosition = wtp.position; 44 wtp.force = Java_TouchPoint_getPressure(env, pt); 45 46 // TODO(djsollen): WebKit stores touch point size as a pair of radii, which 47 // are integers. We receive touch point size from Android as a float 48 // between 0 and 1 and interpret 'size' as an elliptical area. We convert 49 // size to a radius and then scale up to avoid truncating away all of the 50 // data. W3C spec is for the radii to be in units of screen pixels. Need to 51 // change. 52 const static double PI = 3.1415926; 53 const static double SCALE_FACTOR = 1024.0; 54 const int radius = static_cast<int>( 55 (sqrt(Java_TouchPoint_getSize(env, pt)) / PI) * SCALE_FACTOR); 56 wtp.radiusX = radius / dpi_scale; 57 wtp.radiusY = radius / dpi_scale; 58 // Since our radii are equal, a rotation angle doesn't mean anything. 59 wtp.rotationAngle = 0.0; 60 61 // Add the newly created WebTouchPoint to the event 62 event.touches[idx] = wtp; 63 ++(event.touchesLength); 64 } 65 66 } // namespace 67 68 namespace content { 69 70 void TouchPoint::BuildWebTouchEvent(JNIEnv* env, 71 jint type, 72 jlong time_ms, 73 float dpi_scale, 74 jobjectArray pts, 75 WebKit::WebTouchEvent& event) { 76 event.type = static_cast<WebTouchEvent::Type>(type); 77 event.timeStampSeconds = 78 static_cast<double>(time_ms) / base::Time::kMillisecondsPerSecond; 79 int arrayLength = env->GetArrayLength(pts); 80 // Loop until either all of the input points have been consumed or the output 81 // array has been filled 82 for (int i = 0; i < arrayLength; i++) { 83 jobject pt = env->GetObjectArrayElement(pts, i); 84 MaybeAddTouchPoint(env, pt, dpi_scale, event); 85 if (event.touchesLength >= event.touchesLengthCap) 86 break; 87 } 88 DCHECK_GT(event.touchesLength, 0U); 89 } 90 91 static void RegisterConstants(JNIEnv* env) { 92 Java_TouchPoint_initializeConstants( 93 env, 94 WebKit::WebTouchEvent::TouchStart, 95 WebKit::WebTouchEvent::TouchMove, 96 WebKit::WebTouchEvent::TouchEnd, 97 WebKit::WebTouchEvent::TouchCancel, 98 WebKit::WebTouchPoint::StateUndefined, 99 WebKit::WebTouchPoint::StateReleased, 100 WebKit::WebTouchPoint::StatePressed, 101 WebKit::WebTouchPoint::StateMoved, 102 WebKit::WebTouchPoint::StateStationary, 103 WebKit::WebTouchPoint::StateCancelled); 104 } 105 106 bool RegisterTouchPoint(JNIEnv* env) { 107 if (!RegisterNativesImpl(env)) 108 return false; 109 110 RegisterConstants(env); 111 112 return true; 113 } 114 115 } // namespace content 116