OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_emulator.h" | 5 #include "content/browser/renderer_host/input/touch_emulator.h" |
6 | 6 |
7 #include "content/browser/renderer_host/input/motion_event_web.h" | 7 #include "content/browser/renderer_host/input/motion_event_web.h" |
8 #include "content/browser/renderer_host/input/web_input_event_util.h" | 8 #include "content/browser/renderer_host/input/web_input_event_util.h" |
9 #include "content/common/input/web_touch_event_traits.h" | 9 #include "content/common/input/web_touch_event_traits.h" |
10 #include "content/grit/content_resources.h" | 10 #include "content/grit/content_resources.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
39 } | 39 } |
40 | 40 |
41 // Time between two consecutive mouse moves, during which second mouse move | 41 // Time between two consecutive mouse moves, during which second mouse move |
42 // is not converted to touch. | 42 // is not converted to touch. |
43 const double kMouseMoveDropIntervalSeconds = 5.f / 1000; | 43 const double kMouseMoveDropIntervalSeconds = 5.f / 1000; |
44 | 44 |
45 } // namespace | 45 } // namespace |
46 | 46 |
47 TouchEmulator::TouchEmulator(TouchEmulatorClient* client) | 47 TouchEmulator::TouchEmulator(TouchEmulatorClient* client) |
48 : client_(client), | 48 : client_(client), |
49 gesture_provider_(GetGestureProviderConfig(), this), | |
50 enabled_(false), | |
51 emulated_stream_active_sequence_count_(0), | 49 emulated_stream_active_sequence_count_(0), |
52 native_stream_active_sequence_count_(0) { | 50 native_stream_active_sequence_count_(0) { |
53 DCHECK(client_); | 51 DCHECK(client_); |
54 ResetState(); | 52 ResetState(); |
55 | 53 |
56 bool use_2x = gfx::Screen::GetNativeScreen()-> | 54 bool use_2x = gfx::Screen::GetNativeScreen()-> |
57 GetPrimaryDisplay().device_scale_factor() > 1.5f; | 55 GetPrimaryDisplay().device_scale_factor() > 1.5f; |
58 float cursor_scale_factor = use_2x ? 2.f : 1.f; | 56 float cursor_scale_factor = use_2x ? 2.f : 1.f; |
59 cursor_size_ = InitCursorFromResource(&touch_cursor_, | 57 cursor_size_ = InitCursorFromResource(&touch_cursor_, |
60 cursor_scale_factor, | 58 cursor_scale_factor, |
61 use_2x ? IDR_DEVTOOLS_TOUCH_CURSOR_ICON_2X : | 59 use_2x ? IDR_DEVTOOLS_TOUCH_CURSOR_ICON_2X : |
62 IDR_DEVTOOLS_TOUCH_CURSOR_ICON); | 60 IDR_DEVTOOLS_TOUCH_CURSOR_ICON); |
63 InitCursorFromResource(&pinch_cursor_, | 61 InitCursorFromResource(&pinch_cursor_, |
64 cursor_scale_factor, | 62 cursor_scale_factor, |
65 use_2x ? IDR_DEVTOOLS_PINCH_CURSOR_ICON_2X : | 63 use_2x ? IDR_DEVTOOLS_PINCH_CURSOR_ICON_2X : |
66 IDR_DEVTOOLS_PINCH_CURSOR_ICON); | 64 IDR_DEVTOOLS_PINCH_CURSOR_ICON); |
67 | 65 |
68 WebCursor::CursorInfo cursor_info; | 66 WebCursor::CursorInfo cursor_info; |
69 cursor_info.type = blink::WebCursorInfo::TypePointer; | 67 cursor_info.type = blink::WebCursorInfo::TypePointer; |
70 pointer_cursor_.InitFromCursorInfo(cursor_info); | 68 pointer_cursor_.InitFromCursorInfo(cursor_info); |
71 | |
72 // TODO(dgozman): Use synthetic secondary touch to support multi-touch. | |
73 gesture_provider_.SetMultiTouchZoomSupportEnabled(false); | |
74 // TODO(dgozman): Enable double tap if requested by the renderer. | |
75 // TODO(dgozman): Don't break double-tap-based pinch with shift handling. | |
76 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(false); | |
77 } | 69 } |
78 | 70 |
79 TouchEmulator::~TouchEmulator() { | 71 TouchEmulator::~TouchEmulator() { |
80 // We cannot cleanup properly in destructor, as we need roundtrip to the | 72 // We cannot cleanup properly in destructor, as we need roundtrip to the |
81 // renderer for ack. Instead, the owner should call Disable, and only | 73 // renderer for ack. Instead, the owner should call Disable, and only |
82 // destroy this object when renderer is dead. | 74 // destroy this object when renderer is dead. |
83 } | 75 } |
84 | 76 |
85 void TouchEmulator::ResetState() { | 77 void TouchEmulator::ResetState() { |
86 last_mouse_event_was_move_ = false; | 78 last_mouse_event_was_move_ = false; |
87 last_mouse_move_timestamp_ = 0; | 79 last_mouse_move_timestamp_ = 0; |
88 mouse_pressed_ = false; | 80 mouse_pressed_ = false; |
89 shift_pressed_ = false; | 81 shift_pressed_ = false; |
90 suppress_next_fling_cancel_ = false; | 82 suppress_next_fling_cancel_ = false; |
91 pinch_scale_ = 1.f; | 83 pinch_scale_ = 1.f; |
92 pinch_gesture_active_ = false; | 84 pinch_gesture_active_ = false; |
93 } | 85 } |
94 | 86 |
95 void TouchEmulator::Enable() { | 87 void TouchEmulator::Enable() { |
96 if (!enabled_) { | 88 if (!gesture_provider_) { |
97 enabled_ = true; | 89 gesture_provider_.reset(new ui::FilteredGestureProvider( |
90 GetGestureProviderConfig(), this)); | |
91 // TODO(dgozman): Use synthetic secondary touch to support multi-touch. | |
92 gesture_provider_->SetMultiTouchZoomSupportEnabled(false); | |
93 // TODO(dgozman): Enable double tap if requested by the renderer. | |
94 // TODO(dgozman): Don't break double-tap-based pinch with shift handling. | |
95 gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false); | |
96 | |
98 ResetState(); | 97 ResetState(); |
99 } | 98 } |
100 UpdateCursor(); | 99 UpdateCursor(); |
101 } | 100 } |
102 | 101 |
103 void TouchEmulator::Disable() { | 102 void TouchEmulator::Disable() { |
104 if (!enabled_) | 103 if (!gesture_provider_) |
jdduke (slow)
2014/12/30 16:37:19
In these early returns, would it make sense to use
dgozman
2015/01/14 14:14:27
Great idea! Done.
| |
105 return; | 104 return; |
106 | 105 |
107 enabled_ = false; | |
108 UpdateCursor(); | 106 UpdateCursor(); |
109 CancelTouch(); | 107 CancelTouch(); |
108 gesture_provider_.reset(); | |
110 } | 109 } |
111 | 110 |
112 gfx::SizeF TouchEmulator::InitCursorFromResource( | 111 gfx::SizeF TouchEmulator::InitCursorFromResource( |
113 WebCursor* cursor, float scale, int resource_id) { | 112 WebCursor* cursor, float scale, int resource_id) { |
114 gfx::Image& cursor_image = | 113 gfx::Image& cursor_image = |
115 content::GetContentClient()->GetNativeImageNamed(resource_id); | 114 content::GetContentClient()->GetNativeImageNamed(resource_id); |
116 WebCursor::CursorInfo cursor_info; | 115 WebCursor::CursorInfo cursor_info; |
117 cursor_info.type = blink::WebCursorInfo::TypeCustom; | 116 cursor_info.type = blink::WebCursorInfo::TypeCustom; |
118 cursor_info.image_scale_factor = scale; | 117 cursor_info.image_scale_factor = scale; |
119 cursor_info.custom_image = cursor_image.AsBitmap(); | 118 cursor_info.custom_image = cursor_image.AsBitmap(); |
120 cursor_info.hotspot = | 119 cursor_info.hotspot = |
121 gfx::Point(cursor_image.Width() / 2, cursor_image.Height() / 2); | 120 gfx::Point(cursor_image.Width() / 2, cursor_image.Height() / 2); |
122 #if defined(OS_WIN) | 121 #if defined(OS_WIN) |
123 cursor_info.external_handle = 0; | 122 cursor_info.external_handle = 0; |
124 #endif | 123 #endif |
125 | 124 |
126 cursor->InitFromCursorInfo(cursor_info); | 125 cursor->InitFromCursorInfo(cursor_info); |
127 return gfx::ScaleSize(cursor_image.Size(), 1.f / scale); | 126 return gfx::ScaleSize(cursor_image.Size(), 1.f / scale); |
128 } | 127 } |
129 | 128 |
130 bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) { | 129 bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) { |
131 if (!enabled_) | 130 if (!gesture_provider_) |
132 return false; | 131 return false; |
133 | 132 |
134 if (mouse_event.button == WebMouseEvent::ButtonRight && | 133 if (mouse_event.button == WebMouseEvent::ButtonRight && |
135 mouse_event.type == WebInputEvent::MouseDown) { | 134 mouse_event.type == WebInputEvent::MouseDown) { |
136 client_->ShowContextMenuAtPoint(gfx::Point(mouse_event.x, mouse_event.y)); | 135 client_->ShowContextMenuAtPoint(gfx::Point(mouse_event.x, mouse_event.y)); |
137 } | 136 } |
138 | 137 |
139 if (mouse_event.button != WebMouseEvent::ButtonLeft) | 138 if (mouse_event.button != WebMouseEvent::ButtonLeft) |
140 return true; | 139 return true; |
141 | 140 |
(...skipping 23 matching lines...) Expand all Loading... | |
165 } | 164 } |
166 | 165 |
167 FillTouchEventAndPoint(mouse_event); | 166 FillTouchEventAndPoint(mouse_event); |
168 HandleEmulatedTouchEvent(touch_event_); | 167 HandleEmulatedTouchEvent(touch_event_); |
169 | 168 |
170 // Do not pass mouse events to the renderer. | 169 // Do not pass mouse events to the renderer. |
171 return true; | 170 return true; |
172 } | 171 } |
173 | 172 |
174 bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) { | 173 bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) { |
175 if (!enabled_) | 174 if (!gesture_provider_) |
176 return false; | 175 return false; |
177 | 176 |
178 // Send mouse wheel for easy scrolling when there is no active touch. | 177 // Send mouse wheel for easy scrolling when there is no active touch. |
179 return emulated_stream_active_sequence_count_ > 0; | 178 return emulated_stream_active_sequence_count_ > 0; |
180 } | 179 } |
181 | 180 |
182 bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) { | 181 bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) { |
183 if (!enabled_) | 182 if (!gesture_provider_) |
184 return false; | 183 return false; |
185 | 184 |
186 if (!UpdateShiftPressed((event.modifiers & WebInputEvent::ShiftKey) != 0)) | 185 if (!UpdateShiftPressed((event.modifiers & WebInputEvent::ShiftKey) != 0)) |
187 return false; | 186 return false; |
188 | 187 |
189 if (!mouse_pressed_) | 188 if (!mouse_pressed_) |
190 return false; | 189 return false; |
191 | 190 |
192 // Note: The necessary pinch events will be lazily inserted by | 191 // Note: The necessary pinch events will be lazily inserted by |
193 // |OnGestureEvent| depending on the state of |shift_pressed_|, using the | 192 // |OnGestureEvent| depending on the state of |shift_pressed_|, using the |
(...skipping 17 matching lines...) Expand all Loading... | |
211 // Do not allow middle-sequence event to pass through, if start was blocked. | 210 // Do not allow middle-sequence event to pass through, if start was blocked. |
212 if (!native_stream_active_sequence_count_ && !is_sequence_start) | 211 if (!native_stream_active_sequence_count_ && !is_sequence_start) |
213 return true; | 212 return true; |
214 | 213 |
215 if (is_sequence_start) | 214 if (is_sequence_start) |
216 native_stream_active_sequence_count_++; | 215 native_stream_active_sequence_count_++; |
217 return false; | 216 return false; |
218 } | 217 } |
219 | 218 |
220 void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) { | 219 void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) { |
221 auto result = gesture_provider_.OnTouchEvent(MotionEventWeb(event)); | 220 DCHECK(gesture_provider_.get()); |
jdduke (slow)
2014/12/30 16:37:19
Do you need the ".get()" (also below)?
dgozman
2015/01/14 14:14:27
Removed.
| |
221 auto result = gesture_provider_->OnTouchEvent(MotionEventWeb(event)); | |
222 if (!result.succeeded) | 222 if (!result.succeeded) |
223 return; | 223 return; |
224 | 224 |
225 const bool event_consumed = true; | 225 const bool event_consumed = true; |
226 // Block emulated event when emulated native stream is active. | 226 // Block emulated event when emulated native stream is active. |
227 if (native_stream_active_sequence_count_) { | 227 if (native_stream_active_sequence_count_) { |
228 gesture_provider_.OnSyncTouchEventAck(event_consumed); | 228 gesture_provider_->OnSyncTouchEventAck(event_consumed); |
229 return; | 229 return; |
230 } | 230 } |
231 | 231 |
232 bool is_sequence_start = WebTouchEventTraits::IsTouchSequenceStart(event); | 232 bool is_sequence_start = WebTouchEventTraits::IsTouchSequenceStart(event); |
233 // Do not allow middle-sequence event to pass through, if start was blocked. | 233 // Do not allow middle-sequence event to pass through, if start was blocked. |
234 if (!emulated_stream_active_sequence_count_ && !is_sequence_start) { | 234 if (!emulated_stream_active_sequence_count_ && !is_sequence_start) { |
235 gesture_provider_.OnSyncTouchEventAck(event_consumed); | 235 gesture_provider_->OnSyncTouchEventAck(event_consumed); |
236 return; | 236 return; |
237 } | 237 } |
238 | 238 |
239 if (is_sequence_start) | 239 if (is_sequence_start) |
240 emulated_stream_active_sequence_count_++; | 240 emulated_stream_active_sequence_count_++; |
241 | 241 |
242 event.causesScrollingIfUncanceled = result.did_generate_scroll; | 242 event.causesScrollingIfUncanceled = result.did_generate_scroll; |
243 client_->ForwardEmulatedTouchEvent(event); | 243 client_->ForwardEmulatedTouchEvent(event); |
244 } | 244 } |
245 | 245 |
246 bool TouchEmulator::HandleTouchEventAck( | 246 bool TouchEmulator::HandleTouchEventAck( |
247 const blink::WebTouchEvent& event, InputEventAckState ack_result) { | 247 const blink::WebTouchEvent& event, InputEventAckState ack_result) { |
248 bool is_sequence_end = WebTouchEventTraits::IsTouchSequenceEnd(event); | 248 bool is_sequence_end = WebTouchEventTraits::IsTouchSequenceEnd(event); |
249 if (emulated_stream_active_sequence_count_) { | 249 if (emulated_stream_active_sequence_count_) { |
250 if (is_sequence_end) | 250 if (is_sequence_end) |
251 emulated_stream_active_sequence_count_--; | 251 emulated_stream_active_sequence_count_--; |
252 | 252 |
253 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; | 253 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED; |
254 gesture_provider_.OnAsyncTouchEventAck(event_consumed); | 254 if (gesture_provider_) |
255 gesture_provider_->OnAsyncTouchEventAck(event_consumed); | |
255 return true; | 256 return true; |
256 } | 257 } |
257 | 258 |
258 // We may have not seen native touch sequence start (when created in the | 259 // We may have not seen native touch sequence start (when created in the |
259 // middle of a sequence), so don't decrement sequence count below zero. | 260 // middle of a sequence), so don't decrement sequence count below zero. |
260 if (is_sequence_end && native_stream_active_sequence_count_) | 261 if (is_sequence_end && native_stream_active_sequence_count_) |
261 native_stream_active_sequence_count_--; | 262 native_stream_active_sequence_count_--; |
262 return false; | 263 return false; |
263 } | 264 } |
264 | 265 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 } | 330 } |
330 | 331 |
331 void TouchEmulator::CancelTouch() { | 332 void TouchEmulator::CancelTouch() { |
332 if (!emulated_stream_active_sequence_count_) | 333 if (!emulated_stream_active_sequence_count_) |
333 return; | 334 return; |
334 | 335 |
335 WebTouchEventTraits::ResetTypeAndTouchStates( | 336 WebTouchEventTraits::ResetTypeAndTouchStates( |
336 WebInputEvent::TouchCancel, | 337 WebInputEvent::TouchCancel, |
337 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(), | 338 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(), |
338 &touch_event_); | 339 &touch_event_); |
339 if (gesture_provider_.GetCurrentDownEvent()) | 340 DCHECK(gesture_provider_.get()); |
341 if (gesture_provider_->GetCurrentDownEvent()) | |
340 HandleEmulatedTouchEvent(touch_event_); | 342 HandleEmulatedTouchEvent(touch_event_); |
341 } | 343 } |
342 | 344 |
343 void TouchEmulator::UpdateCursor() { | 345 void TouchEmulator::UpdateCursor() { |
344 if (!enabled_) | 346 if (!gesture_provider_) |
345 client_->SetCursor(pointer_cursor_); | 347 client_->SetCursor(pointer_cursor_); |
346 else | 348 else |
347 client_->SetCursor(InPinchGestureMode() ? pinch_cursor_ : touch_cursor_); | 349 client_->SetCursor(InPinchGestureMode() ? pinch_cursor_ : touch_cursor_); |
348 } | 350 } |
349 | 351 |
350 bool TouchEmulator::UpdateShiftPressed(bool shift_pressed) { | 352 bool TouchEmulator::UpdateShiftPressed(bool shift_pressed) { |
351 if (shift_pressed_ == shift_pressed) | 353 if (shift_pressed_ == shift_pressed) |
352 return false; | 354 return false; |
353 shift_pressed_ = shift_pressed; | 355 shift_pressed_ = shift_pressed; |
354 UpdateCursor(); | 356 UpdateCursor(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
433 point.screenPosition.x = mouse_event.globalX; | 435 point.screenPosition.x = mouse_event.globalX; |
434 point.position.y = mouse_event.y; | 436 point.position.y = mouse_event.y; |
435 point.screenPosition.y = mouse_event.globalY; | 437 point.screenPosition.y = mouse_event.globalY; |
436 } | 438 } |
437 | 439 |
438 bool TouchEmulator::InPinchGestureMode() const { | 440 bool TouchEmulator::InPinchGestureMode() const { |
439 return shift_pressed_; | 441 return shift_pressed_; |
440 } | 442 } |
441 | 443 |
442 } // namespace content | 444 } // namespace content |
OLD | NEW |