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 "ui/touch_selection/touch_selection_controller.h" | 5 #include "ui/touch_selection/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 "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
10 | 10 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 | 73 |
74 TouchSelectionController::~TouchSelectionController() { | 74 TouchSelectionController::~TouchSelectionController() { |
75 } | 75 } |
76 | 76 |
77 void TouchSelectionController::OnSelectionBoundsChanged( | 77 void TouchSelectionController::OnSelectionBoundsChanged( |
78 const SelectionBound& start, | 78 const SelectionBound& start, |
79 const SelectionBound& end) { | 79 const SelectionBound& end) { |
80 if (!force_next_update_ && start == start_ && end_ == end) | 80 if (!force_next_update_ && start == start_ && end_ == end) |
81 return; | 81 return; |
82 | 82 |
| 83 // Notify if selection bounds have just been established or dissolved. |
| 84 if (start.type() != SelectionBound::EMPTY && |
| 85 start_.type() == SelectionBound::EMPTY) { |
| 86 client_->OnSelectionEvent(SELECTION_ESTABLISHED); |
| 87 } else if (start.type() == SelectionBound::EMPTY && |
| 88 start_.type() != SelectionBound::EMPTY) { |
| 89 client_->OnSelectionEvent(SELECTION_DISSOLVED); |
| 90 } |
| 91 |
83 start_ = start; | 92 start_ = start; |
84 end_ = end; | 93 end_ = end; |
85 start_orientation_ = ToTouchHandleOrientation(start_.type()); | 94 start_orientation_ = ToTouchHandleOrientation(start_.type()); |
86 end_orientation_ = ToTouchHandleOrientation(end_.type()); | 95 end_orientation_ = ToTouchHandleOrientation(end_.type()); |
87 force_next_update_ = false; | 96 force_next_update_ = false; |
88 | 97 |
89 if (!activate_selection_automatically_ && | 98 if (!activate_selection_automatically_ && |
90 !activate_insertion_automatically_) { | 99 !activate_insertion_automatically_) { |
91 DCHECK_EQ(INACTIVE, active_status_); | 100 DCHECK_EQ(INACTIVE, active_status_); |
92 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); | 101 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 | 298 |
290 const gfx::PointF& TouchSelectionController::GetEndPosition() const { | 299 const gfx::PointF& TouchSelectionController::GetEndPosition() const { |
291 return end_.edge_bottom(); | 300 return end_.edge_bottom(); |
292 } | 301 } |
293 | 302 |
294 void TouchSelectionController::OnDragBegin( | 303 void TouchSelectionController::OnDragBegin( |
295 const TouchSelectionDraggable& draggable, | 304 const TouchSelectionDraggable& draggable, |
296 const gfx::PointF& drag_position) { | 305 const gfx::PointF& drag_position) { |
297 if (&draggable == insertion_handle_.get()) { | 306 if (&draggable == insertion_handle_.get()) { |
298 DCHECK_EQ(active_status_, INSERTION_ACTIVE); | 307 DCHECK_EQ(active_status_, INSERTION_ACTIVE); |
299 client_->OnSelectionEvent(INSERTION_DRAG_STARTED); | 308 client_->OnSelectionEvent(INSERTION_HANDLE_DRAG_STARTED); |
300 anchor_drag_to_selection_start_ = true; | 309 anchor_drag_to_selection_start_ = true; |
301 return; | 310 return; |
302 } | 311 } |
303 | 312 |
304 DCHECK_EQ(active_status_, SELECTION_ACTIVE); | 313 DCHECK_EQ(active_status_, SELECTION_ACTIVE); |
305 | 314 |
306 if (&draggable == start_selection_handle_.get()) { | 315 if (&draggable == start_selection_handle_.get()) { |
307 anchor_drag_to_selection_start_ = true; | 316 anchor_drag_to_selection_start_ = true; |
308 } else if (&draggable == end_selection_handle_.get()) { | 317 } else if (&draggable == end_selection_handle_.get()) { |
309 anchor_drag_to_selection_start_ = false; | 318 anchor_drag_to_selection_start_ = false; |
310 } else { | 319 } else { |
311 DCHECK_EQ(&draggable, &longpress_drag_selector_); | 320 DCHECK_EQ(&draggable, &longpress_drag_selector_); |
312 anchor_drag_to_selection_start_ = | 321 anchor_drag_to_selection_start_ = |
313 (drag_position - GetStartPosition()).LengthSquared() < | 322 (drag_position - GetStartPosition()).LengthSquared() < |
314 (drag_position - GetEndPosition()).LengthSquared(); | 323 (drag_position - GetEndPosition()).LengthSquared(); |
315 } | 324 } |
316 | 325 |
317 gfx::PointF base = GetStartPosition() + GetStartLineOffset(); | 326 gfx::PointF base = GetStartPosition() + GetStartLineOffset(); |
318 gfx::PointF extent = GetEndPosition() + GetEndLineOffset(); | 327 gfx::PointF extent = GetEndPosition() + GetEndLineOffset(); |
319 if (anchor_drag_to_selection_start_) | 328 if (anchor_drag_to_selection_start_) |
320 std::swap(base, extent); | 329 std::swap(base, extent); |
321 | 330 |
322 selection_handle_dragged_ = true; | 331 selection_handle_dragged_ = true; |
323 | 332 |
324 // When moving the handle we want to move only the extent point. Before doing | 333 // When moving the handle we want to move only the extent point. Before doing |
325 // so we must make sure that the base point is set correctly. | 334 // so we must make sure that the base point is set correctly. |
326 client_->SelectBetweenCoordinates(base, extent); | 335 client_->SelectBetweenCoordinates(base, extent); |
327 client_->OnSelectionEvent(SELECTION_DRAG_STARTED); | 336 client_->OnSelectionEvent(SELECTION_HANDLE_DRAG_STARTED); |
328 } | 337 } |
329 | 338 |
330 void TouchSelectionController::OnDragUpdate( | 339 void TouchSelectionController::OnDragUpdate( |
331 const TouchSelectionDraggable& draggable, | 340 const TouchSelectionDraggable& draggable, |
332 const gfx::PointF& drag_position) { | 341 const gfx::PointF& drag_position) { |
333 // As the position corresponds to the bottom left point of the selection | 342 // As the position corresponds to the bottom left point of the selection |
334 // bound, offset it to some reasonable point on the current line of text. | 343 // bound, offset it to some reasonable point on the current line of text. |
335 gfx::Vector2dF line_offset = anchor_drag_to_selection_start_ | 344 gfx::Vector2dF line_offset = anchor_drag_to_selection_start_ |
336 ? GetStartLineOffset() | 345 ? GetStartLineOffset() |
337 : GetEndLineOffset(); | 346 : GetEndLineOffset(); |
338 gfx::PointF line_position = drag_position + line_offset; | 347 gfx::PointF line_position = drag_position + line_offset; |
339 if (&draggable == insertion_handle_.get()) | 348 if (&draggable == insertion_handle_.get()) |
340 client_->MoveCaret(line_position); | 349 client_->MoveCaret(line_position); |
341 else | 350 else |
342 client_->MoveRangeSelectionExtent(line_position); | 351 client_->MoveRangeSelectionExtent(line_position); |
343 } | 352 } |
344 | 353 |
345 void TouchSelectionController::OnDragEnd( | 354 void TouchSelectionController::OnDragEnd( |
346 const TouchSelectionDraggable& draggable) { | 355 const TouchSelectionDraggable& draggable) { |
347 if (&draggable == insertion_handle_.get()) | 356 if (&draggable == insertion_handle_.get()) |
348 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED); | 357 client_->OnSelectionEvent(INSERTION_HANDLE_DRAG_STOPPED); |
349 else | 358 else |
350 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED); | 359 client_->OnSelectionEvent(SELECTION_HANDLE_DRAG_STOPPED); |
351 } | 360 } |
352 | 361 |
353 bool TouchSelectionController::IsWithinTapSlop( | 362 bool TouchSelectionController::IsWithinTapSlop( |
354 const gfx::Vector2dF& delta) const { | 363 const gfx::Vector2dF& delta) const { |
355 return delta.LengthSquared() < | 364 return delta.LengthSquared() < |
356 (static_cast<double>(config_.tap_slop) * config_.tap_slop); | 365 (static_cast<double>(config_.tap_slop) * config_.tap_slop); |
357 } | 366 } |
358 | 367 |
359 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { | 368 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { |
360 if (insertion_handle_ && &handle == insertion_handle_.get()) | 369 if (insertion_handle_ && &handle == insertion_handle_.get()) |
361 client_->OnSelectionEvent(INSERTION_TAPPED); | 370 client_->OnSelectionEvent(INSERTION_HANDLE_TAPPED); |
362 } | 371 } |
363 | 372 |
364 void TouchSelectionController::SetNeedsAnimate() { | 373 void TouchSelectionController::SetNeedsAnimate() { |
365 client_->SetNeedsAnimate(); | 374 client_->SetNeedsAnimate(); |
366 } | 375 } |
367 | 376 |
368 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { | 377 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { |
369 return client_->CreateDrawable(); | 378 return client_->CreateDrawable(); |
370 } | 379 } |
371 | 380 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 | 437 |
429 if (!activate_insertion_automatically_) | 438 if (!activate_insertion_automatically_) |
430 return; | 439 return; |
431 | 440 |
432 const bool activated = ActivateInsertionIfNecessary(); | 441 const bool activated = ActivateInsertionIfNecessary(); |
433 | 442 |
434 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated); | 443 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated); |
435 insertion_handle_->SetVisible(GetStartVisible(), animation); | 444 insertion_handle_->SetVisible(GetStartVisible(), animation); |
436 insertion_handle_->SetPosition(GetStartPosition()); | 445 insertion_handle_->SetPosition(GetStartPosition()); |
437 | 446 |
438 client_->OnSelectionEvent(activated ? INSERTION_SHOWN : INSERTION_MOVED); | 447 client_->OnSelectionEvent(activated ? INSERTION_HANDLE_SHOWN |
| 448 : INSERTION_HANDLE_MOVED); |
439 } | 449 } |
440 | 450 |
441 void TouchSelectionController::OnSelectionChanged() { | 451 void TouchSelectionController::OnSelectionChanged() { |
442 DeactivateInsertion(); | 452 DeactivateInsertion(); |
443 | 453 |
444 if (!activate_selection_automatically_) | 454 if (!activate_selection_automatically_) |
445 return; | 455 return; |
446 | 456 |
447 const bool activated = ActivateSelectionIfNecessary(); | 457 const bool activated = ActivateSelectionIfNecessary(); |
448 | 458 |
449 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated); | 459 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated); |
450 start_selection_handle_->SetVisible(GetStartVisible(), animation); | 460 start_selection_handle_->SetVisible(GetStartVisible(), animation); |
451 end_selection_handle_->SetVisible(GetEndVisible(), animation); | 461 end_selection_handle_->SetVisible(GetEndVisible(), animation); |
452 start_selection_handle_->SetPosition(GetStartPosition()); | 462 start_selection_handle_->SetPosition(GetStartPosition()); |
453 end_selection_handle_->SetPosition(GetEndPosition()); | 463 end_selection_handle_->SetPosition(GetEndPosition()); |
454 | 464 |
455 client_->OnSelectionEvent(activated ? SELECTION_SHOWN : SELECTION_MOVED); | 465 client_->OnSelectionEvent(activated ? SELECTION_HANDLES_SHOWN |
| 466 : SELECTION_HANDLES_MOVED); |
456 } | 467 } |
457 | 468 |
458 bool TouchSelectionController::ActivateInsertionIfNecessary() { | 469 bool TouchSelectionController::ActivateInsertionIfNecessary() { |
459 DCHECK_NE(SELECTION_ACTIVE, active_status_); | 470 DCHECK_NE(SELECTION_ACTIVE, active_status_); |
460 | 471 |
461 if (!insertion_handle_) { | 472 if (!insertion_handle_) { |
462 insertion_handle_.reset( | 473 insertion_handle_.reset( |
463 new TouchHandle(this, TouchHandleOrientation::CENTER)); | 474 new TouchHandle(this, TouchHandleOrientation::CENTER)); |
464 } | 475 } |
465 | 476 |
466 if (active_status_ == INACTIVE) { | 477 if (active_status_ == INACTIVE) { |
467 active_status_ = INSERTION_ACTIVE; | 478 active_status_ = INSERTION_ACTIVE; |
468 insertion_handle_->SetEnabled(true); | 479 insertion_handle_->SetEnabled(true); |
469 return true; | 480 return true; |
470 } | 481 } |
471 return false; | 482 return false; |
472 } | 483 } |
473 | 484 |
474 void TouchSelectionController::DeactivateInsertion() { | 485 void TouchSelectionController::DeactivateInsertion() { |
475 if (active_status_ != INSERTION_ACTIVE) | 486 if (active_status_ != INSERTION_ACTIVE) |
476 return; | 487 return; |
477 DCHECK(insertion_handle_); | 488 DCHECK(insertion_handle_); |
478 active_status_ = INACTIVE; | 489 active_status_ = INACTIVE; |
479 insertion_handle_->SetEnabled(false); | 490 insertion_handle_->SetEnabled(false); |
480 client_->OnSelectionEvent(INSERTION_CLEARED); | 491 client_->OnSelectionEvent(INSERTION_HANDLE_CLEARED); |
481 } | 492 } |
482 | 493 |
483 bool TouchSelectionController::ActivateSelectionIfNecessary() { | 494 bool TouchSelectionController::ActivateSelectionIfNecessary() { |
484 DCHECK_NE(INSERTION_ACTIVE, active_status_); | 495 DCHECK_NE(INSERTION_ACTIVE, active_status_); |
485 | 496 |
486 if (!start_selection_handle_) { | 497 if (!start_selection_handle_) { |
487 start_selection_handle_.reset(new TouchHandle(this, start_orientation_)); | 498 start_selection_handle_.reset(new TouchHandle(this, start_orientation_)); |
488 } else { | 499 } else { |
489 start_selection_handle_->SetEnabled(true); | 500 start_selection_handle_->SetEnabled(true); |
490 start_selection_handle_->SetOrientation(start_orientation_); | 501 start_selection_handle_->SetOrientation(start_orientation_); |
491 } | 502 } |
492 | 503 |
493 if (!end_selection_handle_) { | 504 if (!end_selection_handle_) { |
494 end_selection_handle_.reset(new TouchHandle(this, end_orientation_)); | 505 end_selection_handle_.reset(new TouchHandle(this, end_orientation_)); |
495 } else { | 506 } else { |
496 end_selection_handle_->SetEnabled(true); | 507 end_selection_handle_->SetEnabled(true); |
497 end_selection_handle_->SetOrientation(end_orientation_); | 508 end_selection_handle_->SetOrientation(end_orientation_); |
498 } | 509 } |
499 | 510 |
500 // As a long press received while a selection is already active may trigger | 511 // As a long press received while a selection is already active may trigger |
501 // an entirely new selection, notify the client but avoid sending an | 512 // an entirely new selection, notify the client but avoid sending an |
502 // intervening SELECTION_CLEARED update to avoid unnecessary state changes. | 513 // intervening SELECTION_HANDLES_CLEARED update to avoid unnecessary state |
| 514 // changes. |
503 if (active_status_ == INACTIVE || | 515 if (active_status_ == INACTIVE || |
504 response_pending_input_event_ == LONG_PRESS) { | 516 response_pending_input_event_ == LONG_PRESS) { |
505 if (active_status_ == SELECTION_ACTIVE) { | 517 if (active_status_ == SELECTION_ACTIVE) { |
506 // The active selection session finishes with the start of the new one. | 518 // The active selection session finishes with the start of the new one. |
507 LogSelectionEnd(); | 519 LogSelectionEnd(); |
508 } | 520 } |
509 active_status_ = SELECTION_ACTIVE; | 521 active_status_ = SELECTION_ACTIVE; |
510 selection_handle_dragged_ = false; | 522 selection_handle_dragged_ = false; |
511 selection_start_time_ = base::TimeTicks::Now(); | 523 selection_start_time_ = base::TimeTicks::Now(); |
512 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; | 524 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
513 longpress_drag_selector_.OnSelectionActivated(); | 525 longpress_drag_selector_.OnSelectionActivated(); |
514 return true; | 526 return true; |
515 } | 527 } |
516 return false; | 528 return false; |
517 } | 529 } |
518 | 530 |
519 void TouchSelectionController::DeactivateSelection() { | 531 void TouchSelectionController::DeactivateSelection() { |
520 if (active_status_ != SELECTION_ACTIVE) | 532 if (active_status_ != SELECTION_ACTIVE) |
521 return; | 533 return; |
522 DCHECK(start_selection_handle_); | 534 DCHECK(start_selection_handle_); |
523 DCHECK(end_selection_handle_); | 535 DCHECK(end_selection_handle_); |
524 LogSelectionEnd(); | 536 LogSelectionEnd(); |
525 longpress_drag_selector_.OnSelectionDeactivated(); | 537 longpress_drag_selector_.OnSelectionDeactivated(); |
526 start_selection_handle_->SetEnabled(false); | 538 start_selection_handle_->SetEnabled(false); |
527 end_selection_handle_->SetEnabled(false); | 539 end_selection_handle_->SetEnabled(false); |
528 active_status_ = INACTIVE; | 540 active_status_ = INACTIVE; |
529 client_->OnSelectionEvent(SELECTION_CLEARED); | 541 client_->OnSelectionEvent(SELECTION_HANDLES_CLEARED); |
530 } | 542 } |
531 | 543 |
532 void TouchSelectionController::ForceNextUpdateIfInactive() { | 544 void TouchSelectionController::ForceNextUpdateIfInactive() { |
533 // Only force the update if the reported selection is non-empty but still | 545 // Only force the update if the reported selection is non-empty but still |
534 // considered "inactive", i.e., it wasn't preceded by a user gesture or | 546 // considered "inactive", i.e., it wasn't preceded by a user gesture or |
535 // the handles have since been explicitly hidden. | 547 // the handles have since been explicitly hidden. |
536 if (active_status_ == INACTIVE && | 548 if (active_status_ == INACTIVE && |
537 start_.type() != SelectionBound::EMPTY && | 549 start_.type() != SelectionBound::EMPTY && |
538 end_.type() != SelectionBound::EMPTY) { | 550 end_.type() != SelectionBound::EMPTY) { |
539 force_next_update_ = true; | 551 force_next_update_ = true; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; | 600 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; |
589 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", | 601 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", |
590 duration, | 602 duration, |
591 base::TimeDelta::FromMilliseconds(500), | 603 base::TimeDelta::FromMilliseconds(500), |
592 base::TimeDelta::FromSeconds(60), | 604 base::TimeDelta::FromSeconds(60), |
593 60); | 605 60); |
594 } | 606 } |
595 } | 607 } |
596 | 608 |
597 } // namespace ui | 609 } // namespace ui |
OLD | NEW |