jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 1 | // 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 | |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 7 | #include "base/android/jni_array.h" |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 8 | #include "base/metrics/histogram_macros.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 9 | #include "jni/EventForwarder_jni.h" |
| 10 | #include "ui/android/view_android.h" |
Michael Thiessen | e70dd08d | 2017-12-21 20:59:11 | [diff] [blame] | 11 | #include "ui/android/window_android.h" |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 12 | #include "ui/base/ui_base_switches_util.h" |
| 13 | #include "ui/events/android/drag_event_android.h" |
Jinsuk Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 14 | #include "ui/events/android/gesture_event_android.h" |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame^] | 15 | #include "ui/events/android/gesture_event_type.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 16 | #include "ui/events/android/motion_event_android.h" |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 17 | #include "ui/events/base_event_utils.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 18 | |
| 19 | namespace ui { |
| 20 | |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 21 | using base::android::AppendJavaStringArrayToStringVector; |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 22 | using base::android::JavaParamRef; |
| 23 | using base::android::ScopedJavaLocalRef; |
| 24 | |
| 25 | EventForwarder::EventForwarder(ViewAndroid* view) : view_(view) {} |
| 26 | |
| 27 | EventForwarder::~EventForwarder() { |
| 28 | if (!java_obj_.is_null()) { |
| 29 | Java_EventForwarder_destroy(base::android::AttachCurrentThread(), |
| 30 | java_obj_); |
| 31 | java_obj_.Reset(); |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | ScopedJavaLocalRef<jobject> EventForwarder::GetJavaObject() { |
| 36 | if (java_obj_.is_null()) { |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 37 | JNIEnv* env = base::android::AttachCurrentThread(); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 38 | java_obj_.Reset( |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 39 | Java_EventForwarder_create(env, reinterpret_cast<intptr_t>(this), |
| 40 | switches::IsTouchDragDropEnabled())); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 41 | } |
| 42 | return ScopedJavaLocalRef<jobject>(java_obj_); |
| 43 | } |
| 44 | |
Michael Thiessen | e70dd08d | 2017-12-21 20:59:11 | [diff] [blame] | 45 | ScopedJavaLocalRef<jobject> EventForwarder::GetJavaWindowAndroid( |
| 46 | JNIEnv* env, |
| 47 | const JavaParamRef<jobject>& obj) { |
| 48 | return view_->GetWindowAndroid()->GetJavaObject(); |
| 49 | } |
| 50 | |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 51 | jboolean 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 Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 79 | jboolean for_touch_handle) { |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 80 | 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( |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 87 | 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, |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 89 | 0 /* action_button */, android_button_state, android_meta_state, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 90 | raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0, |
| 91 | &pointer1); |
| 92 | return view_->OnTouchEvent(event); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | void 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( |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 116 | env, nullptr /* event */, 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, |
| 117 | time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */, |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 118 | 0 /* action_index */, android_action_button, android_button_state, |
| 119 | android_meta_state, 0 /* raw_offset_x_pixels */, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 120 | 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer, |
| 121 | nullptr); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 122 | view_->OnMouseEvent(event); |
| 123 | } |
| 124 | |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 125 | void 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 Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 145 | 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); |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 151 | |
| 152 | view_->OnMouseWheelEvent(event); |
| 153 | } |
| 154 | |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 155 | void 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 Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 175 | bool EventForwarder::OnGestureEvent(JNIEnv* env, |
| 176 | const JavaParamRef<jobject>& jobj, |
| 177 | jint type, |
| 178 | jlong time_ms, |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame^] | 179 | jfloat scale) { |
Jinsuk Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 180 | 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 Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame^] | 186 | 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 | |
| 191 | void 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 | |
| 209 | void 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 Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 215 | } |
| 216 | |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 217 | } // namespace ui |