blob: 7be0652c95d60f39c828db48f23fcd838693a6ad [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"
jinsukkim5c3a1202017-03-10 00:02:1416#include "ui/events/android/motion_event_android.h"
jinsukkimb40b402c2017-03-29 09:39:0817#include "ui/events/base_event_utils.h"
jinsukkim5c3a1202017-03-10 00:02:1418
19namespace ui {
20
jinsukkimda11b4d2017-05-26 06:44:4121using base::android::AppendJavaStringArrayToStringVector;
jinsukkim5c3a1202017-03-10 00:02:1422using base::android::JavaParamRef;
23using base::android::ScopedJavaLocalRef;
24
25EventForwarder::EventForwarder(ViewAndroid* view) : view_(view) {}
26
27EventForwarder::~EventForwarder() {
28 if (!java_obj_.is_null()) {
29 Java_EventForwarder_destroy(base::android::AttachCurrentThread(),
30 java_obj_);
31 java_obj_.Reset();
32 }
33}
34
35ScopedJavaLocalRef<jobject> EventForwarder::GetJavaObject() {
36 if (java_obj_.is_null()) {
jinsukkimda11b4d2017-05-26 06:44:4137 JNIEnv* env = base::android::AttachCurrentThread();
jinsukkim5c3a1202017-03-10 00:02:1438 java_obj_.Reset(
jinsukkimda11b4d2017-05-26 06:44:4139 Java_EventForwarder_create(env, reinterpret_cast<intptr_t>(this),
40 switches::IsTouchDragDropEnabled()));
jinsukkim5c3a1202017-03-10 00:02:1441 }
42 return ScopedJavaLocalRef<jobject>(java_obj_);
43}
44
Michael Thiessene70dd08d2017-12-21 20:59:1145ScopedJavaLocalRef<jobject> EventForwarder::GetJavaWindowAndroid(
46 JNIEnv* env,
47 const JavaParamRef<jobject>& obj) {
48 return view_->GetWindowAndroid()->GetJavaObject();
49}
50
jinsukkim5c3a1202017-03-10 00:02:1451jboolean EventForwarder::OnTouchEvent(JNIEnv* env,
52 const JavaParamRef<jobject>& obj,
53 const JavaParamRef<jobject>& motion_event,
54 jlong time_ms,
55 jint android_action,
56 jint pointer_count,
57 jint history_size,
58 jint action_index,
59 jfloat pos_x_0,
60 jfloat pos_y_0,
61 jfloat pos_x_1,
62 jfloat pos_y_1,
63 jint pointer_id_0,
64 jint pointer_id_1,
65 jfloat touch_major_0,
66 jfloat touch_major_1,
67 jfloat touch_minor_0,
68 jfloat touch_minor_1,
69 jfloat orientation_0,
70 jfloat orientation_1,
71 jfloat tilt_0,
72 jfloat tilt_1,
73 jfloat raw_pos_x,
74 jfloat raw_pos_y,
75 jint android_tool_type_0,
76 jint android_tool_type_1,
77 jint android_button_state,
78 jint android_meta_state,
Jinsuk Kim2b859472017-08-30 02:47:1979 jboolean for_touch_handle) {
jinsukkim5c3a1202017-03-10 00:02:1480 ui::MotionEventAndroid::Pointer pointer0(
81 pointer_id_0, pos_x_0, pos_y_0, touch_major_0, touch_minor_0,
82 orientation_0, tilt_0, android_tool_type_0);
83 ui::MotionEventAndroid::Pointer pointer1(
84 pointer_id_1, pos_x_1, pos_y_1, touch_major_1, touch_minor_1,
85 orientation_1, tilt_1, android_tool_type_1);
86 ui::MotionEventAndroid event(
jinsukkimb40b402c2017-03-29 09:39:0887 env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f,
88 time_ms, android_action, pointer_count, history_size, action_index,
jinsukkim5c3a1202017-03-10 00:02:1489 0 /* action_button */, android_button_state, android_meta_state,
Jinsuk Kim2b859472017-08-30 02:47:1990 raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0,
91 &pointer1);
92 return view_->OnTouchEvent(event);
jinsukkim5c3a1202017-03-10 00:02:1493}
94
95void EventForwarder::OnMouseEvent(JNIEnv* env,
96 const JavaParamRef<jobject>& obj,
97 jlong time_ms,
98 jint android_action,
99 jfloat x,
100 jfloat y,
101 jint pointer_id,
102 jfloat orientation,
103 jfloat pressure,
104 jfloat tilt,
105 jint android_action_button,
106 jint android_button_state,
107 jint android_meta_state,
108 jint android_tool_type) {
109 // Construct a motion_event object minimally, only to convert the raw
110 // parameters to ui::MotionEvent values. Since we used only the cached values
111 // at index=0, it is okay to even pass a null event to the constructor.
112 ui::MotionEventAndroid::Pointer pointer(
113 pointer_id, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */,
114 orientation, tilt, android_tool_type);
115 ui::MotionEventAndroid event(
jinsukkimb40b402c2017-03-29 09:39:08116 env, nullptr /* event */, 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f,
117 time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */,
jinsukkim5c3a1202017-03-10 00:02:14118 0 /* action_index */, android_action_button, android_button_state,
119 android_meta_state, 0 /* raw_offset_x_pixels */,
Jinsuk Kim2b859472017-08-30 02:47:19120 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer,
121 nullptr);
jinsukkim5c3a1202017-03-10 00:02:14122 view_->OnMouseEvent(event);
123}
124
jinsukkimb40b402c2017-03-29 09:39:08125void EventForwarder::OnMouseWheelEvent(JNIEnv* env,
126 const JavaParamRef<jobject>& obj,
127 jlong time_ms,
128 jfloat x,
129 jfloat y,
130 jfloat ticks_x,
131 jfloat ticks_y,
132 jfloat pixels_per_tick) {
133 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 Kim2b859472017-08-30 02:47:19145 ui::MotionEventAndroid event(
146 env, nullptr, 1.f / view_->GetDipScale(), ticks_x, ticks_y,
147 pixels_per_tick, time_ms, 0 /* action */, 1 /* pointer_count */,
148 0 /* history_size */, 0 /* action_index */, 0, 0, 0,
149 0 /* raw_offset_x_pixels */, 0 /* raw_offset_y_pixels */,
150 false /* for_touch_handle */, &pointer, nullptr);
jinsukkimb40b402c2017-03-29 09:39:08151
152 view_->OnMouseWheelEvent(event);
153}
154
jinsukkimda11b4d2017-05-26 06:44:41155void EventForwarder::OnDragEvent(JNIEnv* env,
156 const JavaParamRef<jobject>& jobj,
157 jint action,
158 jint x,
159 jint y,
160 jint screen_x,
161 jint screen_y,
162 const JavaParamRef<jobjectArray>& j_mimeTypes,
163 const JavaParamRef<jstring>& j_content) {
164 float dip_scale = view_->GetDipScale();
165 gfx::PointF location(x / dip_scale, y / dip_scale);
166 gfx::PointF root_location(screen_x / dip_scale, screen_y / dip_scale);
167 std::vector<base::string16> mime_types;
168 AppendJavaStringArrayToStringVector(env, j_mimeTypes, &mime_types);
169
170 DragEventAndroid event(env, action, location, root_location, mime_types,
171 j_content.obj());
172 view_->OnDragEvent(event);
173}
174
Jinsuk Kim63626ce42017-11-23 06:19:56175bool EventForwarder::OnGestureEvent(JNIEnv* env,
176 const JavaParamRef<jobject>& jobj,
177 jint type,
178 jlong time_ms,
Jinsuk Kime6c2eafb2018-02-23 01:10:36179 jfloat scale) {
Jinsuk Kim63626ce42017-11-23 06:19:56180 float dip_scale = view_->GetDipScale();
181 auto size = view_->GetSize();
182 float x = size.width() / 2;
183 float y = size.height() / 2;
184 gfx::PointF root_location =
185 ScalePoint(view_->GetLocationOnScreen(x, y), 1.f / dip_scale);
Jinsuk Kime6c2eafb2018-02-23 01:10:36186 return view_->OnGestureEvent(GestureEventAndroid(
187 type, gfx::PointF(x / dip_scale, y / dip_scale), root_location, time_ms,
188 scale, 0, 0, 0, 0, false, false));
189}
190
191void EventForwarder::OnStartFling(JNIEnv* env,
192 const JavaParamRef<jobject>& jobj,
193 jlong time_ms,
194 jfloat velocity_x,
195 jfloat velocity_y,
196 jboolean synthetic_scroll) {
197 OnCancelFling(env, jobj, time_ms);
198 if (velocity_x == 0 && velocity_y == 0)
199 return;
200 // Use velocity as delta in scroll event.
201 view_->OnGestureEvent(GestureEventAndroid(
202 GESTURE_EVENT_TYPE_SCROLL_START, gfx::PointF(), gfx::PointF(), time_ms, 0,
203 velocity_x, velocity_y, 0, 0, true, synthetic_scroll));
204 view_->OnGestureEvent(GestureEventAndroid(
205 GESTURE_EVENT_TYPE_FLING_START, gfx::PointF(), gfx::PointF(), time_ms, 0,
206 0, 0, velocity_x, velocity_y, true, synthetic_scroll));
207}
208
209void EventForwarder::OnCancelFling(JNIEnv* env,
210 const JavaParamRef<jobject>& jobj,
211 jlong time_ms) {
212 view_->OnGestureEvent(
213 GestureEventAndroid(GESTURE_EVENT_TYPE_FLING_CANCEL, gfx::PointF(),
214 gfx::PointF(), time_ms, 0, 0, 0, 0, 0, false, false));
Jinsuk Kim63626ce42017-11-23 06:19:56215}
216
jinsukkim5c3a1202017-03-10 00:02:14217} // namespace ui