Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / input / motion_event_android.cc
blob3f18f95561b3d650ccc3b3d36bd040f6f12f587f
1 // Copyright 2014 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.
5 #include "content/browser/renderer_host/input/motion_event_android.h"
7 #include <android/input.h>
9 #include "base/android/jni_android.h"
10 #include "base/float_util.h"
11 #include "jni/MotionEvent_jni.h"
12 #include "ui/events/event_constants.h"
14 using base::android::AttachCurrentThread;
15 using namespace JNI_MotionEvent;
17 namespace content {
18 namespace {
20 MotionEventAndroid::Action FromAndroidAction(int android_action) {
21 switch (android_action) {
22 case ACTION_DOWN:
23 return MotionEventAndroid::ACTION_DOWN;
24 case ACTION_UP:
25 return MotionEventAndroid::ACTION_UP;
26 case ACTION_MOVE:
27 return MotionEventAndroid::ACTION_MOVE;
28 case ACTION_CANCEL:
29 return MotionEventAndroid::ACTION_CANCEL;
30 case ACTION_POINTER_DOWN:
31 return MotionEventAndroid::ACTION_POINTER_DOWN;
32 case ACTION_POINTER_UP:
33 return MotionEventAndroid::ACTION_POINTER_UP;
34 default:
35 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
36 << android_action;
38 return MotionEventAndroid::ACTION_CANCEL;
41 MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
42 switch (android_tool_type) {
43 case TOOL_TYPE_UNKNOWN:
44 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
45 case TOOL_TYPE_FINGER:
46 return MotionEventAndroid::TOOL_TYPE_FINGER;
47 case TOOL_TYPE_STYLUS:
48 return MotionEventAndroid::TOOL_TYPE_STYLUS;
49 case TOOL_TYPE_MOUSE:
50 return MotionEventAndroid::TOOL_TYPE_MOUSE;
51 case TOOL_TYPE_ERASER:
52 return MotionEventAndroid::TOOL_TYPE_ERASER;
53 default:
54 NOTREACHED() << "Invalid Android MotionEvent tool type: "
55 << android_tool_type;
57 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
60 int FromAndroidButtonState(int button_state) {
61 int result = 0;
62 if ((button_state & BUTTON_BACK) != 0)
63 result |= MotionEventAndroid::BUTTON_BACK;
64 if ((button_state & BUTTON_FORWARD) != 0)
65 result |= MotionEventAndroid::BUTTON_FORWARD;
66 if ((button_state & BUTTON_PRIMARY) != 0)
67 result |= MotionEventAndroid::BUTTON_PRIMARY;
68 if ((button_state & BUTTON_SECONDARY) != 0)
69 result |= MotionEventAndroid::BUTTON_SECONDARY;
70 if ((button_state & BUTTON_TERTIARY) != 0)
71 result |= MotionEventAndroid::BUTTON_TERTIARY;
72 return result;
75 int FromAndroidMetaState(int meta_state) {
76 int flags = ui::EF_NONE;
77 if ((meta_state & AMETA_SHIFT_ON) != 0)
78 flags |= ui::EF_SHIFT_DOWN;
79 if ((meta_state & AMETA_CTRL_ON) != 0)
80 flags |= ui::EF_CONTROL_DOWN;
81 if ((meta_state & AMETA_ALT_ON) != 0)
82 flags |= ui::EF_ALT_DOWN;
83 if ((meta_state & AMETA_META_ON) != 0)
84 flags |= ui::EF_COMMAND_DOWN;
85 if ((meta_state & AMETA_CAPS_LOCK_ON) != 0)
86 flags |= ui::EF_CAPS_LOCK_DOWN;
87 return flags;
90 base::TimeTicks FromAndroidTime(int64 time_ms) {
91 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
94 float ToValidFloat(float x) {
95 if (base::IsNaN(x))
96 return 0.f;
98 // Wildly large orientation values have been observed in the wild after device
99 // rotation. There's not much we can do in that case other than simply
100 // sanitize results beyond an absurd and arbitrary threshold.
101 if (std::abs(x) > 1e5f)
102 return 0.f;
104 return x;
107 size_t ToValidHistorySize(jint history_size, ui::MotionEvent::Action action) {
108 DCHECK_GE(history_size, 0);
109 // While the spec states that only ACTION_MOVE events should contain
110 // historical entries, it's possible that an embedder could repurpose an
111 // ACTION_MOVE event into a different kind of event. In that case, the
112 // historical values are meaningless, and should not be exposed.
113 if (action != ui::MotionEvent::ACTION_MOVE)
114 return 0;
115 return history_size;
118 } // namespace
120 MotionEventAndroid::Pointer::Pointer(jint id,
121 jfloat pos_x_pixels,
122 jfloat pos_y_pixels,
123 jfloat touch_major_pixels,
124 jfloat touch_minor_pixels,
125 jfloat orientation_rad,
126 jint tool_type)
127 : id(id),
128 pos_x_pixels(pos_x_pixels),
129 pos_y_pixels(pos_y_pixels),
130 touch_major_pixels(touch_major_pixels),
131 touch_minor_pixels(touch_minor_pixels),
132 orientation_rad(orientation_rad),
133 tool_type(tool_type) {
136 MotionEventAndroid::CachedPointer::CachedPointer()
137 : id(0),
138 touch_major(0),
139 touch_minor(0),
140 orientation(0),
141 tool_type(TOOL_TYPE_UNKNOWN) {
144 MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
145 JNIEnv* env,
146 jobject event,
147 jlong time_ms,
148 jint android_action,
149 jint pointer_count,
150 jint history_size,
151 jint action_index,
152 jint android_button_state,
153 jint meta_state,
154 jfloat raw_offset_x_pixels,
155 jfloat raw_offset_y_pixels,
156 const Pointer& pointer0,
157 const Pointer& pointer1)
158 : pix_to_dip_(pix_to_dip),
159 cached_time_(FromAndroidTime(time_ms)),
160 cached_action_(FromAndroidAction(android_action)),
161 cached_pointer_count_(pointer_count),
162 cached_history_size_(ToValidHistorySize(history_size, cached_action_)),
163 cached_action_index_(action_index),
164 cached_button_state_(FromAndroidButtonState(android_button_state)),
165 cached_flags_(FromAndroidMetaState(meta_state)),
166 cached_raw_position_offset_(ToDips(raw_offset_x_pixels),
167 ToDips(raw_offset_y_pixels)) {
168 DCHECK_GT(pointer_count, 0);
170 event_.Reset(env, event);
171 if (cached_pointer_count_ > MAX_POINTERS_TO_CACHE || cached_history_size_ > 0)
172 DCHECK(event_.obj());
174 cached_pointers_[0] = FromAndroidPointer(pointer0);
175 cached_pointers_[1] = FromAndroidPointer(pointer1);
178 MotionEventAndroid::~MotionEventAndroid() {
181 int MotionEventAndroid::GetId() const {
182 return 0;
185 MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
186 return cached_action_;
189 int MotionEventAndroid::GetActionIndex() const {
190 DCHECK(cached_action_ == ACTION_POINTER_UP ||
191 cached_action_ == ACTION_POINTER_DOWN)
192 << "Invalid action for GetActionIndex(): " << cached_action_;
193 DCHECK_GE(cached_action_index_, 0);
194 DCHECK_LT(cached_action_index_, static_cast<int>(cached_pointer_count_));
195 return cached_action_index_;
198 size_t MotionEventAndroid::GetPointerCount() const {
199 return cached_pointer_count_;
202 int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
203 DCHECK_LT(pointer_index, cached_pointer_count_);
204 if (pointer_index < MAX_POINTERS_TO_CACHE)
205 return cached_pointers_[pointer_index].id;
206 return Java_MotionEvent_getPointerId(
207 AttachCurrentThread(), event_.obj(), pointer_index);
210 float MotionEventAndroid::GetX(size_t pointer_index) const {
211 DCHECK_LT(pointer_index, cached_pointer_count_);
212 if (pointer_index < MAX_POINTERS_TO_CACHE)
213 return cached_pointers_[pointer_index].position.x();
214 return ToDips(Java_MotionEvent_getXF_I(
215 AttachCurrentThread(), event_.obj(), pointer_index));
218 float MotionEventAndroid::GetY(size_t pointer_index) const {
219 DCHECK_LT(pointer_index, cached_pointer_count_);
220 if (pointer_index < MAX_POINTERS_TO_CACHE)
221 return cached_pointers_[pointer_index].position.y();
222 return ToDips(Java_MotionEvent_getYF_I(
223 AttachCurrentThread(), event_.obj(), pointer_index));
226 float MotionEventAndroid::GetRawX(size_t pointer_index) const {
227 return GetX(pointer_index) + cached_raw_position_offset_.x();
230 float MotionEventAndroid::GetRawY(size_t pointer_index) const {
231 return GetY(pointer_index) + cached_raw_position_offset_.y();
234 float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
235 DCHECK_LT(pointer_index, cached_pointer_count_);
236 if (pointer_index < MAX_POINTERS_TO_CACHE)
237 return cached_pointers_[pointer_index].touch_major;
238 return ToDips(Java_MotionEvent_getTouchMajorF_I(
239 AttachCurrentThread(), event_.obj(), pointer_index));
242 float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
243 DCHECK_LT(pointer_index, cached_pointer_count_);
244 if (pointer_index < MAX_POINTERS_TO_CACHE)
245 return cached_pointers_[pointer_index].touch_minor;
246 return ToDips(Java_MotionEvent_getTouchMinorF_I(
247 AttachCurrentThread(), event_.obj(), pointer_index));
250 float MotionEventAndroid::GetOrientation(size_t pointer_index) const {
251 DCHECK_LT(pointer_index, cached_pointer_count_);
252 if (pointer_index < MAX_POINTERS_TO_CACHE)
253 return cached_pointers_[pointer_index].orientation;
254 return ToValidFloat(Java_MotionEvent_getOrientationF_I(
255 AttachCurrentThread(), event_.obj(), pointer_index));
258 float MotionEventAndroid::GetPressure(size_t pointer_index) const {
259 DCHECK_LT(pointer_index, cached_pointer_count_);
260 // Note that this early return is a special case exercised only in testing, as
261 // caching the pressure values is not a worthwhile optimization (they're
262 // accessed at most once per event instance).
263 if (!event_.obj())
264 return 0.f;
265 return Java_MotionEvent_getPressureF_I(
266 AttachCurrentThread(), event_.obj(), pointer_index);
269 base::TimeTicks MotionEventAndroid::GetEventTime() const {
270 return cached_time_;
273 size_t MotionEventAndroid::GetHistorySize() const {
274 return cached_history_size_;
277 base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
278 size_t historical_index) const {
279 return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
280 AttachCurrentThread(), event_.obj(), historical_index));
283 float MotionEventAndroid::GetHistoricalTouchMajor(
284 size_t pointer_index,
285 size_t historical_index) const {
286 return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
287 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
290 float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
291 size_t historical_index) const {
292 return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
293 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
296 float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
297 size_t historical_index) const {
298 return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
299 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
302 ui::MotionEvent::ToolType MotionEventAndroid::GetToolType(
303 size_t pointer_index) const {
304 DCHECK_LT(pointer_index, cached_pointer_count_);
305 if (pointer_index < MAX_POINTERS_TO_CACHE)
306 return cached_pointers_[pointer_index].tool_type;
307 return FromAndroidToolType(Java_MotionEvent_getToolType(
308 AttachCurrentThread(), event_.obj(), pointer_index));
311 int MotionEventAndroid::GetButtonState() const {
312 return cached_button_state_;
315 int MotionEventAndroid::GetFlags() const {
316 return cached_flags_;
319 float MotionEventAndroid::ToDips(float pixels) const {
320 return pixels * pix_to_dip_;
323 MotionEventAndroid::CachedPointer MotionEventAndroid::FromAndroidPointer(
324 const Pointer& pointer) const {
325 CachedPointer result;
326 result.id = pointer.id;
327 result.position =
328 gfx::PointF(ToDips(pointer.pos_x_pixels), ToDips(pointer.pos_y_pixels));
329 result.touch_major = ToDips(pointer.touch_major_pixels);
330 result.touch_minor = ToDips(pointer.touch_minor_pixels);
331 result.orientation = ToValidFloat(pointer.orientation_rad);
332 result.tool_type = FromAndroidToolType(pointer.tool_type);
333 return result;
336 // static
337 bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
338 return JNI_MotionEvent::RegisterNativesImpl(env);
341 } // namespace content