Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: content/browser/renderer_host/input/motion_event_android.cc

Issue 1430623004: blimp: Add support for input handling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "content/browser/renderer_host/input/motion_event_android.h"
6
7 #include <android/input.h>
8
9 #include <cmath>
10
11 #include "base/android/jni_android.h"
12 #include "jni/MotionEvent_jni.h"
13 #include "ui/events/base_event_utils.h"
14 #include "ui/events/event_constants.h"
15
16 using base::android::AttachCurrentThread;
17 using namespace JNI_MotionEvent;
18
19 namespace content {
20 namespace {
21
22 MotionEventAndroid::Action FromAndroidAction(int android_action) {
23 switch (android_action) {
24 case ACTION_DOWN:
25 return MotionEventAndroid::ACTION_DOWN;
26 case ACTION_UP:
27 return MotionEventAndroid::ACTION_UP;
28 case ACTION_MOVE:
29 return MotionEventAndroid::ACTION_MOVE;
30 case ACTION_CANCEL:
31 return MotionEventAndroid::ACTION_CANCEL;
32 case ACTION_POINTER_DOWN:
33 return MotionEventAndroid::ACTION_POINTER_DOWN;
34 case ACTION_POINTER_UP:
35 return MotionEventAndroid::ACTION_POINTER_UP;
36 default:
37 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
38 << android_action;
39 };
40 return MotionEventAndroid::ACTION_CANCEL;
41 }
42
43 MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
44 switch (android_tool_type) {
45 case TOOL_TYPE_UNKNOWN:
46 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
47 case TOOL_TYPE_FINGER:
48 return MotionEventAndroid::TOOL_TYPE_FINGER;
49 case TOOL_TYPE_STYLUS:
50 return MotionEventAndroid::TOOL_TYPE_STYLUS;
51 case TOOL_TYPE_MOUSE:
52 return MotionEventAndroid::TOOL_TYPE_MOUSE;
53 case TOOL_TYPE_ERASER:
54 return MotionEventAndroid::TOOL_TYPE_ERASER;
55 default:
56 NOTREACHED() << "Invalid Android MotionEvent tool type: "
57 << android_tool_type;
58 };
59 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
60 }
61
62 int FromAndroidButtonState(int button_state) {
63 int result = 0;
64 if ((button_state & BUTTON_BACK) != 0)
65 result |= MotionEventAndroid::BUTTON_BACK;
66 if ((button_state & BUTTON_FORWARD) != 0)
67 result |= MotionEventAndroid::BUTTON_FORWARD;
68 if ((button_state & BUTTON_PRIMARY) != 0)
69 result |= MotionEventAndroid::BUTTON_PRIMARY;
70 if ((button_state & BUTTON_SECONDARY) != 0)
71 result |= MotionEventAndroid::BUTTON_SECONDARY;
72 if ((button_state & BUTTON_TERTIARY) != 0)
73 result |= MotionEventAndroid::BUTTON_TERTIARY;
74 if ((button_state & BUTTON_STYLUS_PRIMARY) != 0)
75 result |= MotionEventAndroid::BUTTON_STYLUS_PRIMARY;
76 if ((button_state & BUTTON_STYLUS_SECONDARY) != 0)
77 result |= MotionEventAndroid::BUTTON_STYLUS_SECONDARY;
78 return result;
79 }
80
81 int FromAndroidMetaState(int meta_state) {
82 int flags = ui::EF_NONE;
83 if ((meta_state & AMETA_SHIFT_ON) != 0)
84 flags |= ui::EF_SHIFT_DOWN;
85 if ((meta_state & AMETA_CTRL_ON) != 0)
86 flags |= ui::EF_CONTROL_DOWN;
87 if ((meta_state & AMETA_ALT_ON) != 0)
88 flags |= ui::EF_ALT_DOWN;
89 if ((meta_state & AMETA_META_ON) != 0)
90 flags |= ui::EF_COMMAND_DOWN;
91 if ((meta_state & AMETA_CAPS_LOCK_ON) != 0)
92 flags |= ui::EF_CAPS_LOCK_DOWN;
93 return flags;
94 }
95
96 base::TimeTicks FromAndroidTime(int64 time_ms) {
97 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
98 }
99
100 float ToValidFloat(float x) {
101 if (std::isnan(x))
102 return 0.f;
103
104 // Wildly large orientation values have been observed in the wild after device
105 // rotation. There's not much we can do in that case other than simply
106 // sanitize results beyond an absurd and arbitrary threshold.
107 if (std::abs(x) > 1e5f)
108 return 0.f;
109
110 return x;
111 }
112
113 size_t ToValidHistorySize(jint history_size, ui::MotionEvent::Action action) {
114 DCHECK_GE(history_size, 0);
115 // While the spec states that only ACTION_MOVE events should contain
116 // historical entries, it's possible that an embedder could repurpose an
117 // ACTION_MOVE event into a different kind of event. In that case, the
118 // historical values are meaningless, and should not be exposed.
119 if (action != ui::MotionEvent::ACTION_MOVE)
120 return 0;
121 return history_size;
122 }
123
124 } // namespace
125
126 MotionEventAndroid::Pointer::Pointer(jint id,
127 jfloat pos_x_pixels,
128 jfloat pos_y_pixels,
129 jfloat touch_major_pixels,
130 jfloat touch_minor_pixels,
131 jfloat orientation_rad,
132 jint tool_type)
133 : id(id),
134 pos_x_pixels(pos_x_pixels),
135 pos_y_pixels(pos_y_pixels),
136 touch_major_pixels(touch_major_pixels),
137 touch_minor_pixels(touch_minor_pixels),
138 orientation_rad(orientation_rad),
139 tool_type(tool_type) {
140 }
141
142 MotionEventAndroid::CachedPointer::CachedPointer()
143 : id(0),
144 touch_major(0),
145 touch_minor(0),
146 orientation(0),
147 tool_type(TOOL_TYPE_UNKNOWN) {
148 }
149
150 MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
151 JNIEnv* env,
152 jobject event,
153 jlong time_ms,
154 jint android_action,
155 jint pointer_count,
156 jint history_size,
157 jint action_index,
158 jint android_button_state,
159 jint meta_state,
160 jfloat raw_offset_x_pixels,
161 jfloat raw_offset_y_pixels,
162 const Pointer& pointer0,
163 const Pointer& pointer1)
164 : pix_to_dip_(pix_to_dip),
165 cached_time_(FromAndroidTime(time_ms)),
166 cached_action_(FromAndroidAction(android_action)),
167 cached_pointer_count_(pointer_count),
168 cached_history_size_(ToValidHistorySize(history_size, cached_action_)),
169 cached_action_index_(action_index),
170 cached_button_state_(FromAndroidButtonState(android_button_state)),
171 cached_flags_(FromAndroidMetaState(meta_state)),
172 cached_raw_position_offset_(ToDips(raw_offset_x_pixels),
173 ToDips(raw_offset_y_pixels)),
174 unique_event_id_(ui::GetNextTouchEventId()) {
175 DCHECK_GT(pointer_count, 0);
176
177 event_.Reset(env, event);
178 if (cached_pointer_count_ > MAX_POINTERS_TO_CACHE || cached_history_size_ > 0)
179 DCHECK(event_.obj());
180
181 cached_pointers_[0] = FromAndroidPointer(pointer0);
182 cached_pointers_[1] = FromAndroidPointer(pointer1);
183 }
184
185 MotionEventAndroid::~MotionEventAndroid() {
186 }
187
188 uint32 MotionEventAndroid::GetUniqueEventId() const {
189 return unique_event_id_;
190 }
191
192 MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
193 return cached_action_;
194 }
195
196 int MotionEventAndroid::GetActionIndex() const {
197 DCHECK(cached_action_ == ACTION_POINTER_UP ||
198 cached_action_ == ACTION_POINTER_DOWN)
199 << "Invalid action for GetActionIndex(): " << cached_action_;
200 DCHECK_GE(cached_action_index_, 0);
201 DCHECK_LT(cached_action_index_, static_cast<int>(cached_pointer_count_));
202 return cached_action_index_;
203 }
204
205 size_t MotionEventAndroid::GetPointerCount() const {
206 return cached_pointer_count_;
207 }
208
209 int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
210 DCHECK_LT(pointer_index, cached_pointer_count_);
211 if (pointer_index < MAX_POINTERS_TO_CACHE)
212 return cached_pointers_[pointer_index].id;
213 return Java_MotionEvent_getPointerId(
214 AttachCurrentThread(), event_.obj(), pointer_index);
215 }
216
217 float MotionEventAndroid::GetX(size_t pointer_index) const {
218 DCHECK_LT(pointer_index, cached_pointer_count_);
219 if (pointer_index < MAX_POINTERS_TO_CACHE)
220 return cached_pointers_[pointer_index].position.x();
221 return ToDips(Java_MotionEvent_getXF_I(
222 AttachCurrentThread(), event_.obj(), pointer_index));
223 }
224
225 float MotionEventAndroid::GetY(size_t pointer_index) const {
226 DCHECK_LT(pointer_index, cached_pointer_count_);
227 if (pointer_index < MAX_POINTERS_TO_CACHE)
228 return cached_pointers_[pointer_index].position.y();
229 return ToDips(Java_MotionEvent_getYF_I(
230 AttachCurrentThread(), event_.obj(), pointer_index));
231 }
232
233 float MotionEventAndroid::GetRawX(size_t pointer_index) const {
234 return GetX(pointer_index) + cached_raw_position_offset_.x();
235 }
236
237 float MotionEventAndroid::GetRawY(size_t pointer_index) const {
238 return GetY(pointer_index) + cached_raw_position_offset_.y();
239 }
240
241 float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
242 DCHECK_LT(pointer_index, cached_pointer_count_);
243 if (pointer_index < MAX_POINTERS_TO_CACHE)
244 return cached_pointers_[pointer_index].touch_major;
245 return ToDips(Java_MotionEvent_getTouchMajorF_I(
246 AttachCurrentThread(), event_.obj(), pointer_index));
247 }
248
249 float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
250 DCHECK_LT(pointer_index, cached_pointer_count_);
251 if (pointer_index < MAX_POINTERS_TO_CACHE)
252 return cached_pointers_[pointer_index].touch_minor;
253 return ToDips(Java_MotionEvent_getTouchMinorF_I(
254 AttachCurrentThread(), event_.obj(), pointer_index));
255 }
256
257 float MotionEventAndroid::GetOrientation(size_t pointer_index) const {
258 DCHECK_LT(pointer_index, cached_pointer_count_);
259 if (pointer_index < MAX_POINTERS_TO_CACHE)
260 return cached_pointers_[pointer_index].orientation;
261 return ToValidFloat(Java_MotionEvent_getOrientationF_I(
262 AttachCurrentThread(), event_.obj(), pointer_index));
263 }
264
265 float MotionEventAndroid::GetPressure(size_t pointer_index) const {
266 DCHECK_LT(pointer_index, cached_pointer_count_);
267 // Note that this early return is a special case exercised only in testing, as
268 // caching the pressure values is not a worthwhile optimization (they're
269 // accessed at most once per event instance).
270 if (!event_.obj())
271 return 0.f;
272 return Java_MotionEvent_getPressureF_I(
273 AttachCurrentThread(), event_.obj(), pointer_index);
274 }
275
276 base::TimeTicks MotionEventAndroid::GetEventTime() const {
277 return cached_time_;
278 }
279
280 size_t MotionEventAndroid::GetHistorySize() const {
281 return cached_history_size_;
282 }
283
284 base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
285 size_t historical_index) const {
286 return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
287 AttachCurrentThread(), event_.obj(), historical_index));
288 }
289
290 float MotionEventAndroid::GetHistoricalTouchMajor(
291 size_t pointer_index,
292 size_t historical_index) const {
293 return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
294 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
295 }
296
297 float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
298 size_t historical_index) const {
299 return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
300 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
301 }
302
303 float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
304 size_t historical_index) const {
305 return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
306 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
307 }
308
309 ui::MotionEvent::ToolType MotionEventAndroid::GetToolType(
310 size_t pointer_index) const {
311 DCHECK_LT(pointer_index, cached_pointer_count_);
312 if (pointer_index < MAX_POINTERS_TO_CACHE)
313 return cached_pointers_[pointer_index].tool_type;
314 return FromAndroidToolType(Java_MotionEvent_getToolType(
315 AttachCurrentThread(), event_.obj(), pointer_index));
316 }
317
318 int MotionEventAndroid::GetButtonState() const {
319 return cached_button_state_;
320 }
321
322 int MotionEventAndroid::GetFlags() const {
323 return cached_flags_;
324 }
325
326 float MotionEventAndroid::ToDips(float pixels) const {
327 return pixels * pix_to_dip_;
328 }
329
330 MotionEventAndroid::CachedPointer MotionEventAndroid::FromAndroidPointer(
331 const Pointer& pointer) const {
332 CachedPointer result;
333 result.id = pointer.id;
334 result.position =
335 gfx::PointF(ToDips(pointer.pos_x_pixels), ToDips(pointer.pos_y_pixels));
336 result.touch_major = ToDips(pointer.touch_major_pixels);
337 result.touch_minor = ToDips(pointer.touch_minor_pixels);
338 result.orientation = ToValidFloat(pointer.orientation_rad);
339 result.tool_type = FromAndroidToolType(pointer.tool_type);
340 return result;
341 }
342
343 // static
344 bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
345 return JNI_MotionEvent::RegisterNativesImpl(env);
346 }
347
348 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698