blob: 16c92c1e1f9dbf8bd501efa4d7095a64bc7918ef [file] [log] [blame]
mthiesse8ba79112017-02-24 23:58:331// 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
Christopher Grant2b3383c22018-02-26 15:41:585#include "chrome/browser/android/vr/android_ui_gesture_target.h"
mthiesse8ba79112017-02-24 23:58:336
Michael Thiessen1af4c932018-02-27 00:09:347#include <cmath>
8
Aldo Culquicondor89d943a2018-07-04 16:31:019#include "chrome/browser/vr/input_event.h"
Finditddef7842019-06-22 02:15:1610#include "jni/AndroidUiGestureTarget_jni.h"
Jinsuk Kim9604d8b2017-08-07 02:47:3011
12using base::android::JavaParamRef;
13using base::android::JavaRef;
14using content::MotionEventAction;
mthiesse8ba79112017-02-24 23:58:3315
Ian Vollick98c28a62018-07-03 21:31:2716static constexpr int kFrameDurationMs = 16;
17static constexpr int kScrollEventsPerFrame = 2;
18
Christopher Grant4128a482018-02-15 16:07:2819namespace vr {
mthiesse8ba79112017-02-24 23:58:3320
Jinsuk Kim9604d8b2017-08-07 02:47:3021AndroidUiGestureTarget::AndroidUiGestureTarget(JNIEnv* env,
22 const JavaParamRef<jobject>& obj,
23 float scale_factor,
Michael Thiessen1af4c932018-02-27 00:09:3424 float scroll_ratio,
25 int touch_slop)
Jinsuk Kim9604d8b2017-08-07 02:47:3026 : scale_factor_(scale_factor),
27 scroll_ratio_(scroll_ratio),
Michael Thiessen1af4c932018-02-27 00:09:3428 touch_slop_(touch_slop),
Jinsuk Kim9604d8b2017-08-07 02:47:3029 java_ref_(env, obj) {}
mthiesse8ba79112017-02-24 23:58:3330
31AndroidUiGestureTarget::~AndroidUiGestureTarget() = default;
32
Aldo Culquicondor89d943a2018-07-04 16:31:0133void AndroidUiGestureTarget::DispatchInputEvent(
34 std::unique_ptr<InputEvent> event) {
35 int64_t event_time_ms = event->time_stamp().since_origin().InMilliseconds();
36 switch (event->type()) {
37 case InputEvent::kScrollBegin: {
38 SetPointer(event->position_in_widget());
Jinsuk Kim9604d8b2017-08-07 02:47:3039 Inject(content::MOTION_EVENT_ACTION_START, event_time_ms);
Michael Thiessen1af4c932018-02-27 00:09:3440
Aldo Culquicondor89d943a2018-07-04 16:31:0141 float xdiff = event->scroll_data.delta_x;
42 float ydiff = event->scroll_data.delta_y;
Michael Thiessen1af4c932018-02-27 00:09:3443
44 if (xdiff == 0 && ydiff == 0)
45 ydiff = touch_slop_;
46 double dist = std::sqrt((xdiff * xdiff) + (ydiff * ydiff));
47 if (dist < touch_slop_) {
48 xdiff *= touch_slop_ / dist;
49 ydiff *= touch_slop_ / dist;
50 }
51
Aldo Culquicondor89d943a2018-07-04 16:31:0152 float xtarget = xdiff * scroll_ratio_ + event->position_in_widget().x();
53 float ytarget = ydiff * scroll_ratio_ + event->position_in_widget().y();
Michael Thiessen1af4c932018-02-27 00:09:3454 scroll_x_ = xtarget > 0 ? std::ceil(xtarget) : std::floor(xtarget);
55 scroll_y_ = ytarget > 0 ? std::ceil(ytarget) : std::floor(ytarget);
56
Jinsuk Kim9604d8b2017-08-07 02:47:3057 SetPointer(scroll_x_, scroll_y_);
mthiesse8ba79112017-02-24 23:58:3358 // Send a move immediately so that we can't accidentally trigger a click.
Jinsuk Kim9604d8b2017-08-07 02:47:3059 Inject(content::MOTION_EVENT_ACTION_MOVE, event_time_ms);
mthiesse8ba79112017-02-24 23:58:3360 break;
Michael Thiessen1af4c932018-02-27 00:09:3461 }
Aldo Culquicondor89d943a2018-07-04 16:31:0162 case InputEvent::kScrollEnd:
Amirhossein Simjour84909262018-02-14 20:58:0763 SetPointer(scroll_x_, scroll_y_);
Jinsuk Kim9604d8b2017-08-07 02:47:3064 Inject(content::MOTION_EVENT_ACTION_END, event_time_ms);
mthiesse8ba79112017-02-24 23:58:3365 break;
Aldo Culquicondor89d943a2018-07-04 16:31:0166 case InputEvent::kScrollUpdate: {
Ian Vollick98c28a62018-07-03 21:31:2767 float scale = scroll_ratio_ / kScrollEventsPerFrame;
Aldo Culquicondor89d943a2018-07-04 16:31:0168 scroll_x_ += event->scroll_data.delta_x * scale;
69 scroll_y_ += event->scroll_data.delta_y * scale;
Ian Vollick98c28a62018-07-03 21:31:2770
Jinsuk Kim9604d8b2017-08-07 02:47:3071 SetPointer(scroll_x_, scroll_y_);
72 Inject(content::MOTION_EVENT_ACTION_MOVE, event_time_ms);
Ian Vollick98c28a62018-07-03 21:31:2773
Aldo Culquicondor89d943a2018-07-04 16:31:0174 scroll_x_ += event->scroll_data.delta_x * scale;
75 scroll_y_ += event->scroll_data.delta_y * scale;
Ian Vollick98c28a62018-07-03 21:31:2776 SetDelayedEvent(scroll_x_, scroll_y_, content::MOTION_EVENT_ACTION_MOVE,
77 event_time_ms, kFrameDurationMs / kScrollEventsPerFrame);
78
mthiesse8ba79112017-02-24 23:58:3379 break;
Ian Vollick98c28a62018-07-03 21:31:2780 }
Aldo Culquicondor89d943a2018-07-04 16:31:0181 case InputEvent::kFlingCancel:
Michael Thiessen1af4c932018-02-27 00:09:3482 Inject(content::MOTION_EVENT_ACTION_START, event_time_ms);
Jinsuk Kim9604d8b2017-08-07 02:47:3083 Inject(content::MOTION_EVENT_ACTION_CANCEL, event_time_ms);
mthiesse8ba79112017-02-24 23:58:3384 break;
Aldo Culquicondor89d943a2018-07-04 16:31:0185 case InputEvent::kHoverEnter:
86 SetPointer(event->position_in_widget());
Jinsuk Kim9604d8b2017-08-07 02:47:3087 Inject(content::MOTION_EVENT_ACTION_HOVER_ENTER, event_time_ms);
mthiesse8ba79112017-02-24 23:58:3388 break;
Aldo Culquicondor89d943a2018-07-04 16:31:0189 case InputEvent::kHoverLeave:
90 case InputEvent::kHoverMove:
Aldo Culquicondor53195552018-06-19 21:53:1391 // The platform ignores HOVER_EXIT, so we instead send a fixed
92 // out-of-bounds point (http://crbug.com/715114).
Aldo Culquicondor89d943a2018-07-04 16:31:0193 SetPointer(event->position_in_widget());
Jinsuk Kim9604d8b2017-08-07 02:47:3094 Inject(content::MOTION_EVENT_ACTION_HOVER_MOVE, event_time_ms);
mthiesse8ba79112017-02-24 23:58:3395 break;
Aldo Culquicondor89d943a2018-07-04 16:31:0196 case InputEvent::kButtonDown:
97 SetPointer(event->position_in_widget());
Jinsuk Kim9604d8b2017-08-07 02:47:3098 Inject(content::MOTION_EVENT_ACTION_START, event_time_ms);
Aldo Culquicondor53195552018-06-19 21:53:1399 break;
Aldo Culquicondor89d943a2018-07-04 16:31:01100 case InputEvent::kButtonUp:
101 SetPointer(event->position_in_widget());
Jinsuk Kim9604d8b2017-08-07 02:47:30102 Inject(content::MOTION_EVENT_ACTION_END, event_time_ms);
mthiesse2a36d1972017-06-14 16:00:14103 break;
Aldo Culquicondor89d943a2018-07-04 16:31:01104 case InputEvent::kMove:
105 SetPointer(event->position_in_widget());
Aldo Culquicondor53195552018-06-19 21:53:13106 Inject(content::MOTION_EVENT_ACTION_MOVE, event_time_ms);
mthiesse2a36d1972017-06-14 16:00:14107 break;
mthiesse8ba79112017-02-24 23:58:33108 default:
mthiesse2a36d1972017-06-14 16:00:14109 NOTREACHED() << "Unsupported event type sent to Android UI.";
mthiesse8ba79112017-02-24 23:58:33110 break;
111 }
112}
113
Jinsuk Kim9604d8b2017-08-07 02:47:30114void AndroidUiGestureTarget::Inject(MotionEventAction action, int64_t time_ms) {
115 JNIEnv* env = base::android::AttachCurrentThread();
116 base::android::ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
117 if (obj.is_null())
118 return;
119
120 Java_AndroidUiGestureTarget_inject(env, obj, action, time_ms);
mthiesse8ba79112017-02-24 23:58:33121}
122
Aldo Culquicondor89d943a2018-07-04 16:31:01123void AndroidUiGestureTarget::SetPointer(const gfx::PointF& position) {
124 SetPointer(position.x(), position.y());
125}
126
127void AndroidUiGestureTarget::SetPointer(float x, float y) {
Jinsuk Kim9604d8b2017-08-07 02:47:30128 JNIEnv* env = base::android::AttachCurrentThread();
129 base::android::ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
130 if (obj.is_null())
131 return;
132
Aldo Culquicondor89d943a2018-07-04 16:31:01133 Java_AndroidUiGestureTarget_setPointer(env, obj,
134 static_cast<int>(x * scale_factor_),
135 static_cast<int>(y * scale_factor_));
mthiesse8ba79112017-02-24 23:58:33136}
137
Aldo Culquicondor89d943a2018-07-04 16:31:01138void AndroidUiGestureTarget::SetDelayedEvent(float x,
139 float y,
Ian Vollick98c28a62018-07-03 21:31:27140 MotionEventAction action,
141 int64_t time_ms,
142 int delay_ms) {
143 JNIEnv* env = base::android::AttachCurrentThread();
144 base::android::ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
145 if (obj.is_null())
146 return;
147
Aldo Culquicondor89d943a2018-07-04 16:31:01148 Java_AndroidUiGestureTarget_setDelayedEvent(
149 env, obj, static_cast<int>(x * scale_factor_),
150 static_cast<int>(y * scale_factor_), action, time_ms, delay_ms);
Ian Vollick98c28a62018-07-03 21:31:27151}
152
Jinsuk Kim9604d8b2017-08-07 02:47:30153// static
154AndroidUiGestureTarget* AndroidUiGestureTarget::FromJavaObject(
155 const JavaRef<jobject>& obj) {
Michael Thiessen63961202018-01-23 01:17:53156 if (obj.is_null())
157 return nullptr;
158
Jinsuk Kim9604d8b2017-08-07 02:47:30159 JNIEnv* env = base::android::AttachCurrentThread();
160 return reinterpret_cast<AndroidUiGestureTarget*>(
161 Java_AndroidUiGestureTarget_getNativeObject(env, obj));
162}
163
Daniel Bratell7aacf952017-11-21 17:51:25164static jlong JNI_AndroidUiGestureTarget_Init(JNIEnv* env,
165 const JavaParamRef<jobject>& obj,
166 jfloat scale_factor,
Michael Thiessen1af4c932018-02-27 00:09:34167 jfloat scroll_ratio,
168 jint touch_slop) {
169 return reinterpret_cast<intptr_t>(new AndroidUiGestureTarget(
170 env, obj, scale_factor, scroll_ratio, touch_slop));
mthiesse8ba79112017-02-24 23:58:33171}
172
Christopher Grant4128a482018-02-15 16:07:28173} // namespace vr