| 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 "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_forwarder.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 Loading... |
| 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::GetEventForwarder() { |
| 106 if (!event_forwarder_) { |
| 107 DCHECK(!ViewTreeHasEventForwarder(this)) |
| 108 << "Root of the ViewAndroid can have at most one handler."; |
| 109 event_forwarder_.reset(new EventForwarder(this)); |
| 110 } |
| 111 return event_forwarder_->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(!SubtreeHasEventForwarder(child) || !ViewTreeHasEventForwarder(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::ViewTreeHasEventForwarder(ViewAndroid* view) { |
| 130 ViewAndroid* v = view; |
| 131 do { |
| 132 if (v->has_event_forwarder()) |
| 133 return true; |
| 134 v = v->parent_; |
| 135 } while (v); |
| 136 return SubtreeHasEventForwarder(view); |
| 137 } |
| 138 |
| 139 // static |
| 140 bool ViewAndroid::SubtreeHasEventForwarder(ViewAndroid* view) { |
| 141 if (view->has_event_forwarder()) |
| 142 return true; |
| 143 for (auto* child : view->children_) { |
| 144 if (SubtreeHasEventForwarder(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 Loading... |
| 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 Loading... |
| 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(ViewClientCallback send_to_client, |
| 309 const MotionEventAndroid& event) { |
| 310 if (client_ && send_to_client.Run(client_, event)) |
| 311 return true; |
| 312 |
| 313 if (!children_.empty()) { |
| 314 std::unique_ptr<MotionEventAndroid> e( |
| 315 event.Offset(-layout_params_.x, -layout_params_.y)); |
| 316 |
| 317 // Match from back to front for hit testing. |
| 318 for (auto* child : base::Reversed(children_)) { |
| 319 bool matched = child->layout_params_.match_parent; |
| 320 if (!matched) { |
| 321 gfx::Rect bound(child->layout_params_.x, child->layout_params_.y, |
| 322 child->layout_params_.width, |
| 323 child->layout_params_.height); |
| 324 matched = bound.Contains(e->GetX(0), e->GetY(0)); |
| 325 } |
| 326 if (matched && child->HitTest(send_to_client, *e)) |
| 327 return true; |
| 328 } |
| 329 } |
| 330 return false; |
| 331 } |
| 332 |
| 230 } // namespace ui | 333 } // namespace ui |
| OLD | NEW |