Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: ui/android/view_android.cc

Issue 2708613002: Add EventForwarder for routing touch events (Closed)
Patch Set: EventForwarder... Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/android/view_android.h ('k') | ui/android/view_android_unittests.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/android/view_android.cc
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc
index 1d5b146653458a83b93c58810f743f6df78e5c46..88ba8c0b5a681646df58e4c1180c1de9fb88fa68 100644
--- a/ui/android/view_android.cc
+++ b/ui/android/view_android.cc
@@ -8,11 +8,14 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/containers/adapters.h"
#include "cc/layers/layer.h"
#include "jni/ViewAndroidDelegate_jni.h"
+#include "ui/android/event_forwarder.h"
+#include "ui/android/view_client.h"
#include "ui/android/window_android.h"
-#include "ui/display/display.h"
-#include "ui/display/screen.h"
+#include "ui/base/layout.h"
+#include "ui/events/android/motion_event_android.h"
#include "url/gurl.h"
namespace ui {
@@ -71,11 +74,12 @@ ViewAndroid::ScopedAnchorView::view() const {
return view_.get(env);
}
-ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate)
+ViewAndroid::ViewAndroid(ViewClient* view_client)
: parent_(nullptr),
- delegate_(base::android::AttachCurrentThread(), delegate.obj()) {}
+ client_(view_client),
+ layout_params_(LayoutParams::MatchParent()) {}
-ViewAndroid::ViewAndroid() : parent_(nullptr) {}
+ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
ViewAndroid::~ViewAndroid() {
RemoveFromParent();
@@ -88,21 +92,71 @@ ViewAndroid::~ViewAndroid() {
}
void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) {
+ // A ViewAndroid may have its own delegate or otherwise will use the next
+ // available parent's delegate.
JNIEnv* env = base::android::AttachCurrentThread();
delegate_ = JavaObjectWeakGlobalRef(env, delegate);
}
+float ViewAndroid::GetDipScale() {
+ return ui::GetScaleFactorForNativeView(this);
+}
+
+ScopedJavaLocalRef<jobject> ViewAndroid::GetEventForwarder() {
+ if (!event_forwarder_) {
+ DCHECK(!ViewTreeHasEventForwarder(this))
+ << "Root of the ViewAndroid can have at most one handler.";
+ event_forwarder_.reset(new EventForwarder(this));
+ }
+ return event_forwarder_->GetJavaObject();
+}
+
void ViewAndroid::AddChild(ViewAndroid* child) {
DCHECK(child);
DCHECK(std::find(children_.begin(), children_.end(), child) ==
children_.end());
+ DCHECK(!SubtreeHasEventForwarder(child) || !ViewTreeHasEventForwarder(this))
+ << "Only one event handler is allowed.";
+ // The new child goes to the top, which is the end of the list.
children_.push_back(child);
if (child->parent_)
child->RemoveFromParent();
child->parent_ = this;
}
+// static
+bool ViewAndroid::ViewTreeHasEventForwarder(ViewAndroid* view) {
+ ViewAndroid* v = view;
+ do {
+ if (v->has_event_forwarder())
+ return true;
+ v = v->parent_;
+ } while (v);
+ return SubtreeHasEventForwarder(view);
+}
+
+// static
+bool ViewAndroid::SubtreeHasEventForwarder(ViewAndroid* view) {
+ if (view->has_event_forwarder())
+ return true;
+ for (auto* child : view->children_) {
+ if (SubtreeHasEventForwarder(child))
+ return true;
+ }
+ return false;
+}
+
+void ViewAndroid::MoveToFront(ViewAndroid* child) {
+ DCHECK(child);
+ auto it = std::find(children_.begin(), children_.end(), child);
+ DCHECK(it != children_.end());
+
+ // Top element is placed at the end of the list.
+ if (*it != children_.back())
+ children_.splice(children_.end(), children_, it);
+}
+
void ViewAndroid::RemoveFromParent() {
if (parent_)
parent_->RemoveChild(this);
@@ -124,15 +178,13 @@ void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor,
if (delegate.is_null())
return;
- float scale = display::Screen::GetScreen()
- ->GetDisplayNearestWindow(this)
- .device_scale_factor();
- int left_margin = std::round(bounds.x() * scale);
- int top_margin = std::round((content_offset().y() + bounds.y()) * scale);
+ float dip_scale = GetDipScale();
+ int left_margin = std::round(bounds.x() * dip_scale);
+ int top_margin = std::round((content_offset().y() + bounds.y()) * dip_scale);
JNIEnv* env = base::android::AttachCurrentThread();
Java_ViewAndroidDelegate_setViewPosition(
env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(),
- bounds.height(), scale, left_margin, top_margin);
+ bounds.height(), dip_scale, left_margin, top_margin);
}
ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
@@ -177,6 +229,10 @@ void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
layer_ = layer;
}
+void ViewAndroid::SetLayout(ViewAndroid::LayoutParams params) {
+ layout_params_ = params;
+}
+
bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
const JavaRef<jobject>& jimage) {
ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
@@ -227,4 +283,51 @@ void ViewAndroid::StartContentIntent(const GURL& content_url,
is_main_frame);
}
+bool ViewAndroid::OnTouchEvent(const MotionEventAndroid& event,
+ bool for_touch_handle) {
+ return HitTest(
+ base::Bind(&ViewAndroid::SendTouchEventToClient, for_touch_handle),
+ event);
+}
+
+bool ViewAndroid::SendTouchEventToClient(bool for_touch_handle,
+ ViewClient* client,
+ const MotionEventAndroid& event) {
+ return client->OnTouchEvent(event, for_touch_handle);
+}
+
+bool ViewAndroid::OnMouseEvent(const MotionEventAndroid& event) {
+ return HitTest(base::Bind(&ViewAndroid::SendMouseEventToClient), event);
+}
+
+bool ViewAndroid::SendMouseEventToClient(ViewClient* client,
+ const MotionEventAndroid& event) {
+ return client->OnMouseEvent(event);
+}
+
+bool ViewAndroid::HitTest(ViewClientCallback send_to_client,
+ const MotionEventAndroid& event) {
+ if (client_ && send_to_client.Run(client_, event))
+ return true;
+
+ if (!children_.empty()) {
+ std::unique_ptr<MotionEventAndroid> e(
+ event.Offset(-layout_params_.x, -layout_params_.y));
+
+ // Match from back to front for hit testing.
+ for (auto* child : base::Reversed(children_)) {
+ bool matched = child->layout_params_.match_parent;
+ if (!matched) {
+ gfx::Rect bound(child->layout_params_.x, child->layout_params_.y,
+ child->layout_params_.width,
+ child->layout_params_.height);
+ matched = bound.Contains(e->GetX(0), e->GetY(0));
+ }
+ if (matched && child->HitTest(send_to_client, *e))
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace ui
« no previous file with comments | « ui/android/view_android.h ('k') | ui/android/view_android_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698