summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/renderer_host/input/motion_event_android.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/renderer_host/input/motion_event_android.cc')
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_android.cc330
1 files changed, 330 insertions, 0 deletions
diff --git a/chromium/content/browser/renderer_host/input/motion_event_android.cc b/chromium/content/browser/renderer_host/input/motion_event_android.cc
new file mode 100644
index 00000000000..7409955bc9c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/motion_event_android.cc
@@ -0,0 +1,330 @@
+// Copyright 2014 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/renderer_host/input/motion_event_android.h"
+
+#include "base/android/jni_android.h"
+#include "jni/MotionEvent_jni.h"
+
+using base::android::AttachCurrentThread;
+using namespace JNI_MotionEvent;
+
+namespace content {
+namespace {
+
+int ToAndroidAction(MotionEventAndroid::Action action) {
+ switch (action) {
+ case MotionEventAndroid::ACTION_DOWN:
+ return ACTION_DOWN;
+ case MotionEventAndroid::ACTION_UP:
+ return ACTION_UP;
+ case MotionEventAndroid::ACTION_MOVE:
+ return ACTION_MOVE;
+ case MotionEventAndroid::ACTION_CANCEL:
+ return ACTION_CANCEL;
+ case MotionEventAndroid::ACTION_POINTER_DOWN:
+ return ACTION_POINTER_DOWN;
+ case MotionEventAndroid::ACTION_POINTER_UP:
+ return ACTION_POINTER_UP;
+ };
+ NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
+ << action;
+ return ACTION_CANCEL;
+}
+
+MotionEventAndroid::Action FromAndroidAction(int android_action) {
+ switch (android_action) {
+ case ACTION_DOWN:
+ return MotionEventAndroid::ACTION_DOWN;
+ case ACTION_UP:
+ return MotionEventAndroid::ACTION_UP;
+ case ACTION_MOVE:
+ return MotionEventAndroid::ACTION_MOVE;
+ case ACTION_CANCEL:
+ return MotionEventAndroid::ACTION_CANCEL;
+ case ACTION_POINTER_DOWN:
+ return MotionEventAndroid::ACTION_POINTER_DOWN;
+ case ACTION_POINTER_UP:
+ return MotionEventAndroid::ACTION_POINTER_UP;
+ default:
+ NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
+ << android_action;
+ };
+ return MotionEventAndroid::ACTION_CANCEL;
+}
+
+int64 ToAndroidTime(base::TimeTicks time) {
+ return (time - base::TimeTicks()).InMilliseconds();
+}
+
+base::TimeTicks FromAndroidTime(int64 time_ms) {
+ return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
+}
+
+} // namespace
+
+MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
+ JNIEnv* env,
+ jobject event,
+ jlong time_ms,
+ jint android_action,
+ jint pointer_count,
+ jint history_size,
+ jint action_index,
+ jfloat pos_x_0_pixels,
+ jfloat pos_y_0_pixels,
+ jfloat pos_x_1_pixels,
+ jfloat pos_y_1_pixels,
+ jint pointer_id_0,
+ jint pointer_id_1,
+ jfloat touch_major_0_pixels,
+ jfloat touch_major_1_pixels,
+ jfloat raw_pos_x_pixels,
+ jfloat raw_pos_y_pixels)
+ : cached_time_(FromAndroidTime(time_ms)),
+ cached_action_(FromAndroidAction(android_action)),
+ cached_pointer_count_(pointer_count),
+ cached_history_size_(history_size),
+ cached_action_index_(action_index),
+ pix_to_dip_(pix_to_dip),
+ should_recycle_(false) {
+ DCHECK_GT(pointer_count, 0);
+ DCHECK_GE(history_size, 0);
+
+ event_.Reset(env, event);
+ DCHECK(event_.obj());
+
+ cached_positions_[0] = ToDips(gfx::PointF(pos_x_0_pixels, pos_y_0_pixels));
+ cached_positions_[1] = ToDips(gfx::PointF(pos_x_1_pixels, pos_y_1_pixels));
+ cached_pointer_ids_[0] = pointer_id_0;
+ cached_pointer_ids_[1] = pointer_id_1;
+ cached_touch_majors_[0] = ToDips(touch_major_0_pixels);
+ cached_touch_majors_[1] = ToDips(touch_major_1_pixels);
+ cached_raw_position_offset_ =
+ ToDips(gfx::PointF(raw_pos_x_pixels, raw_pos_y_pixels)) -
+ cached_positions_[0];
+}
+
+MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
+ JNIEnv* env,
+ jobject event)
+ : cached_time_(FromAndroidTime(Java_MotionEvent_getEventTime(env, event))),
+ cached_action_(
+ FromAndroidAction(Java_MotionEvent_getActionMasked(env, event))),
+ cached_pointer_count_(Java_MotionEvent_getPointerCount(env, event)),
+ cached_history_size_(Java_MotionEvent_getHistorySize(env, event)),
+ cached_action_index_(Java_MotionEvent_getActionIndex(env, event)),
+ pix_to_dip_(pix_to_dip),
+ should_recycle_(true) {
+ event_.Reset(env, event);
+ DCHECK(event_.obj());
+
+ for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
+ if (i < cached_pointer_count_) {
+ cached_positions_[i] =
+ ToDips(gfx::PointF(Java_MotionEvent_getXF_I(env, event, i),
+ Java_MotionEvent_getYF_I(env, event, i)));
+ cached_pointer_ids_[i] = Java_MotionEvent_getPointerId(env, event, i);
+ cached_touch_majors_[i] =
+ ToDips(Java_MotionEvent_getTouchMajorF_I(env, event, i));
+ } else {
+ cached_pointer_ids_[i] = 0;
+ cached_touch_majors_[i] = 0.f;
+ }
+ }
+
+ cached_raw_position_offset_ =
+ ToDips(gfx::PointF(Java_MotionEvent_getRawX(env, event),
+ Java_MotionEvent_getRawY(env, event))) -
+ cached_positions_[0];
+}
+
+MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other)
+ : event_(Obtain(other)),
+ cached_time_(other.cached_time_),
+ cached_action_(other.cached_action_),
+ cached_pointer_count_(other.cached_pointer_count_),
+ cached_history_size_(other.cached_history_size_),
+ cached_action_index_(other.cached_action_index_),
+ cached_raw_position_offset_(other.cached_raw_position_offset_),
+ pix_to_dip_(other.pix_to_dip_),
+ should_recycle_(true) {
+ DCHECK(event_.obj());
+ for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
+ cached_positions_[i] = other.cached_positions_[i];
+ cached_pointer_ids_[i] = other.cached_pointer_ids_[i];
+ cached_touch_majors_[i] = other.cached_touch_majors_[i];
+ }
+}
+
+MotionEventAndroid::~MotionEventAndroid() {
+ if (should_recycle_)
+ Java_MotionEvent_recycle(AttachCurrentThread(), event_.obj());
+}
+
+int MotionEventAndroid::GetId() const {
+ return 0;
+}
+
+MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
+ return cached_action_;
+}
+
+int MotionEventAndroid::GetActionIndex() const {
+ return cached_action_index_;
+}
+
+size_t MotionEventAndroid::GetPointerCount() const {
+ return cached_pointer_count_;
+}
+
+int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_pointer_ids_[pointer_index];
+ return Java_MotionEvent_getPointerId(
+ AttachCurrentThread(), event_.obj(), pointer_index);
+}
+
+float MotionEventAndroid::GetX(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_positions_[pointer_index].x();
+ return ToDips(Java_MotionEvent_getXF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
+float MotionEventAndroid::GetY(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_positions_[pointer_index].y();
+ return ToDips(Java_MotionEvent_getYF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
+float MotionEventAndroid::GetRawX(size_t pointer_index) const {
+ return GetX(pointer_index) + cached_raw_position_offset_.x();
+}
+
+float MotionEventAndroid::GetRawY(size_t pointer_index) const {
+ return GetY(pointer_index) + cached_raw_position_offset_.y();
+}
+
+float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_touch_majors_[pointer_index];
+ return ToDips(Java_MotionEvent_getTouchMajorF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
+float MotionEventAndroid::GetPressure(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ return Java_MotionEvent_getPressureF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index);
+}
+
+base::TimeTicks MotionEventAndroid::GetEventTime() const {
+ return cached_time_;
+}
+
+size_t MotionEventAndroid::GetHistorySize() const {
+ return cached_history_size_;
+}
+
+base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
+ size_t historical_index) const {
+ return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
+ AttachCurrentThread(), event_.obj(), historical_index));
+}
+
+float MotionEventAndroid::GetHistoricalTouchMajor(
+ size_t pointer_index,
+ size_t historical_index) const {
+ return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
+}
+
+float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
+ size_t historical_index) const {
+ return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
+}
+
+float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
+ size_t historical_index) const {
+ return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
+ AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
+}
+
+scoped_ptr<ui::MotionEvent> MotionEventAndroid::Clone() const {
+ return scoped_ptr<MotionEvent>(new MotionEventAndroid(*this));
+}
+
+scoped_ptr<ui::MotionEvent> MotionEventAndroid::Cancel() const {
+ // The input coordinates to |MotionEventAndroid| are always in device pixels,
+ // but the cached coordinates are in DIPs.
+ const gfx::PointF position_pixels =
+ gfx::ScalePoint(cached_positions_[0], 1.f / pix_to_dip_);
+ return scoped_ptr<MotionEvent>(
+ new MotionEventAndroid(pix_to_dip_,
+ AttachCurrentThread(),
+ Obtain(GetDownTime(),
+ GetEventTime(),
+ MotionEventAndroid::ACTION_CANCEL,
+ position_pixels.x(),
+ position_pixels.y()).obj()));
+}
+
+float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
+ return ToDips(Java_MotionEvent_getTouchMinorF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
+float MotionEventAndroid::GetOrientation() const {
+ return Java_MotionEvent_getOrientationF(AttachCurrentThread(), event_.obj());
+}
+
+base::TimeTicks MotionEventAndroid::GetDownTime() const {
+ return FromAndroidTime(
+ Java_MotionEvent_getDownTime(AttachCurrentThread(), event_.obj()));
+}
+
+float MotionEventAndroid::ToDips(float pixels) const {
+ return pixels * pix_to_dip_;
+}
+
+gfx::PointF MotionEventAndroid::ToDips(const gfx::PointF& point_pixels) const {
+ return gfx::ScalePoint(point_pixels, pix_to_dip_);
+}
+
+// static
+bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
+ return JNI_MotionEvent::RegisterNativesImpl(env);
+}
+
+// static
+base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
+ const MotionEventAndroid& event) {
+ return Java_MotionEvent_obtainAVME_AVME(AttachCurrentThread(),
+ event.event_.obj());
+}
+
+// static
+base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
+ base::TimeTicks down_time,
+ base::TimeTicks event_time,
+ Action action,
+ float x_pixels,
+ float y_pixels) {
+ return Java_MotionEvent_obtainAVME_J_J_I_F_F_I(AttachCurrentThread(),
+ ToAndroidTime(down_time),
+ ToAndroidTime(event_time),
+ ToAndroidAction(action),
+ x_pixels,
+ y_pixels,
+ 0);
+}
+
+} // namespace content