Index: ui/android/view_android.cc |
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc |
index b1ea3608998b81ce71032739ac0ee9da3c88367f..0c6c9301df88408e0519a44c4add03c3eb948710 100644 |
--- a/ui/android/view_android.cc |
+++ b/ui/android/view_android.cc |
@@ -8,13 +8,53 @@ |
#include "base/android/jni_android.h" |
#include "cc/layers/layer.h" |
+#include "jni/ViewAndroidDelegate_jni.h" |
#include "ui/android/window_android.h" |
- |
+#include "ui/base/layout.h" |
namespace ui { |
using base::android::JavaRef; |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView( |
+ const JavaRef<jobject>& jview, |
+ const JavaRef<jobject>& jdelegate) |
+ : view_(jview), delegate_(jdelegate) { |
+ // If there's a view, then we need a delegate to remove it. |
+ DCHECK(!jdelegate.is_null() || jview.is_null()); |
+} |
+ |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView() |
+ : ScopedAnchorView(nullptr, nullptr) { } |
+ |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView(ScopedAnchorView&& other) { |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ view_.Reset(env, other.view_.Release()); |
+ delegate_.Reset(env, other.delegate_.Release()); |
+} |
+ |
+ViewAndroid::ScopedAnchorView& |
+ViewAndroid::ScopedAnchorView::operator=(ScopedAnchorView&& other) { |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ if (this != &other) { |
+ view_.Reset(env, other.view_.Release()); |
+ delegate_.Reset(env, other.delegate_.Release()); |
+ } |
+ return *this; |
+} |
+ |
+ViewAndroid::ScopedAnchorView::~ScopedAnchorView() { |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ if (!view_.is_null()) |
+ Java_ViewAndroidDelegate_removeView(env, delegate_.obj(), view_.obj()); |
+ view_.Reset(); |
+} |
+ |
+void ViewAndroid::ScopedAnchorView::Reset() { |
+ view_.Reset(); |
+ delegate_.Reset(); |
+} |
+ |
ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) |
: parent_(nullptr), delegate_(delegate) {} |
@@ -30,6 +70,10 @@ ViewAndroid::~ViewAndroid() { |
} |
} |
+bool ViewAndroid::RegisterViewAndroid(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
void ViewAndroid::AddChild(ViewAndroid* child) { |
DCHECK(child); |
DCHECK(std::find(children_.begin(), children_.end(), child) == |
@@ -46,6 +90,44 @@ void ViewAndroid::RemoveFromParent() { |
parent_->RemoveChild(this); |
} |
+ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { |
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
+ if (delegate.is_null()) |
+ return ViewAndroid::ScopedAnchorView(); |
+ |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ return ViewAndroid::ScopedAnchorView( |
+ Java_ViewAndroidDelegate_acquireView(env, delegate.obj()), |
+ delegate); |
+} |
+ |
+void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, |
+ const gfx::RectF& bounds) { |
+ if (bounds.IsEmpty()) return; |
+ |
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
+ if (delegate.is_null()) |
+ return; |
+ |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ float scale = GetScaleFactorForNativeView(this); |
+ int left_margin = std::round(bounds.x() * scale); |
+ // TODO(jinsukkim): Move content_offset() to ViewAndroid, since it's |
+ // specific to a given web contents/render widget. |
+ float content_offset_y_pix = GetWindowAndroid()->content_offset().y(); |
+ int top_margin = std::round(content_offset_y_pix + bounds.y() * scale); |
+ Java_ViewAndroidDelegate_setViewPosition(env, |
+ delegate.obj(), |
+ anchor.obj(), |
+ bounds.x(), |
+ bounds.y(), |
+ bounds.width(), |
+ bounds.height(), |
+ scale, |
+ left_margin, |
+ top_margin); |
+} |
+ |
void ViewAndroid::RemoveChild(ViewAndroid* child) { |
DCHECK(child); |
DCHECK_EQ(child->parent_, this); |
@@ -61,8 +143,7 @@ WindowAndroid* ViewAndroid::GetWindowAndroid() const { |
return parent_ ? parent_->GetWindowAndroid() : nullptr; |
} |
-const JavaRef<jobject>& ViewAndroid::GetViewAndroidDelegate() |
- const { |
+const JavaRef<jobject>& ViewAndroid::GetViewAndroidDelegate() const { |
if (!delegate_.is_null()) |
return delegate_; |
@@ -79,11 +160,14 @@ void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { |
void ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, |
const JavaRef<jobject>& jimage) { |
- WindowAndroid* window_android = GetWindowAndroid(); |
- if (!window_android) |
- return; |
- |
- window_android->StartDragAndDrop(GetViewAndroidDelegate(), jtext, jimage); |
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
+ if (delegate.is_null()) |
+ return; |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ Java_ViewAndroidDelegate_startDragAndDrop(env, |
+ delegate.obj(), |
+ jtext.obj(), |
+ jimage.obj()); |
} |
} // namespace ui |