Chromium Code Reviews| Index: ui/touch_selection/touch_selection_controller_aura.cc |
| diff --git a/ui/touch_selection/touch_selection_controller_aura.cc b/ui/touch_selection/touch_selection_controller_aura.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..63686ebe6a3489bb4086312b0e38655d3ea02aac |
| --- /dev/null |
| +++ b/ui/touch_selection/touch_selection_controller_aura.cc |
| @@ -0,0 +1,348 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "ui/touch_selection/touch_selection_controller_aura.h" |
| + |
| +#include "ui/aura/client/cursor_client.h" |
| +#include "ui/aura/client/screen_position_client.h" |
| +#include "ui/aura/env.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/events/event.h" |
| +#include "ui/events/gesture_detection/gesture_configuration.h" |
| +#include "ui/events/gestures/motion_event_aura.h" |
| +#include "ui/touch_selection/touch_handle_drawable_aura.h" |
| + |
| +namespace ui { |
| +namespace { |
| + |
| +gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::Rect& rect) { |
| + gfx::Point origin = rect.origin(); |
| + gfx::Point end = gfx::Point(rect.right(), rect.bottom()); |
| + |
| + aura::Window* root_window = window->GetRootWindow(); |
| + if (!root_window) |
| + return rect; |
| + aura::client::ScreenPositionClient* screen_position_client = |
| + aura::client::GetScreenPositionClient(root_window); |
| + if (!screen_position_client) |
| + return rect; |
| + screen_position_client->ConvertPointToScreen(window, &origin); |
| + screen_position_client->ConvertPointToScreen(window, &end); |
| + return gfx::Rect(origin.x(), origin.y(), end.x() - origin.x(), |
| + end.y() - origin.y()); |
|
sadrul
2015/03/05 12:37:03
I don't think this is correct if there's rotation
mohsen
2015/03/06 23:10:08
I've just copied an existing code (from RWHVAura::
|
| +} |
| + |
| +void ClipPoint(gfx::PointF* point, const gfx::Rect& clip_rect) { |
| + point->SetToMax(clip_rect.origin()); |
| + point->SetToMin(clip_rect.bottom_right()); |
| +} |
| + |
| +void ClipSelectionBound(SelectionBound* bound, const gfx::Rect& clip_rect) { |
| + gfx::PointF edge_top = bound->edge_top(); |
| + gfx::PointF edge_bottom = bound->edge_bottom(); |
| + ClipPoint(&edge_top, clip_rect); |
| + ClipPoint(&edge_bottom, clip_rect); |
| + bound->SetEdge(edge_top, edge_bottom); |
| +} |
| + |
| +} // namespace |
| + |
| +TouchSelectionControllerAura::TouchSelectionControllerAura( |
| + TouchSelectionControllerAuraClient* client) |
| + : client_(client), |
| + motion_event_(new MotionEventAura), |
| + scroll_in_progress_(false), |
| + overscroll_in_progress_(false), |
| + handle_drag_in_progress_(false), |
| + selection_editable_(false) { |
| + int tap_timeout_ms = |
| + GestureConfiguration::GetInstance()->show_press_delay_in_ms(); |
| + int touch_slop = |
| + GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); |
| + bool show_on_tap_for_empty_editable = true; |
| + controller_.reset(new TouchSelectionController( |
| + this, |
| + base::TimeDelta::FromMilliseconds(tap_timeout_ms), |
| + touch_slop, |
| + show_on_tap_for_empty_editable)); |
| +} |
| + |
| +TouchSelectionControllerAura::~TouchSelectionControllerAura() { |
| +} |
| + |
| +void TouchSelectionControllerAura::OnSelectionEditable(bool editable) { |
| + selection_editable_ = editable; |
| + controller_->OnSelectionEditable(editable); |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnSelectionEmpty(bool empty) { |
| + controller_->OnSelectionEmpty(empty); |
| + UpdateQuickMenu(); |
| +} |
| + |
| + |
| +void TouchSelectionControllerAura::OnSelectionBoundsUpdated( |
| + const SelectionBound& start, |
| + const SelectionBound& end) { |
| + if (controller_->OnSelectionBoundsUpdated(start, end)) |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::HandleGestureEvent(GestureEvent* event) { |
| + switch (event->type()) { |
| + case ET_GESTURE_LONG_PRESS: |
| + controller_->OnLongPressEvent(); |
| + break; |
| + case ET_GESTURE_TAP: |
| + if (RectBetweenSelectionBounds( |
| + controller_->start(), |
| + controller_->end()).Contains(event->x(), event->y())) { |
| + if (!controller_->is_insertion_active() && |
| + !controller_->is_selection_active()) { |
| + controller_->AllowShowingFromCurrentSelection(); |
| + event->SetHandled(); |
| + } else if (!selection_editable_) { |
| + event->SetHandled(); |
| + } |
| + } |
| + if (!event->handled()) |
| + controller_->OnTapEvent(); |
| + break; |
| + case ET_GESTURE_SCROLL_BEGIN: |
| + scroll_in_progress_ = true; |
| + UpdateQuickMenu(); |
| + break; |
| + case ET_GESTURE_SCROLL_END: |
| + scroll_in_progress_ = false; |
| + UpdateQuickMenu(); |
| + break; |
| + default: |
| + break; |
| + } |
| +} |
| + |
| +void TouchSelectionControllerAura::HandleTouchEvent(TouchEvent* event) { |
| + const int index = motion_event_->FindPointerIndexOfId(event->touch_id()); |
| + const bool pointer_id_is_active = index != -1; |
| + |
| + if (event->type() != ET_TOUCH_PRESSED && !pointer_id_is_active) |
| + return; |
| + |
| + if (event->type() == ET_TOUCH_PRESSED && pointer_id_is_active) |
| + motion_event_.reset(new MotionEventAura); |
| + |
| + motion_event_->OnTouch(*event); |
| + if (controller_->WillHandleTouchEvent(*motion_event_)) |
| + event->SetHandled(); |
| + motion_event_->CleanupRemovedTouchPoints(*event); |
| +} |
| + |
| +void TouchSelectionControllerAura::HideAndDisallowShowingAutomatically() { |
| + controller_->HideAndDisallowShowingAutomatically(); |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnWindowMoved() { |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnOverscrollStarted() { |
| + overscroll_in_progress_ = true; |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnOverscrollCompleted() { |
| + overscroll_in_progress_ = false; |
| + UpdateQuickMenu(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnFlingCompleted() { |
| + scroll_in_progress_ = false; |
| + UpdateQuickMenu(); |
| +} |
| + |
| +bool TouchSelectionControllerAura::SupportsAnimation() const { |
| + return false; |
| +} |
| + |
| +void TouchSelectionControllerAura::SetNeedsAnimate() { |
| + NOTREACHED(); |
| +} |
| + |
| +void TouchSelectionControllerAura::MoveCaret(const gfx::PointF& position) { |
| + client_->MoveCaret(position); |
| +} |
| + |
| +void TouchSelectionControllerAura::MoveRangeSelectionExtent( |
| + const gfx::PointF& extent) { |
| + client_->MoveRangeSelectionExtent(extent); |
| +} |
| + |
| +void TouchSelectionControllerAura::SelectBetweenCoordinates( |
| + const gfx::PointF& base, |
| + const gfx::PointF& extent) { |
| + client_->SelectBetweenCoordinates(base, extent); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnSelectionEvent( |
| + SelectionEventType event, |
| + const gfx::PointF& position) { |
| + switch (event) { |
| + case SELECTION_SHOWN: |
| + UpdateQuickMenu(); |
| + aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| + aura::Env::GetInstance()->AddPreTargetHandler(this); |
|
sadrul
2015/03/05 12:37:03
Whoa. Why is this necessary?
mohsen
2015/03/06 23:10:08
This was needed as we might have multiple selectio
|
| + break; |
| + case SELECTION_CLEARED: |
| + aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| + UpdateQuickMenu(); |
| + break; |
| + case SELECTION_DRAG_STARTED: |
| + handle_drag_in_progress_ = true; |
| + UpdateQuickMenu(); |
| + break; |
| + case SELECTION_DRAG_STOPPED: |
| + handle_drag_in_progress_ = false; |
| + UpdateQuickMenu(); |
| + break; |
| + case INSERTION_SHOWN: |
| + UpdateQuickMenu(); |
| + aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| + aura::Env::GetInstance()->AddPreTargetHandler(this); |
|
sadrul
2015/03/05 12:37:03
ditto
|
| + break; |
| + case INSERTION_MOVED: |
| + break; |
| + case INSERTION_TAPPED: |
| + //UpdateQuickMenu(); |
| + break; |
| + case INSERTION_CLEARED: |
| + aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| + UpdateQuickMenu(); |
| + break; |
| + case INSERTION_DRAG_STARTED: |
| + handle_drag_in_progress_ = true; |
| + UpdateQuickMenu(); |
| + break; |
| + case INSERTION_DRAG_STOPPED: |
| + handle_drag_in_progress_ = false; |
| + UpdateQuickMenu(); |
| + break; |
| + }; |
| +} |
| + |
| +scoped_ptr<TouchHandleDrawable> TouchSelectionControllerAura::CreateDrawable() { |
| + return scoped_ptr<TouchHandleDrawable>( |
| + new TouchHandleDrawableAura(client_->GetParentWindow())); |
| +} |
| + |
| +gfx::Rect TouchSelectionControllerAura::GetMenuAnchorRect() const { |
| + SelectionBound start = controller_->start(); |
| + SelectionBound end = controller_->end(); |
| + const gfx::Rect& client_bounds = client_->GetClientBounds(); |
| + if (start.visible()) |
| + ClipSelectionBound(&start, client_bounds); |
| + if (end.visible()) |
| + ClipSelectionBound(&end, client_bounds); |
| + |
| + if (start.visible() && end.visible()) |
| + return RectBetweenSelectionBounds(start, end); |
| + if (end.visible()) |
| + return gfx::BoundingRect(end.edge_top_rounded(), end.edge_bottom_rounded()); |
| + return gfx::BoundingRect(start.edge_top_rounded(), |
| + start.edge_bottom_rounded()); |
| +} |
| + |
| +void TouchSelectionControllerAura::ShowQuickMenu() { |
| + DCHECK(controller_->is_insertion_active() || |
| + controller_->is_selection_active()); |
| + |
| + if (!controller_->start().visible() && !controller_->end().visible()) |
| + return; |
| + |
| + if (TouchSelectionMenuRunner::GetInstance()) { |
| + aura::Window* parent = client_->GetParentWindow(); |
| + TouchSelectionMenuRunner::GetInstance()->RunMenu( |
| + this, |
| + ConvertRectToScreen(parent, GetMenuAnchorRect()), |
| + TouchHandleDrawableAura::GetMaxHandleImageSize(), |
| + parent->GetToplevelWindow()); |
| + } |
| +} |
| + |
| +void TouchSelectionControllerAura::UpdateQuickMenu() { |
| + // Hide quick menu if there is any. |
| + if (TouchSelectionMenuRunner::GetInstance() && |
| + TouchSelectionMenuRunner::GetInstance()->IsRunning()) { |
| + TouchSelectionMenuRunner::GetInstance()->CloseMenu(); |
| + } else { |
| + quick_menu_timer_.Stop(); |
| + } |
| + |
| + // Start timer to show quick menu if necessary. |
| + if (!controller_->is_insertion_active() && |
| + !controller_->is_selection_active()) |
| + return; |
| + |
| + if (!IsQuickMenuAllowed()) |
| + return; |
| + |
| + if (immediate_quick_menu_for_testing_) { |
| + ShowQuickMenu(); |
| + } else { |
| + quick_menu_timer_.Start( |
| + FROM_HERE, |
| + base::TimeDelta::FromMilliseconds(100), |
| + this, |
| + &TouchSelectionControllerAura::ShowQuickMenu); |
| + } |
| +} |
| + |
| +bool TouchSelectionControllerAura::IsQuickMenuAllowed() const { |
| + return !scroll_in_progress_ && !overscroll_in_progress_ && |
| + !handle_drag_in_progress_; |
| +} |
| + |
| +bool TouchSelectionControllerAura::IsCommandIdEnabled(int command_id) const { |
| + return client_->IsCommandIdEnabled(command_id); |
| +} |
| + |
| +void TouchSelectionControllerAura::ExecuteCommand(int command_id, |
| + int event_flags) { |
| + HideAndDisallowShowingAutomatically(); |
| + client_->ExecuteCommand(command_id, event_flags); |
| +} |
| + |
| +void TouchSelectionControllerAura::OpenContextMenu() { |
| + HideAndDisallowShowingAutomatically(); |
| + gfx::Rect anchor_rect = GetMenuAnchorRect(); |
| + client_->OpenContextMenu(gfx::Point(anchor_rect.CenterPoint().x(), |
| + anchor_rect.y())); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnKeyEvent(KeyEvent* event) { |
| + DCHECK(controller_->is_insertion_active() || |
| + controller_->is_selection_active()); |
| + |
| + HideAndDisallowShowingAutomatically(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnMouseEvent(MouseEvent* event) { |
| + DCHECK(controller_->is_insertion_active() || |
| + controller_->is_selection_active()); |
| + |
| + aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( |
| + client_->GetParentWindow()->GetRootWindow()); |
| + if (!cursor_client || cursor_client->IsMouseEventsEnabled()) |
| + HideAndDisallowShowingAutomatically(); |
| +} |
| + |
| +void TouchSelectionControllerAura::OnScrollEvent(ScrollEvent* event) { |
| + DCHECK(controller_->is_insertion_active() || |
| + controller_->is_selection_active()); |
| + |
| + HideAndDisallowShowingAutomatically(); |
| +} |
| + |
| +} // namespace ui |