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" |
Andrew Grieve | 4a42c22e | 2019-06-24 16:14:29 | [diff] [blame] | 8 | #include "ui/android/ui_android_jni_headers/EventForwarder_jni.h" |
Michael Thiessen | e70dd08d | 2017-12-21 20:59:11 | [diff] [blame] | 9 | #include "ui/android/window_android.h" |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 10 | #include "ui/base/ui_base_switches_util.h" |
| 11 | #include "ui/events/android/drag_event_android.h" |
Jinsuk Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 12 | #include "ui/events/android/gesture_event_android.h" |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 13 | #include "ui/events/android/gesture_event_type.h" |
Jinsuk Kim | 5a3ae93c | 2018-04-25 21:49:06 | [diff] [blame] | 14 | #include "ui/events/android/key_event_android.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 15 | #include "ui/events/android/motion_event_android.h" |
| 16 | |
| 17 | namespace ui { |
| 18 | |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 19 | using base::android::AppendJavaStringArrayToStringVector; |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 20 | using base::android::JavaParamRef; |
| 21 | using base::android::ScopedJavaLocalRef; |
| 22 | |
| 23 | EventForwarder::EventForwarder(ViewAndroid* view) : view_(view) {} |
| 24 | |
| 25 | EventForwarder::~EventForwarder() { |
| 26 | if (!java_obj_.is_null()) { |
| 27 | Java_EventForwarder_destroy(base::android::AttachCurrentThread(), |
| 28 | java_obj_); |
| 29 | java_obj_.Reset(); |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | ScopedJavaLocalRef<jobject> EventForwarder::GetJavaObject() { |
| 34 | if (java_obj_.is_null()) { |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 35 | JNIEnv* env = base::android::AttachCurrentThread(); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 36 | java_obj_.Reset( |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 37 | Java_EventForwarder_create(env, reinterpret_cast<intptr_t>(this), |
| 38 | switches::IsTouchDragDropEnabled())); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 39 | } |
| 40 | return ScopedJavaLocalRef<jobject>(java_obj_); |
| 41 | } |
| 42 | |
Michael Thiessen | e70dd08d | 2017-12-21 20:59:11 | [diff] [blame] | 43 | ScopedJavaLocalRef<jobject> EventForwarder::GetJavaWindowAndroid( |
| 44 | JNIEnv* env, |
| 45 | const JavaParamRef<jobject>& obj) { |
| 46 | return view_->GetWindowAndroid()->GetJavaObject(); |
| 47 | } |
| 48 | |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 49 | jboolean EventForwarder::OnTouchEvent(JNIEnv* env, |
| 50 | const JavaParamRef<jobject>& obj, |
| 51 | const JavaParamRef<jobject>& motion_event, |
| 52 | jlong time_ms, |
| 53 | jint android_action, |
| 54 | jint pointer_count, |
| 55 | jint history_size, |
| 56 | jint action_index, |
| 57 | jfloat pos_x_0, |
| 58 | jfloat pos_y_0, |
| 59 | jfloat pos_x_1, |
| 60 | jfloat pos_y_1, |
| 61 | jint pointer_id_0, |
| 62 | jint pointer_id_1, |
| 63 | jfloat touch_major_0, |
| 64 | jfloat touch_major_1, |
| 65 | jfloat touch_minor_0, |
| 66 | jfloat touch_minor_1, |
| 67 | jfloat orientation_0, |
| 68 | jfloat orientation_1, |
| 69 | jfloat tilt_0, |
| 70 | jfloat tilt_1, |
| 71 | jfloat raw_pos_x, |
| 72 | jfloat raw_pos_y, |
| 73 | jint android_tool_type_0, |
| 74 | jint android_tool_type_1, |
| 75 | jint android_button_state, |
| 76 | jint android_meta_state, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 77 | jboolean for_touch_handle) { |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 78 | ui::MotionEventAndroid::Pointer pointer0( |
| 79 | pointer_id_0, pos_x_0, pos_y_0, touch_major_0, touch_minor_0, |
| 80 | orientation_0, tilt_0, android_tool_type_0); |
| 81 | ui::MotionEventAndroid::Pointer pointer1( |
| 82 | pointer_id_1, pos_x_1, pos_y_1, touch_major_1, touch_minor_1, |
| 83 | orientation_1, tilt_1, android_tool_type_1); |
| 84 | ui::MotionEventAndroid event( |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 85 | env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, |
| 86 | time_ms, android_action, pointer_count, history_size, action_index, |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 87 | 0 /* action_button */, android_button_state, android_meta_state, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 88 | raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0, |
| 89 | &pointer1); |
| 90 | return view_->OnTouchEvent(event); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | void EventForwarder::OnMouseEvent(JNIEnv* env, |
| 94 | const JavaParamRef<jobject>& obj, |
| 95 | jlong time_ms, |
| 96 | jint android_action, |
| 97 | jfloat x, |
| 98 | jfloat y, |
| 99 | jint pointer_id, |
| 100 | jfloat orientation, |
| 101 | jfloat pressure, |
| 102 | jfloat tilt, |
| 103 | jint android_action_button, |
| 104 | jint android_button_state, |
| 105 | jint android_meta_state, |
| 106 | jint android_tool_type) { |
| 107 | // Construct a motion_event object minimally, only to convert the raw |
| 108 | // parameters to ui::MotionEvent values. Since we used only the cached values |
| 109 | // at index=0, it is okay to even pass a null event to the constructor. |
| 110 | ui::MotionEventAndroid::Pointer pointer( |
| 111 | pointer_id, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */, |
| 112 | orientation, tilt, android_tool_type); |
| 113 | ui::MotionEventAndroid event( |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 114 | env, nullptr /* event */, 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, |
| 115 | time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */, |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 116 | 0 /* action_index */, android_action_button, android_button_state, |
| 117 | android_meta_state, 0 /* raw_offset_x_pixels */, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 118 | 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer, |
| 119 | nullptr); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 120 | view_->OnMouseEvent(event); |
| 121 | } |
| 122 | |
jinsukkim | da11b4d | 2017-05-26 06:44:41 | [diff] [blame] | 123 | void EventForwarder::OnDragEvent(JNIEnv* env, |
| 124 | const JavaParamRef<jobject>& jobj, |
| 125 | jint action, |
| 126 | jint x, |
| 127 | jint y, |
| 128 | jint screen_x, |
| 129 | jint screen_y, |
| 130 | const JavaParamRef<jobjectArray>& j_mimeTypes, |
| 131 | const JavaParamRef<jstring>& j_content) { |
| 132 | float dip_scale = view_->GetDipScale(); |
| 133 | gfx::PointF location(x / dip_scale, y / dip_scale); |
| 134 | gfx::PointF root_location(screen_x / dip_scale, screen_y / dip_scale); |
| 135 | std::vector<base::string16> mime_types; |
| 136 | AppendJavaStringArrayToStringVector(env, j_mimeTypes, &mime_types); |
| 137 | |
| 138 | DragEventAndroid event(env, action, location, root_location, mime_types, |
| 139 | j_content.obj()); |
| 140 | view_->OnDragEvent(event); |
| 141 | } |
| 142 | |
Jinsuk Kim | 5a3ae93c | 2018-04-25 21:49:06 | [diff] [blame] | 143 | jboolean EventForwarder::OnGestureEvent(JNIEnv* env, |
| 144 | const JavaParamRef<jobject>& jobj, |
| 145 | jint type, |
| 146 | jlong time_ms, |
| 147 | jfloat scale) { |
Jinsuk Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 148 | float dip_scale = view_->GetDipScale(); |
| 149 | auto size = view_->GetSize(); |
| 150 | float x = size.width() / 2; |
| 151 | float y = size.height() / 2; |
| 152 | gfx::PointF root_location = |
| 153 | ScalePoint(view_->GetLocationOnScreen(x, y), 1.f / dip_scale); |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 154 | return view_->OnGestureEvent(GestureEventAndroid( |
| 155 | type, gfx::PointF(x / dip_scale, y / dip_scale), root_location, time_ms, |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 156 | scale, 0, 0, 0, 0, /*target_viewport*/ false, /*synthetic_scroll*/ false, |
| 157 | /*prevent_boosting*/ false)); |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 158 | } |
| 159 | |
Jinsuk Kim | 7ba8f240 | 2018-05-04 20:44:36 | [diff] [blame] | 160 | jboolean EventForwarder::OnGenericMotionEvent( |
| 161 | JNIEnv* env, |
| 162 | const JavaParamRef<jobject>& obj, |
| 163 | const JavaParamRef<jobject>& motion_event, |
| 164 | jlong time_ms) { |
| 165 | auto size = view_->GetSize(); |
| 166 | float x = size.width() / 2; |
| 167 | float y = size.height() / 2; |
| 168 | ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0); |
| 169 | ui::MotionEventAndroid event( |
| 170 | env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, |
| 171 | time_ms, 0, 1, 0, 0, 0, 0, 0, 0, 0, false, &pointer0, nullptr); |
| 172 | return view_->OnGenericMotionEvent(event); |
| 173 | } |
| 174 | |
Jinsuk Kim | 5a3ae93c | 2018-04-25 21:49:06 | [diff] [blame] | 175 | jboolean EventForwarder::OnKeyUp(JNIEnv* env, |
| 176 | const JavaParamRef<jobject>& obj, |
| 177 | const JavaParamRef<jobject>& key_event, |
| 178 | jint key_code) { |
| 179 | return view_->OnKeyUp(KeyEventAndroid(env, key_event, key_code)); |
| 180 | } |
| 181 | |
| 182 | jboolean EventForwarder::DispatchKeyEvent( |
| 183 | JNIEnv* env, |
| 184 | const JavaParamRef<jobject>& obj, |
| 185 | const JavaParamRef<jobject>& key_event) { |
| 186 | return view_->DispatchKeyEvent(KeyEventAndroid(env, key_event, 0)); |
| 187 | } |
| 188 | |
Jinsuk Kim | 7ba8f240 | 2018-05-04 20:44:36 | [diff] [blame] | 189 | void EventForwarder::ScrollBy(JNIEnv* env, |
| 190 | const JavaParamRef<jobject>& jobj, |
| 191 | jfloat delta_x, |
| 192 | jfloat delta_y) { |
| 193 | view_->ScrollBy(delta_x, delta_y); |
| 194 | } |
| 195 | |
| 196 | void EventForwarder::ScrollTo(JNIEnv* env, |
| 197 | const JavaParamRef<jobject>& jobj, |
| 198 | jfloat x, |
| 199 | jfloat y) { |
| 200 | view_->ScrollTo(x, y); |
Jinsuk Kim | 7862733 | 2018-03-05 23:33:39 | [diff] [blame] | 201 | } |
| 202 | |
| 203 | void EventForwarder::DoubleTap(JNIEnv* env, |
| 204 | const JavaParamRef<jobject>& jobj, |
| 205 | jlong time_ms, |
| 206 | jint x, |
| 207 | jint y) { |
| 208 | float dip_scale = view_->GetDipScale(); |
| 209 | view_->OnGestureEvent(GestureEventAndroid( |
| 210 | GESTURE_EVENT_TYPE_DOUBLE_TAP, gfx::PointF(x / dip_scale, y / dip_scale), |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 211 | gfx::PointF(), time_ms, 0, 0, 0, 0, 0, /*target_viewport*/ true, |
| 212 | /*synthetic_scroll*/ false, /*prevent_boosting*/ false)); |
Jinsuk Kim | 7862733 | 2018-03-05 23:33:39 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | void EventForwarder::StartFling(JNIEnv* env, |
| 216 | const JavaParamRef<jobject>& jobj, |
| 217 | jlong time_ms, |
| 218 | jfloat velocity_x, |
| 219 | jfloat velocity_y, |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 220 | jboolean synthetic_scroll, |
| 221 | jboolean prevent_boosting) { |
| 222 | CancelFling(env, jobj, time_ms, prevent_boosting); |
| 223 | |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 224 | if (velocity_x == 0 && velocity_y == 0) |
| 225 | return; |
Ella Ge | b1b8722 | 2019-04-02 17:19:50 | [diff] [blame] | 226 | float dip_scale = view_->GetDipScale(); |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 227 | // Use velocity as delta in scroll event. |
| 228 | view_->OnGestureEvent(GestureEventAndroid( |
| 229 | GESTURE_EVENT_TYPE_SCROLL_START, gfx::PointF(), gfx::PointF(), time_ms, 0, |
Ella Ge | b1b8722 | 2019-04-02 17:19:50 | [diff] [blame] | 230 | velocity_x / dip_scale, velocity_y / dip_scale, 0, 0, |
| 231 | /*target_viewport*/ true, synthetic_scroll, |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 232 | /*prevent_boosting*/ false)); |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 233 | view_->OnGestureEvent(GestureEventAndroid( |
| 234 | GESTURE_EVENT_TYPE_FLING_START, gfx::PointF(), gfx::PointF(), time_ms, 0, |
Ella Ge | b1b8722 | 2019-04-02 17:19:50 | [diff] [blame] | 235 | 0, 0, velocity_x / dip_scale, velocity_y / dip_scale, |
| 236 | /*target_viewport*/ true, synthetic_scroll, |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 237 | /*prevent_boosting*/ false)); |
Jinsuk Kim | e6c2eafb | 2018-02-23 01:10:36 | [diff] [blame] | 238 | } |
| 239 | |
Jinsuk Kim | 7862733 | 2018-03-05 23:33:39 | [diff] [blame] | 240 | void EventForwarder::CancelFling(JNIEnv* env, |
| 241 | const JavaParamRef<jobject>& jobj, |
David Bokan | 4b32e5d1 | 2018-07-09 02:11:59 | [diff] [blame] | 242 | jlong time_ms, |
| 243 | jboolean prevent_boosting) { |
| 244 | view_->OnGestureEvent(GestureEventAndroid( |
| 245 | GESTURE_EVENT_TYPE_FLING_CANCEL, gfx::PointF(), gfx::PointF(), time_ms, 0, |
| 246 | 0, 0, 0, 0, |
| 247 | /*target_viewport*/ false, /*synthetic_scroll*/ false, prevent_boosting)); |
Jinsuk Kim | 63626ce4 | 2017-11-23 06:19:56 | [diff] [blame] | 248 | } |
| 249 | |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 250 | } // namespace ui |