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> | 7 #include <math.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 client_(client), | 68 client_(client), |
69 ack_handler_(ack_handler), | 69 ack_handler_(ack_handler), |
70 routing_id_(routing_id), | 70 routing_id_(routing_id), |
71 select_message_pending_(false), | 71 select_message_pending_(false), |
72 move_caret_pending_(false), | 72 move_caret_pending_(false), |
73 mouse_move_pending_(false), | 73 mouse_move_pending_(false), |
74 mouse_wheel_pending_(false), | 74 mouse_wheel_pending_(false), |
75 current_view_flags_(0), | 75 current_view_flags_(0), |
76 current_ack_source_(ACK_SOURCE_NONE), | 76 current_ack_source_(ACK_SOURCE_NONE), |
77 flush_requested_(false), | 77 flush_requested_(false), |
| 78 in_shutdown_(false), |
78 touch_event_queue_(this, config.touch_config), | 79 touch_event_queue_(this, config.touch_config), |
79 gesture_event_queue_(this, this, config.gesture_config) { | 80 gesture_event_queue_(this, this, config.gesture_config) { |
80 DCHECK(sender); | 81 DCHECK(sender); |
81 DCHECK(client); | 82 DCHECK(client); |
82 DCHECK(ack_handler); | 83 DCHECK(ack_handler); |
83 UpdateTouchAckTimeoutEnabled(); | 84 UpdateTouchAckTimeoutEnabled(); |
84 } | 85 } |
85 | 86 |
86 InputRouterImpl::~InputRouterImpl() { | 87 InputRouterImpl::~InputRouterImpl() { |
87 STLDeleteElements(&pending_select_messages_); | 88 STLDeleteElements(&pending_select_messages_); |
88 } | 89 in_shutdown_ = true; |
89 | 90 // As upstream code may depend on acks for currently queued touch events, |
90 void InputRouterImpl::Flush() { | 91 // explicitly flush the touch queue, dropping any generated gesture events. |
91 flush_requested_ = true; | 92 touch_event_queue_.Flush(INPUT_EVENT_ACK_STATE_CONSUMED); |
92 SignalFlushedIfNecessary(); | 93 if (flush_requested_) { |
| 94 flush_requested_ = false; |
| 95 client_->DidFlush(); |
| 96 } |
93 } | 97 } |
94 | 98 |
95 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { | 99 bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { |
96 DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); | 100 DCHECK(!in_shutdown_); |
| 101 DCHECK_EQ(IPC_MESSAGE_ID_CLASS(message->type()), |
| 102 static_cast<uint32>(InputMsgStart)); |
97 switch (message->type()) { | 103 switch (message->type()) { |
98 // Check for types that require an ACK. | 104 // Check for types that require an ACK. |
99 case InputMsg_SelectRange::ID: | 105 case InputMsg_SelectRange::ID: |
100 case InputMsg_MoveRangeSelectionExtent::ID: | 106 case InputMsg_MoveRangeSelectionExtent::ID: |
101 return SendSelectMessage(message.Pass()); | 107 return SendSelectMessage(message.Pass()); |
102 case InputMsg_MoveCaret::ID: | 108 case InputMsg_MoveCaret::ID: |
103 return SendMoveCaret(message.Pass()); | 109 return SendMoveCaret(message.Pass()); |
104 case InputMsg_HandleInputEvent::ID: | 110 case InputMsg_HandleInputEvent::ID: |
105 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; | 111 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; |
106 return false; | 112 return false; |
107 default: | 113 default: |
108 return Send(message.release()); | 114 return Send(message.release()); |
109 } | 115 } |
110 } | 116 } |
111 | 117 |
112 void InputRouterImpl::SendMouseEvent( | 118 void InputRouterImpl::SendMouseEvent( |
113 const MouseEventWithLatencyInfo& mouse_event) { | 119 const MouseEventWithLatencyInfo& mouse_event) { |
| 120 DCHECK(!in_shutdown_); |
114 if (mouse_event.event.type == WebInputEvent::MouseDown && | 121 if (mouse_event.event.type == WebInputEvent::MouseDown && |
115 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 122 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
116 ShouldDeferMouseDown(mouse_event)) | 123 ShouldDeferMouseDown(mouse_event)) |
117 return; | 124 return; |
118 if (mouse_event.event.type == WebInputEvent::MouseUp && | 125 if (mouse_event.event.type == WebInputEvent::MouseUp && |
119 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 126 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
120 ShouldSuppressMouseUp()) | 127 ShouldSuppressMouseUp()) |
121 return; | 128 return; |
122 | 129 |
123 SendMouseEventImmediately(mouse_event); | 130 SendMouseEventImmediately(mouse_event); |
124 } | 131 } |
125 | 132 |
126 void InputRouterImpl::SendWheelEvent( | 133 void InputRouterImpl::SendWheelEvent( |
127 const MouseWheelEventWithLatencyInfo& wheel_event) { | 134 const MouseWheelEventWithLatencyInfo& wheel_event) { |
| 135 DCHECK(!in_shutdown_); |
128 SendWheelEvent(QueuedWheelEvent(wheel_event, false)); | 136 SendWheelEvent(QueuedWheelEvent(wheel_event, false)); |
129 } | 137 } |
130 | 138 |
131 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { | 139 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { |
| 140 DCHECK(!in_shutdown_); |
132 if (mouse_wheel_pending_) { | 141 if (mouse_wheel_pending_) { |
133 // If there's already a mouse wheel event waiting to be sent to the | 142 // If there's already a mouse wheel event waiting to be sent to the |
134 // renderer, add the new deltas to that event. Not doing so (e.g., by | 143 // renderer, add the new deltas to that event. Not doing so (e.g., by |
135 // dropping the old event, as for mouse moves) results in very slow | 144 // dropping the old event, as for mouse moves) results in very slow |
136 // scrolling on the Mac (on which many, very small wheel events are sent). | 145 // scrolling on the Mac (on which many, very small wheel events are sent). |
137 // Note that we can't coalesce wheel events for pinches because the GEQ | 146 // Note that we can't coalesce wheel events for pinches because the GEQ |
138 // expects one ACK for each (but it's fine to coalesce non-pinch wheels | 147 // expects one ACK for each (but it's fine to coalesce non-pinch wheels |
139 // into a pinch one). Note that the GestureEventQueue ensures we only | 148 // into a pinch one). Note that the GestureEventQueue ensures we only |
140 // ever have a single pinch event queued here. | 149 // ever have a single pinch event queued here. |
141 if (coalesced_mouse_wheel_events_.empty() || | 150 if (coalesced_mouse_wheel_events_.empty() || |
(...skipping 14 matching lines...) Expand all Loading... |
156 LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | 165 LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
157 coalesced_mouse_wheel_events_.size()); | 166 coalesced_mouse_wheel_events_.size()); |
158 | 167 |
159 FilterAndSendWebInputEvent( | 168 FilterAndSendWebInputEvent( |
160 wheel_event.event.event, wheel_event.event.latency, false); | 169 wheel_event.event.event, wheel_event.event.latency, false); |
161 } | 170 } |
162 | 171 |
163 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, | 172 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
164 const ui::LatencyInfo& latency_info, | 173 const ui::LatencyInfo& latency_info, |
165 bool is_keyboard_shortcut) { | 174 bool is_keyboard_shortcut) { |
| 175 DCHECK(!in_shutdown_); |
166 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 176 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
167 // renderer and we need to give something to the HandleKeyboardEvent | 177 // renderer and we need to give something to the HandleKeyboardEvent |
168 // handler. | 178 // handler. |
169 key_queue_.push_back(key_event); | 179 key_queue_.push_back(key_event); |
170 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 180 LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
171 | 181 |
172 gesture_event_queue_.FlingHasBeenHalted(); | 182 gesture_event_queue_.FlingHasBeenHalted(); |
173 | 183 |
174 // Only forward the non-native portions of our event. | 184 // Only forward the non-native portions of our event. |
175 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); | 185 FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); |
176 } | 186 } |
177 | 187 |
178 void InputRouterImpl::SendGestureEvent( | 188 void InputRouterImpl::SendGestureEvent( |
179 const GestureEventWithLatencyInfo& original_gesture_event) { | 189 const GestureEventWithLatencyInfo& original_gesture_event) { |
| 190 if (in_shutdown_) |
| 191 return; |
| 192 |
180 input_stream_validator_.Validate(original_gesture_event.event); | 193 input_stream_validator_.Validate(original_gesture_event.event); |
181 | 194 |
182 GestureEventWithLatencyInfo gesture_event(original_gesture_event); | 195 GestureEventWithLatencyInfo gesture_event(original_gesture_event); |
183 | 196 |
184 if (touch_action_filter_.FilterGestureEvent(&gesture_event.event)) | 197 if (touch_action_filter_.FilterGestureEvent(&gesture_event.event)) |
185 return; | 198 return; |
186 | 199 |
187 if (gesture_event.event.sourceDevice == blink::WebGestureDeviceTouchscreen) | 200 if (gesture_event.event.sourceDevice == blink::WebGestureDeviceTouchscreen) |
188 touch_event_queue_.OnGestureScrollEvent(gesture_event); | 201 touch_event_queue_.OnGestureScrollEvent(gesture_event); |
189 | 202 |
190 if (!gesture_event_queue_.ShouldForward(gesture_event)) | 203 if (!gesture_event_queue_.ShouldForward(gesture_event)) |
191 return; | 204 return; |
192 | 205 |
193 SendGestureEventImmediately(gesture_event); | 206 SendGestureEventImmediately(gesture_event); |
194 } | 207 } |
195 | 208 |
196 void InputRouterImpl::SendTouchEvent( | 209 void InputRouterImpl::SendTouchEvent( |
197 const TouchEventWithLatencyInfo& touch_event) { | 210 const TouchEventWithLatencyInfo& touch_event) { |
| 211 DCHECK(!in_shutdown_); |
198 input_stream_validator_.Validate(touch_event.event); | 212 input_stream_validator_.Validate(touch_event.event); |
199 touch_event_queue_.QueueEvent(touch_event); | 213 touch_event_queue_.QueueEvent(touch_event); |
200 } | 214 } |
201 | 215 |
| 216 void InputRouterImpl::RequestFlushedNotification() { |
| 217 flush_requested_ = true; |
| 218 SignalFlushedIfNecessary(); |
| 219 } |
| 220 |
202 // Forwards MouseEvent without passing it through | 221 // Forwards MouseEvent without passing it through |
203 // TouchpadTapSuppressionController. | 222 // TouchpadTapSuppressionController. |
204 void InputRouterImpl::SendMouseEventImmediately( | 223 void InputRouterImpl::SendMouseEventImmediately( |
205 const MouseEventWithLatencyInfo& mouse_event) { | 224 const MouseEventWithLatencyInfo& mouse_event) { |
206 // Avoid spamming the renderer with mouse move events. It is important | 225 // Avoid spamming the renderer with mouse move events. It is important |
207 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our | 226 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our |
208 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way | 227 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way |
209 // more WM_MOUSEMOVE events than we wish to send to the renderer. | 228 // more WM_MOUSEMOVE events than we wish to send to the renderer. |
210 if (mouse_event.event.type == WebInputEvent::MouseMove) { | 229 if (mouse_event.event.type == WebInputEvent::MouseMove) { |
211 if (mouse_move_pending_) { | 230 if (mouse_move_pending_) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 | 338 |
320 pending_select_messages_.push_back(message.release()); | 339 pending_select_messages_.push_back(message.release()); |
321 return true; | 340 return true; |
322 } | 341 } |
323 | 342 |
324 select_message_pending_ = true; | 343 select_message_pending_ = true; |
325 return Send(message.release()); | 344 return Send(message.release()); |
326 } | 345 } |
327 | 346 |
328 bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) { | 347 bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) { |
329 DCHECK(message->type() == InputMsg_MoveCaret::ID); | 348 DCHECK_EQ(message->type(), static_cast<uint32>(InputMsg_MoveCaret::ID)); |
330 if (move_caret_pending_) { | 349 if (move_caret_pending_) { |
331 next_move_caret_ = message.Pass(); | 350 next_move_caret_ = message.Pass(); |
332 return true; | 351 return true; |
333 } | 352 } |
334 | 353 |
335 move_caret_pending_ = true; | 354 move_caret_pending_ = true; |
336 return Send(message.release()); | 355 return Send(message.release()); |
337 } | 356 } |
338 | 357 |
339 bool InputRouterImpl::Send(IPC::Message* message) { | 358 bool InputRouterImpl::Send(IPC::Message* message) { |
(...skipping 11 matching lines...) Expand all Loading... |
351 | 370 |
352 // Any input event cancels a pending mouse move event. | 371 // Any input event cancels a pending mouse move event. |
353 next_mouse_move_.reset(); | 372 next_mouse_move_.reset(); |
354 | 373 |
355 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); | 374 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); |
356 } | 375 } |
357 | 376 |
358 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, | 377 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, |
359 const ui::LatencyInfo& latency_info, | 378 const ui::LatencyInfo& latency_info, |
360 bool is_keyboard_shortcut) { | 379 bool is_keyboard_shortcut) { |
| 380 DCHECK(!in_shutdown_); |
361 output_stream_validator_.Validate(input_event); | 381 output_stream_validator_.Validate(input_event); |
362 | 382 |
363 if (OfferToClient(input_event, latency_info)) | 383 if (OfferToClient(input_event, latency_info)) |
364 return; | 384 return; |
365 | 385 |
366 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); | 386 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); |
367 | 387 |
368 // Touch events should always indicate in the event whether they are | 388 // Touch events should always indicate in the event whether they are |
369 // cancelable (respect ACK disposition) or not. | 389 // cancelable (respect ACK disposition) or not. |
370 bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event); | 390 bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 // Lack of a touch handler indicates that the page either has no touch-action | 541 // Lack of a touch handler indicates that the page either has no touch-action |
522 // modifiers or that all its touch-action modifiers are auto. Resetting the | 542 // modifiers or that all its touch-action modifiers are auto. Resetting the |
523 // touch-action here allows forwarding of subsequent gestures even if the | 543 // touch-action here allows forwarding of subsequent gestures even if the |
524 // underlying touches never reach the router. | 544 // underlying touches never reach the router. |
525 // TODO(jdduke): Reset touch-action only at the end of a touch sequence to | 545 // TODO(jdduke): Reset touch-action only at the end of a touch sequence to |
526 // prevent potentially strange mid-sequence behavior, crbug.com/375940. | 546 // prevent potentially strange mid-sequence behavior, crbug.com/375940. |
527 if (!has_handlers) | 547 if (!has_handlers) |
528 touch_action_filter_.ResetTouchAction(); | 548 touch_action_filter_.ResetTouchAction(); |
529 | 549 |
530 touch_event_queue_.OnHasTouchEventHandlers(has_handlers); | 550 touch_event_queue_.OnHasTouchEventHandlers(has_handlers); |
531 client_->OnHasTouchEventHandlers(has_handlers); | |
532 } | 551 } |
533 | 552 |
534 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { | 553 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { |
535 // Synthetic touchstart events should get filtered out in RenderWidget. | 554 // Synthetic touchstart events should get filtered out in RenderWidget. |
536 DCHECK(touch_event_queue_.IsPendingAckTouchStart()); | 555 DCHECK(touch_event_queue_.IsPendingAckTouchStart()); |
537 TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", | 556 TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", |
538 "action", touch_action); | 557 "action", touch_action); |
539 | 558 |
540 touch_action_filter_.OnSetTouchAction(touch_action); | 559 touch_action_filter_.OnSetTouchAction(touch_action); |
541 | 560 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 ProcessGestureAck(event_type, ack_result, latency_info); | 593 ProcessGestureAck(event_type, ack_result, latency_info); |
575 } else if (event_type != WebInputEvent::Undefined) { | 594 } else if (event_type != WebInputEvent::Undefined) { |
576 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 595 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
577 } | 596 } |
578 | 597 |
579 SignalFlushedIfNecessary(); | 598 SignalFlushedIfNecessary(); |
580 } | 599 } |
581 | 600 |
582 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, | 601 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, |
583 InputEventAckState ack_result) { | 602 InputEventAckState ack_result) { |
584 if (key_queue_.empty()) { | 603 if (key_queue_.empty()) |
585 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK); | 604 return; |
586 } else if (key_queue_.front().type != type) { | 605 |
| 606 if (key_queue_.front().type != type) { |
587 // Something must be wrong. Clear the |key_queue_| and char event | 607 // Something must be wrong. Clear the |key_queue_| and char event |
588 // suppression so that we can resume from the error. | 608 // suppression so that we can resume from the error. |
589 key_queue_.clear(); | 609 key_queue_.clear(); |
590 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE); | 610 ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_EVENT_TYPE); |
591 } else { | 611 } else { |
592 NativeWebKeyboardEvent front_item = key_queue_.front(); | 612 NativeWebKeyboardEvent front_item = key_queue_.front(); |
593 key_queue_.pop_front(); | 613 key_queue_.pop_front(); |
594 | 614 |
595 ack_handler_->OnKeyboardEventAck(front_item, ack_result); | 615 ack_handler_->OnKeyboardEventAck(front_item, ack_result); |
596 // WARNING: This InputRouterImpl can be deallocated at this point | 616 // WARNING: This InputRouterImpl can be deallocated at this point |
597 // (i.e. in the case of Ctrl+W, where the call to | 617 // (i.e. in the case of Ctrl+W, where the call to |
598 // HandleKeyboardEvent destroys this InputRouterImpl). | 618 // HandleKeyboardEvent destroys this InputRouterImpl). |
599 // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async. | 619 // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async. |
600 } | 620 } |
601 } | 621 } |
602 | 622 |
603 void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type, | 623 void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type, |
604 InputEventAckState ack_result) { | 624 InputEventAckState ack_result) { |
605 if (type != WebInputEvent::MouseMove) | 625 if (type != WebInputEvent::MouseMove) |
606 return; | 626 return; |
607 | 627 |
608 DCHECK(mouse_move_pending_); | |
609 mouse_move_pending_ = false; | 628 mouse_move_pending_ = false; |
610 | 629 |
611 if (next_mouse_move_) { | 630 if (next_mouse_move_) { |
612 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 631 DCHECK_EQ(next_mouse_move_->event.type, WebInputEvent::MouseMove); |
613 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 632 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
614 = next_mouse_move_.Pass(); | 633 = next_mouse_move_.Pass(); |
615 SendMouseEvent(*next_mouse_move); | 634 SendMouseEvent(*next_mouse_move); |
616 } | 635 } |
617 } | 636 } |
618 | 637 |
619 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, | 638 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
620 const ui::LatencyInfo& latency) { | 639 const ui::LatencyInfo& latency) { |
621 // TODO(miletus): Add renderer side latency to each uncoalesced mouse | 640 // TODO(miletus): Add renderer side latency to each uncoalesced mouse |
622 // wheel event and add terminal component to each of them. | 641 // wheel event and add terminal component to each of them. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent( | 730 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent( |
712 const MouseWheelEventWithLatencyInfo& event, | 731 const MouseWheelEventWithLatencyInfo& event, |
713 bool synthesized_from_pinch) | 732 bool synthesized_from_pinch) |
714 : event(event), synthesized_from_pinch(synthesized_from_pinch) { | 733 : event(event), synthesized_from_pinch(synthesized_from_pinch) { |
715 } | 734 } |
716 | 735 |
717 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() { | 736 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() { |
718 } | 737 } |
719 | 738 |
720 } // namespace content | 739 } // namespace content |
OLD | NEW |