Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: content/browser/renderer_host/input/mouse_wheel_event_queue.cc

Issue 1749343004: Implement Wheel Gesture Scrolling on OSX. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ensure only high precision scroll begins are used Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
(...skipping 19 matching lines...) Expand all
30 private: 30 private:
31 bool original_can_scroll_; 31 bool original_can_scroll_;
32 DISALLOW_COPY_AND_ASSIGN(QueuedWebMouseWheelEvent); 32 DISALLOW_COPY_AND_ASSIGN(QueuedWebMouseWheelEvent);
33 }; 33 };
34 34
35 MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client, 35 MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
36 bool send_gestures, 36 bool send_gestures,
37 int64_t scroll_transaction_ms) 37 int64_t scroll_transaction_ms)
38 : client_(client), 38 : client_(client),
39 needs_scroll_begin_(true), 39 needs_scroll_begin_(true),
40 needs_scroll_end_(false),
40 send_gestures_(send_gestures), 41 send_gestures_(send_gestures),
41 scroll_transaction_ms_(scroll_transaction_ms), 42 scroll_transaction_ms_(scroll_transaction_ms),
42 scrolling_device_(blink::WebGestureDeviceUninitialized) { 43 scrolling_device_(blink::WebGestureDeviceUninitialized) {
43 DCHECK(client); 44 DCHECK(client);
44 } 45 }
45 46
46 MouseWheelEventQueue::~MouseWheelEventQueue() { 47 MouseWheelEventQueue::~MouseWheelEventQueue() {
47 if (!wheel_queue_.empty()) 48 if (!wheel_queue_.empty())
48 STLDeleteElements(&wheel_queue_); 49 STLDeleteElements(&wheel_queue_);
49 } 50 }
(...skipping 28 matching lines...) Expand all
78 79
79 event_sent_for_gesture_ack_->latency.AddNewLatencyFrom(latency_info); 80 event_sent_for_gesture_ack_->latency.AddNewLatencyFrom(latency_info);
80 client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result); 81 client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result);
81 82
82 // If event wasn't consumed then generate a gesture scroll for it. 83 // If event wasn't consumed then generate a gesture scroll for it.
83 if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED && 84 if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
84 event_sent_for_gesture_ack_->event.canScroll && 85 event_sent_for_gesture_ack_->event.canScroll &&
85 (scrolling_device_ == blink::WebGestureDeviceUninitialized || 86 (scrolling_device_ == blink::WebGestureDeviceUninitialized ||
86 scrolling_device_ == blink::WebGestureDeviceTouchpad)) { 87 scrolling_device_ == blink::WebGestureDeviceTouchpad)) {
87 GestureEventWithLatencyInfo scroll_update; 88 GestureEventWithLatencyInfo scroll_update;
89 scroll_update.event.timeStampSeconds =
90 event_sent_for_gesture_ack_->event.timeStampSeconds;
91
88 scroll_update.event.x = event_sent_for_gesture_ack_->event.x; 92 scroll_update.event.x = event_sent_for_gesture_ack_->event.x;
89 scroll_update.event.y = event_sent_for_gesture_ack_->event.y; 93 scroll_update.event.y = event_sent_for_gesture_ack_->event.y;
90 scroll_update.event.globalX = event_sent_for_gesture_ack_->event.globalX; 94 scroll_update.event.globalX = event_sent_for_gesture_ack_->event.globalX;
91 scroll_update.event.globalY = event_sent_for_gesture_ack_->event.globalY; 95 scroll_update.event.globalY = event_sent_for_gesture_ack_->event.globalY;
92 scroll_update.event.type = WebInputEvent::GestureScrollUpdate; 96 scroll_update.event.type = WebInputEvent::GestureScrollUpdate;
93 scroll_update.event.sourceDevice = blink::WebGestureDeviceTouchpad; 97 scroll_update.event.sourceDevice = blink::WebGestureDeviceTouchpad;
94 scroll_update.event.resendingPluginId = -1; 98 scroll_update.event.resendingPluginId = -1;
95 scroll_update.event.data.scrollUpdate.deltaX = 99 scroll_update.event.data.scrollUpdate.deltaX =
96 event_sent_for_gesture_ack_->event.deltaX; 100 event_sent_for_gesture_ack_->event.deltaX;
97 scroll_update.event.data.scrollUpdate.deltaY = 101 scroll_update.event.data.scrollUpdate.deltaY =
98 event_sent_for_gesture_ack_->event.deltaY; 102 event_sent_for_gesture_ack_->event.deltaY;
103 // Only OSX populates the momentumPhase; so expect this to
104 // always be PhaseNone on all other platforms.
105 scroll_update.event.data.scrollUpdate.inertial =
106 event_sent_for_gesture_ack_->event.momentumPhase !=
107 blink::WebMouseWheelEvent::PhaseNone;
99 if (event_sent_for_gesture_ack_->event.scrollByPage) { 108 if (event_sent_for_gesture_ack_->event.scrollByPage) {
100 scroll_update.event.data.scrollUpdate.deltaUnits = 109 scroll_update.event.data.scrollUpdate.deltaUnits =
101 blink::WebGestureEvent::Page; 110 blink::WebGestureEvent::Page;
102 111
103 // Turn page scrolls into a *single* page scroll because 112 // Turn page scrolls into a *single* page scroll because
104 // the magnitude the number of ticks is lost when coalescing. 113 // the magnitude the number of ticks is lost when coalescing.
105 if (scroll_update.event.data.scrollUpdate.deltaX) 114 if (scroll_update.event.data.scrollUpdate.deltaX)
106 scroll_update.event.data.scrollUpdate.deltaX = 115 scroll_update.event.data.scrollUpdate.deltaX =
107 scroll_update.event.data.scrollUpdate.deltaX > 0 ? 1 : -1; 116 scroll_update.event.data.scrollUpdate.deltaX > 0 ? 1 : -1;
108 if (scroll_update.event.data.scrollUpdate.deltaY) 117 if (scroll_update.event.data.scrollUpdate.deltaY)
109 scroll_update.event.data.scrollUpdate.deltaY = 118 scroll_update.event.data.scrollUpdate.deltaY =
110 scroll_update.event.data.scrollUpdate.deltaY > 0 ? 1 : -1; 119 scroll_update.event.data.scrollUpdate.deltaY > 0 ? 1 : -1;
111 } else { 120 } else {
112 scroll_update.event.data.scrollUpdate.deltaUnits = 121 scroll_update.event.data.scrollUpdate.deltaUnits =
113 event_sent_for_gesture_ack_->event.hasPreciseScrollingDeltas 122 event_sent_for_gesture_ack_->event.hasPreciseScrollingDeltas
114 ? blink::WebGestureEvent::PrecisePixels 123 ? blink::WebGestureEvent::PrecisePixels
115 : blink::WebGestureEvent::Pixels; 124 : blink::WebGestureEvent::Pixels;
116 } 125 }
117 SendGesture(scroll_update); 126
127 bool current_phase_ended = false;
128 bool has_phase_info = false;
129
130 if (event_sent_for_gesture_ack_->event.phase !=
131 blink::WebMouseWheelEvent::PhaseNone ||
132 event_sent_for_gesture_ack_->event.momentumPhase !=
133 blink::WebMouseWheelEvent::PhaseNone) {
134 has_phase_info = true;
135 current_phase_ended = event_sent_for_gesture_ack_->event.phase ==
136 blink::WebMouseWheelEvent::PhaseEnded ||
137 event_sent_for_gesture_ack_->event.phase ==
138 blink::WebMouseWheelEvent::PhaseCancelled ||
139 event_sent_for_gesture_ack_->event.momentumPhase ==
140 blink::WebMouseWheelEvent::PhaseEnded ||
141 event_sent_for_gesture_ack_->event.momentumPhase ==
142 blink::WebMouseWheelEvent::PhaseCancelled;
143 }
144
145 bool needs_update = scroll_update.event.data.scrollUpdate.deltaX != 0 ||
146 scroll_update.event.data.scrollUpdate.deltaY != 0;
147
148 // If there is no update to send and the current phase is ended yet a GSB
149 // needs to be sent, this event sequence doesn't need to be generated
150 // because the events generated will be a GSB (non-synthetic) and GSE
151 // (non-synthetic). This situation arises when OSX generates double
152 // phase end information.
153 bool empty_sequence =
154 !needs_update && needs_scroll_begin_ && current_phase_ended;
155
156 if (needs_update || !empty_sequence) {
157 if (needs_scroll_begin_) {
158 // If no GSB has been sent, it will be a non-synthetic GSB.
159 SendScrollBegin(scroll_update, false);
160 } else if (has_phase_info) {
161 // If a GSB has been sent, generate a synthetic GSB if we have phase
162 // information. This should be removed once crbug.com/526463 is fully
163 // implemented.
164 SendScrollBegin(scroll_update, true);
165 }
166
167 if (needs_update)
168 client_->SendGestureEvent(scroll_update);
169
170 if (current_phase_ended) {
171 // Non-synthetic GSEs are sent when the current phase is canceled or
172 // ended.
173 SendScrollEnd(scroll_update.event, false);
174 } else if (has_phase_info) {
175 // Generate a synthetic GSE for every update to force hit testing so
176 // that the non-latching behavior is preserved. Remove once
177 // crbug.com/526463 is fully implemented.
178 SendScrollEnd(scroll_update.event, true);
179 } else {
180 scroll_end_timer_.Start(
181 FROM_HERE,
182 base::TimeDelta::FromMilliseconds(scroll_transaction_ms_),
183 base::Bind(&MouseWheelEventQueue::SendScrollEnd,
184 base::Unretained(this), scroll_update.event, false));
185 }
186 }
118 } 187 }
119 188
120 event_sent_for_gesture_ack_.reset(); 189 event_sent_for_gesture_ack_.reset();
121 TryForwardNextEventToRenderer(); 190 TryForwardNextEventToRenderer();
122 } 191 }
123 192
124 void MouseWheelEventQueue::OnGestureScrollEvent( 193 void MouseWheelEventQueue::OnGestureScrollEvent(
125 const GestureEventWithLatencyInfo& gesture_event) { 194 const GestureEventWithLatencyInfo& gesture_event) {
126 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { 195 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) {
127 // If there is a current scroll going on and a new scroll that isn't 196 // If there is a current scroll going on and a new scroll that isn't
(...skipping 23 matching lines...) Expand all
151 event_sent_for_gesture_ack_.reset(wheel_queue_.front()); 220 event_sent_for_gesture_ack_.reset(wheel_queue_.front());
152 wheel_queue_.pop_front(); 221 wheel_queue_.pop_front();
153 222
154 MouseWheelEventWithLatencyInfo send_event(*event_sent_for_gesture_ack_); 223 MouseWheelEventWithLatencyInfo send_event(*event_sent_for_gesture_ack_);
155 if (send_gestures_) 224 if (send_gestures_)
156 send_event.event.canScroll = false; 225 send_event.event.canScroll = false;
157 226
158 client_->SendMouseWheelEventImmediately(send_event); 227 client_->SendMouseWheelEventImmediately(send_event);
159 } 228 }
160 229
161 void MouseWheelEventQueue::SendScrollEnd(blink::WebGestureEvent update_event) { 230 void MouseWheelEventQueue::SendScrollEnd(blink::WebGestureEvent update_event,
162 GestureEventWithLatencyInfo scroll_end; 231 bool synthetic) {
232 DCHECK((synthetic && !needs_scroll_end_) || needs_scroll_end_);
233
234 GestureEventWithLatencyInfo scroll_end(update_event);
235 scroll_end.event.timeStampSeconds =
236 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
163 scroll_end.event.type = WebInputEvent::GestureScrollEnd; 237 scroll_end.event.type = WebInputEvent::GestureScrollEnd;
164 scroll_end.event.sourceDevice = blink::WebGestureDeviceTouchpad;
165 scroll_end.event.resendingPluginId = -1; 238 scroll_end.event.resendingPluginId = -1;
239 scroll_end.event.data.scrollEnd.synthetic = synthetic;
240 scroll_end.event.data.scrollEnd.inertial =
241 update_event.data.scrollUpdate.inertial;
166 scroll_end.event.data.scrollEnd.deltaUnits = 242 scroll_end.event.data.scrollEnd.deltaUnits =
167 update_event.data.scrollUpdate.deltaUnits; 243 update_event.data.scrollUpdate.deltaUnits;
168 scroll_end.event.x = update_event.x;
169 scroll_end.event.y = update_event.y;
170 scroll_end.event.globalX = update_event.globalX;
171 scroll_end.event.globalY = update_event.globalY;
172 244
173 SendGesture(scroll_end); 245 if (!synthetic) {
246 needs_scroll_begin_ = true;
247 needs_scroll_end_ = false;
248
249 if (scroll_end_timer_.IsRunning())
250 scroll_end_timer_.Reset();
251 }
252 client_->SendGestureEvent(scroll_end);
174 } 253 }
175 254
176 void MouseWheelEventQueue::SendGesture( 255 void MouseWheelEventQueue::SendScrollBegin(
177 const GestureEventWithLatencyInfo& gesture) { 256 const GestureEventWithLatencyInfo& gesture_update,
178 switch (gesture.event.type) { 257 bool synthetic) {
179 case WebInputEvent::GestureScrollUpdate: 258 DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_);
180 if (needs_scroll_begin_) {
181 GestureEventWithLatencyInfo scroll_begin(gesture);
182 scroll_begin.event.x = gesture.event.x;
183 scroll_begin.event.y = gesture.event.y;
184 scroll_begin.event.globalX = gesture.event.globalX;
185 scroll_begin.event.globalY = gesture.event.globalY;
186 scroll_begin.event.type = WebInputEvent::GestureScrollBegin;
187 scroll_begin.event.data.scrollBegin.deltaXHint =
188 gesture.event.data.scrollUpdate.deltaX;
189 scroll_begin.event.data.scrollBegin.deltaYHint =
190 gesture.event.data.scrollUpdate.deltaY;
191 scroll_begin.event.data.scrollBegin.targetViewport = false;
192 scroll_begin.event.data.scrollBegin.deltaHintUnits =
193 gesture.event.data.scrollUpdate.deltaUnits;
194 259
195 SendGesture(scroll_begin); 260 GestureEventWithLatencyInfo scroll_begin(gesture_update);
196 } 261 scroll_begin.event.type = WebInputEvent::GestureScrollBegin;
197 if (scroll_end_timer_.IsRunning()) { 262 scroll_begin.event.data.scrollBegin.synthetic = synthetic;
198 scroll_end_timer_.Reset(); 263 scroll_begin.event.data.scrollBegin.inertial =
199 } else { 264 gesture_update.event.data.scrollUpdate.inertial;
200 scroll_end_timer_.Start( 265 scroll_begin.event.data.scrollBegin.deltaXHint =
201 FROM_HERE, 266 gesture_update.event.data.scrollUpdate.deltaX;
202 base::TimeDelta::FromMilliseconds(scroll_transaction_ms_), 267 scroll_begin.event.data.scrollBegin.deltaYHint =
203 base::Bind(&MouseWheelEventQueue::SendScrollEnd, 268 gesture_update.event.data.scrollUpdate.deltaY;
204 base::Unretained(this), gesture.event)); 269 scroll_begin.event.data.scrollBegin.targetViewport = false;
205 } 270 scroll_begin.event.data.scrollBegin.deltaHintUnits =
206 break; 271 gesture_update.event.data.scrollUpdate.deltaUnits;
207 case WebInputEvent::GestureScrollEnd: 272
208 needs_scroll_begin_ = true; 273 needs_scroll_begin_ = false;
209 break; 274 needs_scroll_end_ = true;
210 case WebInputEvent::GestureScrollBegin: 275 client_->SendGestureEvent(scroll_begin);
211 needs_scroll_begin_ = false;
212 break;
213 default:
214 return;
215 }
216 client_->SendGestureEvent(gesture);
217 } 276 }
218 277
219 } // namespace content 278 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698