| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/views/touchui/touch_selection_controller_impl.h" | 5 #include "ui/views/touchui/touch_selection_controller_impl.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
| 9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
| 10 #include "ui/aura/client/cursor_client.h" | 10 #include "ui/aura/client/cursor_client.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 // Return the appropriate handle image based on the bound's type | 118 // Return the appropriate handle image based on the bound's type |
| 119 gfx::Image* GetHandleImage(ui::SelectionBound::Type bound_type) { | 119 gfx::Image* GetHandleImage(ui::SelectionBound::Type bound_type) { |
| 120 switch(bound_type) { | 120 switch(bound_type) { |
| 121 case ui::SelectionBound::LEFT: | 121 case ui::SelectionBound::LEFT: |
| 122 return GetLeftHandleImage(); | 122 return GetLeftHandleImage(); |
| 123 case ui::SelectionBound::CENTER: | 123 case ui::SelectionBound::CENTER: |
| 124 return GetCenterHandleImage(); | 124 return GetCenterHandleImage(); |
| 125 case ui::SelectionBound::RIGHT: | 125 case ui::SelectionBound::RIGHT: |
| 126 return GetRightHandleImage(); | 126 return GetRightHandleImage(); |
| 127 default: | 127 default: |
| 128 NOTREACHED() << "Invalid touch handle bound type."; | 128 NOTREACHED() << "Invalid touch handle bound type: " << bound_type; |
| 129 return nullptr; | 129 return nullptr; |
| 130 }; | 130 }; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Calculates the bounds of the widget containing the selection handle based | 133 // Calculates the bounds of the widget containing the selection handle based |
| 134 // on the SelectionBound's type and location | 134 // on the SelectionBound's type and location |
| 135 gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) { | 135 gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) { |
| 136 gfx::Size image_size = GetHandleImage(bound.type())->Size(); | 136 gfx::Size image_size = GetHandleImage(bound.type())->Size(); |
| 137 int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding; | 137 int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding; |
| 138 int widget_height = bound.GetHeight() + image_size.height() + | 138 int widget_height = bound.GetHeight() + image_size.height() + |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 aura::Window* window = widget_->GetNativeWindow(); | 242 aura::Window* window = widget_->GetNativeWindow(); |
| 243 window->SetEventTargeter(std::unique_ptr<ui::EventTargeter>( | 243 window->SetEventTargeter(std::unique_ptr<ui::EventTargeter>( |
| 244 new TouchHandleWindowTargeter(window, this))); | 244 new TouchHandleWindowTargeter(window, this))); |
| 245 | 245 |
| 246 // We are owned by the TouchSelectionControllerImpl. | 246 // We are owned by the TouchSelectionControllerImpl. |
| 247 set_owned_by_client(); | 247 set_owned_by_client(); |
| 248 } | 248 } |
| 249 | 249 |
| 250 ~EditingHandleView() override { SetWidgetVisible(false, false); } | 250 ~EditingHandleView() override { SetWidgetVisible(false, false); } |
| 251 | 251 |
| 252 ui::SelectionBound::Type selection_bound_type() { |
| 253 return selection_bound_.type(); |
| 254 } |
| 255 |
| 252 // Overridden from views::WidgetDelegateView: | 256 // Overridden from views::WidgetDelegateView: |
| 253 bool WidgetHasHitTestMask() const override { return true; } | 257 bool WidgetHasHitTestMask() const override { return true; } |
| 254 | 258 |
| 255 void GetWidgetHitTestMask(gfx::Path* mask) const override { | 259 void GetWidgetHitTestMask(gfx::Path* mask) const override { |
| 256 gfx::Size image_size = image_->Size(); | 260 gfx::Size image_size = image_->Size(); |
| 257 mask->addRect( | 261 mask->addRect( |
| 258 SkIntToScalar(0), | 262 SkIntToScalar(0), |
| 259 SkIntToScalar(selection_bound_.GetHeight() + | 263 SkIntToScalar(selection_bound_.GetHeight() + |
| 260 kSelectionHandleVerticalVisualOffset), | 264 kSelectionHandleVerticalVisualOffset), |
| 261 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, | 265 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 return; | 333 return; |
| 330 widget_->SetVisibilityAnimationDuration( | 334 widget_->SetVisibilityAnimationDuration( |
| 331 base::TimeDelta::FromMilliseconds( | 335 base::TimeDelta::FromMilliseconds( |
| 332 quick ? kSelectionHandleQuickFadeDurationMs : 0)); | 336 quick ? kSelectionHandleQuickFadeDurationMs : 0)); |
| 333 if (visible) | 337 if (visible) |
| 334 widget_->Show(); | 338 widget_->Show(); |
| 335 else | 339 else |
| 336 widget_->Hide(); | 340 widget_->Hide(); |
| 337 } | 341 } |
| 338 | 342 |
| 339 void SetBoundInScreen(const ui::SelectionBound& bound) { | 343 // If |is_visible| is true, this will update the widget and trigger a repaint |
| 344 // if necessary. Otherwise this will only update the internal state: |
| 345 // |selection_bound_| and |image_|, so that the state is valid for the time |
| 346 // this becomes visible. |
| 347 void SetBoundInScreen(const ui::SelectionBound& bound, bool is_visible) { |
| 340 bool update_bound_type = false; | 348 bool update_bound_type = false; |
| 341 // Cursor handle should always have the bound type CENTER | 349 // Cursor handle should always have the bound type CENTER |
| 342 DCHECK(!is_cursor_handle_ || bound.type() == ui::SelectionBound::CENTER); | 350 DCHECK(!is_cursor_handle_ || bound.type() == ui::SelectionBound::CENTER); |
| 343 | 351 |
| 344 if (bound.type() != selection_bound_.type()) { | 352 if (bound.type() != selection_bound_.type()) { |
| 345 // Unless this is a cursor handle, do not set the type to CENTER - | 353 // Unless this is a cursor handle, do not set the type to CENTER - |
| 346 // selection handles corresponding to a selection should always use left | 354 // selection handles corresponding to a selection should always use left |
| 347 // or right handle image. If selection handles are dragged to be located | 355 // or right handle image. If selection handles are dragged to be located |
| 348 // at the same spot, the |bound|'s type here will be CENTER for both of | 356 // at the same spot, the |bound|'s type here will be CENTER for both of |
| 349 // them. In this case do not update the type of the |selection_bound_|. | 357 // them. In this case do not update the type of the |selection_bound_|. |
| 350 if (bound.type() != ui::SelectionBound::CENTER || is_cursor_handle_) | 358 if (bound.type() != ui::SelectionBound::CENTER || is_cursor_handle_) |
| 351 update_bound_type = true; | 359 update_bound_type = true; |
| 352 } | 360 } |
| 353 if (update_bound_type) { | 361 if (update_bound_type) { |
| 354 selection_bound_.set_type(bound.type()); | 362 selection_bound_.set_type(bound.type()); |
| 355 image_ = GetHandleImage(bound.type()); | 363 image_ = GetHandleImage(bound.type()); |
| 356 SchedulePaint(); | 364 if (is_visible) |
| 365 SchedulePaint(); |
| 357 } | 366 } |
| 367 |
| 368 if (!is_visible) |
| 369 return; |
| 370 |
| 358 selection_bound_.SetEdge(bound.edge_top(), bound.edge_bottom()); | 371 selection_bound_.SetEdge(bound.edge_top(), bound.edge_bottom()); |
| 359 | 372 |
| 360 widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_)); | 373 widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_)); |
| 361 | 374 |
| 362 aura::Window* window = widget_->GetNativeView(); | 375 aura::Window* window = widget_->GetNativeView(); |
| 363 gfx::Point edge_top = selection_bound_.edge_top_rounded(); | 376 gfx::Point edge_top = selection_bound_.edge_top_rounded(); |
| 364 gfx::Point edge_bottom = selection_bound_.edge_bottom_rounded(); | 377 gfx::Point edge_bottom = selection_bound_.edge_bottom_rounded(); |
| 365 wm::ConvertPointFromScreen(window, &edge_top); | 378 wm::ConvertPointFromScreen(window, &edge_top); |
| 366 wm::ConvertPointFromScreen(window, &edge_bottom); | 379 wm::ConvertPointFromScreen(window, &edge_bottom); |
| 367 selection_bound_.SetEdge(gfx::PointF(edge_top), gfx::PointF(edge_bottom)); | 380 selection_bound_.SetEdge(gfx::PointF(edge_top), gfx::PointF(edge_bottom)); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 } | 498 } |
| 486 | 499 |
| 487 if (dragging_handle_) { | 500 if (dragging_handle_) { |
| 488 // We need to reposition only the selection handle that is being dragged. | 501 // We need to reposition only the selection handle that is being dragged. |
| 489 // The other handle stays the same. Also, the selection handle being dragged | 502 // The other handle stays the same. Also, the selection handle being dragged |
| 490 // will always be at the end of selection, while the other handle will be at | 503 // will always be at the end of selection, while the other handle will be at |
| 491 // the start. | 504 // the start. |
| 492 // If the new location of this handle is out of client view, its widget | 505 // If the new location of this handle is out of client view, its widget |
| 493 // should not get hidden, since it should still receive touch events. | 506 // should not get hidden, since it should still receive touch events. |
| 494 // Hence, we are not using |SetHandleBound()| method here. | 507 // Hence, we are not using |SetHandleBound()| method here. |
| 495 dragging_handle_->SetBoundInScreen(screen_bound_focus_clipped); | 508 dragging_handle_->SetBoundInScreen(screen_bound_focus_clipped, true); |
| 496 | 509 |
| 497 // Temporary fix for selection handle going outside a window. On a webpage, | 510 // Temporary fix for selection handle going outside a window. On a webpage, |
| 498 // the page should scroll if the selection handle is dragged outside the | 511 // the page should scroll if the selection handle is dragged outside the |
| 499 // window. That does not happen currently. So we just hide the handle for | 512 // window. That does not happen currently. So we just hide the handle for |
| 500 // now. | 513 // now. |
| 501 // TODO(varunjain): Fix this: crbug.com/269003 | 514 // TODO(varunjain): Fix this: crbug.com/269003 |
| 502 dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(focus)); | 515 dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(focus)); |
| 503 | 516 |
| 504 if (dragging_handle_ != cursor_handle_.get()) { | 517 if (dragging_handle_ != cursor_handle_.get()) { |
| 505 // The non-dragging-handle might have recently become visible. | 518 // The non-dragging-handle might have recently become visible. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 EditingHandleView* source, gfx::Point* point) { | 598 EditingHandleView* source, gfx::Point* point) { |
| 586 View::ConvertPointToScreen(source, point); | 599 View::ConvertPointToScreen(source, point); |
| 587 client_view_->ConvertPointFromScreen(point); | 600 client_view_->ConvertPointFromScreen(point); |
| 588 } | 601 } |
| 589 | 602 |
| 590 void TouchSelectionControllerImpl::SetHandleBound( | 603 void TouchSelectionControllerImpl::SetHandleBound( |
| 591 EditingHandleView* handle, | 604 EditingHandleView* handle, |
| 592 const ui::SelectionBound& bound, | 605 const ui::SelectionBound& bound, |
| 593 const ui::SelectionBound& bound_in_screen) { | 606 const ui::SelectionBound& bound_in_screen) { |
| 594 handle->SetWidgetVisible(ShouldShowHandleFor(bound), false); | 607 handle->SetWidgetVisible(ShouldShowHandleFor(bound), false); |
| 595 if (handle->IsWidgetVisible()) | 608 handle->SetBoundInScreen(bound_in_screen, handle->IsWidgetVisible()); |
| 596 handle->SetBoundInScreen(bound_in_screen); | |
| 597 } | 609 } |
| 598 | 610 |
| 599 bool TouchSelectionControllerImpl::ShouldShowHandleFor( | 611 bool TouchSelectionControllerImpl::ShouldShowHandleFor( |
| 600 const ui::SelectionBound& bound) const { | 612 const ui::SelectionBound& bound) const { |
| 601 if (bound.GetHeight() < kSelectionHandleBarMinHeight) | 613 if (bound.GetHeight() < kSelectionHandleBarMinHeight) |
| 602 return false; | 614 return false; |
| 603 gfx::Rect client_bounds = client_view_->GetBounds(); | 615 gfx::Rect client_bounds = client_view_->GetBounds(); |
| 604 client_bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance); | 616 client_bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance); |
| 605 return client_bounds.Contains(BoundToRect(bound)); | 617 return client_bounds.Contains(BoundToRect(bound)); |
| 606 } | 618 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 // by the same distance the handles are offset from the text. | 744 // by the same distance the handles are offset from the text. |
| 733 menu_anchor.Inset(0, -kSelectionHandleVerticalVisualOffset); | 745 menu_anchor.Inset(0, -kSelectionHandleVerticalVisualOffset); |
| 734 | 746 |
| 735 return menu_anchor; | 747 return menu_anchor; |
| 736 } | 748 } |
| 737 | 749 |
| 738 gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() { | 750 gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() { |
| 739 return cursor_handle_->GetWidget()->GetNativeView(); | 751 return cursor_handle_->GetWidget()->GetNativeView(); |
| 740 } | 752 } |
| 741 | 753 |
| 754 ui::SelectionBound::Type |
| 755 TouchSelectionControllerImpl::GetSelectionHandle1Type() { |
| 756 return selection_handle_1_->selection_bound_type(); |
| 757 } |
| 758 |
| 742 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle1Bounds() { | 759 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle1Bounds() { |
| 743 return selection_handle_1_->GetBoundsInScreen(); | 760 return selection_handle_1_->GetBoundsInScreen(); |
| 744 } | 761 } |
| 745 | 762 |
| 746 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle2Bounds() { | 763 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle2Bounds() { |
| 747 return selection_handle_2_->GetBoundsInScreen(); | 764 return selection_handle_2_->GetBoundsInScreen(); |
| 748 } | 765 } |
| 749 | 766 |
| 750 gfx::Rect TouchSelectionControllerImpl::GetCursorHandleBounds() { | 767 gfx::Rect TouchSelectionControllerImpl::GetCursorHandleBounds() { |
| 751 return cursor_handle_->GetBoundsInScreen(); | 768 return cursor_handle_->GetBoundsInScreen(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 770 | 787 |
| 771 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() { | 788 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() { |
| 772 return selection_handle_1_.get(); | 789 return selection_handle_1_.get(); |
| 773 } | 790 } |
| 774 | 791 |
| 775 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() { | 792 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() { |
| 776 return selection_handle_2_.get(); | 793 return selection_handle_2_.get(); |
| 777 } | 794 } |
| 778 | 795 |
| 779 } // namespace views | 796 } // namespace views |
| OLD | NEW |