| 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/input_router_impl.h" | 5 #include "content/browser/renderer_host/input/input_router_impl.h" |
| 6 | 6 |
| 7 #include <math.h> |
| 8 |
| 7 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 8 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 9 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 11 #include "content/browser/renderer_host/input/gesture_event_queue.h" | 13 #include "content/browser/renderer_host/input/gesture_event_queue.h" |
| 12 #include "content/browser/renderer_host/input/input_ack_handler.h" | 14 #include "content/browser/renderer_host/input/input_ack_handler.h" |
| 13 #include "content/browser/renderer_host/input/input_router_client.h" | 15 #include "content/browser/renderer_host/input/input_router_client.h" |
| 14 #include "content/browser/renderer_host/input/touch_event_queue.h" | 16 #include "content/browser/renderer_host/input/touch_event_queue.h" |
| 15 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" | 17 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle
r.h" |
| 16 #include "content/browser/renderer_host/overscroll_controller.h" | 18 #include "content/browser/renderer_host/overscroll_controller.h" |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 if (mouse_event.event.type == WebInputEvent::MouseUp && | 175 if (mouse_event.event.type == WebInputEvent::MouseUp && |
| 174 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 176 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
| 175 ShouldSuppressMouseUp()) | 177 ShouldSuppressMouseUp()) |
| 176 return; | 178 return; |
| 177 | 179 |
| 178 SendMouseEventImmediately(mouse_event); | 180 SendMouseEventImmediately(mouse_event); |
| 179 } | 181 } |
| 180 | 182 |
| 181 void InputRouterImpl::SendWheelEvent( | 183 void InputRouterImpl::SendWheelEvent( |
| 182 const MouseWheelEventWithLatencyInfo& wheel_event) { | 184 const MouseWheelEventWithLatencyInfo& wheel_event) { |
| 183 // If there's already a mouse wheel event waiting to be sent to the renderer, | 185 SendWheelEvent(QueuedWheelEvent(wheel_event, false)); |
| 184 // add the new deltas to that event. Not doing so (e.g., by dropping the old | 186 } |
| 185 // event, as for mouse moves) results in very slow scrolling on the Mac (on | 187 |
| 186 // which many, very small wheel events are sent). | 188 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { |
| 187 if (mouse_wheel_pending_) { | 189 if (mouse_wheel_pending_) { |
| 190 // If there's already a mouse wheel event waiting to be sent to the |
| 191 // renderer, add the new deltas to that event. Not doing so (e.g., by |
| 192 // dropping the old event, as for mouse moves) results in very slow |
| 193 // scrolling on the Mac (on which many, very small wheel events are sent). |
| 194 // Note that we can't coalesce wheel events for pinches because the GEQ |
| 195 // expects one ACK for each (but it's fine to coalesce non-pinch wheels |
| 196 // into a pinch one). Note that the GestureEventQueue ensures we only |
| 197 // ever have a single pinch event queued here. |
| 188 if (coalesced_mouse_wheel_events_.empty() || | 198 if (coalesced_mouse_wheel_events_.empty() || |
| 189 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { | 199 wheel_event.synthesized_from_pinch || |
| 200 !coalesced_mouse_wheel_events_.back().event.CanCoalesceWith( |
| 201 wheel_event.event)) { |
| 190 coalesced_mouse_wheel_events_.push_back(wheel_event); | 202 coalesced_mouse_wheel_events_.push_back(wheel_event); |
| 191 } else { | 203 } else { |
| 192 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); | 204 coalesced_mouse_wheel_events_.back().event.CoalesceWith( |
| 205 wheel_event.event); |
| 193 } | 206 } |
| 194 return; | 207 return; |
| 195 } | 208 } |
| 209 |
| 196 mouse_wheel_pending_ = true; | 210 mouse_wheel_pending_ = true; |
| 197 current_wheel_event_ = wheel_event; | 211 current_wheel_event_ = wheel_event; |
| 198 | 212 |
| 199 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | 213 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
| 200 coalesced_mouse_wheel_events_.size()); | 214 coalesced_mouse_wheel_events_.size()); |
| 201 | 215 |
| 202 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); | 216 FilterAndSendWebInputEvent( |
| 217 wheel_event.event.event, wheel_event.event.latency, false); |
| 203 } | 218 } |
| 204 | 219 |
| 205 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, | 220 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
| 206 const ui::LatencyInfo& latency_info, | 221 const ui::LatencyInfo& latency_info, |
| 207 bool is_keyboard_shortcut) { | 222 bool is_keyboard_shortcut) { |
| 208 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 223 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
| 209 // renderer and we need to give something to the HandleKeyboardEvent | 224 // renderer and we need to give something to the HandleKeyboardEvent |
| 210 // handler. | 225 // handler. |
| 211 key_queue_.push_back(key_event); | 226 key_queue_.push_back(key_event); |
| 212 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 227 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 228 touch_event_queue_.OnGestureScrollEvent(gesture_event); | 243 touch_event_queue_.OnGestureScrollEvent(gesture_event); |
| 229 | 244 |
| 230 if (!IsInOverscrollGesture() && | 245 if (!IsInOverscrollGesture() && |
| 231 !gesture_event_queue_.ShouldForward(gesture_event)) { | 246 !gesture_event_queue_.ShouldForward(gesture_event)) { |
| 232 OverscrollController* controller = client_->GetOverscrollController(); | 247 OverscrollController* controller = client_->GetOverscrollController(); |
| 233 if (controller) | 248 if (controller) |
| 234 controller->DiscardingGestureEvent(gesture_event.event); | 249 controller->DiscardingGestureEvent(gesture_event.event); |
| 235 return; | 250 return; |
| 236 } | 251 } |
| 237 | 252 |
| 238 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 253 SendGestureEventImmediately(gesture_event); |
| 239 } | 254 } |
| 240 | 255 |
| 241 void InputRouterImpl::SendTouchEvent( | 256 void InputRouterImpl::SendTouchEvent( |
| 242 const TouchEventWithLatencyInfo& touch_event) { | 257 const TouchEventWithLatencyInfo& touch_event) { |
| 243 touch_event_queue_.QueueEvent(touch_event); | 258 touch_event_queue_.QueueEvent(touch_event); |
| 244 } | 259 } |
| 245 | 260 |
| 246 // Forwards MouseEvent without passing it through | 261 // Forwards MouseEvent without passing it through |
| 247 // TouchpadTapSuppressionController. | 262 // TouchpadTapSuppressionController. |
| 248 void InputRouterImpl::SendMouseEventImmediately( | 263 void InputRouterImpl::SendMouseEventImmediately( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 274 // sequence. This is a desirable side-effect, giving the renderer a chance | 289 // sequence. This is a desirable side-effect, giving the renderer a chance |
| 275 // to send a touch-action response without racing against the ack timeout. | 290 // to send a touch-action response without racing against the ack timeout. |
| 276 UpdateTouchAckTimeoutEnabled(); | 291 UpdateTouchAckTimeoutEnabled(); |
| 277 } | 292 } |
| 278 | 293 |
| 279 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); | 294 FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); |
| 280 } | 295 } |
| 281 | 296 |
| 282 void InputRouterImpl::SendGestureEventImmediately( | 297 void InputRouterImpl::SendGestureEventImmediately( |
| 283 const GestureEventWithLatencyInfo& gesture_event) { | 298 const GestureEventWithLatencyInfo& gesture_event) { |
| 299 if (gesture_event.event.type == WebInputEvent::GesturePinchUpdate && |
| 300 gesture_event.event.sourceDevice == WebGestureEvent::Touchpad) { |
| 301 SendSyntheticWheelEventForPinch(gesture_event); |
| 302 return; |
| 303 } |
| 304 |
| 284 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); | 305 FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); |
| 285 } | 306 } |
| 286 | 307 |
| 287 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { | 308 const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { |
| 288 if (key_queue_.empty()) | 309 if (key_queue_.empty()) |
| 289 return NULL; | 310 return NULL; |
| 290 return &key_queue_.front(); | 311 return &key_queue_.front(); |
| 291 } | 312 } |
| 292 | 313 |
| 293 bool InputRouterImpl::ShouldForwardTouchEvent() const { | 314 bool InputRouterImpl::ShouldForwardTouchEvent() const { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 392 |
| 372 void InputRouterImpl::FilterAndSendWebInputEvent( | 393 void InputRouterImpl::FilterAndSendWebInputEvent( |
| 373 const WebInputEvent& input_event, | 394 const WebInputEvent& input_event, |
| 374 const ui::LatencyInfo& latency_info, | 395 const ui::LatencyInfo& latency_info, |
| 375 bool is_keyboard_shortcut) { | 396 bool is_keyboard_shortcut) { |
| 376 TRACE_EVENT1("input", | 397 TRACE_EVENT1("input", |
| 377 "InputRouterImpl::FilterAndSendWebInputEvent", | 398 "InputRouterImpl::FilterAndSendWebInputEvent", |
| 378 "type", | 399 "type", |
| 379 WebInputEventTraits::GetName(input_event.type)); | 400 WebInputEventTraits::GetName(input_event.type)); |
| 380 | 401 |
| 381 // Transmit any pending wheel events on a non-wheel event. This ensures that | |
| 382 // final PhaseEnded wheel event is received, which is necessary to terminate | |
| 383 // rubber-banding, for example. | |
| 384 if (input_event.type != WebInputEvent::MouseWheel) { | |
| 385 WheelEventQueue mouse_wheel_events; | |
| 386 mouse_wheel_events.swap(coalesced_mouse_wheel_events_); | |
| 387 for (size_t i = 0; i < mouse_wheel_events.size(); ++i) { | |
| 388 OfferToHandlers(mouse_wheel_events[i].event, | |
| 389 mouse_wheel_events[i].latency, | |
| 390 false); | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 // Any input event cancels a pending mouse move event. | 402 // Any input event cancels a pending mouse move event. |
| 395 next_mouse_move_.reset(); | 403 next_mouse_move_.reset(); |
| 396 | 404 |
| 397 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); | 405 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); |
| 398 } | 406 } |
| 399 | 407 |
| 400 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, | 408 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, |
| 401 const ui::LatencyInfo& latency_info, | 409 const ui::LatencyInfo& latency_info, |
| 402 bool is_keyboard_shortcut) { | 410 bool is_keyboard_shortcut) { |
| 403 // Trackpad pinch gestures are not yet handled by the renderer. | |
| 404 // TODO(rbyers): Send mousewheel for trackpad pinch - crbug.com/289887. | |
| 405 if (input_event.type == WebInputEvent::GesturePinchUpdate && | |
| 406 static_cast<const WebGestureEvent&>(input_event).sourceDevice == | |
| 407 WebGestureEvent::Touchpad) { | |
| 408 ProcessInputEventAck(input_event.type, | |
| 409 INPUT_EVENT_ACK_STATE_NOT_CONSUMED, | |
| 410 latency_info, | |
| 411 ACK_SOURCE_NONE); | |
| 412 return; | |
| 413 } | |
| 414 | |
| 415 if (OfferToOverscrollController(input_event, latency_info)) | 411 if (OfferToOverscrollController(input_event, latency_info)) |
| 416 return; | 412 return; |
| 417 | 413 |
| 418 if (OfferToClient(input_event, latency_info)) | 414 if (OfferToClient(input_event, latency_info)) |
| 419 return; | 415 return; |
| 420 | 416 |
| 421 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); | 417 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); |
| 422 | 418 |
| 423 // Touch events should always indicate in the event whether they are | 419 // Touch events should always indicate in the event whether they are |
| 424 // cancelable (respect ACK disposition) or not. | 420 // cancelable (respect ACK disposition) or not. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 // or in-flight event count metrics. | 504 // or in-flight event count metrics. |
| 509 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { | 505 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { |
| 510 input_event_start_time_ = TimeTicks::Now(); | 506 input_event_start_time_ = TimeTicks::Now(); |
| 511 client_->IncrementInFlightEventCount(); | 507 client_->IncrementInFlightEventCount(); |
| 512 } | 508 } |
| 513 return true; | 509 return true; |
| 514 } | 510 } |
| 515 return false; | 511 return false; |
| 516 } | 512 } |
| 517 | 513 |
| 514 void InputRouterImpl::SendSyntheticWheelEventForPinch( |
| 515 const GestureEventWithLatencyInfo& pinch_event) { |
| 516 // We match typical trackpad behavior on Windows by sending fake wheel events |
| 517 // with the ctrl modifier set when we see trackpad pinch gestures. Ideally |
| 518 // we'd someday get a standard 'pinch' event and send that instead. |
| 519 |
| 520 WebMouseWheelEvent wheelEvent; |
| 521 wheelEvent.type = WebInputEvent::MouseWheel; |
| 522 wheelEvent.timeStampSeconds = pinch_event.event.timeStampSeconds; |
| 523 wheelEvent.windowX = wheelEvent.x = pinch_event.event.x; |
| 524 wheelEvent.windowY = wheelEvent.y = pinch_event.event.y; |
| 525 wheelEvent.globalX = pinch_event.event.globalX; |
| 526 wheelEvent.globalY = pinch_event.event.globalY; |
| 527 wheelEvent.modifiers = |
| 528 pinch_event.event.modifiers | WebInputEvent::ControlKey; |
| 529 wheelEvent.deltaX = 0; |
| 530 // The function to convert scales to deltaY values is designed to be |
| 531 // compatible with websites existing use of wheel events, and with existing |
| 532 // Windows trackpad behavior. In particular, we want: |
| 533 // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2) |
| 534 // - deltas should invert via negation: f(1/s) == -f(s) |
| 535 // - zoom in should be positive: f(s) > 0 iff s > 1 |
| 536 // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100 |
| 537 // - a formula that's relatively easy to use from JavaScript |
| 538 // Note that 'wheel' event deltaY values have their sign inverted. So to |
| 539 // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100). |
| 540 DCHECK_GT(pinch_event.event.data.pinchUpdate.scale, 0); |
| 541 wheelEvent.deltaY = 100.0f * log(pinch_event.event.data.pinchUpdate.scale); |
| 542 wheelEvent.hasPreciseScrollingDeltas = true; |
| 543 wheelEvent.wheelTicksX = 0; |
| 544 wheelEvent.wheelTicksY = |
| 545 pinch_event.event.data.pinchUpdate.scale > 1 ? 1 : -1; |
| 546 |
| 547 SendWheelEvent(QueuedWheelEvent( |
| 548 MouseWheelEventWithLatencyInfo(wheelEvent, pinch_event.latency), true)); |
| 549 } |
| 550 |
| 518 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, | 551 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, |
| 519 InputEventAckState ack_result, | 552 InputEventAckState ack_result, |
| 520 const ui::LatencyInfo& latency_info) { | 553 const ui::LatencyInfo& latency_info) { |
| 521 client_->DecrementInFlightEventCount(); | 554 client_->DecrementInFlightEventCount(); |
| 522 | 555 |
| 523 // Log the time delta for processing an input event. | 556 // Log the time delta for processing an input event. |
| 524 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 557 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
| 525 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); | 558 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); |
| 526 | 559 |
| 527 ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER); | 560 ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 if (next_mouse_move_) { | 673 if (next_mouse_move_) { |
| 641 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 674 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); |
| 642 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 675 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
| 643 = next_mouse_move_.Pass(); | 676 = next_mouse_move_.Pass(); |
| 644 SendMouseEvent(*next_mouse_move); | 677 SendMouseEvent(*next_mouse_move); |
| 645 } | 678 } |
| 646 } | 679 } |
| 647 | 680 |
| 648 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, | 681 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
| 649 const ui::LatencyInfo& latency) { | 682 const ui::LatencyInfo& latency) { |
| 650 ProcessAckForOverscroll(current_wheel_event_.event, ack_result); | |
| 651 | |
| 652 // TODO(miletus): Add renderer side latency to each uncoalesced mouse | 683 // TODO(miletus): Add renderer side latency to each uncoalesced mouse |
| 653 // wheel event and add terminal component to each of them. | 684 // wheel event and add terminal component to each of them. |
| 654 current_wheel_event_.latency.AddNewLatencyFrom(latency); | 685 current_wheel_event_.event.latency.AddNewLatencyFrom(latency); |
| 655 // Process the unhandled wheel event here before calling SendWheelEvent() | 686 |
| 656 // since it will mutate current_wheel_event_. | 687 if (current_wheel_event_.synthesized_from_pinch) { |
| 657 ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); | 688 // Ack the GesturePinchUpdate event that generated this wheel event. |
| 689 ProcessInputEventAck(WebInputEvent::GesturePinchUpdate, |
| 690 ack_result, |
| 691 current_wheel_event_.event.latency, |
| 692 current_ack_source_); |
| 693 } else { |
| 694 // Process the unhandled wheel event here before calling SendWheelEvent() |
| 695 // since it will mutate current_wheel_event_. |
| 696 ProcessAckForOverscroll(current_wheel_event_.event.event, ack_result); |
| 697 ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result); |
| 698 } |
| 699 |
| 700 // Mark the wheel event complete only after the ACKs have been handled above. |
| 701 // For example, ACKing the GesturePinchUpdate could cause another |
| 702 // GesturePinchUpdate to be sent, which should queue a wheel event rather than |
| 703 // send it immediately. |
| 658 mouse_wheel_pending_ = false; | 704 mouse_wheel_pending_ = false; |
| 659 | 705 |
| 660 // Now send the next (coalesced) mouse wheel event. | 706 // Send the next (coalesced or synthetic) mouse wheel event. |
| 661 if (!coalesced_mouse_wheel_events_.empty()) { | 707 if (!coalesced_mouse_wheel_events_.empty()) { |
| 662 MouseWheelEventWithLatencyInfo next_wheel_event = | 708 QueuedWheelEvent next_wheel_event = coalesced_mouse_wheel_events_.front(); |
| 663 coalesced_mouse_wheel_events_.front(); | |
| 664 coalesced_mouse_wheel_events_.pop_front(); | 709 coalesced_mouse_wheel_events_.pop_front(); |
| 665 SendWheelEvent(next_wheel_event); | 710 SendWheelEvent(next_wheel_event); |
| 666 } | 711 } |
| 667 } | 712 } |
| 668 | 713 |
| 669 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, | 714 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, |
| 670 InputEventAckState ack_result, | 715 InputEventAckState ack_result, |
| 671 const ui::LatencyInfo& latency) { | 716 const ui::LatencyInfo& latency) { |
| 672 // If |ack_result| originated from the overscroll controller, only | 717 // If |ack_result| originated from the overscroll controller, only |
| 673 // feed |gesture_event_queue_| the ack if it was expecting one. | 718 // feed |gesture_event_queue_| the ack if it was expecting one. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 mouse_wheel_pending_ || | 790 mouse_wheel_pending_ || |
| 746 select_range_pending_ || | 791 select_range_pending_ || |
| 747 move_caret_pending_; | 792 move_caret_pending_; |
| 748 } | 793 } |
| 749 | 794 |
| 750 bool InputRouterImpl::IsInOverscrollGesture() const { | 795 bool InputRouterImpl::IsInOverscrollGesture() const { |
| 751 OverscrollController* controller = client_->GetOverscrollController(); | 796 OverscrollController* controller = client_->GetOverscrollController(); |
| 752 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 797 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
| 753 } | 798 } |
| 754 | 799 |
| 800 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent() |
| 801 : synthesized_from_pinch(false) { |
| 802 } |
| 803 |
| 804 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent( |
| 805 const MouseWheelEventWithLatencyInfo& event, |
| 806 bool synthesized_from_pinch) |
| 807 : event(event), synthesized_from_pinch(synthesized_from_pinch) { |
| 808 } |
| 809 |
| 810 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() { |
| 811 } |
| 812 |
| 755 } // namespace content | 813 } // namespace content |
| OLD | NEW |