| 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_.target) { | 42 if (view == touch_target_) { |
| 43 touch_target_.target = nullptr; | 43 touch_target_ = nullptr; |
| 44 touch_delta_ = gfx::Vector2d(); |
| 44 active_touches_ = 0; | 45 active_touches_ = 0; |
| 45 } | 46 } |
| 46 | 47 |
| 47 // If the target that's being destroyed is in the gesture target queue, we | 48 // If the target that's being destroyed is in the gesture target queue, we |
| 48 // replace it with nullptr so that we maintain the 1:1 correspondence between | 49 // replace it with nullptr so that we maintain the 1:1 correspondence between |
| 49 // queue entries and the touch sequences that underly them. | 50 // queue entries and the touch sequences that underly them. |
| 50 for (size_t i = 0; i < touchscreen_gesture_target_queue_.size(); ++i) { | 51 for (size_t i = 0; i < gesture_target_queue_.size(); ++i) { |
| 51 if (touchscreen_gesture_target_queue_[i].target == view) | 52 if (gesture_target_queue_[i].target == view) |
| 52 touchscreen_gesture_target_queue_[i].target = nullptr; | 53 gesture_target_queue_[i].target = nullptr; |
| 53 } | 54 } |
| 54 | 55 |
| 55 if (view == touchscreen_gesture_target_.target) | 56 if (view == gesture_target_) { |
| 56 touchscreen_gesture_target_.target = nullptr; | 57 gesture_target_ = nullptr; |
| 57 | 58 gesture_delta_ = gfx::Vector2d(); |
| 58 if (view == touchpad_gesture_target_.target) | 59 } |
| 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 : active_touches_(0) {} | 92 : touch_target_(nullptr), |
| 93 gesture_target_(nullptr), |
| 94 active_touches_(0) {} |
| 93 | 95 |
| 94 RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() { | 96 RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() { |
| 95 // We may be destroyed before some of the owners in the map, so we must | 97 // We may be destroyed before some of the owners in the map, so we must |
| 96 // remove ourself from their observer lists. | 98 // remove ourself from their observer lists. |
| 97 ClearAllObserverRegistrations(); | 99 ClearAllObserverRegistrations(); |
| 98 } | 100 } |
| 99 | 101 |
| 100 RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget( | 102 RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget( |
| 101 RenderWidgetHostViewBase* root_view, | 103 RenderWidgetHostViewBase* root_view, |
| 102 const gfx::Point& point, | 104 const gfx::Point& point, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 event->x = transformed_point.x(); | 158 event->x = transformed_point.x(); |
| 157 event->y = transformed_point.y(); | 159 event->y = transformed_point.y(); |
| 158 | 160 |
| 159 target->ProcessMouseWheelEvent(*event); | 161 target->ProcessMouseWheelEvent(*event); |
| 160 } | 162 } |
| 161 | 163 |
| 162 void RenderWidgetHostInputEventRouter::RouteGestureEvent( | 164 void RenderWidgetHostInputEventRouter::RouteGestureEvent( |
| 163 RenderWidgetHostViewBase* root_view, | 165 RenderWidgetHostViewBase* root_view, |
| 164 blink::WebGestureEvent* event, | 166 blink::WebGestureEvent* event, |
| 165 const ui::LatencyInfo& latency) { | 167 const ui::LatencyInfo& latency) { |
| 166 switch (event->sourceDevice) { | 168 // We use GestureTapDown to detect the start of a gesture sequence since there |
| 167 case blink::WebGestureDeviceUninitialized: | 169 // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this |
| 168 NOTREACHED() << "Uninitialized device type is not allowed"; | 170 // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and |
| 169 break; | 171 // GestureTapDown is sent to the previous target, in case it is still in a |
| 170 case blink::WebGestureDeviceTouchpad: | 172 // fling. |
| 171 RouteTouchpadGestureEvent(root_view, event, latency); | 173 if (event->type == blink::WebInputEvent::GestureTapDown) { |
| 172 break; | 174 if (gesture_target_queue_.empty()) { |
| 173 case blink::WebGestureDeviceTouchscreen: | 175 LOG(ERROR) << "Gesture sequence start detected with no target available."; |
| 174 RouteTouchscreenGestureEvent(root_view, event, latency); | 176 // Ignore this gesture sequence as no target is available. |
| 175 break; | 177 // TODO(wjmaclean): this only happens on Windows, and should not happen. |
| 176 }; | 178 // https://crbug.com/595422 |
| 179 gesture_target_ = nullptr; |
| 180 base::debug::DumpWithoutCrashing(); |
| 181 return; |
| 182 } |
| 183 |
| 184 const GestureTargetData& data = gesture_target_queue_.front(); |
| 185 gesture_target_ = data.target; |
| 186 gesture_delta_ = data.delta; |
| 187 gesture_target_queue_.pop_front(); |
| 188 } |
| 189 |
| 190 if (!gesture_target_) |
| 191 return; |
| 192 |
| 193 event->x += gesture_delta_.x(); |
| 194 event->y += gesture_delta_.y(); |
| 195 gesture_target_->ProcessGestureEvent(*event, latency); |
| 177 } | 196 } |
| 178 | 197 |
| 179 void RenderWidgetHostInputEventRouter::RouteTouchEvent( | 198 void RenderWidgetHostInputEventRouter::RouteTouchEvent( |
| 180 RenderWidgetHostViewBase* root_view, | 199 RenderWidgetHostViewBase* root_view, |
| 181 blink::WebTouchEvent* event, | 200 blink::WebTouchEvent* event, |
| 182 const ui::LatencyInfo& latency) { | 201 const ui::LatencyInfo& latency) { |
| 183 switch (event->type) { | 202 switch (event->type) { |
| 184 case blink::WebInputEvent::TouchStart: { | 203 case blink::WebInputEvent::TouchStart: { |
| 185 if (!active_touches_) { | 204 if (!active_touches_) { |
| 186 // Since this is the first touch, it defines the target for the rest | 205 // Since this is the first touch, it defines the target for the rest |
| 187 // of this sequence. | 206 // of this sequence. |
| 188 DCHECK(!touch_target_.target); | 207 DCHECK(!touch_target_); |
| 189 gfx::Point transformed_point; | 208 gfx::Point transformed_point; |
| 190 gfx::Point original_point(event->touches[0].position.x, | 209 gfx::Point original_point(event->touches[0].position.x, |
| 191 event->touches[0].position.y); | 210 event->touches[0].position.y); |
| 192 touch_target_.target = | 211 touch_target_ = |
| 193 FindEventTarget(root_view, original_point, &transformed_point); | 212 FindEventTarget(root_view, original_point, &transformed_point); |
| 194 | 213 |
| 195 // TODO(wjmaclean): Instead of just computing a delta, we should extract | 214 // TODO(wjmaclean): Instead of just computing a delta, we should extract |
| 196 // the complete transform. We assume it doesn't change for the duration | 215 // the complete transform. We assume it doesn't change for the duration |
| 197 // of the touch sequence, though this could be wrong; a better approach | 216 // of the touch sequence, though this could be wrong; a better approach |
| 198 // might be to always transform each point to the |touch_target_.target| | 217 // might be to always transform each point to the touch_target_ |
| 199 // for the duration of the sequence. | 218 // for the duration of the sequence. |
| 200 touch_target_.delta = transformed_point - original_point; | 219 touch_delta_ = transformed_point - original_point; |
| 201 touchscreen_gesture_target_queue_.push_back(touch_target_); | 220 gesture_target_queue_.emplace_back(touch_target_, touch_delta_); |
| 202 | 221 |
| 203 if (!touch_target_.target) | 222 if (!touch_target_) |
| 204 return; | 223 return; |
| 205 } | 224 } |
| 206 ++active_touches_; | 225 ++active_touches_; |
| 207 if (touch_target_.target) { | 226 if (touch_target_) { |
| 208 TransformEventTouchPositions(event, touch_target_.delta); | 227 TransformEventTouchPositions(event, touch_delta_); |
| 209 touch_target_.target->ProcessTouchEvent(*event, latency); | 228 touch_target_->ProcessTouchEvent(*event, latency); |
| 210 } | 229 } |
| 211 break; | 230 break; |
| 212 } | 231 } |
| 213 case blink::WebInputEvent::TouchMove: | 232 case blink::WebInputEvent::TouchMove: |
| 214 if (touch_target_.target) { | 233 if (touch_target_) { |
| 215 TransformEventTouchPositions(event, touch_target_.delta); | 234 TransformEventTouchPositions(event, touch_delta_); |
| 216 touch_target_.target->ProcessTouchEvent(*event, latency); | 235 touch_target_->ProcessTouchEvent(*event, latency); |
| 217 } | 236 } |
| 218 break; | 237 break; |
| 219 case blink::WebInputEvent::TouchEnd: | 238 case blink::WebInputEvent::TouchEnd: |
| 220 case blink::WebInputEvent::TouchCancel: | 239 case blink::WebInputEvent::TouchCancel: |
| 221 if (!touch_target_.target) | 240 if (!touch_target_) |
| 222 break; | 241 break; |
| 223 | 242 |
| 224 DCHECK(active_touches_); | 243 DCHECK(active_touches_); |
| 225 TransformEventTouchPositions(event, touch_target_.delta); | 244 TransformEventTouchPositions(event, touch_delta_); |
| 226 touch_target_.target->ProcessTouchEvent(*event, latency); | 245 touch_target_->ProcessTouchEvent(*event, latency); |
| 227 --active_touches_; | 246 --active_touches_; |
| 228 if (!active_touches_) | 247 if (!active_touches_) { |
| 229 touch_target_.target = nullptr; | 248 touch_target_ = nullptr; |
| 249 touch_delta_ = gfx::Vector2d(); |
| 250 } |
| 230 break; | 251 break; |
| 231 default: | 252 default: |
| 232 NOTREACHED(); | 253 NOTREACHED(); |
| 233 } | 254 } |
| 234 } | 255 } |
| 235 | 256 |
| 236 void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner( | 257 void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner( |
| 237 uint32_t id, | 258 uint32_t id, |
| 238 RenderWidgetHostViewBase* owner) { | 259 RenderWidgetHostViewBase* owner) { |
| 239 DCHECK(owner_map_.find(id) == owner_map_.end()); | 260 DCHECK(owner_map_.find(id) == owner_map_.end()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 262 void RenderWidgetHostInputEventRouter::OnHittestData( | 283 void RenderWidgetHostInputEventRouter::OnHittestData( |
| 263 const FrameHostMsg_HittestData_Params& params) { | 284 const FrameHostMsg_HittestData_Params& params) { |
| 264 if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) { | 285 if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) { |
| 265 return; | 286 return; |
| 266 } | 287 } |
| 267 HittestData data; | 288 HittestData data; |
| 268 data.ignored_for_hittest = params.ignored_for_hittest; | 289 data.ignored_for_hittest = params.ignored_for_hittest; |
| 269 hittest_data_[params.surface_id] = data; | 290 hittest_data_[params.surface_id] = data; |
| 270 } | 291 } |
| 271 | 292 |
| 272 void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent( | |
| 273 RenderWidgetHostViewBase* root_view, | |
| 274 blink::WebGestureEvent* event, | |
| 275 const ui::LatencyInfo& latency) { | |
| 276 DCHECK_EQ(blink::WebGestureDeviceTouchscreen, event->sourceDevice); | |
| 277 | |
| 278 // We use GestureTapDown to detect the start of a gesture sequence since there | |
| 279 // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this | |
| 280 // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and | |
| 281 // GestureTapDown is sent to the previous target, in case it is still in a | |
| 282 // fling. | |
| 283 if (event->type == blink::WebInputEvent::GestureTapDown) { | |
| 284 if (touchscreen_gesture_target_queue_.empty()) { | |
| 285 LOG(ERROR) << "Gesture sequence start detected with no target available."; | |
| 286 // Ignore this gesture sequence as no target is available. | |
| 287 // TODO(wjmaclean): this only happens on Windows, and should not happen. | |
| 288 // https://crbug.com/595422 | |
| 289 touchscreen_gesture_target_.target = nullptr; | |
| 290 base::debug::DumpWithoutCrashing(); | |
| 291 return; | |
| 292 } | |
| 293 | |
| 294 touchscreen_gesture_target_ = touchscreen_gesture_target_queue_.front(); | |
| 295 touchscreen_gesture_target_queue_.pop_front(); | |
| 296 } | |
| 297 | |
| 298 if (!touchscreen_gesture_target_.target) | |
| 299 return; | |
| 300 | |
| 301 // TODO(mohsen): Add tests to check event location. | |
| 302 event->x += touchscreen_gesture_target_.delta.x(); | |
| 303 event->y += touchscreen_gesture_target_.delta.y(); | |
| 304 touchscreen_gesture_target_.target->ProcessGestureEvent(*event, latency); | |
| 305 } | |
| 306 | |
| 307 void RenderWidgetHostInputEventRouter::RouteTouchpadGestureEvent( | |
| 308 RenderWidgetHostViewBase* root_view, | |
| 309 blink::WebGestureEvent* event, | |
| 310 const ui::LatencyInfo& latency) { | |
| 311 DCHECK_EQ(blink::WebGestureDeviceTouchpad, event->sourceDevice); | |
| 312 DCHECK(event->type == blink::WebInputEvent::GesturePinchBegin || | |
| 313 event->type == blink::WebInputEvent::GesturePinchUpdate || | |
| 314 event->type == blink::WebInputEvent::GesturePinchEnd); | |
| 315 | |
| 316 if (event->type == blink::WebInputEvent::GesturePinchBegin) { | |
| 317 gfx::Point transformed_point; | |
| 318 gfx::Point original_point(event->x, event->y); | |
| 319 touchpad_gesture_target_.target = | |
| 320 FindEventTarget(root_view, original_point, &transformed_point); | |
| 321 // TODO(mohsen): Instead of just computing a delta, we should extract the | |
| 322 // complete transform. We assume it doesn't change for the duration of the | |
| 323 // touchpad gesture sequence, though this could be wrong; a better approach | |
| 324 // might be to always transform each point to the | |
| 325 // |touchpad_gesture_target_.target| for the duration of the sequence. | |
| 326 touchpad_gesture_target_.delta = transformed_point - original_point; | |
| 327 } | |
| 328 | |
| 329 if (!touchpad_gesture_target_.target) | |
| 330 return; | |
| 331 | |
| 332 // TODO(mohsen): Add tests to check event location. | |
| 333 event->x += touchpad_gesture_target_.delta.x(); | |
| 334 event->y += touchpad_gesture_target_.delta.y(); | |
| 335 touchpad_gesture_target_.target->ProcessGestureEvent(*event, latency); | |
| 336 } | |
| 337 | |
| 338 } // namespace content | 293 } // namespace content |
| OLD | NEW |