Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(892)

Side by Side Diff: ui/android/view_android.cc

Issue 2708613002: Add EventForwarder for routing touch events (Closed)
Patch Set: removed MotionEventData Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/android/view_android.h" 5 #include "ui/android/view_android.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
11 #include "base/containers/adapters.h"
11 #include "cc/layers/layer.h" 12 #include "cc/layers/layer.h"
12 #include "jni/ViewAndroidDelegate_jni.h" 13 #include "jni/ViewAndroidDelegate_jni.h"
14 #include "ui/android/event_handler.h"
15 #include "ui/android/view_client.h"
13 #include "ui/android/window_android.h" 16 #include "ui/android/window_android.h"
14 #include "ui/display/display.h" 17 #include "ui/base/layout.h"
15 #include "ui/display/screen.h" 18 #include "ui/events/android/motion_event_android.h"
16 #include "url/gurl.h" 19 #include "url/gurl.h"
17 20
18 namespace ui { 21 namespace ui {
19 22
20 using base::android::ConvertUTF8ToJavaString; 23 using base::android::ConvertUTF8ToJavaString;
21 using base::android::JavaRef; 24 using base::android::JavaRef;
22 using base::android::ScopedJavaLocalRef; 25 using base::android::ScopedJavaLocalRef;
23 26
27 namespace {
28
29 struct TouchEventSender : ViewAndroid::EventSender {
30 TouchEventSender(bool for_touch_handle)
31 : for_touch_handle_(for_touch_handle) {}
32 bool SendToView(ViewAndroid* view,
33 const MotionEventAndroid& e) const override {
34 return view->OnTouchEvent(e, for_touch_handle_);
35 }
36
37 bool SendToClient(ViewClient* client,
38 const MotionEventAndroid& e) const override {
39 return client->OnTouchEvent(e, for_touch_handle_);
40 }
41
42 private:
43 bool for_touch_handle_;
44 };
45
46 struct MouseEventSender : ViewAndroid::EventSender {
47 MouseEventSender() {}
48 bool SendToView(ViewAndroid* view,
49 const MotionEventAndroid& e) const override {
50 return view->OnMouseEvent(e);
51 }
52
53 bool SendToClient(ViewClient* client,
54 const MotionEventAndroid& e) const override {
55 return client->OnMouseEvent(e);
56 }
57 };
58
59 } // namespace
60
24 ViewAndroid::ScopedAnchorView::ScopedAnchorView( 61 ViewAndroid::ScopedAnchorView::ScopedAnchorView(
25 JNIEnv* env, 62 JNIEnv* env,
26 const JavaRef<jobject>& jview, 63 const JavaRef<jobject>& jview,
27 const JavaRef<jobject>& jdelegate) 64 const JavaRef<jobject>& jdelegate)
28 : view_(env, jview.obj()), delegate_(env, jdelegate.obj()) { 65 : view_(env, jview.obj()), delegate_(env, jdelegate.obj()) {
29 // If there's a view, then we need a delegate to remove it. 66 // If there's a view, then we need a delegate to remove it.
30 DCHECK(!jdelegate.is_null() || jview.is_null()); 67 DCHECK(!jdelegate.is_null() || jview.is_null());
31 } 68 }
32 69
33 ViewAndroid::ScopedAnchorView::ScopedAnchorView() { } 70 ViewAndroid::ScopedAnchorView::ScopedAnchorView() { }
(...skipping 30 matching lines...) Expand all
64 view_.reset(); 101 view_.reset();
65 delegate_.reset(); 102 delegate_.reset();
66 } 103 }
67 104
68 const base::android::ScopedJavaLocalRef<jobject> 105 const base::android::ScopedJavaLocalRef<jobject>
69 ViewAndroid::ScopedAnchorView::view() const { 106 ViewAndroid::ScopedAnchorView::view() const {
70 JNIEnv* env = base::android::AttachCurrentThread(); 107 JNIEnv* env = base::android::AttachCurrentThread();
71 return view_.get(env); 108 return view_.get(env);
72 } 109 }
73 110
74 ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) 111 ViewAndroid::ViewAndroid(ViewClient* view_client)
75 : parent_(nullptr), 112 : parent_(nullptr), client_(view_client) {}
76 delegate_(base::android::AttachCurrentThread(), delegate.obj()) {}
77 113
78 ViewAndroid::ViewAndroid() : parent_(nullptr) {} 114 ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
79 115
80 ViewAndroid::~ViewAndroid() { 116 ViewAndroid::~ViewAndroid() {
81 RemoveFromParent(); 117 RemoveFromParent();
82 118
83 for (std::list<ViewAndroid*>::iterator it = children_.begin(); 119 for (std::list<ViewAndroid*>::iterator it = children_.begin();
84 it != children_.end(); it++) { 120 it != children_.end(); it++) {
85 DCHECK_EQ((*it)->parent_, this); 121 DCHECK_EQ((*it)->parent_, this);
86 (*it)->parent_ = nullptr; 122 (*it)->parent_ = nullptr;
87 } 123 }
88 } 124 }
89 125
90 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) { 126 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) {
127 // A ViewAndroid may have its own delegate or otherwise will use the next
128 // available parent's delegate.
91 JNIEnv* env = base::android::AttachCurrentThread(); 129 JNIEnv* env = base::android::AttachCurrentThread();
92 delegate_ = JavaObjectWeakGlobalRef(env, delegate); 130 delegate_ = JavaObjectWeakGlobalRef(env, delegate);
93 } 131 }
94 132
133 float ViewAndroid::GetDipScale() {
134 return ui::GetScaleFactorForNativeView(this);
135 }
136
137 ScopedJavaLocalRef<jobject> ViewAndroid::GetEventHandler() {
138 if (!event_handler_) {
139 DCHECK(!ViewTreeHasEventHandler(this))
140 << "Root of the ViewAndroid can have at most one handler.";
141 event_handler_.reset(new EventHandler(this));
142 }
143 return event_handler_->GetJavaObject();
144 }
145
95 void ViewAndroid::AddChild(ViewAndroid* child) { 146 void ViewAndroid::AddChild(ViewAndroid* child) {
96 DCHECK(child); 147 DCHECK(child);
97 DCHECK(std::find(children_.begin(), children_.end(), child) == 148 DCHECK(std::find(children_.begin(), children_.end(), child) ==
98 children_.end()); 149 children_.end());
150 DCHECK(!ChildrenHaveEventHandler(child) || !ViewTreeHasEventHandler(this))
Khushal 2017/03/03 23:36:07 nit: this is a bit confusing. How about: DCHECK(!c
Jinsuk Kim 2017/03/06 04:07:34 has_event_handler() won't be enough since it only
Khushal 2017/03/07 04:17:08 Sorry I missed that. Much clearer now. Thanks.
151 << "Only one event handler is allowed.";
99 152
153 // The new child goes to the top, which is the end of the list.
100 children_.push_back(child); 154 children_.push_back(child);
101 if (child->parent_) 155 if (child->parent_)
102 child->RemoveFromParent(); 156 child->RemoveFromParent();
103 child->parent_ = this; 157 child->parent_ = this;
104 } 158 }
105 159
160 // static
161 bool ViewAndroid::ViewTreeHasEventHandler(ViewAndroid* view) {
162 ViewAndroid* v = view;
163 do {
164 if (v->has_event_handler())
165 return true;
166 v = v->parent_;
167 } while (v);
168 return ChildrenHaveEventHandler(view);
169 }
170
171 // static
172 bool ViewAndroid::ChildrenHaveEventHandler(ViewAndroid* view) {
173 if (view->has_event_handler())
174 return true;
175 for (auto* child : view->children_) {
176 if (child->ChildrenHaveEventHandler(child))
Khushal 2017/03/03 23:36:08 You're calling a static method on child? And these
Jinsuk Kim 2017/03/06 04:07:34 They access non-public member/method which I'd rat
Khushal 2017/03/07 04:17:07 That should still be possible if you put it in the
Jinsuk Kim 2017/03/07 05:02:23 Sorry I still don't get it - |view->children_|, |v
Khushal 2017/03/07 06:32:05 Sorry for being unclear. I meant |ChildrenHaveEven
Khushal 2017/03/07 06:43:13 I see it now. :l Please ignore me here.
Jinsuk Kim 2017/03/08 02:16:16 Acknowledged.
177 return true;
178 }
179 return false;
180 }
181
182 void ViewAndroid::MoveToTop(ViewAndroid* child) {
183 DCHECK(child);
184 auto it = std::find(children_.begin(), children_.end(), child);
185 DCHECK(it != children_.end());
186
187 // Top element is placed at the end of the list.
188 if (*it != children_.back())
189 children_.splice(children_.end(), children_, it);
190 }
191
106 void ViewAndroid::RemoveFromParent() { 192 void ViewAndroid::RemoveFromParent() {
107 if (parent_) 193 if (parent_)
108 parent_->RemoveChild(this); 194 parent_->RemoveChild(this);
109 } 195 }
110 196
111 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { 197 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() {
112 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 198 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
113 if (delegate.is_null()) 199 if (delegate.is_null())
114 return ViewAndroid::ScopedAnchorView(); 200 return ViewAndroid::ScopedAnchorView();
115 201
116 JNIEnv* env = base::android::AttachCurrentThread(); 202 JNIEnv* env = base::android::AttachCurrentThread();
117 return ViewAndroid::ScopedAnchorView( 203 return ViewAndroid::ScopedAnchorView(
118 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); 204 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate);
119 } 205 }
120 206
121 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, 207 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor,
122 const gfx::RectF& bounds) { 208 const gfx::RectF& bounds) {
123 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 209 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
124 if (delegate.is_null()) 210 if (delegate.is_null())
125 return; 211 return;
126 212
127 float scale = display::Screen::GetScreen() 213 float dip_scale = GetDipScale();
128 ->GetDisplayNearestWindow(this) 214 int left_margin = std::round(bounds.x() * dip_scale);
129 .device_scale_factor(); 215 int top_margin = std::round((content_offset().y() + bounds.y()) * dip_scale);
130 int left_margin = std::round(bounds.x() * scale);
131 int top_margin = std::round((content_offset().y() + bounds.y()) * scale);
132 JNIEnv* env = base::android::AttachCurrentThread(); 216 JNIEnv* env = base::android::AttachCurrentThread();
133 Java_ViewAndroidDelegate_setViewPosition( 217 Java_ViewAndroidDelegate_setViewPosition(
134 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), 218 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(),
135 bounds.height(), scale, left_margin, top_margin); 219 bounds.height(), dip_scale, left_margin, top_margin);
136 } 220 }
137 221
138 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { 222 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
139 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 223 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
140 if (delegate.is_null()) 224 if (delegate.is_null())
141 return nullptr; 225 return nullptr;
142 226
143 JNIEnv* env = base::android::AttachCurrentThread(); 227 JNIEnv* env = base::android::AttachCurrentThread();
144 return Java_ViewAndroidDelegate_getContainerView(env, delegate); 228 return Java_ViewAndroidDelegate_getContainerView(env, delegate);
145 } 229 }
(...skipping 24 matching lines...) Expand all
170 } 254 }
171 255
172 cc::Layer* ViewAndroid::GetLayer() const { 256 cc::Layer* ViewAndroid::GetLayer() const {
173 return layer_.get(); 257 return layer_.get();
174 } 258 }
175 259
176 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { 260 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
177 layer_ = layer; 261 layer_ = layer;
178 } 262 }
179 263
264 void ViewAndroid::SetLayout(int x,
265 int y,
266 int width,
267 int height,
268 bool match_parent) {
269 DCHECK(!match_parent || (x == 0 && y == 0 && width == 0 && height == 0))
270 << "Should give empty dimension when view layout matches its parent. "
271 << "match_parent: " << match_parent << " x: " << x << " y: " << y
272 << " width: " << width << " height: " << height;
273 origin_.SetPoint(x, y);
274 size_.SetSize(width, height);
275 match_parent_ = match_parent;
276 }
277
180 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, 278 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
181 const JavaRef<jobject>& jimage) { 279 const JavaRef<jobject>& jimage) {
182 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 280 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
183 if (delegate.is_null()) 281 if (delegate.is_null())
184 return false; 282 return false;
185 JNIEnv* env = base::android::AttachCurrentThread(); 283 JNIEnv* env = base::android::AttachCurrentThread();
186 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, 284 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext,
187 jimage); 285 jimage);
188 } 286 }
189 287
(...skipping 30 matching lines...) Expand all
220 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 318 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
221 if (delegate.is_null()) 319 if (delegate.is_null())
222 return; 320 return;
223 JNIEnv* env = base::android::AttachCurrentThread(); 321 JNIEnv* env = base::android::AttachCurrentThread();
224 ScopedJavaLocalRef<jstring> jcontent_url = 322 ScopedJavaLocalRef<jstring> jcontent_url =
225 ConvertUTF8ToJavaString(env, content_url.spec()); 323 ConvertUTF8ToJavaString(env, content_url.spec());
226 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url, 324 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url,
227 is_main_frame); 325 is_main_frame);
228 } 326 }
229 327
328 bool ViewAndroid::OnTouchEvent(const MotionEventAndroid& event,
329 bool for_touch_handle) {
330 return HitTest(TouchEventSender(for_touch_handle), event);
331 }
332
333 bool ViewAndroid::OnMouseEvent(const MotionEventAndroid& event) {
334 return HitTest(MouseEventSender(), event);
335 }
336
337 bool ViewAndroid::HitTest(const EventSender& es,
boliu 2017/03/03 22:01:32 what you need here is argument binding, which of c
Jinsuk Kim 2017/03/06 04:07:34 Maybe I need your help on this. I tried Bind here
338 const MotionEventAndroid& event) {
339 if (!children_.empty()) {
340 MotionEventAndroid e(event, -origin_.x(), -origin_.y());
341
342 // Match from back to front for hit testing.
343 for (auto* child : base::Reversed(children_)) {
344 bool matched = child->match_parent_;
345 if (!matched) {
346 gfx::Rect bound(child->origin_, child->size_);
347 matched = bound.Contains(e.GetX(0), e.GetY(0));
348 }
349 if (matched && es.SendToView(child, e))
Khushal 2017/03/03 23:36:08 Given that we first send the event to the children
Jinsuk Kim 2017/03/06 04:07:34 You're correct. See my other comment about switchi
350 return true;
351 }
352 }
353 return client_ && es.SendToClient(client_, event);
354 }
355
230 } // namespace ui 356 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698