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())) | |
| 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() { | |
| 109 DCHECK(parent_) << "View is not attached to a tree yet."; | |
| 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 | |
| 106 void ViewAndroid::RemoveFromParent() { | 141 void ViewAndroid::RemoveFromParent() { |
| 107 if (parent_) | 142 if (parent_) |
| 108 parent_->RemoveChild(this); | 143 parent_->RemoveChild(this); |
| 109 } | 144 } |
| 110 | 145 |
| 111 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { | 146 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { |
| 112 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); | 147 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
| 113 if (delegate.is_null()) | 148 if (delegate.is_null()) |
| 114 return ViewAndroid::ScopedAnchorView(); | 149 return ViewAndroid::ScopedAnchorView(); |
| 115 | 150 |
| 116 JNIEnv* env = base::android::AttachCurrentThread(); | 151 JNIEnv* env = base::android::AttachCurrentThread(); |
| 117 return ViewAndroid::ScopedAnchorView( | 152 return ViewAndroid::ScopedAnchorView( |
| 118 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); | 153 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); |
| 119 } | 154 } |
| 120 | 155 |
| 121 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, | 156 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, |
| 122 const gfx::RectF& bounds) { | 157 const gfx::RectF& bounds) { |
| 123 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); | 158 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
| 124 if (delegate.is_null()) | 159 if (delegate.is_null()) |
| 125 return; | 160 return; |
| 126 | 161 |
| 127 float scale = display::Screen::GetScreen() | 162 float dip_scale = GetDipScale(); |
| 128 ->GetDisplayNearestWindow(this) | 163 int left_margin = std::round(bounds.x() * dip_scale); |
| 129 .device_scale_factor(); | 164 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(); | 165 JNIEnv* env = base::android::AttachCurrentThread(); |
| 133 Java_ViewAndroidDelegate_setViewPosition( | 166 Java_ViewAndroidDelegate_setViewPosition( |
| 134 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), | 167 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), |
| 135 bounds.height(), scale, left_margin, top_margin); | 168 bounds.height(), dip_scale, left_margin, top_margin); |
| 136 } | 169 } |
| 137 | 170 |
| 138 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { | 171 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { |
| 139 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); | 172 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
| 140 if (delegate.is_null()) | 173 if (delegate.is_null()) |
| 141 return nullptr; | 174 return nullptr; |
| 142 | 175 |
| 143 JNIEnv* env = base::android::AttachCurrentThread(); | 176 JNIEnv* env = base::android::AttachCurrentThread(); |
| 144 return Java_ViewAndroidDelegate_getContainerView(env, delegate); | 177 return Java_ViewAndroidDelegate_getContainerView(env, delegate); |
| 145 } | 178 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 170 } | 203 } |
| 171 | 204 |
| 172 cc::Layer* ViewAndroid::GetLayer() const { | 205 cc::Layer* ViewAndroid::GetLayer() const { |
| 173 return layer_.get(); | 206 return layer_.get(); |
| 174 } | 207 } |
| 175 | 208 |
| 176 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { | 209 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { |
| 177 layer_ = layer; | 210 layer_ = layer; |
| 178 } | 211 } |
| 179 | 212 |
| 213 void ViewAndroid::SetLayout(int x, | |
| 214 int y, | |
| 215 int width, | |
| 216 int height, | |
| 217 bool match_parent) { | |
| 218 DCHECK(!match_parent || (x == 0 && y == 0 && width == 0 && height == 0)); | |
|
boliu
2017/02/28 22:44:54
can you write this in a way such that when it fail
Jinsuk Kim
2017/03/02 04:08:35
Added a message about the condition when |match_pa
| |
| 219 origin_.SetPoint(x, y); | |
| 220 size_.SetSize(width, height); | |
| 221 match_parent_ = match_parent; | |
| 222 } | |
| 223 | |
| 180 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, | 224 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, |
| 181 const JavaRef<jobject>& jimage) { | 225 const JavaRef<jobject>& jimage) { |
| 182 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); | 226 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
| 183 if (delegate.is_null()) | 227 if (delegate.is_null()) |
| 184 return false; | 228 return false; |
| 185 JNIEnv* env = base::android::AttachCurrentThread(); | 229 JNIEnv* env = base::android::AttachCurrentThread(); |
| 186 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, | 230 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, |
| 187 jimage); | 231 jimage); |
| 188 } | 232 } |
| 189 | 233 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 220 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); | 264 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
| 221 if (delegate.is_null()) | 265 if (delegate.is_null()) |
| 222 return; | 266 return; |
| 223 JNIEnv* env = base::android::AttachCurrentThread(); | 267 JNIEnv* env = base::android::AttachCurrentThread(); |
| 224 ScopedJavaLocalRef<jstring> jcontent_url = | 268 ScopedJavaLocalRef<jstring> jcontent_url = |
| 225 ConvertUTF8ToJavaString(env, content_url.spec()); | 269 ConvertUTF8ToJavaString(env, content_url.spec()); |
| 226 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url, | 270 Java_ViewAndroidDelegate_onStartContentIntent(env, delegate, jcontent_url, |
| 227 is_main_frame); | 271 is_main_frame); |
| 228 } | 272 } |
| 229 | 273 |
| 274 bool ViewAndroid::OnTouchEvent(const MotionEventData& event) { | |
| 275 if (!children_.empty()) { | |
| 276 const MotionEventData& e = | |
| 277 origin_.IsOrigin() ? event : event.Offset(-origin_.x(), -origin_.y()); | |
| 278 | |
| 279 for (auto it = children_.rbegin(); it != children_.rend(); ++it) { | |
| 280 bool matched = (*it)->match_parent_; | |
| 281 if (!matched) { | |
| 282 gfx::Rect bound((*it)->origin_, (*it)->size_); | |
| 283 matched = bound.Contains(e.GetX(), e.GetY()); | |
| 284 } | |
| 285 if (matched && (*it)->OnTouchEvent(e)) | |
| 286 return true; | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 if (client_ && client_->OnTouchEvent(event)) | |
| 291 return true; | |
| 292 | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 bool ViewAndroid::OnMouseEvent(const MotionEventData& event) { | |
| 297 if (!children_.empty()) { | |
| 298 const MotionEventData& e = | |
| 299 origin_.IsOrigin() ? event : event.Offset(-origin_.x(), -origin_.y()); | |
| 300 | |
| 301 for (auto it = children_.rbegin(); it != children_.rend(); ++it) { | |
| 302 bool matched = (*it)->match_parent_; | |
| 303 if (!matched) { | |
| 304 gfx::Rect bound((*it)->origin_, (*it)->size_); | |
| 305 matched = bound.Contains(e.GetX(), e.GetY()); | |
| 306 } | |
| 307 if (matched && (*it)->OnMouseEvent(e)) | |
| 308 return true; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 if (client_ && client_->OnMouseEvent(event)) | |
| 313 return true; | |
| 314 | |
| 315 return false; | |
| 316 } | |
| 317 | |
| 230 } // namespace ui | 318 } // namespace ui |
| OLD | NEW |