Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |