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

Side by Side Diff: ui/android/view_android.cc

Issue 2645353004: ViewRoot class for event forwarding on Android (Closed)
Patch Set: fix tests Created 3 years, 10 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 unified diff | Download patch
OLDNEW
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 "cc/layers/layer.h" 10 #include "cc/layers/layer.h"
11 #include "jni/ViewAndroidDelegate_jni.h" 11 #include "jni/ViewAndroidDelegate_jni.h"
12 #include "ui/android/window_android.h" 12 #include "ui/android/window_android.h"
13 #include "ui/display/display.h" 13 #include "ui/display/display.h"
14 #include "ui/display/screen.h" 14 #include "ui/display/screen.h"
15 15
16 namespace ui { 16 namespace ui {
17 17
18 using base::android::JavaRef; 18 using base::android::JavaRef;
19 using base::android::ScopedJavaLocalRef; 19 using base::android::ScopedJavaLocalRef;
20 20
21 // ViewAndroid::ScopedAndroidView
21 ViewAndroid::ScopedAnchorView::ScopedAnchorView( 22 ViewAndroid::ScopedAnchorView::ScopedAnchorView(
22 JNIEnv* env, 23 JNIEnv* env,
23 const JavaRef<jobject>& jview, 24 const JavaRef<jobject>& jview,
24 const JavaRef<jobject>& jdelegate) 25 const JavaRef<jobject>& jdelegate)
25 : view_(env, jview.obj()), delegate_(env, jdelegate.obj()) { 26 : view_(env, jview.obj()), delegate_(env, jdelegate.obj()) {
26 // If there's a view, then we need a delegate to remove it. 27 // If there's a view, then we need a delegate to remove it.
27 DCHECK(!jdelegate.is_null() || jview.is_null()); 28 DCHECK(!jdelegate.is_null() || jview.is_null());
28 } 29 }
29 30
30 ViewAndroid::ScopedAnchorView::ScopedAnchorView() { } 31 ViewAndroid::ScopedAnchorView::ScopedAnchorView() { }
(...skipping 30 matching lines...) Expand all
61 view_.reset(); 62 view_.reset();
62 delegate_.reset(); 63 delegate_.reset();
63 } 64 }
64 65
65 const base::android::ScopedJavaLocalRef<jobject> 66 const base::android::ScopedJavaLocalRef<jobject>
66 ViewAndroid::ScopedAnchorView::view() const { 67 ViewAndroid::ScopedAnchorView::view() const {
67 JNIEnv* env = base::android::AttachCurrentThread(); 68 JNIEnv* env = base::android::AttachCurrentThread();
68 return view_.get(env); 69 return view_.get(env);
69 } 70 }
70 71
71 ViewAndroid::ViewAndroid(const JavaRef<jobject>& delegate) 72 // ViewAndroid::Bounds
72 : parent_(nullptr) 73 void ViewAndroid::Bounds::SetBounds(const gfx::Point& origin,
73 , delegate_(base::android::AttachCurrentThread(), 74 int width,
74 delegate.obj()) {} 75 int height) {
76 rect_.SetRect(origin.x(), origin.y(), width, height);
77 }
75 78
76 ViewAndroid::ViewAndroid() : parent_(nullptr) {} 79 bool ViewAndroid::Bounds::IsInBounds(const MotionEventData& event) {
80 bool width_matched = (rect_.width() == Bounds::kMatchParent) ?
boliu 2017/01/24 23:47:12 this only holds during the root to child recursion
Jinsuk Kim 2017/01/25 02:34:33 Removed the method and check it directly in the ca
81 true : rect_.x() <= event.GetX() && event.GetX() < rect_.right();
82 bool height_matched = (rect_.height() == Bounds::kMatchParent) ?
83 true : rect_.y() <= event.GetY() && event.GetY() < rect_.bottom();
84 return width_matched && height_matched;
85 }
86
87 // ViewAndroid
88 ViewAndroid::ViewAndroid(ViewClient* client) : parent_(nullptr),
89 client_(client) {}
90 ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
77 91
78 ViewAndroid::~ViewAndroid() { 92 ViewAndroid::~ViewAndroid() {
79 RemoveFromParent(); 93 RemoveFromParent();
80 94
81 for (std::list<ViewAndroid*>::iterator it = children_.begin(); 95 for (auto& child : children_) {
82 it != children_.end(); it++) { 96 DCHECK_EQ(child->parent_, this);
83 DCHECK_EQ((*it)->parent_, this); 97 child->parent_ = nullptr;
84 (*it)->parent_ = nullptr;
85 } 98 }
86 } 99 }
87 100
88 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) { 101 void ViewAndroid::SetDelegate(const JavaRef<jobject>& delegate) {
102 // A ViewAndroid may have its own delegate or otherwise will
103 // use the next available parent's delegate.
89 JNIEnv* env = base::android::AttachCurrentThread(); 104 JNIEnv* env = base::android::AttachCurrentThread();
90 delegate_ = JavaObjectWeakGlobalRef(env, delegate); 105 delegate_ = JavaObjectWeakGlobalRef(env, delegate);
91 } 106 }
92 107
93 void ViewAndroid::AddChild(ViewAndroid* child) { 108 void ViewAndroid::AddChild(ViewAndroid* child) {
94 DCHECK(child); 109 DCHECK(child);
110 DCHECK(!child->IsViewRoot()); // ViewRoot cannot be a child.
95 DCHECK(std::find(children_.begin(), children_.end(), child) == 111 DCHECK(std::find(children_.begin(), children_.end(), child) ==
96 children_.end()); 112 children_.end());
97 113
98 children_.push_back(child); 114 children_.push_front(child);
boliu 2017/01/24 23:47:12 why push front?
Jinsuk Kim 2017/01/25 02:34:33 This is for newly added view to go to front among
99 if (child->parent_) 115 if (child->parent_)
100 child->RemoveFromParent(); 116 child->RemoveFromParent();
101 child->parent_ = this; 117 child->parent_ = this;
102 } 118 }
103 119
104 void ViewAndroid::RemoveFromParent() { 120 void ViewAndroid::RemoveFromParent() {
105 if (parent_) 121 if (parent_)
106 parent_->RemoveChild(this); 122 parent_->RemoveChild(this);
107 } 123 }
108 124
125 void ViewAndroid::SetBounds(const gfx::Point& origin, int width, int height) {
126 bounds_.SetBounds(origin, width, height);
127 }
128
129 bool ViewAndroid::IsInBounds(const MotionEventData& event) {
130 return bounds_.IsInBounds(event);
131 }
132
109 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() { 133 ViewAndroid::ScopedAnchorView ViewAndroid::AcquireAnchorView() {
110 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 134 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
111 if (delegate.is_null()) 135 if (delegate.is_null())
112 return ViewAndroid::ScopedAnchorView(); 136 return ViewAndroid::ScopedAnchorView();
113 137
114 JNIEnv* env = base::android::AttachCurrentThread(); 138 JNIEnv* env = base::android::AttachCurrentThread();
115 return ViewAndroid::ScopedAnchorView( 139 return ViewAndroid::ScopedAnchorView(
116 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate); 140 env, Java_ViewAndroidDelegate_acquireView(env, delegate), delegate);
117 } 141 }
118 142
143 float ViewAndroid::GetDipScale() {
144 return display::Screen::GetScreen()
145 ->GetDisplayNearestWindow(this)
146 .device_scale_factor();
147 }
148
119 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor, 149 void ViewAndroid::SetAnchorRect(const JavaRef<jobject>& anchor,
120 const gfx::RectF& bounds) { 150 const gfx::RectF& bounds) {
121 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 151 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
122 if (delegate.is_null()) 152 if (delegate.is_null())
123 return; 153 return;
124 154
125 float scale = display::Screen::GetScreen() 155 float scale = GetDipScale();
126 ->GetDisplayNearestWindow(this)
127 .device_scale_factor();
128 int left_margin = std::round(bounds.x() * scale); 156 int left_margin = std::round(bounds.x() * scale);
129 int top_margin = std::round((content_offset().y() + bounds.y()) * scale); 157 int top_margin = std::round((content_offset().y() + bounds.y()) * scale);
130 JNIEnv* env = base::android::AttachCurrentThread(); 158 JNIEnv* env = base::android::AttachCurrentThread();
131 Java_ViewAndroidDelegate_setViewPosition( 159 Java_ViewAndroidDelegate_setViewPosition(
132 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(), 160 env, delegate, anchor, bounds.x(), bounds.y(), bounds.width(),
133 bounds.height(), scale, left_margin, top_margin); 161 bounds.height(), scale, left_margin, top_margin);
134 } 162 }
135 163
136 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() { 164 ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
137 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 165 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
(...skipping 30 matching lines...) Expand all
168 } 196 }
169 197
170 cc::Layer* ViewAndroid::GetLayer() const { 198 cc::Layer* ViewAndroid::GetLayer() const {
171 return layer_.get(); 199 return layer_.get();
172 } 200 }
173 201
174 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) { 202 void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
175 layer_ = layer; 203 layer_ = layer;
176 } 204 }
177 205
206 ViewAndroid* ViewAndroid::GetViewRoot() {
207 return parent_ ? parent_->GetViewRoot() : nullptr;
208 }
209
210 bool ViewAndroid::IsViewRoot() {
211 return GetViewRoot() == this;
212 }
213
178 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, 214 bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
179 const JavaRef<jobject>& jimage) { 215 const JavaRef<jobject>& jimage) {
180 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); 216 ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
181 if (delegate.is_null()) 217 if (delegate.is_null())
182 return false; 218 return false;
183 JNIEnv* env = base::android::AttachCurrentThread(); 219 JNIEnv* env = base::android::AttachCurrentThread();
184 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext, 220 return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext,
185 jimage); 221 jimage);
186 } 222 }
187 223
224 bool ViewAndroid::OnTouchEventInternal(const MotionEventData& event) {
225 if (!IsInBounds(event))
226 return false;
227
228 if (!children_.empty()) {
229 gfx::Point delta = bounds_.origin();
boliu 2017/01/24 23:47:12 this is not wrong, but just a bit odd while readin
Jinsuk Kim 2017/01/25 02:34:33 Would you elaborate? I *think* the event is transl
230 const MotionEventData& e =
boliu 2017/01/24 23:47:12 I'm blanking on whether this is safe c++.. if IsO
Jinsuk Kim 2017/01/25 02:34:33 Const guarantees its lifetime: https://herbsutter.
231 delta.IsOrigin() ? event : event.Offset(-delta.x(), -delta.y());
232
233 for (auto& child: children_) {
234 if (child->OnTouchEventInternal(e))
235 return true;
236 }
237 }
238
239 if (client_ && client_->OnTouchEvent(event))
boliu 2017/01/24 23:47:12 hmm, should this happen before looping over childr
Jinsuk Kim 2017/01/25 02:34:33 To the best of my knowledge, child views receives
240 return true;
241
242 return false;
243 }
244
188 } // namespace ui 245 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698