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

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

Issue 2708613002: Add EventForwarder for routing touch events (Closed)
Patch Set: unittests 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 "cc/layers/layer.h" 11 #include "cc/layers/layer.h"
12 #include "jni/ViewAndroidDelegate_jni.h" 12 #include "jni/ViewAndroidDelegate_jni.h"
13 #include "ui/android/event_handler.h"
14 #include "ui/android/view_client.h"
13 #include "ui/android/window_android.h" 15 #include "ui/android/window_android.h"
14 #include "ui/display/display.h" 16 #include "ui/base/layout.h"
15 #include "ui/display/screen.h"
16 #include "url/gurl.h" 17 #include "url/gurl.h"
17 18
18 namespace ui { 19 namespace ui {
19 20
20 using base::android::ConvertUTF8ToJavaString; 21 using base::android::ConvertUTF8ToJavaString;
21 using base::android::JavaRef; 22 using base::android::JavaRef;
22 using base::android::ScopedJavaLocalRef; 23 using base::android::ScopedJavaLocalRef;
23 24
24 ViewAndroid::ScopedAnchorView::ScopedAnchorView( 25 ViewAndroid::ScopedAnchorView::ScopedAnchorView(
25 JNIEnv* env, 26 JNIEnv* env,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 view_.reset(); 65 view_.reset();
65 delegate_.reset(); 66 delegate_.reset();
66 } 67 }
67 68
68 const base::android::ScopedJavaLocalRef<jobject> 69 const base::android::ScopedJavaLocalRef<jobject>
69 ViewAndroid::ScopedAnchorView::view() const { 70 ViewAndroid::ScopedAnchorView::view() const {
70 JNIEnv* env = base::android::AttachCurrentThread(); 71 JNIEnv* env = base::android::AttachCurrentThread();
71 return view_.get(env); 72 return view_.get(env);
72 } 73 }
73 74
74 ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) 75 ViewAndroid::ViewAndroid(ViewClient* view_client)
75 : parent_(nullptr), 76 : parent_(nullptr), client_(view_client) {}
76 delegate_(base::android::AttachCurrentThread(), delegate.obj()) {}
77 77
78 ViewAndroid::ViewAndroid() : parent_(nullptr) {} 78 ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
79 79
80 ViewAndroid::~ViewAndroid() { 80 ViewAndroid::~ViewAndroid() {
81 RemoveFromParent(); 81 RemoveFromParent();
82 82
83 for (std::list<ViewAndroid*>::iterator it = children_.begin(); 83 for (std::list<ViewAndroid*>::iterator it = children_.begin();
84 it != children_.end(); it++) { 84 it != children_.end(); it++) {
85 DCHECK_EQ((*it)->parent_, this); 85 DCHECK_EQ((*it)->parent_, this);
86 (*it)->parent_ = nullptr; 86 (*it)->parent_ = nullptr;
87 } 87 }
88 } 88 }
89 89
90 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) { 90 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) {
91 // A ViewAndroid may have its own delegate or otherwise will use the next
92 // available parent's delegate.
91 JNIEnv* env = base::android::AttachCurrentThread(); 93 JNIEnv* env = base::android::AttachCurrentThread();
92 delegate_ = JavaObjectWeakGlobalRef(env, delegate); 94 delegate_ = JavaObjectWeakGlobalRef(env, delegate);
93 } 95 }
94 96
97 float ViewAndroid::GetDipScale() {
98 return ui::GetScaleFactorForNativeView(this);
99 }
100
101 EventHandler* ViewAndroid::CreateEventHandler() {
102 DCHECK(!ViewTreeHasEventHandler(GetViewRoot()))
Khushal 2017/03/02 21:46:15 That feels like a lot of unnecessary complexity ju
boliu 2017/03/02 22:02:16 I asked for these checks. Imo it's a correctness g
Khushal 2017/03/02 22:08:59 What 2 sources are we worried about? The event met
boliu 2017/03/02 22:17:41 I want to make sure nothing can be receiving event
Khushal 2017/03/02 22:34:34 Is there a good reason for why we need to have a c
boliu 2017/03/02 22:41:50 Can keep doing that *within* ViewAndroids/ViewClie
Khushal 2017/03/02 23:11:36 So here is where my understanding of source. We ar
boliu 2017/03/02 23:16:06 Totally disagree with that assessment. Having any
Khushal 2017/03/03 00:37:55 Okay, if you know this has caused pain in the past
Jinsuk Kim 2017/03/03 06:29:21 Hid native EventHandler instance (owned by ViewAnd
103 << "Root of the ViewAndroid can have at most one handler.";
104 event_handler_.reset(EventHandler::Create(this));
105 return event_handler_.get();
106 }
107
108 ViewAndroid* ViewAndroid::GetViewRoot() {
boliu 2017/03/02 20:58:14 So.. viewroot is the immediate children of windowa
Jinsuk Kim 2017/03/03 06:29:21 Removed GetViewRoot(). It was used for |ViewTreeHa
109 DCHECK(parent_) << "View is not attached to a tree yet.";
Khushal 2017/03/02 21:46:15 nit: This doesn't really need to be a DCHECK. Just
Jinsuk Kim 2017/03/03 06:29:22 Removed this method.
110
111 // The root of VA tree is that of WCVA for now.
112 return parent_ == GetWindowAndroid() ? this : nullptr;
113 }
114
95 void ViewAndroid::AddChild(ViewAndroid* child) { 115 void ViewAndroid::AddChild(ViewAndroid* child) {
96 DCHECK(child); 116 DCHECK(child);
97 DCHECK(std::find(children_.begin(), children_.end(), child) == 117 DCHECK(std::find(children_.begin(), children_.end(), child) ==
98 children_.end()); 118 children_.end());
119 DCHECK(!ViewTreeHasEventHandler(child) ||
120 !ViewTreeHasEventHandler(GetViewRoot()))
121 << "Only one event handler is allowed.";
99 122
123 // The new child goes to the top, which is the end of the list.
100 children_.push_back(child); 124 children_.push_back(child);
101 if (child->parent_) 125 if (child->parent_)
102 child->RemoveFromParent(); 126 child->RemoveFromParent();
103 child->parent_ = this; 127 child->parent_ = this;
104 } 128 }
105 129
130 // static
131 bool ViewAndroid::ViewTreeHasEventHandler(ViewAndroid* view) {
132 if (view->has_event_handler())
133 return true;
134 for (auto& child : view->children_) {
135 if (child->has_event_handler())
136 return true;
137 }
138 return false;
139 }
140
141 void ViewAndroid::MoveToTop(ViewAndroid* child) {
David Trainor- moved to gerrit 2017/03/03 23:04:34 MoveToFront feels more clear
Jinsuk Kim 2017/03/06 04:07:33 Done.
142 DCHECK(child);
143 auto it = std::find(children_.begin(), children_.end(), child);
144 DCHECK(it != children_.end());
145
146 // Top element is placed at the end of the list.
147 if (*it != children_.back())
148 children_.splice(children_.rbegin().base(), children_, it);
Khushal 2017/03/02 21:46:15 nit: children_.end() instead of children_.rbegin()
Jinsuk Kim 2017/03/03 06:29:22 Done.
149 }
150
106 void ViewAndroid::RemoveFromParent() { 151 void ViewAndroid::RemoveFromParent() {
107 if (parent_) 152 if (parent_)
108 parent_->RemoveChild(this); 153 parent_->RemoveChild(this);
109 } 154 }
110 155
111 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { 156 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() {
112 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 157 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
113 if (delegate.is_null()) 158 if (delegate.is_null())
114 return ViewAndroid::ScopedAnchorView(); 159 return ViewAndroid::ScopedAnchorView();
115 160
116 JNIEnv* env = base::android::AttachCurrentThread(); 161 JNIEnv* env = base::android::AttachCurrentThread();
117 return ViewAndroid::ScopedAnchorView( 162 return ViewAndroid::ScopedAnchorView(
118 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); 163 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate);
119 } 164 }
120 165
121 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, 166 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor,
122 const gfx::RectF& bounds) { 167 const gfx::RectF& bounds) {
123 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 168 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
124 if (delegate.is_null()) 169 if (delegate.is_null())
125 return; 170 return;
126 171
127 float scale = display::Screen::GetScreen() 172 float dip_scale = GetDipScale();
128 ->GetDisplayNearestWindow(this) 173 int left_margin = std::round(bounds.x() * dip_scale);
129 .device_scale_factor(); 174 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(); 175 JNIEnv* env = base::android::AttachCurrentThread();
133 Java_ViewAndroidDelegate_setViewPosition( 176 Java_ViewAndroidDelegate_setViewPosition(
134 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), 177 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(),
135 bounds.height(), scale, left_margin, top_margin); 178 bounds.height(), dip_scale, left_margin, top_margin);
136 } 179 }
137 180
138 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { 181 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
139 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 182 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
140 if (delegate.is_null()) 183 if (delegate.is_null())
141 return nullptr; 184 return nullptr;
142 185
143 JNIEnv* env = base::android::AttachCurrentThread(); 186 JNIEnv* env = base::android::AttachCurrentThread();
144 return Java_ViewAndroidDelegate_getContainerView(env, delegate); 187 return Java_ViewAndroidDelegate_getContainerView(env, delegate);
145 } 188 }
(...skipping 24 matching lines...) Expand all
170 } 213 }
171 214
172 cc::Layer* ViewAndroid::GetLayer() const { 215 cc::Layer* ViewAndroid::GetLayer() const {
173 return layer_.get(); 216 return layer_.get();
174 } 217 }
175 218
176 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { 219 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
177 layer_ = layer; 220 layer_ = layer;
178 } 221 }
179 222
223 void ViewAndroid::SetLayout(int x,
Khushal 2017/03/02 21:46:15 Do you want to split this into 2 methods: SetBound
Jinsuk Kim 2017/03/03 06:29:22 I haven't found a case that needs the splitting ye
boliu 2017/03/03 19:46:18 Actually, should not do split this. This is our ve
David Trainor- moved to gerrit 2017/03/03 23:04:34 The behavior of this feels a bit weird to me. mat
boliu 2017/03/03 23:10:27 We certainly do the same thing. Make a struct with
Khushal 2017/03/03 23:36:06 It looked a bit awkward for me to see an API where
Jinsuk Kim 2017/03/06 04:07:33 Added a struct to make match_parent and other para
224 int y,
225 int width,
226 int height,
227 bool match_parent) {
228 DCHECK(!match_parent || (x == 0 && y == 0 && width == 0 && height == 0))
229 << "Should give empty dimension when view layout matches its parent.";
boliu 2017/03/02 20:58:14 this can be better still. like if I trigger this D
Jinsuk Kim 2017/03/03 06:29:21 Logged all the parameters.
230 origin_.SetPoint(x, y);
231 size_.SetSize(width, height);
232 match_parent_ = match_parent;
233 }
234
180 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, 235 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
181 const JavaRef<jobject>& jimage) { 236 const JavaRef<jobject>& jimage) {
182 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 237 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
183 if (delegate.is_null()) 238 if (delegate.is_null())
184 return false; 239 return false;
185 JNIEnv* env = base::android::AttachCurrentThread(); 240 JNIEnv* env = base::android::AttachCurrentThread();
186 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, 241 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext,
187 jimage); 242 jimage);
188 } 243 }
189 244
(...skipping 30 matching lines...) Expand all
220 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 275 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
221 if (delegate.is_null()) 276 if (delegate.is_null())
222 return; 277 return;
223 JNIEnv* env = base::android::AttachCurrentThread(); 278 JNIEnv* env = base::android::AttachCurrentThread();
224 ScopedJavaLocalRef<jstring> jcontent_url = 279 ScopedJavaLocalRef<jstring> jcontent_url =
225 ConvertUTF8ToJavaString(env, content_url.spec()); 280 ConvertUTF8ToJavaString(env, content_url.spec());
226 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url, 281 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url,
227 is_main_frame); 282 is_main_frame);
228 } 283 }
229 284
285 bool ViewAndroid::OnTouchEvent(const MotionEventData& event) {
286 if (!children_.empty()) {
287 const MotionEventData& e =
288 origin_.IsOrigin() ? event : event.Offset(-origin_.x(), -origin_.y());
289
290 for (auto it = children_.rbegin(); it != children_.rend(); ++it) {
Khushal 2017/03/02 21:46:15 nit: for (auto* child : children_)?
boliu 2017/03/02 22:02:16 back to forward order is desired here. we modeled
Khushal 2017/03/02 22:08:59 Oh Duh, didn't notice that. Yeah, a comment for th
Jinsuk Kim 2017/03/03 06:29:22 Thanks for the suggestion. Reversed looks nicer. D
291 bool matched = (*it)->match_parent_;
292 if (!matched) {
293 gfx::Rect bound((*it)->origin_, (*it)->size_);
294 matched = bound.Contains(e.GetX(), e.GetY());
boliu 2017/03/02 20:58:14 can we abstract out hit testing into its own metho
Jinsuk Kim 2017/03/03 06:29:22 Good idea. Done.
295 }
296 if (matched && (*it)->OnTouchEvent(e))
297 return true;
298 }
299 }
300
301 if (client_ && client_->OnTouchEvent(event))
Khushal 2017/03/02 21:46:15 nit: return client_ ? client_->OnTouchEvent(event)
Jinsuk Kim 2017/03/03 06:29:22 Done.
302 return true;
303
304 return false;
305 }
306
307 bool ViewAndroid::OnMouseEvent(const MotionEventData& event) {
308 if (!children_.empty()) {
309 const MotionEventData& e =
310 origin_.IsOrigin() ? event : event.Offset(-origin_.x(), -origin_.y());
311
312 for (auto it = children_.rbegin(); it != children_.rend(); ++it) {
313 bool matched = (*it)->match_parent_;
314 if (!matched) {
315 gfx::Rect bound((*it)->origin_, (*it)->size_);
316 matched = bound.Contains(e.GetX(), e.GetY());
317 }
318 if (matched && (*it)->OnMouseEvent(e))
319 return true;
320 }
321 }
322
323 if (client_ && client_->OnMouseEvent(event))
324 return true;
325
326 return false;
327 }
328
230 } // namespace ui 329 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698