blob: e9b2434bd1ba543815424addba7f59c1526769c4 [file] [log] [blame]
jinsukkim5c3a1202017-03-10 00:02:141// Copyright 2017 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 "ui/android/event_forwarder.h"
6
jinsukkimda11b4d2017-05-26 06:44:417#include "base/android/jni_array.h"
jinsukkimb40b402c2017-03-29 09:39:088#include "base/metrics/histogram_macros.h"
jinsukkim5c3a1202017-03-10 00:02:149#include "jni/EventForwarder_jni.h"
10#include "ui/android/view_android.h"
Michael Thiessene70dd08d2017-12-21 20:59:1111#include "ui/android/window_android.h"
jinsukkimda11b4d2017-05-26 06:44:4112#include "ui/base/ui_base_switches_util.h"
13#include "ui/events/android/drag_event_android.h"
Jinsuk Kim63626ce42017-11-23 06:19:5614#include "ui/events/android/gesture_event_android.h"
Jinsuk Kime6c2eafb2018-02-23 01:10:3615#include "ui/events/android/gesture_event_type.h"
Jinsuk Kim5a3ae93c2018-04-25 21:49:0616#include "ui/events/android/key_event_android.h"
jinsukkim5c3a1202017-03-10 00:02:1417#include "ui/events/android/motion_event_android.h"
jinsukkimb40b402c2017-03-29 09:39:0818#include "ui/events/base_event_utils.h"
jinsukkim5c3a1202017-03-10 00:02:1419
20namespace ui {
21
jinsukkimda11b4d2017-05-26 06:44:4122using base::android::AppendJavaStringArrayToStringVector;
jinsukkim5c3a1202017-03-10 00:02:1423using base::android::JavaParamRef;
24using base::android::ScopedJavaLocalRef;
25
26EventForwarder::EventForwarder(ViewAndroid* view) : view_(view) {}
27
28EventForwarder::~EventForwarder() {
29 if (!java_obj_.is_null()) {
30 Java_EventForwarder_destroy(base::android::AttachCurrentThread(),
31 java_obj_);
32 java_obj_.Reset();
33 }
34}
35
36ScopedJavaLocalRef<jobject> EventForwarder::GetJavaObject() {
37 if (java_obj_.is_null()) {
jinsukkimda11b4d2017-05-26 06:44:4138 JNIEnv* env = base::android::AttachCurrentThread();
jinsukkim5c3a1202017-03-10 00:02:1439 java_obj_.Reset(
jinsukkimda11b4d2017-05-26 06:44:4140 Java_EventForwarder_create(env, reinterpret_cast<intptr_t>(this),
41 switches::IsTouchDragDropEnabled()));
jinsukkim5c3a1202017-03-10 00:02:1442 }
43 return ScopedJavaLocalRef<jobject>(java_obj_);
44}
45
Michael Thiessene70dd08d2017-12-21 20:59:1146ScopedJavaLocalRef<jobject> EventForwarder::GetJavaWindowAndroid(
47 JNIEnv* env,
48 const JavaParamRef<jobject>& obj) {
49 return view_->GetWindowAndroid()->GetJavaObject();
50}
51
jinsukkim5c3a1202017-03-10 00:02:1452jboolean EventForwarder::OnTouchEvent(JNIEnv* env,
53 const JavaParamRef<jobject>& obj,
54 const JavaParamRef<jobject>& motion_event,
55 jlong time_ms,
56 jint android_action,
57 jint pointer_count,
58 jint history_size,
59 jint action_index,
60 jfloat pos_x_0,
61 jfloat pos_y_0,
62 jfloat pos_x_1,
63 jfloat pos_y_1,
64 jint pointer_id_0,
65 jint pointer_id_1,
66 jfloat touch_major_0,
67 jfloat touch_major_1,
68 jfloat touch_minor_0,
69 jfloat touch_minor_1,
70 jfloat orientation_0,
71 jfloat orientation_1,
72 jfloat tilt_0,
73 jfloat tilt_1,
74 jfloat raw_pos_x,
75 jfloat raw_pos_y,
76 jint android_tool_type_0,
77 jint android_tool_type_1,
78 jint android_button_state,
79 jint android_meta_state,
Jinsuk Kim2b859472017-08-30 02:47:1980 jboolean for_touch_handle) {
jinsukkim5c3a1202017-03-10 00:02:1481 ui::MotionEventAndroid::Pointer pointer0(
82 pointer_id_0, pos_x_0, pos_y_0, touch_major_0, touch_minor_0,
83 orientation_0, tilt_0, android_tool_type_0);
84 ui::MotionEventAndroid::Pointer pointer1(
85 pointer_id_1, pos_x_1, pos_y_1, touch_major_1, touch_minor_1,
86 orientation_1, tilt_1, android_tool_type_1);
87 ui::MotionEventAndroid event(
jinsukkimb40b402c2017-03-29 09:39:0888 env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f,
89 time_ms, android_action, pointer_count, history_size, action_index,
jinsukkim5c3a1202017-03-10 00:02:1490 0 /* action_button */, android_button_state, android_meta_state,
Jinsuk Kim2b859472017-08-30 02:47:1991 raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0,
92 &pointer1);
93 return view_->OnTouchEvent(event);
jinsukkim5c3a1202017-03-10 00:02:1494}
95
96void EventForwarder::OnMouseEvent(JNIEnv* env,
97 const JavaParamRef<jobject>& obj,
98 jlong time_ms,
99 jint android_action,
100 jfloat x,
101 jfloat y,
102 jint pointer_id,
103 jfloat orientation,
104 jfloat pressure,
105 jfloat tilt,
106 jint android_action_button,
107 jint android_button_state,
108 jint android_meta_state,
109 jint android_tool_type) {
110 // Construct a motion_event object minimally, only to convert the raw
111 // parameters to ui::MotionEvent values. Since we used only the cached values
112 // at index=0, it is okay to even pass a null event to the constructor.
113 ui::MotionEventAndroid::Pointer pointer(
114 pointer_id, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */,
115 orientation, tilt, android_tool_type);
116 ui::MotionEventAndroid event(
jinsukkimb40b402c2017-03-29 09:39:08117 env, nullptr /* event */, 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f,
118 time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */,
jinsukkim5c3a1202017-03-10 00:02:14119 0 /* action_index */, android_action_button, android_button_state,
120 android_meta_state, 0 /* raw_offset_x_pixels */,
Jinsuk Kim2b859472017-08-30 02:47:19121 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer,
122 nullptr);
jinsukkim5c3a1202017-03-10 00:02:14123 view_->OnMouseEvent(event);
124}
125
jinsukkimb40b402c2017-03-29 09:39:08126void EventForwarder::OnMouseWheelEvent(JNIEnv* env,
127 const JavaParamRef<jobject>& obj,
128 jlong time_ms,
129 jfloat x,
130 jfloat y,
131 jfloat ticks_x,
Jinsuk Kim00e46982018-03-07 07:54:36132 jfloat ticks_y) {
jinsukkimb40b402c2017-03-29 09:39:08133 if (!ticks_x && !ticks_y)
134 return;
135
136 // Compute Event.Latency.OS.MOUSE_WHEEL histogram.
137 base::TimeTicks current_time = ui::EventTimeForNow();
138 base::TimeTicks event_time =
139 base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
140 base::TimeDelta delta = current_time - event_time;
141 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.MOUSE_WHEEL",
142 delta.InMicroseconds(), 1, 1000000, 50);
143 ui::MotionEventAndroid::Pointer pointer(
144 0, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */, 0.0f, 0.0f, 0);
Jinsuk Kim00e46982018-03-07 07:54:36145
146 auto* window = view_->GetWindowAndroid();
Jinsuk Kim4583ba52018-03-14 04:58:56147 float pixels_per_tick =
148 window ? window->mouse_wheel_scroll_factor()
149 : kDefaultMouseWheelTickMultiplier * view_->GetDipScale();
Jinsuk Kim2b859472017-08-30 02:47:19150 ui::MotionEventAndroid event(
151 env, nullptr, 1.f / view_->GetDipScale(), ticks_x, ticks_y,
152 pixels_per_tick, time_ms, 0 /* action */, 1 /* pointer_count */,
153 0 /* history_size */, 0 /* action_index */, 0, 0, 0,
154 0 /* raw_offset_x_pixels */, 0 /* raw_offset_y_pixels */,
155 false /* for_touch_handle */, &pointer, nullptr);
jinsukkimb40b402c2017-03-29 09:39:08156
157 view_->OnMouseWheelEvent(event);
158}
159
jinsukkimda11b4d2017-05-26 06:44:41160void EventForwarder::OnDragEvent(JNIEnv* env,
161 const JavaParamRef<jobject>& jobj,
162 jint action,
163 jint x,
164 jint y,
165 jint screen_x,
166 jint screen_y,
167 const JavaParamRef<jobjectArray>& j_mimeTypes,
168 const JavaParamRef<jstring>& j_content) {
169 float dip_scale = view_->GetDipScale();
170 gfx::PointF location(x / dip_scale, y / dip_scale);
171 gfx::PointF root_location(screen_x / dip_scale, screen_y / dip_scale);
172 std::vector<base::string16> mime_types;
173 AppendJavaStringArrayToStringVector(env, j_mimeTypes, &mime_types);
174
175 DragEventAndroid event(env, action, location, root_location, mime_types,
176 j_content.obj());
177 view_->OnDragEvent(event);
178}
179
Jinsuk Kim5a3ae93c2018-04-25 21:49:06180jboolean EventForwarder::OnGestureEvent(JNIEnv* env,
181 const JavaParamRef<jobject>& jobj,
182 jint type,
183 jlong time_ms,
184 jfloat scale) {
Jinsuk Kim63626ce42017-11-23 06:19:56185 float dip_scale = view_->GetDipScale();
186 auto size = view_->GetSize();
187 float x = size.width() / 2;
188 float y = size.height() / 2;
189 gfx::PointF root_location =
190 ScalePoint(view_->GetLocationOnScreen(x, y), 1.f / dip_scale);
Jinsuk Kime6c2eafb2018-02-23 01:10:36191 return view_->OnGestureEvent(GestureEventAndroid(
192 type, gfx::PointF(x / dip_scale, y / dip_scale), root_location, time_ms,
193 scale, 0, 0, 0, 0, false, false));
194}
195
Jinsuk Kim5a3ae93c2018-04-25 21:49:06196jboolean EventForwarder::OnKeyUp(JNIEnv* env,
197 const JavaParamRef<jobject>& obj,
198 const JavaParamRef<jobject>& key_event,
199 jint key_code) {
200 return view_->OnKeyUp(KeyEventAndroid(env, key_event, key_code));
201}
202
203jboolean EventForwarder::DispatchKeyEvent(
204 JNIEnv* env,
205 const JavaParamRef<jobject>& obj,
206 const JavaParamRef<jobject>& key_event) {
207 return view_->DispatchKeyEvent(KeyEventAndroid(env, key_event, 0));
208}
209
Jinsuk Kim78627332018-03-05 23:33:39210void EventForwarder::Scroll(JNIEnv* env,
211 const JavaParamRef<jobject>& jobj,
212 jlong time_ms,
213 jfloat delta_x,
214 jfloat delta_y) {
215 float dip_scale = view_->GetDipScale();
216 float delta_xdip = delta_x / dip_scale;
217 float delta_ydip = delta_y / dip_scale;
218 view_->OnGestureEvent(GestureEventAndroid(
219 GESTURE_EVENT_TYPE_SCROLL_START, gfx::PointF(), gfx::PointF(), time_ms, 0,
220 -delta_xdip, -delta_ydip, 0, 0, true, false));
221 view_->OnGestureEvent(GestureEventAndroid(
222 GESTURE_EVENT_TYPE_SCROLL_BY, gfx::PointF(), gfx::PointF(), time_ms, 0,
223 -delta_xdip, -delta_ydip, 0, 0, true, false));
224 view_->OnGestureEvent(GestureEventAndroid(
225 GESTURE_EVENT_TYPE_SCROLL_END, gfx::PointF(), gfx::PointF(), time_ms, 0,
226 -delta_xdip, -delta_ydip, 0, 0, true, false));
227}
228
229void EventForwarder::DoubleTap(JNIEnv* env,
230 const JavaParamRef<jobject>& jobj,
231 jlong time_ms,
232 jint x,
233 jint y) {
234 float dip_scale = view_->GetDipScale();
235 view_->OnGestureEvent(GestureEventAndroid(
236 GESTURE_EVENT_TYPE_DOUBLE_TAP, gfx::PointF(x / dip_scale, y / dip_scale),
237 gfx::PointF(), time_ms, 0, 0, 0, 0, 0, true, false));
238}
239
240void EventForwarder::StartFling(JNIEnv* env,
241 const JavaParamRef<jobject>& jobj,
242 jlong time_ms,
243 jfloat velocity_x,
244 jfloat velocity_y,
245 jboolean synthetic_scroll) {
246 CancelFling(env, jobj, time_ms);
Jinsuk Kime6c2eafb2018-02-23 01:10:36247 if (velocity_x == 0 && velocity_y == 0)
248 return;
249 // Use velocity as delta in scroll event.
250 view_->OnGestureEvent(GestureEventAndroid(
251 GESTURE_EVENT_TYPE_SCROLL_START, gfx::PointF(), gfx::PointF(), time_ms, 0,
252 velocity_x, velocity_y, 0, 0, true, synthetic_scroll));
253 view_->OnGestureEvent(GestureEventAndroid(
254 GESTURE_EVENT_TYPE_FLING_START, gfx::PointF(), gfx::PointF(), time_ms, 0,
255 0, 0, velocity_x, velocity_y, true, synthetic_scroll));
256}
257
Jinsuk Kim78627332018-03-05 23:33:39258void EventForwarder::CancelFling(JNIEnv* env,
259 const JavaParamRef<jobject>& jobj,
260 jlong time_ms) {
Jinsuk Kime6c2eafb2018-02-23 01:10:36261 view_->OnGestureEvent(
262 GestureEventAndroid(GESTURE_EVENT_TYPE_FLING_CANCEL, gfx::PointF(),
263 gfx::PointF(), time_ms, 0, 0, 0, 0, 0, false, false));
Jinsuk Kim63626ce42017-11-23 06:19:56264}
265
jinsukkim5c3a1202017-03-10 00:02:14266} // namespace ui