Chromium Code Reviews| 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 |