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 |