diff options
-rw-r--r-- | content/app/android/content_jni_registrar.cc | 2 | ||||
-rw-r--r-- | content/browser/android/touch_point.cc | 108 | ||||
-rw-r--r-- | content/browser/android/touch_point.h | 27 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/content_jni.gypi | 2 | ||||
-rw-r--r-- | content/public/android/java/org/chromium/content/browser/TouchPoint.java | 144 |
6 files changed, 285 insertions, 0 deletions
diff --git a/content/app/android/content_jni_registrar.cc b/content/app/android/content_jni_registrar.cc index a9fe08d..9f858b9 100644 --- a/content/app/android/content_jni_registrar.cc +++ b/content/app/android/content_jni_registrar.cc @@ -14,6 +14,7 @@ #include "content/browser/android/device_info.h" #include "content/browser/android/download_controller.h" #include "content/browser/android/sandboxed_process_launcher.h" +#include "content/browser/android/touch_point.h" #include "content/common/android/command_line.h" #include "content/common/android/surface_callback.h" #include "content/common/android/trace_event_binding.h" @@ -32,6 +33,7 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = { { "SandboxedProcessLauncher", content::RegisterSandboxedProcessLauncher }, { "SandboxedProcessService", content::RegisterSandboxedProcessService }, { "SurfaceCallback", content::RegisterSurfaceCallback }, + { "TouchPoint", content::RegisterTouchPoint }, { "TraceEvent", RegisterTraceEvent }, }; diff --git a/content/browser/android/touch_point.cc b/content/browser/android/touch_point.cc new file mode 100644 index 0000000..17d888d --- /dev/null +++ b/content/browser/android/touch_point.cc @@ -0,0 +1,108 @@ +// 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. + +#include "content/browser/android/touch_point.h" + +#include "base/debug/debugger.h" +#include "base/time.h" +#include "base/logging.h" + +#include "jni/touch_point_jni.h" + +using WebKit::WebTouchEvent; +using WebKit::WebTouchPoint; + +namespace { + +void MaybeAddTouchPoint(JNIEnv* env, jobject pt, WebKit::WebTouchEvent& event) { + WebTouchPoint::State state = static_cast<WebTouchPoint::State>( + Java_TouchPoint_getState(env, pt)); + if (state == WebTouchPoint::StateUndefined) + return; + + // When generating a cancel event from an event of a different type, the + // touch points are out of sync, so we ensure the points are marked as + // canceled as well. + if (event.type == WebTouchEvent::TouchCancel) + state = WebTouchPoint::StateCancelled; + + // Record the current number of points in the WebTouchEvent + const int idx = event.touchesLength; + DCHECK_LT(idx, WebKit::WebTouchEvent::touchesLengthCap); + + WebTouchPoint wtp; + wtp.id = Java_TouchPoint_getId(env, pt); + wtp.state = state; + wtp.position.x = Java_TouchPoint_getX(env, pt); + wtp.position.y = Java_TouchPoint_getY(env, pt); + // TODO(joth): Raw event co-ordinates. + wtp.screenPosition = wtp.position; + wtp.force = Java_TouchPoint_getPressure(env, pt); + + // TODO(djsollen): WebKit stores touch point size as a pair of radii, which + // are integers. We receive touch point size from Android as a float + // between 0 and 1 and interpret 'size' as an elliptical area. We convert + // size to a radius and then scale up to avoid truncating away all of the + // data. W3C spec is for the radii to be in units of screen pixels. Need to + // change. + const static double PI = 3.1415926; + const static double SCALE_FACTOR = 1024.0; + const int radius = static_cast<int>( + (sqrt(Java_TouchPoint_getSize(env, pt)) / PI) * SCALE_FACTOR); + wtp.radiusX = radius; + wtp.radiusY = radius; + // Since our radii are equal, a rotation angle doesn't mean anything. + wtp.rotationAngle = 0.0; + + // Add the newly created WebTouchPoint to the event + event.touches[idx] = wtp; + ++(event.touchesLength); +} + +} // namespace + +namespace content { + +void TouchPoint::BuildWebTouchEvent(JNIEnv* env, jint type, jlong time_ms, + jobjectArray pts, WebKit::WebTouchEvent& event) { + event.type = static_cast<WebTouchEvent::Type>(type); + event.timeStampSeconds = + static_cast<double>(time_ms) / base::Time::kMillisecondsPerSecond; + int arrayLength = env->GetArrayLength(pts); + // Loop until either all of the input points have been consumed or the output + // array has been filled + for (int i = 0; i < arrayLength; i++) { + jobject pt = env->GetObjectArrayElement(pts, i); + MaybeAddTouchPoint(env, pt, event); + if (event.touchesLength >= event.touchesLengthCap) + break; + } + DCHECK_GT(event.touchesLength, 0U); +} + +static void RegisterConstants(JNIEnv* env) { + Java_TouchPoint_initializeConstants( + env, + WebKit::WebTouchEvent::TouchStart, + WebKit::WebTouchEvent::TouchMove, + WebKit::WebTouchEvent::TouchEnd, + WebKit::WebTouchEvent::TouchCancel, + WebKit::WebTouchPoint::StateUndefined, + WebKit::WebTouchPoint::StateReleased, + WebKit::WebTouchPoint::StatePressed, + WebKit::WebTouchPoint::StateMoved, + WebKit::WebTouchPoint::StateStationary, + WebKit::WebTouchPoint::StateCancelled); +} + +bool RegisterTouchPoint(JNIEnv* env) { + if (!RegisterNativesImpl(env)) + return false; + + RegisterConstants(env); + + return true; +} + +} // namespace content diff --git a/content/browser/android/touch_point.h b/content/browser/android/touch_point.h new file mode 100644 index 0000000..7bbc379 --- /dev/null +++ b/content/browser/android/touch_point.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef CONTENT_BROWSER_ANDROID_TOUCH_POINT_H_ +#define CONTENT_BROWSER_ANDROID_TOUCH_POINT_H_ +#pragma once + +#include <jni.h> + +#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" + +namespace content { + +// This class provides a helper method to convert a java object array of touch +// events into a WebKit::WebTouchEvent. +class TouchPoint { + public: + static void BuildWebTouchEvent(JNIEnv* env, jint type, jlong time_ms, + jobjectArray pts, WebKit::WebTouchEvent& event); +}; + +bool RegisterTouchPoint(JNIEnv* env); + +} // namespace content + +#endif // CONTENT_BROWSER_ANDROID_CHROME_VIEW_H_ diff --git a/content/content_browser.gypi b/content/content_browser.gypi index ce0439d..4d8dbd7 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -201,6 +201,8 @@ 'browser/android/download_controller.h', 'browser/android/sandboxed_process_launcher.cc', 'browser/android/sandboxed_process_launcher.h', + 'browser/android/touch_point.cc', + 'browser/android/touch_point.h', 'browser/appcache/appcache_dispatcher_host.cc', 'browser/appcache/appcache_dispatcher_host.h', 'browser/appcache/appcache_frontend_proxy.cc', diff --git a/content/content_jni.gypi b/content/content_jni.gypi index 0a97966..0ab5255 100644 --- a/content/content_jni.gypi +++ b/content/content_jni.gypi @@ -20,6 +20,7 @@ 'public/android/java/org/chromium/content/browser/DownloadController.java', 'public/android/java/org/chromium/content/browser/LocationProvider.java', 'public/android/java/org/chromium/content/browser/SandboxedProcessLauncher.java', + 'public/android/java/org/chromium/content/browser/TouchPoint.java', 'public/android/java/org/chromium/content/common/CommandLine.java', 'public/android/java/org/chromium/content/common/SurfaceCallback.java', 'public/android/java/org/chromium/content/common/TraceEvent.java', @@ -36,6 +37,7 @@ '<(SHARED_INTERMEDIATE_DIR)/content/jni/download_controller_jni.h', '<(SHARED_INTERMEDIATE_DIR)/content/jni/location_provider_jni.h', '<(SHARED_INTERMEDIATE_DIR)/content/jni/sandboxed_process_launcher_jni.h', + '<(SHARED_INTERMEDIATE_DIR)/content/jni/touch_point_jni.h', '<(SHARED_INTERMEDIATE_DIR)/content/jni/command_line_jni.h', '<(SHARED_INTERMEDIATE_DIR)/content/jni/surface_callback_jni.h', '<(SHARED_INTERMEDIATE_DIR)/content/jni/trace_event_jni.h', diff --git a/content/public/android/java/org/chromium/content/browser/TouchPoint.java b/content/public/android/java/org/chromium/content/browser/TouchPoint.java new file mode 100644 index 0000000..66e35b1 --- /dev/null +++ b/content/public/android/java/org/chromium/content/browser/TouchPoint.java @@ -0,0 +1,144 @@ +// 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(). + private static int TOUCH_EVENT_TYPE_START; + private static int TOUCH_EVENT_TYPE_MOVE; + private static int TOUCH_EVENT_TYPE_END; + private 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; + } +} |