| 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/auto_reset.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "third_party/WebKit/public/web/WebInputEvent.h" | 9 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 10 | 10 |
| 11 namespace content { | 11 namespace content { |
| 12 namespace { |
| 13 |
| 14 TouchHandleOrientation ToTouchHandleOrientation(cc::SelectionBoundType type) { |
| 15 switch (type) { |
| 16 case cc::SELECTION_BOUND_LEFT: |
| 17 return TOUCH_HANDLE_LEFT; |
| 18 case cc::SELECTION_BOUND_RIGHT: |
| 19 return TOUCH_HANDLE_RIGHT; |
| 20 case cc::SELECTION_BOUND_CENTER: |
| 21 return TOUCH_HANDLE_CENTER; |
| 22 case cc::SELECTION_BOUND_EMPTY: |
| 23 return TOUCH_HANDLE_ORIENTATION_UNDEFINED; |
| 24 } |
| 25 NOTREACHED() << "Invalid selection bound type: " << type; |
| 26 return TOUCH_HANDLE_ORIENTATION_UNDEFINED; |
| 27 } |
| 28 |
| 29 } // namespace |
| 12 | 30 |
| 13 TouchSelectionController::TouchSelectionController( | 31 TouchSelectionController::TouchSelectionController( |
| 14 TouchSelectionControllerClient* client) | 32 TouchSelectionControllerClient* client) |
| 15 : client_(client), | 33 : client_(client), |
| 16 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), | 34 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), |
| 17 start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 35 start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), |
| 18 start_visible_(false), | |
| 19 end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | 36 end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), |
| 20 end_visible_(false), | |
| 21 is_insertion_active_(false), | 37 is_insertion_active_(false), |
| 22 activate_insertion_automatically_(false), | 38 activate_insertion_automatically_(false), |
| 23 is_selection_active_(false), | 39 is_selection_active_(false), |
| 24 activate_selection_automatically_(false), | 40 activate_selection_automatically_(false), |
| 25 selection_empty_(false), | 41 selection_empty_(false), |
| 26 selection_editable_(false), | 42 selection_editable_(false), |
| 27 temporarily_hidden_(false) { | 43 temporarily_hidden_(false) { |
| 28 DCHECK(client_); | 44 DCHECK(client_); |
| 29 HideAndDisallowShowingAutomatically(); | 45 HideAndDisallowShowingAutomatically(); |
| 30 } | 46 } |
| 31 | 47 |
| 32 TouchSelectionController::~TouchSelectionController() { | 48 TouchSelectionController::~TouchSelectionController() { |
| 33 } | 49 } |
| 34 | 50 |
| 35 void TouchSelectionController::OnSelectionBoundsChanged( | 51 void TouchSelectionController::OnSelectionBoundsChanged( |
| 36 const gfx::RectF& start_rect, | 52 const cc::ViewportSelectionBound& start, |
| 37 TouchHandleOrientation start_orientation, | 53 const cc::ViewportSelectionBound& end) { |
| 38 bool start_visible, | |
| 39 const gfx::RectF& end_rect, | |
| 40 TouchHandleOrientation end_orientation, | |
| 41 bool end_visible) { | |
| 42 if (!activate_selection_automatically_ && | 54 if (!activate_selection_automatically_ && |
| 43 !activate_insertion_automatically_) { | 55 !activate_insertion_automatically_) { |
| 44 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); | 56 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); |
| 45 return; | 57 return; |
| 46 } | 58 } |
| 47 | 59 |
| 48 if (start_rect_ == start_rect && end_rect_ == end_rect && | 60 if (start == start_ && end_ == end) |
| 49 start_orientation_ == start_orientation && | |
| 50 end_orientation_ == end_orientation && start_visible_ == start_visible && | |
| 51 end_visible_ == end_visible) | |
| 52 return; | 61 return; |
| 53 | 62 |
| 54 start_rect_ = start_rect; | 63 start_ = start; |
| 55 start_orientation_ = start_orientation; | 64 end_ = end; |
| 56 start_visible_ = start_visible; | 65 start_orientation_ = ToTouchHandleOrientation(start_.type); |
| 57 end_rect_ = end_rect; | 66 end_orientation_ = ToTouchHandleOrientation(end_.type); |
| 58 end_orientation_ = end_orientation; | |
| 59 end_visible_ = end_visible; | |
| 60 | 67 |
| 61 // Ensure that |response_pending_input_event_| is cleared after the method | 68 // Ensure that |response_pending_input_event_| is cleared after the method |
| 62 // completes, while also making its current value available for the duration | 69 // completes, while also making its current value available for the duration |
| 63 // of the call. | 70 // of the call. |
| 64 InputEventType causal_input_event = response_pending_input_event_; | 71 InputEventType causal_input_event = response_pending_input_event_; |
| 65 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; | 72 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| 66 base::AutoReset<InputEventType> auto_reset_response_pending_input_event( | 73 base::AutoReset<InputEventType> auto_reset_response_pending_input_event( |
| 67 &response_pending_input_event_, causal_input_event); | 74 &response_pending_input_event_, causal_input_event); |
| 68 | 75 |
| 69 const bool is_selection_dragging = | 76 const bool is_selection_dragging = |
| 70 is_selection_active_ && (start_selection_handle_->is_dragging() || | 77 is_selection_active_ && (start_selection_handle_->is_dragging() || |
| 71 end_selection_handle_->is_dragging()); | 78 end_selection_handle_->is_dragging()); |
| 72 | 79 |
| 73 // It's possible that the bounds temporarily overlap while a selection handle | 80 // It's possible that the bounds temporarily overlap while a selection handle |
| 74 // is being dragged, incorrectly reporting a CENTER orientation. | 81 // is being dragged, incorrectly reporting a CENTER orientation. |
| 75 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response | 82 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response |
| 76 // from handle positioning occurs *after* the handle dragging has ceased. | 83 // from handle positioning occurs *after* the handle dragging has ceased. |
| 77 // Instead, prevent selection -> insertion transitions without an intervening | 84 // Instead, prevent selection -> insertion transitions without an intervening |
| 78 // action or selection clearing of some sort, crbug.com/392696. | 85 // action or selection clearing of some sort, crbug.com/392696. |
| 79 if (is_selection_dragging) { | 86 if (is_selection_dragging) { |
| 80 if (start_orientation_ == TOUCH_HANDLE_CENTER) | 87 if (start_orientation_ == TOUCH_HANDLE_CENTER) |
| 81 start_orientation_ = start_selection_handle_->orientation(); | 88 start_orientation_ = start_selection_handle_->orientation(); |
| 82 if (end_orientation_ == TOUCH_HANDLE_CENTER) | 89 if (end_orientation_ == TOUCH_HANDLE_CENTER) |
| 83 end_orientation_ = end_selection_handle_->orientation(); | 90 end_orientation_ = end_selection_handle_->orientation(); |
| 84 } | 91 } |
| 85 | 92 |
| 86 const gfx::PointF start = GetStartPosition(); | 93 if (GetStartPosition() != GetEndPosition() || |
| 87 const gfx::PointF end = GetEndPosition(); | |
| 88 if (start != end || | |
| 89 (is_selection_dragging && | 94 (is_selection_dragging && |
| 90 start_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED && | 95 start_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED && |
| 91 end_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED)) { | 96 end_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED)) { |
| 92 OnSelectionChanged(); | 97 OnSelectionChanged(); |
| 93 return; | 98 return; |
| 94 } | 99 } |
| 95 | 100 |
| 96 if (start_orientation_ == TOUCH_HANDLE_CENTER && selection_editable_) { | 101 if (start_orientation_ == TOUCH_HANDLE_CENTER && selection_editable_) { |
| 97 OnInsertionChanged(); | 102 OnInsertionChanged(); |
| 98 return; | 103 return; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 return false; | 199 return false; |
| 195 } | 200 } |
| 196 | 201 |
| 197 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { | 202 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { |
| 198 if (&handle == insertion_handle_.get()) { | 203 if (&handle == insertion_handle_.get()) { |
| 199 client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position()); | 204 client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position()); |
| 200 return; | 205 return; |
| 201 } | 206 } |
| 202 | 207 |
| 203 if (&handle == start_selection_handle_.get()) { | 208 if (&handle == start_selection_handle_.get()) { |
| 204 fixed_handle_position_ = end_selection_handle_->position() - | 209 fixed_handle_position_ = |
| 205 gfx::Vector2dF(0, GetEndLineHeight() / 2.f); | 210 end_selection_handle_->position() + GetEndLineOffset(); |
| 206 } else { | 211 } else { |
| 207 fixed_handle_position_ = start_selection_handle_->position() - | 212 fixed_handle_position_ = |
| 208 gfx::Vector2dF(0, GetStartLineHeight() / 2.f); | 213 start_selection_handle_->position() + GetStartLineOffset(); |
| 209 } | 214 } |
| 210 client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position()); | 215 client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position()); |
| 211 } | 216 } |
| 212 | 217 |
| 213 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, | 218 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, |
| 214 const gfx::PointF& position) { | 219 const gfx::PointF& position) { |
| 215 // As the position corresponds to the bottom left point of the selection | 220 // As the position corresponds to the bottom left point of the selection |
| 216 // bound, offset it by half the corresponding line height. | 221 // bound, offset it by half the corresponding line height. |
| 217 float half_line_height = &handle == end_selection_handle_.get() | 222 gfx::Vector2dF line_offset = &handle == end_selection_handle_.get() |
| 218 ? GetEndLineHeight() / 2.f | 223 ? GetStartLineOffset() |
| 219 : GetStartLineHeight() / 2.f; | 224 : GetEndLineOffset(); |
| 220 gfx::PointF line_position = position - gfx::Vector2dF(0, half_line_height); | 225 gfx::PointF line_position = position + line_offset; |
| 221 if (&handle == insertion_handle_.get()) { | 226 if (&handle == insertion_handle_.get()) { |
| 222 client_->MoveCaret(line_position); | 227 client_->MoveCaret(line_position); |
| 223 } else { | 228 } else { |
| 224 client_->SelectBetweenCoordinates(fixed_handle_position_, line_position); | 229 client_->SelectBetweenCoordinates(fixed_handle_position_, line_position); |
| 225 } | 230 } |
| 226 } | 231 } |
| 227 | 232 |
| 228 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { | 233 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { |
| 229 if (&handle != insertion_handle_.get()) | 234 if (&handle != insertion_handle_.get()) |
| 230 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position()); | 235 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position()); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 DCHECK(end_selection_handle_); | 358 DCHECK(end_selection_handle_); |
| 354 start_selection_handle_->SetEnabled(false); | 359 start_selection_handle_->SetEnabled(false); |
| 355 end_selection_handle_->SetEnabled(false); | 360 end_selection_handle_->SetEnabled(false); |
| 356 is_selection_active_ = false; | 361 is_selection_active_ = false; |
| 357 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); | 362 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); |
| 358 } | 363 } |
| 359 | 364 |
| 360 void TouchSelectionController::ResetCachedValuesIfInactive() { | 365 void TouchSelectionController::ResetCachedValuesIfInactive() { |
| 361 if (is_selection_active_ || is_insertion_active_) | 366 if (is_selection_active_ || is_insertion_active_) |
| 362 return; | 367 return; |
| 363 start_rect_ = gfx::RectF(); | 368 start_ = cc::ViewportSelectionBound(); |
| 364 end_rect_ = gfx::RectF(); | 369 end_ = cc::ViewportSelectionBound(); |
| 365 start_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 370 start_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; |
| 366 end_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | 371 end_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; |
| 367 start_visible_ = false; | |
| 368 end_visible_ = false; | |
| 369 } | 372 } |
| 370 | 373 |
| 371 gfx::PointF TouchSelectionController::GetStartPosition() const { | 374 const gfx::PointF& TouchSelectionController::GetStartPosition() const { |
| 372 return start_rect_.bottom_left(); | 375 return start_.edge_bottom; |
| 373 } | 376 } |
| 374 | 377 |
| 375 gfx::PointF TouchSelectionController::GetEndPosition() const { | 378 const gfx::PointF& TouchSelectionController::GetEndPosition() const { |
| 376 return end_rect_.bottom_left(); | 379 return end_.edge_bottom; |
| 377 } | 380 } |
| 378 | 381 |
| 379 float TouchSelectionController::GetStartLineHeight() const { | 382 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { |
| 380 return start_rect_.height(); | 383 return gfx::ScaleVector2d(start_.edge_top - start_.edge_bottom, 0.5f); |
| 381 } | 384 } |
| 382 | 385 |
| 383 float TouchSelectionController::GetEndLineHeight() const { | 386 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { |
| 384 return end_rect_.height(); | 387 return gfx::ScaleVector2d(end_.edge_top - end_.edge_bottom, 0.5f); |
| 385 } | 388 } |
| 386 | 389 |
| 387 bool TouchSelectionController::GetStartVisible() const { | 390 bool TouchSelectionController::GetStartVisible() const { |
| 388 return start_visible_ && !temporarily_hidden_; | 391 return start_.visible && !temporarily_hidden_; |
| 389 } | 392 } |
| 390 | 393 |
| 391 bool TouchSelectionController::GetEndVisible() const { | 394 bool TouchSelectionController::GetEndVisible() const { |
| 392 return end_visible_ && !temporarily_hidden_; | 395 return end_.visible && !temporarily_hidden_; |
| 393 } | 396 } |
| 394 | 397 |
| 395 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( | 398 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( |
| 396 bool was_active) const { | 399 bool was_active) const { |
| 397 return was_active && client_->SupportsAnimation() | 400 return was_active && client_->SupportsAnimation() |
| 398 ? TouchHandle::ANIMATION_SMOOTH | 401 ? TouchHandle::ANIMATION_SMOOTH |
| 399 : TouchHandle::ANIMATION_NONE; | 402 : TouchHandle::ANIMATION_NONE; |
| 400 } | 403 } |
| 401 | 404 |
| 402 } // namespace content | 405 } // namespace content |
| OLD | NEW |