| 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());
|
| +}
|
| +
|
| +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);
|
| + 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);
|
| + 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
|
|
|