Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/mouse_wheel_event_queue.h" | 5 #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
| 10 | 10 |
| 11 using blink::WebGestureEvent; | |
| 11 using blink::WebInputEvent; | 12 using blink::WebInputEvent; |
| 12 using blink::WebMouseWheelEvent; | 13 using blink::WebMouseWheelEvent; |
| 13 using ui::LatencyInfo; | 14 using ui::LatencyInfo; |
| 14 | 15 |
| 15 namespace content { | 16 namespace content { |
| 16 | 17 |
| 17 // This class represents a single queued mouse wheel event. Its main use | 18 // This class represents a single queued mouse wheel event. Its main use |
| 18 // is that it is reported via trace events. | 19 // is that it is reported via trace events. |
| 19 class QueuedWebMouseWheelEvent : public MouseWheelEventWithLatencyInfo { | 20 class QueuedWebMouseWheelEvent : public MouseWheelEventWithLatencyInfo { |
| 20 public: | 21 public: |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 return; | 79 return; |
| 79 | 80 |
| 80 event_sent_for_gesture_ack_->latency.AddNewLatencyFrom(latency_info); | 81 event_sent_for_gesture_ack_->latency.AddNewLatencyFrom(latency_info); |
| 81 client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result); | 82 client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result); |
| 82 | 83 |
| 83 // If event wasn't consumed then generate a gesture scroll for it. | 84 // If event wasn't consumed then generate a gesture scroll for it. |
| 84 if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED && | 85 if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED && |
| 85 event_sent_for_gesture_ack_->event.canScroll && | 86 event_sent_for_gesture_ack_->event.canScroll && |
| 86 (scrolling_device_ == blink::WebGestureDeviceUninitialized || | 87 (scrolling_device_ == blink::WebGestureDeviceUninitialized || |
| 87 scrolling_device_ == blink::WebGestureDeviceTouchpad)) { | 88 scrolling_device_ == blink::WebGestureDeviceTouchpad)) { |
| 88 GestureEventWithLatencyInfo scroll_update; | 89 WebGestureEvent scroll_update; |
| 89 scroll_update.event.timeStampSeconds = | 90 scroll_update.timeStampSeconds = |
| 90 event_sent_for_gesture_ack_->event.timeStampSeconds; | 91 event_sent_for_gesture_ack_->event.timeStampSeconds; |
| 91 | 92 |
| 92 scroll_update.event.x = event_sent_for_gesture_ack_->event.x; | 93 scroll_update.x = event_sent_for_gesture_ack_->event.x; |
| 93 scroll_update.event.y = event_sent_for_gesture_ack_->event.y; | 94 scroll_update.y = event_sent_for_gesture_ack_->event.y; |
| 94 scroll_update.event.globalX = event_sent_for_gesture_ack_->event.globalX; | 95 scroll_update.globalX = event_sent_for_gesture_ack_->event.globalX; |
| 95 scroll_update.event.globalY = event_sent_for_gesture_ack_->event.globalY; | 96 scroll_update.globalY = event_sent_for_gesture_ack_->event.globalY; |
| 96 scroll_update.event.type = WebInputEvent::GestureScrollUpdate; | 97 scroll_update.type = WebInputEvent::GestureScrollUpdate; |
| 97 scroll_update.event.sourceDevice = blink::WebGestureDeviceTouchpad; | 98 scroll_update.sourceDevice = blink::WebGestureDeviceTouchpad; |
| 98 scroll_update.event.resendingPluginId = -1; | 99 scroll_update.resendingPluginId = -1; |
| 99 scroll_update.event.data.scrollUpdate.deltaX = | 100 scroll_update.data.scrollUpdate.deltaX = |
| 100 event_sent_for_gesture_ack_->event.deltaX; | 101 event_sent_for_gesture_ack_->event.deltaX; |
| 101 scroll_update.event.data.scrollUpdate.deltaY = | 102 scroll_update.data.scrollUpdate.deltaY = |
| 102 event_sent_for_gesture_ack_->event.deltaY; | 103 event_sent_for_gesture_ack_->event.deltaY; |
| 103 // Only OSX populates the momentumPhase; so expect this to | 104 // Only OSX populates the momentumPhase; so expect this to |
| 104 // always be PhaseNone on all other platforms. | 105 // always be PhaseNone on all other platforms. |
| 105 scroll_update.event.data.scrollUpdate.inertial = | 106 scroll_update.data.scrollUpdate.inertial = |
| 106 event_sent_for_gesture_ack_->event.momentumPhase != | 107 event_sent_for_gesture_ack_->event.momentumPhase != |
| 107 blink::WebMouseWheelEvent::PhaseNone; | 108 blink::WebMouseWheelEvent::PhaseNone; |
| 108 if (event_sent_for_gesture_ack_->event.scrollByPage) { | 109 if (event_sent_for_gesture_ack_->event.scrollByPage) { |
| 109 scroll_update.event.data.scrollUpdate.deltaUnits = | 110 scroll_update.data.scrollUpdate.deltaUnits = WebGestureEvent::Page; |
| 110 blink::WebGestureEvent::Page; | |
| 111 | 111 |
| 112 // Turn page scrolls into a *single* page scroll because | 112 // Turn page scrolls into a *single* page scroll because |
| 113 // the magnitude the number of ticks is lost when coalescing. | 113 // the magnitude the number of ticks is lost when coalescing. |
| 114 if (scroll_update.event.data.scrollUpdate.deltaX) | 114 if (scroll_update.data.scrollUpdate.deltaX) |
| 115 scroll_update.event.data.scrollUpdate.deltaX = | 115 scroll_update.data.scrollUpdate.deltaX = |
| 116 scroll_update.event.data.scrollUpdate.deltaX > 0 ? 1 : -1; | 116 scroll_update.data.scrollUpdate.deltaX > 0 ? 1 : -1; |
| 117 if (scroll_update.event.data.scrollUpdate.deltaY) | 117 if (scroll_update.data.scrollUpdate.deltaY) |
| 118 scroll_update.event.data.scrollUpdate.deltaY = | 118 scroll_update.data.scrollUpdate.deltaY = |
| 119 scroll_update.event.data.scrollUpdate.deltaY > 0 ? 1 : -1; | 119 scroll_update.data.scrollUpdate.deltaY > 0 ? 1 : -1; |
| 120 } else { | 120 } else { |
| 121 scroll_update.event.data.scrollUpdate.deltaUnits = | 121 scroll_update.data.scrollUpdate.deltaUnits = |
| 122 event_sent_for_gesture_ack_->event.hasPreciseScrollingDeltas | 122 event_sent_for_gesture_ack_->event.hasPreciseScrollingDeltas |
| 123 ? blink::WebGestureEvent::PrecisePixels | 123 ? WebGestureEvent::PrecisePixels |
| 124 : blink::WebGestureEvent::Pixels; | 124 : WebGestureEvent::Pixels; |
| 125 | 125 |
| 126 if (event_sent_for_gesture_ack_->event.railsMode == | 126 if (event_sent_for_gesture_ack_->event.railsMode == |
| 127 WebInputEvent::RailsModeVertical) | 127 WebInputEvent::RailsModeVertical) |
| 128 scroll_update.event.data.scrollUpdate.deltaX = 0; | 128 scroll_update.data.scrollUpdate.deltaX = 0; |
| 129 if (event_sent_for_gesture_ack_->event.railsMode == | 129 if (event_sent_for_gesture_ack_->event.railsMode == |
| 130 WebInputEvent::RailsModeHorizontal) | 130 WebInputEvent::RailsModeHorizontal) |
| 131 scroll_update.event.data.scrollUpdate.deltaY = 0; | 131 scroll_update.data.scrollUpdate.deltaY = 0; |
| 132 } | 132 } |
| 133 | 133 |
| 134 bool current_phase_ended = false; | 134 bool current_phase_ended = false; |
| 135 bool has_phase_info = false; | 135 bool has_phase_info = false; |
| 136 | 136 |
| 137 if (event_sent_for_gesture_ack_->event.phase != | 137 if (event_sent_for_gesture_ack_->event.phase != |
| 138 blink::WebMouseWheelEvent::PhaseNone || | 138 blink::WebMouseWheelEvent::PhaseNone || |
| 139 event_sent_for_gesture_ack_->event.momentumPhase != | 139 event_sent_for_gesture_ack_->event.momentumPhase != |
| 140 blink::WebMouseWheelEvent::PhaseNone) { | 140 blink::WebMouseWheelEvent::PhaseNone) { |
| 141 has_phase_info = true; | 141 has_phase_info = true; |
| 142 current_phase_ended = event_sent_for_gesture_ack_->event.phase == | 142 current_phase_ended = event_sent_for_gesture_ack_->event.phase == |
| 143 blink::WebMouseWheelEvent::PhaseEnded || | 143 blink::WebMouseWheelEvent::PhaseEnded || |
| 144 event_sent_for_gesture_ack_->event.phase == | 144 event_sent_for_gesture_ack_->event.phase == |
| 145 blink::WebMouseWheelEvent::PhaseCancelled || | 145 blink::WebMouseWheelEvent::PhaseCancelled || |
| 146 event_sent_for_gesture_ack_->event.momentumPhase == | 146 event_sent_for_gesture_ack_->event.momentumPhase == |
| 147 blink::WebMouseWheelEvent::PhaseEnded || | 147 blink::WebMouseWheelEvent::PhaseEnded || |
| 148 event_sent_for_gesture_ack_->event.momentumPhase == | 148 event_sent_for_gesture_ack_->event.momentumPhase == |
| 149 blink::WebMouseWheelEvent::PhaseCancelled; | 149 blink::WebMouseWheelEvent::PhaseCancelled; |
| 150 } | 150 } |
| 151 | 151 |
| 152 bool needs_update = scroll_update.event.data.scrollUpdate.deltaX != 0 || | 152 bool needs_update = scroll_update.data.scrollUpdate.deltaX != 0 || |
| 153 scroll_update.event.data.scrollUpdate.deltaY != 0; | 153 scroll_update.data.scrollUpdate.deltaY != 0; |
| 154 | 154 |
| 155 // If there is no update to send and the current phase is ended yet a GSB | 155 // If there is no update to send and the current phase is ended yet a GSB |
| 156 // needs to be sent, this event sequence doesn't need to be generated | 156 // needs to be sent, this event sequence doesn't need to be generated |
| 157 // because the events generated will be a GSB (non-synthetic) and GSE | 157 // because the events generated will be a GSB (non-synthetic) and GSE |
| 158 // (non-synthetic). This situation arises when OSX generates double | 158 // (non-synthetic). This situation arises when OSX generates double |
| 159 // phase end information. | 159 // phase end information. |
| 160 bool empty_sequence = | 160 bool empty_sequence = |
| 161 !needs_update && needs_scroll_begin_ && current_phase_ended; | 161 !needs_update && needs_scroll_begin_ && current_phase_ended; |
| 162 | 162 |
| 163 if (needs_update || !empty_sequence) { | 163 if (needs_update || !empty_sequence) { |
| 164 if (needs_scroll_begin_) { | 164 if (needs_scroll_begin_) { |
| 165 // If no GSB has been sent, it will be a non-synthetic GSB. | 165 // If no GSB has been sent, it will be a non-synthetic GSB. |
| 166 SendScrollBegin(scroll_update, false); | 166 SendScrollBegin(scroll_update, false); |
| 167 } else if (has_phase_info) { | 167 } else if (has_phase_info) { |
| 168 // If a GSB has been sent, generate a synthetic GSB if we have phase | 168 // If a GSB has been sent, generate a synthetic GSB if we have phase |
| 169 // information. This should be removed once crbug.com/526463 is fully | 169 // information. This should be removed once crbug.com/526463 is fully |
| 170 // implemented. | 170 // implemented. |
| 171 SendScrollBegin(scroll_update, true); | 171 SendScrollBegin(scroll_update, true); |
| 172 } | 172 } |
| 173 | 173 |
| 174 if (needs_update) | 174 if (needs_update) |
| 175 client_->SendGestureEvent(scroll_update); | 175 client_->ForwardGestureEvent(scroll_update); |
| 176 | 176 |
| 177 if (current_phase_ended) { | 177 if (current_phase_ended) { |
| 178 // Non-synthetic GSEs are sent when the current phase is canceled or | 178 // Non-synthetic GSEs are sent when the current phase is canceled or |
| 179 // ended. | 179 // ended. |
| 180 SendScrollEnd(scroll_update.event, false); | 180 SendScrollEnd(scroll_update, false); |
| 181 } else if (has_phase_info) { | 181 } else if (has_phase_info) { |
| 182 // Generate a synthetic GSE for every update to force hit testing so | 182 // Generate a synthetic GSE for every update to force hit testing so |
| 183 // that the non-latching behavior is preserved. Remove once | 183 // that the non-latching behavior is preserved. Remove once |
| 184 // crbug.com/526463 is fully implemented. | 184 // crbug.com/526463 is fully implemented. |
| 185 SendScrollEnd(scroll_update.event, true); | 185 SendScrollEnd(scroll_update, true); |
| 186 } else { | 186 } else { |
| 187 scroll_end_timer_.Start( | 187 scroll_end_timer_.Start( |
| 188 FROM_HERE, | 188 FROM_HERE, |
| 189 base::TimeDelta::FromMilliseconds(scroll_transaction_ms_), | 189 base::TimeDelta::FromMilliseconds(scroll_transaction_ms_), |
| 190 base::Bind(&MouseWheelEventQueue::SendScrollEnd, | 190 base::Bind(&MouseWheelEventQueue::SendScrollEnd, |
| 191 base::Unretained(this), scroll_update.event, false)); | 191 base::Unretained(this), scroll_update, false)); |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 | 195 |
| 196 event_sent_for_gesture_ack_.reset(); | 196 event_sent_for_gesture_ack_.reset(); |
| 197 TryForwardNextEventToRenderer(); | 197 TryForwardNextEventToRenderer(); |
| 198 } | 198 } |
| 199 | 199 |
| 200 void MouseWheelEventQueue::OnGestureScrollEvent( | 200 void MouseWheelEventQueue::OnGestureScrollEvent( |
| 201 const GestureEventWithLatencyInfo& gesture_event) { | 201 const GestureEventWithLatencyInfo& gesture_event) { |
| 202 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { | 202 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { |
| 203 // If there is a current scroll going on and a new scroll that isn't | 203 // If there is a current scroll going on and a new scroll that isn't |
| 204 // wheel based cancel current one by sending a ScrollEnd. | 204 // wheel based cancel current one by sending a ScrollEnd. |
| 205 if (scroll_end_timer_.IsRunning() && | 205 if (scroll_end_timer_.IsRunning() && |
| 206 gesture_event.event.sourceDevice != blink::WebGestureDeviceTouchpad) { | 206 gesture_event.event.sourceDevice != blink::WebGestureDeviceTouchpad) { |
| 207 base::Closure task = scroll_end_timer_.user_task(); | 207 base::Closure task = scroll_end_timer_.user_task(); |
| 208 scroll_end_timer_.Reset(); | 208 scroll_end_timer_.Reset(); |
| 209 task.Run(); | 209 task.Run(); |
| 210 } | 210 } |
| 211 scrolling_device_ = gesture_event.event.sourceDevice; | 211 scrolling_device_ = gesture_event.event.sourceDevice; |
| 212 } else if (scrolling_device_ == gesture_event.event.sourceDevice && | 212 } else if (scrolling_device_ == gesture_event.event.sourceDevice && |
| 213 (gesture_event.event.type == | 213 (gesture_event.event.type == |
| 214 blink::WebInputEvent::GestureScrollEnd || | 214 blink::WebInputEvent::GestureScrollEnd || |
| 215 gesture_event.event.type == | 215 gesture_event.event.type == |
| 216 blink::WebInputEvent::GestureFlingStart)) { | 216 blink::WebInputEvent::GestureFlingStart)) { |
| 217 scrolling_device_ = blink::WebGestureDeviceUninitialized; | 217 scrolling_device_ = blink::WebGestureDeviceUninitialized; |
| 218 if (scroll_end_timer_.IsRunning()) | |
| 219 scroll_end_timer_.Reset(); | |
|
dtapuska
2016/04/04 14:53:15
Although this typically wouldn't get hit. The one
| |
| 218 } | 220 } |
| 219 } | 221 } |
| 220 | 222 |
| 221 void MouseWheelEventQueue::TryForwardNextEventToRenderer() { | 223 void MouseWheelEventQueue::TryForwardNextEventToRenderer() { |
| 222 TRACE_EVENT0("input", "MouseWheelEventQueue::TryForwardNextEventToRenderer"); | 224 TRACE_EVENT0("input", "MouseWheelEventQueue::TryForwardNextEventToRenderer"); |
| 223 | 225 |
| 224 if (wheel_queue_.empty() || event_sent_for_gesture_ack_) | 226 if (wheel_queue_.empty() || event_sent_for_gesture_ack_) |
| 225 return; | 227 return; |
| 226 | 228 |
| 227 event_sent_for_gesture_ack_.reset(wheel_queue_.front()); | 229 event_sent_for_gesture_ack_.reset(wheel_queue_.front()); |
| 228 wheel_queue_.pop_front(); | 230 wheel_queue_.pop_front(); |
| 229 | 231 |
| 230 client_->SendMouseWheelEventImmediately(*event_sent_for_gesture_ack_); | 232 client_->SendMouseWheelEventImmediately(*event_sent_for_gesture_ack_); |
| 231 } | 233 } |
| 232 | 234 |
| 233 void MouseWheelEventQueue::SendScrollEnd(blink::WebGestureEvent update_event, | 235 void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event, |
| 234 bool synthetic) { | 236 bool synthetic) { |
| 235 DCHECK((synthetic && !needs_scroll_end_) || needs_scroll_end_); | 237 DCHECK((synthetic && !needs_scroll_end_) || needs_scroll_end_); |
| 236 | 238 |
| 237 GestureEventWithLatencyInfo scroll_end(update_event); | 239 WebGestureEvent scroll_end(update_event); |
| 238 scroll_end.event.timeStampSeconds = | 240 scroll_end.timeStampSeconds = |
| 239 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); | 241 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
| 240 scroll_end.event.type = WebInputEvent::GestureScrollEnd; | 242 scroll_end.type = WebInputEvent::GestureScrollEnd; |
| 241 scroll_end.event.resendingPluginId = -1; | 243 scroll_end.resendingPluginId = -1; |
| 242 scroll_end.event.data.scrollEnd.synthetic = synthetic; | 244 scroll_end.data.scrollEnd.synthetic = synthetic; |
| 243 scroll_end.event.data.scrollEnd.inertial = | 245 scroll_end.data.scrollEnd.inertial = update_event.data.scrollUpdate.inertial; |
| 244 update_event.data.scrollUpdate.inertial; | 246 scroll_end.data.scrollEnd.deltaUnits = |
| 245 scroll_end.event.data.scrollEnd.deltaUnits = | |
| 246 update_event.data.scrollUpdate.deltaUnits; | 247 update_event.data.scrollUpdate.deltaUnits; |
| 247 | 248 |
| 248 if (!synthetic) { | 249 if (!synthetic) { |
| 249 needs_scroll_begin_ = true; | 250 needs_scroll_begin_ = true; |
| 250 needs_scroll_end_ = false; | 251 needs_scroll_end_ = false; |
| 251 | 252 |
| 252 if (scroll_end_timer_.IsRunning()) | 253 if (scroll_end_timer_.IsRunning()) |
| 253 scroll_end_timer_.Reset(); | 254 scroll_end_timer_.Reset(); |
| 254 } | 255 } |
| 255 client_->SendGestureEvent(scroll_end); | 256 client_->ForwardGestureEvent(scroll_end); |
| 256 } | 257 } |
| 257 | 258 |
| 258 void MouseWheelEventQueue::SendScrollBegin( | 259 void MouseWheelEventQueue::SendScrollBegin( |
| 259 const GestureEventWithLatencyInfo& gesture_update, | 260 const WebGestureEvent& gesture_update, |
| 260 bool synthetic) { | 261 bool synthetic) { |
| 261 DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_); | 262 DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_); |
| 262 | 263 |
| 263 GestureEventWithLatencyInfo scroll_begin(gesture_update); | 264 WebGestureEvent scroll_begin(gesture_update); |
| 264 scroll_begin.event.type = WebInputEvent::GestureScrollBegin; | 265 scroll_begin.type = WebInputEvent::GestureScrollBegin; |
| 265 scroll_begin.event.data.scrollBegin.synthetic = synthetic; | 266 scroll_begin.data.scrollBegin.synthetic = synthetic; |
| 266 scroll_begin.event.data.scrollBegin.inertial = | 267 scroll_begin.data.scrollBegin.inertial = |
| 267 gesture_update.event.data.scrollUpdate.inertial; | 268 gesture_update.data.scrollUpdate.inertial; |
| 268 scroll_begin.event.data.scrollBegin.deltaXHint = | 269 scroll_begin.data.scrollBegin.deltaXHint = |
| 269 gesture_update.event.data.scrollUpdate.deltaX; | 270 gesture_update.data.scrollUpdate.deltaX; |
| 270 scroll_begin.event.data.scrollBegin.deltaYHint = | 271 scroll_begin.data.scrollBegin.deltaYHint = |
| 271 gesture_update.event.data.scrollUpdate.deltaY; | 272 gesture_update.data.scrollUpdate.deltaY; |
| 272 scroll_begin.event.data.scrollBegin.targetViewport = false; | 273 scroll_begin.data.scrollBegin.targetViewport = false; |
| 273 scroll_begin.event.data.scrollBegin.deltaHintUnits = | 274 scroll_begin.data.scrollBegin.deltaHintUnits = |
| 274 gesture_update.event.data.scrollUpdate.deltaUnits; | 275 gesture_update.data.scrollUpdate.deltaUnits; |
| 275 | 276 |
| 276 needs_scroll_begin_ = false; | 277 needs_scroll_begin_ = false; |
| 277 needs_scroll_end_ = true; | 278 needs_scroll_end_ = true; |
| 278 client_->SendGestureEvent(scroll_begin); | 279 client_->ForwardGestureEvent(scroll_begin); |
| 279 } | 280 } |
| 280 | 281 |
| 281 } // namespace content | 282 } // namespace content |
| OLD | NEW |