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

Side by Side Diff: content/browser/renderer_host/render_widget_host_input_event_router.cc

Issue 2034213002: Reland: Fix touchpad gesture routing to renderers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed Windows failure Created 4 years, 5 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/browser/renderer_host/render_widget_host_input_event_router.h" 5 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
6 6
7 #include "base/debug/dump_without_crashing.h" 7 #include "base/debug/dump_without_crashing.h"
8 #include "cc/quads/surface_draw_quad.h" 8 #include "cc/quads/surface_draw_quad.h"
9 #include "cc/surfaces/surface_id_allocator.h" 9 #include "cc/surfaces/surface_id_allocator.h"
10 #include "cc/surfaces/surface_manager.h" 10 #include "cc/surfaces/surface_manager.h"
(...skipping 21 matching lines...) Expand all
32 32
33 // Remove this view from the owner_map. 33 // Remove this view from the owner_map.
34 for (auto entry : owner_map_) { 34 for (auto entry : owner_map_) {
35 if (entry.second == view) { 35 if (entry.second == view) {
36 owner_map_.erase(entry.first); 36 owner_map_.erase(entry.first);
37 // There will only be one instance of a particular view in the map. 37 // There will only be one instance of a particular view in the map.
38 break; 38 break;
39 } 39 }
40 } 40 }
41 41
42 if (view == touch_target_) { 42 if (view == touch_target_.target) {
43 touch_target_ = nullptr; 43 touch_target_.target = nullptr;
44 touch_delta_ = gfx::Vector2d();
45 active_touches_ = 0; 44 active_touches_ = 0;
46 } 45 }
47 46
48 // If the target that's being destroyed is in the gesture target queue, we 47 // If the target that's being destroyed is in the gesture target queue, we
49 // replace it with nullptr so that we maintain the 1:1 correspondence between 48 // replace it with nullptr so that we maintain the 1:1 correspondence between
50 // queue entries and the touch sequences that underly them. 49 // queue entries and the touch sequences that underly them.
51 for (size_t i = 0; i < gesture_target_queue_.size(); ++i) { 50 for (size_t i = 0; i < touchscreen_gesture_target_queue_.size(); ++i) {
52 if (gesture_target_queue_[i].target == view) 51 if (touchscreen_gesture_target_queue_[i].target == view)
53 gesture_target_queue_[i].target = nullptr; 52 touchscreen_gesture_target_queue_[i].target = nullptr;
54 } 53 }
55 54
56 if (view == gesture_target_) { 55 if (view == touchscreen_gesture_target_.target)
57 gesture_target_ = nullptr; 56 touchscreen_gesture_target_.target = nullptr;
58 gesture_delta_ = gfx::Vector2d(); 57
59 } 58 if (view == touchpad_gesture_target_.target)
59 touchpad_gesture_target_.target = nullptr;
60 } 60 }
61 61
62 void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() { 62 void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() {
63 for (auto entry : owner_map_) 63 for (auto entry : owner_map_)
64 entry.second->RemoveObserver(this); 64 entry.second->RemoveObserver(this);
65 owner_map_.clear(); 65 owner_map_.clear();
66 } 66 }
67 67
68 RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate( 68 RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate(
69 const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>& 69 const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
(...skipping 12 matching lines...) Expand all
82 bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget( 82 bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
83 const cc::SurfaceDrawQuad* surface_quad, 83 const cc::SurfaceDrawQuad* surface_quad,
84 const gfx::Point& point_in_quad_space) { 84 const gfx::Point& point_in_quad_space) {
85 auto it = hittest_data_.find(surface_quad->surface_id); 85 auto it = hittest_data_.find(surface_quad->surface_id);
86 if (it != hittest_data_.end() && !it->second.ignored_for_hittest) 86 if (it != hittest_data_.end() && !it->second.ignored_for_hittest)
87 return true; 87 return true;
88 return false; 88 return false;
89 } 89 }
90 90
91 RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter() 91 RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
92 : touch_target_(nullptr), 92 : active_touches_(0) {}
93 gesture_target_(nullptr),
94 active_touches_(0) {}
95 93
96 RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() { 94 RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() {
97 // We may be destroyed before some of the owners in the map, so we must 95 // We may be destroyed before some of the owners in the map, so we must
98 // remove ourself from their observer lists. 96 // remove ourself from their observer lists.
99 ClearAllObserverRegistrations(); 97 ClearAllObserverRegistrations();
100 } 98 }
101 99
102 RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget( 100 RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
103 RenderWidgetHostViewBase* root_view, 101 RenderWidgetHostViewBase* root_view,
104 const gfx::Point& point, 102 const gfx::Point& point,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 // TODO(wjmaclean): Initialize latency info correctly for OOPIFs. 160 // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
163 // https://crbug.com/613628 161 // https://crbug.com/613628
164 ui::LatencyInfo latency_info; 162 ui::LatencyInfo latency_info;
165 target->ProcessMouseWheelEvent(*event, latency_info); 163 target->ProcessMouseWheelEvent(*event, latency_info);
166 } 164 }
167 165
168 void RenderWidgetHostInputEventRouter::RouteGestureEvent( 166 void RenderWidgetHostInputEventRouter::RouteGestureEvent(
169 RenderWidgetHostViewBase* root_view, 167 RenderWidgetHostViewBase* root_view,
170 blink::WebGestureEvent* event, 168 blink::WebGestureEvent* event,
171 const ui::LatencyInfo& latency) { 169 const ui::LatencyInfo& latency) {
172 // We use GestureTapDown to detect the start of a gesture sequence since there 170 switch (event->sourceDevice) {
173 // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this 171 case blink::WebGestureDeviceUninitialized:
174 // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and 172 NOTREACHED() << "Uninitialized device type is not allowed";
175 // GestureTapDown is sent to the previous target, in case it is still in a 173 break;
176 // fling. 174 case blink::WebGestureDeviceTouchpad:
177 if (event->type == blink::WebInputEvent::GestureTapDown) { 175 RouteTouchpadGestureEvent(root_view, event, latency);
178 if (gesture_target_queue_.empty()) { 176 break;
179 LOG(ERROR) << "Gesture sequence start detected with no target available."; 177 case blink::WebGestureDeviceTouchscreen:
180 // Ignore this gesture sequence as no target is available. 178 RouteTouchscreenGestureEvent(root_view, event, latency);
181 // TODO(wjmaclean): this only happens on Windows, and should not happen. 179 break;
182 // https://crbug.com/595422 180 };
183 gesture_target_ = nullptr;
184 base::debug::DumpWithoutCrashing();
185 return;
186 }
187
188 const GestureTargetData& data = gesture_target_queue_.front();
189 gesture_target_ = data.target;
190 gesture_delta_ = data.delta;
191 gesture_target_queue_.pop_front();
192 }
193
194 if (!gesture_target_)
195 return;
196
197 event->x += gesture_delta_.x();
198 event->y += gesture_delta_.y();
199 gesture_target_->ProcessGestureEvent(*event, latency);
200 } 181 }
201 182
202 void RenderWidgetHostInputEventRouter::RouteTouchEvent( 183 void RenderWidgetHostInputEventRouter::RouteTouchEvent(
203 RenderWidgetHostViewBase* root_view, 184 RenderWidgetHostViewBase* root_view,
204 blink::WebTouchEvent* event, 185 blink::WebTouchEvent* event,
205 const ui::LatencyInfo& latency) { 186 const ui::LatencyInfo& latency) {
206 switch (event->type) { 187 switch (event->type) {
207 case blink::WebInputEvent::TouchStart: { 188 case blink::WebInputEvent::TouchStart: {
208 if (!active_touches_) { 189 if (!active_touches_) {
209 // Since this is the first touch, it defines the target for the rest 190 // Since this is the first touch, it defines the target for the rest
210 // of this sequence. 191 // of this sequence.
211 DCHECK(!touch_target_); 192 DCHECK(!touch_target_.target);
212 gfx::Point transformed_point; 193 gfx::Point transformed_point;
213 gfx::Point original_point(event->touches[0].position.x, 194 gfx::Point original_point(event->touches[0].position.x,
214 event->touches[0].position.y); 195 event->touches[0].position.y);
215 touch_target_ = 196 touch_target_.target =
216 FindEventTarget(root_view, original_point, &transformed_point); 197 FindEventTarget(root_view, original_point, &transformed_point);
217 198
218 // TODO(wjmaclean): Instead of just computing a delta, we should extract 199 // TODO(wjmaclean): Instead of just computing a delta, we should extract
219 // the complete transform. We assume it doesn't change for the duration 200 // the complete transform. We assume it doesn't change for the duration
220 // of the touch sequence, though this could be wrong; a better approach 201 // of the touch sequence, though this could be wrong; a better approach
221 // might be to always transform each point to the touch_target_ 202 // might be to always transform each point to the |touch_target_.target|
222 // for the duration of the sequence. 203 // for the duration of the sequence.
223 touch_delta_ = transformed_point - original_point; 204 touch_target_.delta = transformed_point - original_point;
224 gesture_target_queue_.emplace_back(touch_target_, touch_delta_); 205 touchscreen_gesture_target_queue_.push_back(touch_target_);
225 206
226 if (!touch_target_) 207 if (!touch_target_.target)
227 return; 208 return;
228 } 209 }
229 ++active_touches_; 210 ++active_touches_;
230 if (touch_target_) { 211 if (touch_target_.target) {
231 TransformEventTouchPositions(event, touch_delta_); 212 TransformEventTouchPositions(event, touch_target_.delta);
232 touch_target_->ProcessTouchEvent(*event, latency); 213 touch_target_.target->ProcessTouchEvent(*event, latency);
233 } 214 }
234 break; 215 break;
235 } 216 }
236 case blink::WebInputEvent::TouchMove: 217 case blink::WebInputEvent::TouchMove:
237 if (touch_target_) { 218 if (touch_target_.target) {
238 TransformEventTouchPositions(event, touch_delta_); 219 TransformEventTouchPositions(event, touch_target_.delta);
239 touch_target_->ProcessTouchEvent(*event, latency); 220 touch_target_.target->ProcessTouchEvent(*event, latency);
240 } 221 }
241 break; 222 break;
242 case blink::WebInputEvent::TouchEnd: 223 case blink::WebInputEvent::TouchEnd:
243 case blink::WebInputEvent::TouchCancel: 224 case blink::WebInputEvent::TouchCancel:
244 if (!touch_target_) 225 if (!touch_target_.target)
245 break; 226 break;
246 227
247 DCHECK(active_touches_); 228 DCHECK(active_touches_);
248 TransformEventTouchPositions(event, touch_delta_); 229 TransformEventTouchPositions(event, touch_target_.delta);
249 touch_target_->ProcessTouchEvent(*event, latency); 230 touch_target_.target->ProcessTouchEvent(*event, latency);
250 --active_touches_; 231 --active_touches_;
251 if (!active_touches_) { 232 if (!active_touches_)
252 touch_target_ = nullptr; 233 touch_target_.target = nullptr;
253 touch_delta_ = gfx::Vector2d();
254 }
255 break; 234 break;
256 default: 235 default:
257 NOTREACHED(); 236 NOTREACHED();
258 } 237 }
259 } 238 }
260 239
261 void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner( 240 void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner(
262 uint32_t id, 241 uint32_t id,
263 RenderWidgetHostViewBase* owner) { 242 RenderWidgetHostViewBase* owner) {
264 DCHECK(owner_map_.find(id) == owner_map_.end()); 243 DCHECK(owner_map_.find(id) == owner_map_.end());
(...skipping 22 matching lines...) Expand all
287 void RenderWidgetHostInputEventRouter::OnHittestData( 266 void RenderWidgetHostInputEventRouter::OnHittestData(
288 const FrameHostMsg_HittestData_Params& params) { 267 const FrameHostMsg_HittestData_Params& params) {
289 if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) { 268 if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) {
290 return; 269 return;
291 } 270 }
292 HittestData data; 271 HittestData data;
293 data.ignored_for_hittest = params.ignored_for_hittest; 272 data.ignored_for_hittest = params.ignored_for_hittest;
294 hittest_data_[params.surface_id] = data; 273 hittest_data_[params.surface_id] = data;
295 } 274 }
296 275
276 void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent(
277 RenderWidgetHostViewBase* root_view,
278 blink::WebGestureEvent* event,
279 const ui::LatencyInfo& latency) {
280 DCHECK_EQ(blink::WebGestureDeviceTouchscreen, event->sourceDevice);
281
282 // We use GestureTapDown to detect the start of a gesture sequence since there
283 // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this
284 // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and
285 // GestureTapDown is sent to the previous target, in case it is still in a
286 // fling.
287 if (event->type == blink::WebInputEvent::GestureTapDown) {
288 if (touchscreen_gesture_target_queue_.empty()) {
289 LOG(ERROR) << "Gesture sequence start detected with no target available.";
290 // Ignore this gesture sequence as no target is available.
291 // TODO(wjmaclean): this only happens on Windows, and should not happen.
292 // https://crbug.com/595422
293 touchscreen_gesture_target_.target = nullptr;
294 base::debug::DumpWithoutCrashing();
295 return;
296 }
297
298 touchscreen_gesture_target_ = touchscreen_gesture_target_queue_.front();
299 touchscreen_gesture_target_queue_.pop_front();
300 }
301
302 if (!touchscreen_gesture_target_.target)
303 return;
304
305 // TODO(mohsen): Add tests to check event location.
306 event->x += touchscreen_gesture_target_.delta.x();
307 event->y += touchscreen_gesture_target_.delta.y();
308 touchscreen_gesture_target_.target->ProcessGestureEvent(*event, latency);
309 }
310
311 void RenderWidgetHostInputEventRouter::RouteTouchpadGestureEvent(
312 RenderWidgetHostViewBase* root_view,
313 blink::WebGestureEvent* event,
314 const ui::LatencyInfo& latency) {
315 DCHECK_EQ(blink::WebGestureDeviceTouchpad, event->sourceDevice);
316
317 if (event->type == blink::WebInputEvent::GesturePinchBegin ||
wjmaclean 2016/07/14 12:15:11 As best I recall, we should *never* be sending pin
mohsen 2016/07/15 14:40:05 I think *touchpad* pinch events need to be sent to
mohsen 2016/07/15 14:46:19 Also, don't we already send touchscreen pinch even
318 event->type == blink::WebInputEvent::GestureFlingStart) {
319 gfx::Point transformed_point;
320 gfx::Point original_point(event->x, event->y);
321 touchpad_gesture_target_.target =
322 FindEventTarget(root_view, original_point, &transformed_point);
323 // TODO(mohsen): Instead of just computing a delta, we should extract the
324 // complete transform. We assume it doesn't change for the duration of the
325 // touchpad gesture sequence, though this could be wrong; a better approach
326 // might be to always transform each point to the
327 // |touchpad_gesture_target_.target| for the duration of the sequence.
328 touchpad_gesture_target_.delta = transformed_point - original_point;
329 }
330
331 if (!touchpad_gesture_target_.target)
332 return;
333
334 // TODO(mohsen): Add tests to check event location.
335 event->x += touchpad_gesture_target_.delta.x();
336 event->y += touchpad_gesture_target_.delta.y();
337 touchpad_gesture_target_.target->ProcessGestureEvent(*event, latency);
338 }
339
297 } // namespace content 340 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_widget_host_input_event_router.h ('k') | content/browser/site_per_process_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698