Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |