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

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

Issue 2708613002: Add EventForwarder for routing touch events (Closed)
Patch Set: comment 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
24 ViewAndroid::ScopedAnchorView::ScopedAnchorView( 27 ViewAndroid::ScopedAnchorView::ScopedAnchorView(
25 JNIEnv* env, 28 JNIEnv* env,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 view_.reset(); 67 view_.reset();
65 delegate_.reset(); 68 delegate_.reset();
66 } 69 }
67 70
68 const base::android::ScopedJavaLocalRef<jobject> 71 const base::android::ScopedJavaLocalRef<jobject>
69 ViewAndroid::ScopedAnchorView::view() const { 72 ViewAndroid::ScopedAnchorView::view() const {
70 JNIEnv* env = base::android::AttachCurrentThread(); 73 JNIEnv* env = base::android::AttachCurrentThread();
71 return view_.get(env); 74 return view_.get(env);
72 } 75 }
73 76
74 ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) 77 ViewAndroid::ViewAndroid(ViewClient* view_client)
75 : parent_(nullptr), 78 : parent_(nullptr),
76 delegate_(base::android::AttachCurrentThread(), delegate.obj()) {} 79 client_(view_client),
80 layout_params_(LayoutParams::MatchParent()) {}
77 81
78 ViewAndroid::ViewAndroid() : parent_(nullptr) {} 82 ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
79 83
80 ViewAndroid::~ViewAndroid() { 84 ViewAndroid::~ViewAndroid() {
81 RemoveFromParent(); 85 RemoveFromParent();
82 86
83 for (std::list<ViewAndroid*>::iterator it = children_.begin(); 87 for (std::list<ViewAndroid*>::iterator it = children_.begin();
84 it != children_.end(); it++) { 88 it != children_.end(); it++) {
85 DCHECK_EQ((*it)->parent_, this); 89 DCHECK_EQ((*it)->parent_, this);
86 (*it)->parent_ = nullptr; 90 (*it)->parent_ = nullptr;
87 } 91 }
88 } 92 }
89 93
90 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) { 94 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) {
95 // A ViewAndroid may have its own delegate or otherwise will use the next
96 // available parent's delegate.
91 JNIEnv* env = base::android::AttachCurrentThread(); 97 JNIEnv* env = base::android::AttachCurrentThread();
92 delegate_ = JavaObjectWeakGlobalRef(env, delegate); 98 delegate_ = JavaObjectWeakGlobalRef(env, delegate);
93 } 99 }
94 100
101 float ViewAndroid::GetDipScale() {
102 return ui::GetScaleFactorForNativeView(this);
103 }
104
105 ScopedJavaLocalRef<jobject> ViewAndroid::GetEventHandler() {
106 if (!event_handler_) {
107 DCHECK(!ViewTreeHasEventHandler(this))
108 << "Root of the ViewAndroid can have at most one handler.";
109 event_handler_.reset(new EventHandler(this));
110 }
111 return event_handler_->GetJavaObject();
112 }
113
95 void ViewAndroid::AddChild(ViewAndroid* child) { 114 void ViewAndroid::AddChild(ViewAndroid* child) {
96 DCHECK(child); 115 DCHECK(child);
97 DCHECK(std::find(children_.begin(), children_.end(), child) == 116 DCHECK(std::find(children_.begin(), children_.end(), child) ==
98 children_.end()); 117 children_.end());
118 DCHECK(!SubtreeHasEventHandler(child) || !ViewTreeHasEventHandler(this))
119 << "Only one event handler is allowed.";
99 120
121 // The new child goes to the top, which is the end of the list.
100 children_.push_back(child); 122 children_.push_back(child);
101 if (child->parent_) 123 if (child->parent_)
102 child->RemoveFromParent(); 124 child->RemoveFromParent();
103 child->parent_ = this; 125 child->parent_ = this;
104 } 126 }
105 127
128 // static
129 bool ViewAndroid::ViewTreeHasEventHandler(ViewAndroid* view) {
130 ViewAndroid* v = view;
131 do {
132 if (v->has_event_handler())
133 return true;
134 v = v->parent_;
135 } while (v);
136 return SubtreeHasEventHandler(view);
137 }
138
139 // static
140 bool ViewAndroid::SubtreeHasEventHandler(ViewAndroid* view) {
141 if (view->has_event_handler())
142 return true;
143 for (auto* child : view->children_) {
144 if (SubtreeHasEventHandler(child))
145 return true;
146 }
147 return false;
148 }
149
150 void ViewAndroid::MoveToFront(ViewAndroid* child) {
151 DCHECK(child);
152 auto it = std::find(children_.begin(), children_.end(), child);
153 DCHECK(it != children_.end());
154
155 // Top element is placed at the end of the list.
156 if (*it != children_.back())
157 children_.splice(children_.end(), children_, it);
158 }
159
106 void ViewAndroid::RemoveFromParent() { 160 void ViewAndroid::RemoveFromParent() {
107 if (parent_) 161 if (parent_)
108 parent_->RemoveChild(this); 162 parent_->RemoveChild(this);
109 } 163 }
110 164
111 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { 165 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() {
112 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 166 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
113 if (delegate.is_null()) 167 if (delegate.is_null())
114 return ViewAndroid::ScopedAnchorView(); 168 return ViewAndroid::ScopedAnchorView();
115 169
116 JNIEnv* env = base::android::AttachCurrentThread(); 170 JNIEnv* env = base::android::AttachCurrentThread();
117 return ViewAndroid::ScopedAnchorView( 171 return ViewAndroid::ScopedAnchorView(
118 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); 172 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate);
119 } 173 }
120 174
121 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, 175 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor,
122 const gfx::RectF& bounds) { 176 const gfx::RectF& bounds) {
123 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 177 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
124 if (delegate.is_null()) 178 if (delegate.is_null())
125 return; 179 return;
126 180
127 float scale = display::Screen::GetScreen() 181 float dip_scale = GetDipScale();
128 ->GetDisplayNearestWindow(this) 182 int left_margin = std::round(bounds.x() * dip_scale);
129 .device_scale_factor(); 183 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(); 184 JNIEnv* env = base::android::AttachCurrentThread();
133 Java_ViewAndroidDelegate_setViewPosition( 185 Java_ViewAndroidDelegate_setViewPosition(
134 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), 186 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(),
135 bounds.height(), scale, left_margin, top_margin); 187 bounds.height(), dip_scale, left_margin, top_margin);
136 } 188 }
137 189
138 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { 190 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
139 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 191 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
140 if (delegate.is_null()) 192 if (delegate.is_null())
141 return nullptr; 193 return nullptr;
142 194
143 JNIEnv* env = base::android::AttachCurrentThread(); 195 JNIEnv* env = base::android::AttachCurrentThread();
144 return Java_ViewAndroidDelegate_getContainerView(env, delegate); 196 return Java_ViewAndroidDelegate_getContainerView(env, delegate);
145 } 197 }
(...skipping 24 matching lines...) Expand all
170 } 222 }
171 223
172 cc::Layer* ViewAndroid::GetLayer() const { 224 cc::Layer* ViewAndroid::GetLayer() const {
173 return layer_.get(); 225 return layer_.get();
174 } 226 }
175 227
176 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { 228 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
177 layer_ = layer; 229 layer_ = layer;
178 } 230 }
179 231
232 void ViewAndroid::SetLayout(ViewAndroid::LayoutParams params) {
233 layout_params_ = params;
234 }
235
180 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, 236 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
181 const JavaRef<jobject>& jimage) { 237 const JavaRef<jobject>& jimage) {
182 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 238 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
183 if (delegate.is_null()) 239 if (delegate.is_null())
184 return false; 240 return false;
185 JNIEnv* env = base::android::AttachCurrentThread(); 241 JNIEnv* env = base::android::AttachCurrentThread();
186 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, 242 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext,
187 jimage); 243 jimage);
188 } 244 }
189 245
(...skipping 30 matching lines...) Expand all
220 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 276 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
221 if (delegate.is_null()) 277 if (delegate.is_null())
222 return; 278 return;
223 JNIEnv* env = base::android::AttachCurrentThread(); 279 JNIEnv* env = base::android::AttachCurrentThread();
224 ScopedJavaLocalRef<jstring> jcontent_url = 280 ScopedJavaLocalRef<jstring> jcontent_url =
225 ConvertUTF8ToJavaString(env, content_url.spec()); 281 ConvertUTF8ToJavaString(env, content_url.spec());
226 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url, 282 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url,
227 is_main_frame); 283 is_main_frame);
228 } 284 }
229 285
286 bool ViewAndroid::OnTouchEvent(const MotionEventAndroid& event,
287 bool for_touch_handle) {
288 return HitTest(
289 base::Bind(&ViewAndroid::SendTouchEventToClient, for_touch_handle),
290 event);
291 }
292
293 bool ViewAndroid::SendTouchEventToClient(bool for_touch_handle,
294 ViewClient* client,
295 const MotionEventAndroid& event) {
296 return client->OnTouchEvent(event, for_touch_handle);
297 }
298
299 bool ViewAndroid::OnMouseEvent(const MotionEventAndroid& event) {
300 return HitTest(base::Bind(&ViewAndroid::SendMouseEventToClient), event);
301 }
302
303 bool ViewAndroid::SendMouseEventToClient(ViewClient* client,
304 const MotionEventAndroid& event) {
305 return client->OnMouseEvent(event);
306 }
307
308 bool ViewAndroid::HitTest(
309 const base::Callback<bool(ViewClient*, const MotionEventAndroid&)>
310 send_to_client,
311 const MotionEventAndroid& event) {
312 if (client_ && send_to_client.Run(client_, event))
313 return true;
314
315 if (!children_.empty()) {
316 std::unique_ptr<MotionEventAndroid> e(
317 event.Offset(-layout_params_.x, -layout_params_.y));
318
319 // Match from back to front for hit testing.
320 for (auto* child : base::Reversed(children_)) {
321 bool matched = child->layout_params_.match_parent;
322 if (!matched) {
323 gfx::Rect bound(child->layout_params_.x, child->layout_params_.y,
324 child->layout_params_.width,
325 child->layout_params_.height);
326 matched = bound.Contains(e->GetX(0), e->GetY(0));
327 }
328 if (matched && child->HitTest(send_to_client, *e))
329 return true;
330 }
331 }
332 return false;
333 }
334
230 } // namespace ui 335 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698