Index: ui/android/view_android.cc |
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc |
index b1ea3608998b81ce71032739ac0ee9da3c88367f..4e969e25a7a314db9bbc462d843e07ff32bb96bd 100644 |
--- a/ui/android/view_android.cc |
+++ b/ui/android/view_android.cc |
@@ -8,15 +8,71 @@ |
#include "base/android/jni_android.h" |
#include "cc/layers/layer.h" |
+#include "jni/ViewAndroidDelegate_jni.h" |
#include "ui/android/window_android.h" |
- |
+#include "ui/display/display.h" |
+#include "ui/display/screen.h" |
namespace ui { |
using base::android::JavaRef; |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView( |
+ JNIEnv* env, |
+ const JavaRef<jobject>& jview, |
+ const JavaRef<jobject>& jdelegate) |
+ : view_(env, jview.obj()), delegate_(env, jdelegate.obj()) { |
+ // If there's a view, then we need a delegate to remove it. |
+ DCHECK(!jdelegate.is_null() || jview.is_null()); |
+} |
+ |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView() { } |
+ |
+ViewAndroid::ScopedAnchorView::ScopedAnchorView(ScopedAnchorView&& other) { |
+ view_ = other.view_; |
+ other.view_.reset(); |
+ delegate_ = other.delegate_; |
+ other.delegate_.reset(); |
+} |
+ |
+ViewAndroid::ScopedAnchorView& |
+ViewAndroid::ScopedAnchorView::operator=(ScopedAnchorView&& other) { |
+ if (this != &other) { |
+ view_ = other.view_; |
+ other.view_.reset(); |
+ delegate_ = other.delegate_; |
+ other.delegate_.reset(); |
+ } |
+ return *this; |
+} |
+ |
+ViewAndroid::ScopedAnchorView::~ScopedAnchorView() { |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ const ScopedJavaLocalRef<jobject> view = view_.get(env); |
+ const ScopedJavaLocalRef<jobject> delegate = delegate_.get(env); |
+ if (!view.is_null() && !delegate.is_null()) { |
+ Java_ViewAndroidDelegate_removeView(env, |
+ delegate.obj(), |
+ view.obj()); |
+ } |
+ view_.reset(); |
+} |
+ |
+void ViewAndroid::ScopedAnchorView::Reset() { |
+ view_.reset(); |
+ delegate_.reset(); |
+} |
+ |
+const base::android::ScopedJavaLocalRef<jobject> |
+ViewAndroid::ScopedAnchorView::view() const { |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ return view_.get(env); |
+} |
+ |
ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) |
- : parent_(nullptr), delegate_(delegate) {} |
+ : parent_(nullptr) |
+ , delegate_(base::android::AttachCurrentThread(), |
+ delegate.obj()) {} |
ViewAndroid::ViewAndroid() : parent_(nullptr) {} |
@@ -46,6 +102,48 @@ 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( |
+ env, |
+ 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; |
+ |
+ float scale = display::Screen::GetScreen() |
+ ->GetDisplayNearestWindow(this) |
+ .device_scale_factor(); |
+ 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); |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ 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,12 +159,14 @@ WindowAndroid* ViewAndroid::GetWindowAndroid() const { |
return parent_ ? parent_->GetWindowAndroid() : nullptr; |
} |
-const JavaRef<jobject>& ViewAndroid::GetViewAndroidDelegate() |
+const ScopedJavaLocalRef<jobject> ViewAndroid::GetViewAndroidDelegate() |
const { |
- if (!delegate_.is_null()) |
- return delegate_; |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ const ScopedJavaLocalRef<jobject> delegate = delegate_.get(env); |
+ if (!delegate.is_null()) |
+ return delegate; |
- return parent_ ? parent_->GetViewAndroidDelegate() : delegate_; |
+ return parent_ ? parent_->GetViewAndroidDelegate() : delegate; |
} |
cc::Layer* ViewAndroid::GetLayer() const { |
@@ -79,11 +179,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) |
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); |
+ if (delegate.is_null()) |
return; |
- |
- window_android->StartDragAndDrop(GetViewAndroidDelegate(), jtext, jimage); |
+ JNIEnv* env = base::android::AttachCurrentThread(); |
+ Java_ViewAndroidDelegate_startDragAndDrop(env, |
+ delegate.obj(), |
+ jtext.obj(), |
+ jimage.obj()); |
} |
} // namespace ui |