| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/input/touch_event_queue.h" | 5 #include "content/browser/renderer_host/input/touch_event_queue.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "content/browser/renderer_host/input/timeout_monitor.h" | 10 #include "content/browser/renderer_host/input/timeout_monitor.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 // Time interval at which touchmove events will be forwarded to the client while | 22 // Time interval at which touchmove events will be forwarded to the client while |
| 23 // scrolling is active and possible. | 23 // scrolling is active and possible. |
| 24 const double kAsyncTouchMoveIntervalSec = .2; | 24 const double kAsyncTouchMoveIntervalSec = .2; |
| 25 | 25 |
| 26 // A slop region just larger than that used by many web applications. When | 26 // A slop region just larger than that used by many web applications. When |
| 27 // touchmove's are being sent asynchronously, movement outside this region will | 27 // touchmove's are being sent asynchronously, movement outside this region will |
| 28 // trigger an immediate async touchmove to cancel potential tap-related logic. | 28 // trigger an immediate async touchmove to cancel potential tap-related logic. |
| 29 const double kApplicationSlopRegionLengthDipsSqared = 15. * 15.; | 29 const double kApplicationSlopRegionLengthDipsSqared = 15. * 15.; |
| 30 | 30 |
| 31 // Using a small epsilon when comparing slop distances allows pixel perfect | |
| 32 // slop determination when using fractional DIP coordinates (assuming the slop | |
| 33 // region and DPI scale are reasonably proportioned). | |
| 34 const float kSlopEpsilon = .05f; | |
| 35 | |
| 36 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( | 31 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( |
| 37 const TouchEventWithLatencyInfo& event_to_cancel) { | 32 const TouchEventWithLatencyInfo& event_to_cancel) { |
| 38 TouchEventWithLatencyInfo event = event_to_cancel; | 33 TouchEventWithLatencyInfo event = event_to_cancel; |
| 39 WebTouchEventTraits::ResetTypeAndTouchStates( | 34 WebTouchEventTraits::ResetTypeAndTouchStates( |
| 40 WebInputEvent::TouchCancel, | 35 WebInputEvent::TouchCancel, |
| 41 // TODO(rbyers): Shouldn't we use a fresh timestamp? | 36 // TODO(rbyers): Shouldn't we use a fresh timestamp? |
| 42 event.event.timeStampSeconds, | 37 event.event.timeStampSeconds, |
| 43 &event.event); | 38 &event.event); |
| 44 return event; | 39 return event; |
| 45 } | 40 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 // The event for which the ack timeout is triggered. | 203 // The event for which the ack timeout is triggered. |
| 209 TouchEventWithLatencyInfo timeout_event_; | 204 TouchEventWithLatencyInfo timeout_event_; |
| 210 | 205 |
| 211 // Provides timeout-based callback behavior. | 206 // Provides timeout-based callback behavior. |
| 212 TimeoutMonitor timeout_monitor_; | 207 TimeoutMonitor timeout_monitor_; |
| 213 | 208 |
| 214 bool enabled_; | 209 bool enabled_; |
| 215 bool enabled_for_current_sequence_; | 210 bool enabled_for_current_sequence_; |
| 216 }; | 211 }; |
| 217 | 212 |
| 218 // Provides touchmove slop suppression for a single touch that remains within | 213 // Provides touchmove slop suppression for a touch sequence until a |
| 219 // a given slop region, unless the touchstart is preventDefault'ed. | 214 // (unprevented) touch will trigger immediate scrolling. |
| 220 // TODO(jdduke): Use a flag bundled with each TouchEvent declaring whether it | |
| 221 // has exceeded the slop region, removing duplicated slop determination logic. | |
| 222 class TouchEventQueue::TouchMoveSlopSuppressor { | 215 class TouchEventQueue::TouchMoveSlopSuppressor { |
| 223 public: | 216 public: |
| 224 TouchMoveSlopSuppressor(double slop_suppression_length_dips) | 217 TouchMoveSlopSuppressor() : suppressing_touchmoves_(false) {} |
| 225 : slop_suppression_length_dips_squared_(0), | |
| 226 suppressing_touchmoves_(false) { | |
| 227 if (slop_suppression_length_dips) { | |
| 228 slop_suppression_length_dips += kSlopEpsilon; | |
| 229 slop_suppression_length_dips_squared_ = | |
| 230 slop_suppression_length_dips * slop_suppression_length_dips; | |
| 231 } | |
| 232 } | |
| 233 | 218 |
| 234 bool FilterEvent(const WebTouchEvent& event) { | 219 bool FilterEvent(const WebTouchEvent& event) { |
| 235 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { | 220 if (WebTouchEventTraits::IsTouchSequenceStart(event)) |
| 236 touch_sequence_start_position_ = | 221 suppressing_touchmoves_ = true; |
| 237 gfx::PointF(event.touches[0].position); | |
| 238 suppressing_touchmoves_ = slop_suppression_length_dips_squared_ != 0; | |
| 239 } | |
| 240 | 222 |
| 241 if (event.type == WebInputEvent::TouchEnd || | 223 if (event.type == WebInputEvent::TouchEnd || |
| 242 event.type == WebInputEvent::TouchCancel) | 224 event.type == WebInputEvent::TouchCancel) |
| 243 suppressing_touchmoves_ = false; | 225 suppressing_touchmoves_ = false; |
| 244 | 226 |
| 245 if (event.type != WebInputEvent::TouchMove) | 227 if (event.type != WebInputEvent::TouchMove) |
| 246 return false; | 228 return false; |
| 247 | 229 |
| 248 if (suppressing_touchmoves_) { | 230 if (suppressing_touchmoves_) { |
| 249 // Movement with a secondary pointer should terminate suppression. | 231 if (event.touchesLength > 1) |
| 250 if (event.touchesLength > 1) { | |
| 251 suppressing_touchmoves_ = false; | 232 suppressing_touchmoves_ = false; |
| 252 } else if (event.touchesLength == 1) { | 233 if (event.causesScrollingIfUncanceled) |
| 253 // Movement outside of the slop region should terminate suppression. | 234 suppressing_touchmoves_ = false; |
| 254 gfx::PointF position(event.touches[0].position); | |
| 255 if ((position - touch_sequence_start_position_).LengthSquared() > | |
| 256 slop_suppression_length_dips_squared_) | |
| 257 suppressing_touchmoves_ = false; | |
| 258 } | |
| 259 } | 235 } |
| 236 |
| 260 return suppressing_touchmoves_; | 237 return suppressing_touchmoves_; |
| 261 } | 238 } |
| 262 | 239 |
| 263 void ConfirmTouchEvent(InputEventAckState ack_result) { | 240 void ConfirmTouchEvent(InputEventAckState ack_result) { |
| 264 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) | 241 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 265 suppressing_touchmoves_ = false; | 242 suppressing_touchmoves_ = false; |
| 266 } | 243 } |
| 267 | 244 |
| 268 bool suppressing_touchmoves() const { return suppressing_touchmoves_; } | 245 bool suppressing_touchmoves() const { return suppressing_touchmoves_; } |
| 269 | 246 |
| 270 private: | 247 private: |
| 271 double slop_suppression_length_dips_squared_; | |
| 272 gfx::PointF touch_sequence_start_position_; | |
| 273 bool suppressing_touchmoves_; | 248 bool suppressing_touchmoves_; |
| 274 | 249 |
| 275 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); | 250 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); |
| 276 }; | 251 }; |
| 277 | 252 |
| 278 // This class represents a single coalesced touch event. However, it also keeps | 253 // This class represents a single coalesced touch event. However, it also keeps |
| 279 // track of all the original touch-events that were coalesced into a single | 254 // track of all the original touch-events that were coalesced into a single |
| 280 // event. The coalesced event is forwarded to the renderer, while the original | 255 // event. The coalesced event is forwarded to the renderer, while the original |
| 281 // touch-events are sent to the Client (on ACK for the coalesced event) so that | 256 // touch-events are sent to the Client (on ACK for the coalesced event) so that |
| 282 // the Client receives the event with their original timestamp. | 257 // the Client receives the event with their original timestamp. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // Note that this will be empty if no coalescing has occurred. | 330 // Note that this will be empty if no coalescing has occurred. |
| 356 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 331 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| 357 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; | 332 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; |
| 358 | 333 |
| 359 bool suppress_client_ack_; | 334 bool suppress_client_ack_; |
| 360 | 335 |
| 361 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); | 336 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
| 362 }; | 337 }; |
| 363 | 338 |
| 364 TouchEventQueue::Config::Config() | 339 TouchEventQueue::Config::Config() |
| 365 : touchmove_slop_suppression_length_dips(0), | 340 : touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), |
| 366 touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), | |
| 367 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), | 341 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), |
| 368 touch_ack_timeout_supported(false) { | 342 touch_ack_timeout_supported(false) { |
| 369 } | 343 } |
| 370 | 344 |
| 371 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, | 345 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, |
| 372 const Config& config) | 346 const Config& config) |
| 373 : client_(client), | 347 : client_(client), |
| 374 dispatching_touch_ack_(NULL), | 348 dispatching_touch_ack_(NULL), |
| 375 dispatching_touch_(false), | 349 dispatching_touch_(false), |
| 376 has_handlers_(true), | 350 has_handlers_(true), |
| 377 drop_remaining_touches_in_sequence_(false), | 351 drop_remaining_touches_in_sequence_(false), |
| 378 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor( | 352 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), |
| 379 config.touchmove_slop_suppression_length_dips)), | |
| 380 send_touch_events_async_(false), | 353 send_touch_events_async_(false), |
| 381 needs_async_touchmove_for_outer_slop_region_(false), | 354 needs_async_touchmove_for_outer_slop_region_(false), |
| 382 last_sent_touch_timestamp_sec_(0), | 355 last_sent_touch_timestamp_sec_(0), |
| 383 touch_scrolling_mode_(config.touch_scrolling_mode) { | 356 touch_scrolling_mode_(config.touch_scrolling_mode) { |
| 384 DCHECK(client); | 357 DCHECK(client); |
| 385 if (config.touch_ack_timeout_supported) { | 358 if (config.touch_ack_timeout_supported) { |
| 386 timeout_handler_.reset( | 359 timeout_handler_.reset( |
| 387 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); | 360 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); |
| 388 } | 361 } |
| 389 } | 362 } |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 750 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 778 touch_consumer_states_.mark_bit(point.id); | 751 touch_consumer_states_.mark_bit(point.id); |
| 779 else | 752 else |
| 780 touch_consumer_states_.clear_bit(point.id); | 753 touch_consumer_states_.clear_bit(point.id); |
| 781 } | 754 } |
| 782 } | 755 } |
| 783 } | 756 } |
| 784 } | 757 } |
| 785 | 758 |
| 786 } // namespace content | 759 } // namespace content |
| OLD | NEW |