| 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_selection_controller.h" | 5 #include "content/browser/renderer_host/input/touch_selection_controller.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 8 #include "third_party/WebKit/public/web/WebInputEvent.h" | 9 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 9 | 10 |
| 10 namespace content { | 11 namespace content { |
| 11 | 12 |
| 12 TouchSelectionController::TouchSelectionController( | 13 TouchSelectionController::TouchSelectionController( |
| 13 TouchSelectionControllerClient* client) | 14 TouchSelectionControllerClient* client) |
| 14 : client_(client), | 15 : client_(client), |
| 15 last_input_event_type_(INPUT_EVENT_TYPE_NONE), | 16 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), |
| 16 start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 17 start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), |
| 17 start_visible_(false), | 18 start_visible_(false), |
| 18 end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 19 end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), |
| 19 end_visible_(false), | 20 end_visible_(false), |
| 20 is_insertion_active_(false), | 21 is_insertion_active_(false), |
| 21 activate_insertion_automatically_(false), | 22 activate_insertion_automatically_(false), |
| 22 is_selection_active_(false), | 23 is_selection_active_(false), |
| 23 activate_selection_automatically_(false), | 24 activate_selection_automatically_(false), |
| 24 selection_empty_(false), | 25 selection_empty_(false), |
| 25 selection_editable_(false), | 26 selection_editable_(false), |
| 26 temporarily_hidden_(false) { | 27 temporarily_hidden_(false) { |
| 27 DCHECK(client_); | 28 DCHECK(client_); |
| 28 HideAndDisallowShowingAutomatically(); | 29 HideAndDisallowShowingAutomatically(); |
| 29 } | 30 } |
| 30 | 31 |
| 31 TouchSelectionController::~TouchSelectionController() { | 32 TouchSelectionController::~TouchSelectionController() { |
| 32 } | 33 } |
| 33 | 34 |
| 34 void TouchSelectionController::OnSelectionBoundsChanged( | 35 void TouchSelectionController::OnSelectionBoundsChanged( |
| 35 const gfx::RectF& start_rect, | 36 const gfx::RectF& start_rect, |
| 36 TouchHandleOrientation start_orientation, | 37 TouchHandleOrientation start_orientation, |
| 37 bool start_visible, | 38 bool start_visible, |
| 38 const gfx::RectF& end_rect, | 39 const gfx::RectF& end_rect, |
| 39 TouchHandleOrientation end_orientation, | 40 TouchHandleOrientation end_orientation, |
| 40 bool end_visible) { | 41 bool end_visible) { |
| 41 if (!activate_selection_automatically_ && !activate_insertion_automatically_) | 42 if (!activate_selection_automatically_ && |
| 43 !activate_insertion_automatically_) { |
| 44 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); |
| 42 return; | 45 return; |
| 46 } |
| 43 | 47 |
| 44 if (start_rect_ == start_rect && end_rect_ == end_rect && | 48 if (start_rect_ == start_rect && end_rect_ == end_rect && |
| 45 start_orientation_ == start_orientation && | 49 start_orientation_ == start_orientation && |
| 46 end_orientation_ == end_orientation && start_visible_ == start_visible && | 50 end_orientation_ == end_orientation && start_visible_ == start_visible && |
| 47 end_visible_ == end_visible) | 51 end_visible_ == end_visible) |
| 48 return; | 52 return; |
| 49 | 53 |
| 50 start_rect_ = start_rect; | 54 start_rect_ = start_rect; |
| 51 start_orientation_ = start_orientation; | 55 start_orientation_ = start_orientation; |
| 52 start_visible_ = start_visible; | 56 start_visible_ = start_visible; |
| 53 end_rect_ = end_rect; | 57 end_rect_ = end_rect; |
| 54 end_orientation_ = end_orientation; | 58 end_orientation_ = end_orientation; |
| 55 end_visible_ = end_visible; | 59 end_visible_ = end_visible; |
| 56 | 60 |
| 61 // Ensure that |response_pending_input_event_| is cleared after the method |
| 62 // completes, while also making its current value available for the duration |
| 63 // of the call. |
| 64 InputEventType causal_input_event = response_pending_input_event_; |
| 65 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| 66 base::AutoReset<InputEventType> auto_reset_response_pending_input_event( |
| 67 &response_pending_input_event_, causal_input_event); |
| 68 |
| 57 const bool is_selection_dragging = | 69 const bool is_selection_dragging = |
| 58 is_selection_active_ && (start_selection_handle_->is_dragging() || | 70 is_selection_active_ && (start_selection_handle_->is_dragging() || |
| 59 end_selection_handle_->is_dragging()); | 71 end_selection_handle_->is_dragging()); |
| 60 | 72 |
| 61 // It's possible that the bounds temporarily overlap while a selection handle | 73 // It's possible that the bounds temporarily overlap while a selection handle |
| 62 // is being dragged, incorrectly reporting a CENTER orientation. | 74 // is being dragged, incorrectly reporting a CENTER orientation. |
| 63 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response | 75 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response |
| 64 // from handle positioning occurs *after* the handle dragging has ceased. | 76 // from handle positioning occurs *after* the handle dragging has ceased. |
| 65 // Instead, prevent selection -> insertion transitions without an intervening | 77 // Instead, prevent selection -> insertion transitions without an intervening |
| 66 // action or selection clearing of some sort, crbug.com/392696. | 78 // action or selection clearing of some sort, crbug.com/392696. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 (event_pos - GetEndPosition()).LengthSquared()) | 122 (event_pos - GetEndPosition()).LengthSquared()) |
| 111 return start_selection_handle_->WillHandleTouchEvent(event); | 123 return start_selection_handle_->WillHandleTouchEvent(event); |
| 112 else | 124 else |
| 113 return end_selection_handle_->WillHandleTouchEvent(event); | 125 return end_selection_handle_->WillHandleTouchEvent(event); |
| 114 } | 126 } |
| 115 | 127 |
| 116 return false; | 128 return false; |
| 117 } | 129 } |
| 118 | 130 |
| 119 void TouchSelectionController::OnLongPressEvent() { | 131 void TouchSelectionController::OnLongPressEvent() { |
| 120 last_input_event_type_ = LONG_PRESS; | 132 response_pending_input_event_ = LONG_PRESS; |
| 121 ShowSelectionHandlesAutomatically(); | 133 ShowSelectionHandlesAutomatically(); |
| 122 ShowInsertionHandleAutomatically(); | 134 ShowInsertionHandleAutomatically(); |
| 123 ResetCachedValuesIfInactive(); | 135 ResetCachedValuesIfInactive(); |
| 124 } | 136 } |
| 125 | 137 |
| 126 void TouchSelectionController::OnTapEvent() { | 138 void TouchSelectionController::OnTapEvent() { |
| 127 last_input_event_type_ = TAP; | 139 response_pending_input_event_ = TAP; |
| 128 activate_selection_automatically_ = false; | 140 activate_selection_automatically_ = false; |
| 129 DeactivateSelection(); | 141 DeactivateSelection(); |
| 130 ShowInsertionHandleAutomatically(); | 142 ShowInsertionHandleAutomatically(); |
| 131 ResetCachedValuesIfInactive(); | 143 ResetCachedValuesIfInactive(); |
| 132 } | 144 } |
| 133 | 145 |
| 134 void TouchSelectionController::HideAndDisallowShowingAutomatically() { | 146 void TouchSelectionController::HideAndDisallowShowingAutomatically() { |
| 135 last_input_event_type_ = INPUT_EVENT_TYPE_NONE; | 147 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| 136 DeactivateInsertion(); | 148 DeactivateInsertion(); |
| 137 DeactivateSelection(); | 149 DeactivateSelection(); |
| 138 activate_insertion_automatically_ = false; | 150 activate_insertion_automatically_ = false; |
| 139 activate_selection_automatically_ = false; | 151 activate_selection_automatically_ = false; |
| 140 } | 152 } |
| 141 | 153 |
| 142 void TouchSelectionController::SetTemporarilyHidden(bool hidden) { | 154 void TouchSelectionController::SetTemporarilyHidden(bool hidden) { |
| 143 if (temporarily_hidden_ == hidden) | 155 if (temporarily_hidden_ == hidden) |
| 144 return; | 156 return; |
| 145 temporarily_hidden_ = hidden; | 157 temporarily_hidden_ = hidden; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 void TouchSelectionController::ShowSelectionHandlesAutomatically() { | 253 void TouchSelectionController::ShowSelectionHandlesAutomatically() { |
| 242 if (activate_selection_automatically_) | 254 if (activate_selection_automatically_) |
| 243 return; | 255 return; |
| 244 activate_selection_automatically_ = true; | 256 activate_selection_automatically_ = true; |
| 245 ResetCachedValuesIfInactive(); | 257 ResetCachedValuesIfInactive(); |
| 246 } | 258 } |
| 247 | 259 |
| 248 void TouchSelectionController::OnInsertionChanged() { | 260 void TouchSelectionController::OnInsertionChanged() { |
| 249 DeactivateSelection(); | 261 DeactivateSelection(); |
| 250 | 262 |
| 251 if (last_input_event_type_ == TAP && selection_empty_) { | 263 if (response_pending_input_event_ == TAP && selection_empty_) { |
| 252 HideAndDisallowShowingAutomatically(); | 264 HideAndDisallowShowingAutomatically(); |
| 253 return; | 265 return; |
| 254 } | 266 } |
| 255 | 267 |
| 256 if (!activate_insertion_automatically_) | 268 if (!activate_insertion_automatically_) |
| 257 return; | 269 return; |
| 258 | 270 |
| 259 const bool was_active = is_insertion_active_; | 271 const bool was_active = is_insertion_active_; |
| 260 const gfx::PointF position = GetStartPosition(); | 272 const gfx::PointF position = GetStartPosition(); |
| 261 if (!is_insertion_active_) | 273 if (!is_insertion_active_) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 start_selection_handle_->SetOrientation(start_orientation_); | 329 start_selection_handle_->SetOrientation(start_orientation_); |
| 318 } | 330 } |
| 319 | 331 |
| 320 if (!end_selection_handle_) { | 332 if (!end_selection_handle_) { |
| 321 end_selection_handle_.reset(new TouchHandle(this, end_orientation_)); | 333 end_selection_handle_.reset(new TouchHandle(this, end_orientation_)); |
| 322 } else { | 334 } else { |
| 323 end_selection_handle_->SetEnabled(true); | 335 end_selection_handle_->SetEnabled(true); |
| 324 end_selection_handle_->SetOrientation(end_orientation_); | 336 end_selection_handle_->SetOrientation(end_orientation_); |
| 325 } | 337 } |
| 326 | 338 |
| 327 if (!is_selection_active_) { | 339 // As a long press received while a selection is already active may trigger |
| 340 // an entirely new selection, notify the client but avoid sending an |
| 341 // intervening SELECTION_CLEARED update to avoid unnecessary state changes. |
| 342 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) { |
| 328 is_selection_active_ = true; | 343 is_selection_active_ = true; |
| 344 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| 329 client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition()); | 345 client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition()); |
| 330 } | 346 } |
| 331 } | 347 } |
| 332 | 348 |
| 333 void TouchSelectionController::DeactivateSelection() { | 349 void TouchSelectionController::DeactivateSelection() { |
| 334 if (!is_selection_active_) | 350 if (!is_selection_active_) |
| 335 return; | 351 return; |
| 336 DCHECK(start_selection_handle_); | 352 DCHECK(start_selection_handle_); |
| 337 DCHECK(end_selection_handle_); | 353 DCHECK(end_selection_handle_); |
| 338 start_selection_handle_->SetEnabled(false); | 354 start_selection_handle_->SetEnabled(false); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 393 } |
| 378 | 394 |
| 379 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( | 395 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( |
| 380 bool was_active) const { | 396 bool was_active) const { |
| 381 return was_active && client_->SupportsAnimation() | 397 return was_active && client_->SupportsAnimation() |
| 382 ? TouchHandle::ANIMATION_SMOOTH | 398 ? TouchHandle::ANIMATION_SMOOTH |
| 383 : TouchHandle::ANIMATION_NONE; | 399 : TouchHandle::ANIMATION_NONE; |
| 384 } | 400 } |
| 385 | 401 |
| 386 } // namespace content | 402 } // namespace content |
| OLD | NEW |