diff options
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.cc | 330 |
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 |