| Index: content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
|
| diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ada3e9f2fc7549240bf0d1d5061a92a562044e58
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
|
| @@ -0,0 +1,353 @@
|
| +// 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 "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
|
| +
|
| +#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
| +#include "content/browser/renderer_host/render_widget_host_impl.h"
|
| +#include "content/browser/renderer_host/render_widget_host_view_aura.h"
|
| +#include "content/common/view_messages.h"
|
| +#include "content/public/browser/render_view_host.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/base/clipboard/clipboard.h"
|
| +#include "ui/gfx/geometry/point_conversions.h"
|
| +#include "ui/gfx/geometry/size_conversions.h"
|
| +#include "ui/strings/grit/ui_strings.h"
|
| +#include "ui/touch_selection/touch_handle_drawable_aura.h"
|
| +#include "ui/touch_selection/touch_selection_menu_runner.h"
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +// Delay before showing the quick menu, in milliseconds.
|
| +const int kQuickMenuDelayInMs = 100;
|
| +
|
| +gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::RectF& rect) {
|
| + gfx::Point origin = gfx::ToRoundedPoint(rect.origin());
|
| + gfx::Point bottom_right = gfx::ToRoundedPoint(rect.bottom_right());
|
| +
|
| + aura::Window* root_window = window->GetRootWindow();
|
| + if (root_window) {
|
| + aura::client::ScreenPositionClient* screen_position_client =
|
| + aura::client::GetScreenPositionClient(root_window);
|
| + if (screen_position_client) {
|
| + screen_position_client->ConvertPointToScreen(window, &origin);
|
| + screen_position_client->ConvertPointToScreen(window, &bottom_right);
|
| + }
|
| + }
|
| + return gfx::Rect(origin.x(), origin.y(), bottom_right.x() - origin.x(),
|
| + bottom_right.y() - origin.y());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// A pre-target event handler for aura::Env which deactivates touch selection on
|
| +// mouse and keyboard events.
|
| +class TouchSelectionControllerClientAura::EnvPreTargetHandler
|
| + : public ui::EventHandler {
|
| + public:
|
| + EnvPreTargetHandler(ui::TouchSelectionController* selection_controller,
|
| + aura::Window* window);
|
| + ~EnvPreTargetHandler() override;
|
| +
|
| + private:
|
| + // EventHandler:
|
| + void OnKeyEvent(ui::KeyEvent* event) override;
|
| + void OnMouseEvent(ui::MouseEvent* event) override;
|
| + void OnScrollEvent(ui::ScrollEvent* event) override;
|
| +
|
| + ui::TouchSelectionController* selection_controller_;
|
| + aura::Window* window_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(EnvPreTargetHandler);
|
| +};
|
| +
|
| +TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler(
|
| + ui::TouchSelectionController* selection_controller,
|
| + aura::Window* window)
|
| + : selection_controller_(selection_controller), window_(window) {
|
| + aura::Env::GetInstance()->AddPreTargetHandler(this);
|
| +}
|
| +
|
| +TouchSelectionControllerClientAura::EnvPreTargetHandler::
|
| + ~EnvPreTargetHandler() {
|
| + aura::Env::GetInstance()->RemovePreTargetHandler(this);
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent(
|
| + ui::KeyEvent* event) {
|
| + DCHECK_NE(ui::TouchSelectionController::INACTIVE,
|
| + selection_controller_->active_status());
|
| +
|
| + selection_controller_->HideAndDisallowShowingAutomatically();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
|
| + ui::MouseEvent* event) {
|
| + DCHECK_NE(ui::TouchSelectionController::INACTIVE,
|
| + selection_controller_->active_status());
|
| +
|
| + // If mouse events are not enabled, this mouse event is synthesized from a
|
| + // touch event in which case we don't want to deactivate touch selection.
|
| + aura::client::CursorClient* cursor_client =
|
| + aura::client::GetCursorClient(window_->GetRootWindow());
|
| + if (!cursor_client || cursor_client->IsMouseEventsEnabled())
|
| + selection_controller_->HideAndDisallowShowingAutomatically();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent(
|
| + ui::ScrollEvent* event) {
|
| + DCHECK_NE(ui::TouchSelectionController::INACTIVE,
|
| + selection_controller_->active_status());
|
| +
|
| + selection_controller_->HideAndDisallowShowingAutomatically();
|
| +}
|
| +
|
| +TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
|
| + RenderWidgetHostViewAura* rwhva)
|
| + : rwhva_(rwhva),
|
| + quick_menu_timer_(
|
| + FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
|
| + base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu,
|
| + base::Unretained(this)),
|
| + false),
|
| + touch_down_(false),
|
| + scroll_in_progress_(false),
|
| + handle_drag_in_progress_(false) {
|
| + DCHECK(rwhva_);
|
| +}
|
| +
|
| +TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() {
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnWindowMoved() {
|
| + UpdateQuickMenu();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnTouchDown() {
|
| + touch_down_ = true;
|
| + UpdateQuickMenu();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnTouchUp() {
|
| + touch_down_ = false;
|
| + UpdateQuickMenu();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnScrollStarted() {
|
| + scroll_in_progress_ = true;
|
| + rwhva_->selection_controller()->SetTemporarilyHidden(true);
|
| + UpdateQuickMenu();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnScrollCompleted() {
|
| + scroll_in_progress_ = false;
|
| + rwhva_->selection_controller()->SetTemporarilyHidden(false);
|
| + UpdateQuickMenu();
|
| +}
|
| +
|
| +bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const {
|
| + return !touch_down_ && !scroll_in_progress_ && !handle_drag_in_progress_;
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::ShowQuickMenu() {
|
| + if (!ui::TouchSelectionMenuRunner::GetInstance())
|
| + return;
|
| +
|
| + gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds();
|
| +
|
| + // Clip rect, which is in |rwhva_|'s window's coordinate space, to client
|
| + // bounds.
|
| + gfx::PointF origin = rect.origin();
|
| + gfx::PointF bottom_right = rect.bottom_right();
|
| + gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds();
|
| + origin.SetToMax(client_bounds.origin());
|
| + bottom_right.SetToMin(client_bounds.bottom_right());
|
| + if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
|
| + return;
|
| +
|
| + gfx::Vector2dF diagonal = bottom_right - origin;
|
| + gfx::SizeF size(diagonal.x(), diagonal.y());
|
| + gfx::RectF anchor_rect(origin, size);
|
| +
|
| + // Calculate maximum handle image size;
|
| + gfx::SizeF max_handle_size =
|
| + rwhva_->selection_controller()->GetStartHandleRect().size();
|
| + max_handle_size.SetToMax(
|
| + rwhva_->selection_controller()->GetEndHandleRect().size());
|
| +
|
| + aura::Window* parent = rwhva_->GetNativeView();
|
| + ui::TouchSelectionMenuRunner::GetInstance()->OpenMenu(
|
| + this, ConvertRectToScreen(parent, anchor_rect),
|
| + gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::UpdateQuickMenu() {
|
| + bool menu_is_showing =
|
| + ui::TouchSelectionMenuRunner::GetInstance() &&
|
| + ui::TouchSelectionMenuRunner::GetInstance()->IsRunning();
|
| + bool menu_should_show = rwhva_->selection_controller()->active_status() !=
|
| + ui::TouchSelectionController::INACTIVE &&
|
| + IsQuickMenuAllowed();
|
| +
|
| + // Hide the quick menu if there is any. This should happen even if the menu
|
| + // should be shown again, in order to update its location or content.
|
| + if (menu_is_showing)
|
| + ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
|
| + else
|
| + quick_menu_timer_.Stop();
|
| +
|
| + // Start timer to show quick menu if necessary.
|
| + if (menu_should_show) {
|
| + if (show_quick_menu_immediately_for_test_)
|
| + ShowQuickMenu();
|
| + else
|
| + quick_menu_timer_.Reset();
|
| + }
|
| +}
|
| +
|
| +bool TouchSelectionControllerClientAura::SupportsAnimation() const {
|
| + return false;
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::SetNeedsAnimate() {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::MoveCaret(
|
| + const gfx::PointF& position) {
|
| + RenderWidgetHostImpl* host =
|
| + RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
|
| + host->MoveCaret(gfx::ToRoundedPoint(position));
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
|
| + const gfx::PointF& extent) {
|
| + RenderWidgetHostDelegate* host_delegate =
|
| + RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
|
| + if (host_delegate)
|
| + host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
|
| + const gfx::PointF& base,
|
| + const gfx::PointF& extent) {
|
| + RenderWidgetHostDelegate* host_delegate =
|
| + RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
|
| + if (host_delegate) {
|
| + host_delegate->SelectRange(gfx::ToRoundedPoint(base),
|
| + gfx::ToRoundedPoint(extent));
|
| + }
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::OnSelectionEvent(
|
| + ui::SelectionEventType event) {
|
| + switch (event) {
|
| + case ui::SELECTION_HANDLES_SHOWN:
|
| + case ui::INSERTION_HANDLE_SHOWN:
|
| + UpdateQuickMenu();
|
| + env_pre_target_handler_.reset(new EnvPreTargetHandler(
|
| + rwhva_->selection_controller(), rwhva_->GetNativeView()));
|
| + break;
|
| + case ui::SELECTION_HANDLES_CLEARED:
|
| + case ui::INSERTION_HANDLE_CLEARED:
|
| + env_pre_target_handler_.reset();
|
| + UpdateQuickMenu();
|
| + break;
|
| + case ui::SELECTION_HANDLE_DRAG_STARTED:
|
| + case ui::INSERTION_HANDLE_DRAG_STARTED:
|
| + handle_drag_in_progress_ = true;
|
| + UpdateQuickMenu();
|
| + break;
|
| + case ui::SELECTION_HANDLE_DRAG_STOPPED:
|
| + case ui::INSERTION_HANDLE_DRAG_STOPPED:
|
| + handle_drag_in_progress_ = false;
|
| + UpdateQuickMenu();
|
| + break;
|
| + case ui::SELECTION_HANDLES_MOVED:
|
| + case ui::INSERTION_HANDLE_MOVED:
|
| + UpdateQuickMenu();
|
| + break;
|
| + case ui::INSERTION_HANDLE_TAPPED:
|
| + case ui::SELECTION_ESTABLISHED:
|
| + case ui::SELECTION_DISSOLVED:
|
| + break;
|
| + };
|
| +}
|
| +
|
| +scoped_ptr<ui::TouchHandleDrawable>
|
| +TouchSelectionControllerClientAura::CreateDrawable() {
|
| + return scoped_ptr<ui::TouchHandleDrawable>(
|
| + new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
|
| +}
|
| +
|
| +bool TouchSelectionControllerClientAura::IsCommandIdEnabled(
|
| + int command_id) const {
|
| + bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
|
| + bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
|
| + gfx::Range selection_range;
|
| + rwhva_->GetSelectionRange(&selection_range);
|
| + bool has_selection = !selection_range.is_empty();
|
| + switch (command_id) {
|
| + case IDS_APP_CUT:
|
| + return editable && readable && has_selection;
|
| + case IDS_APP_COPY:
|
| + return readable && has_selection;
|
| + case IDS_APP_PASTE: {
|
| + base::string16 result;
|
| + ui::Clipboard::GetForCurrentThread()->ReadText(
|
| + ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
|
| + return editable && !result.empty();
|
| + }
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
|
| + int event_flags) {
|
| + rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
|
| + RenderWidgetHostDelegate* host_delegate =
|
| + RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
|
| + if (!host_delegate)
|
| + return;
|
| +
|
| + switch (command_id) {
|
| + case IDS_APP_CUT:
|
| + host_delegate->Cut();
|
| + break;
|
| + case IDS_APP_COPY:
|
| + host_delegate->Copy();
|
| + break;
|
| + case IDS_APP_PASTE:
|
| + host_delegate->Paste();
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void TouchSelectionControllerClientAura::RunContextMenu() {
|
| + gfx::RectF anchor_rect =
|
| + rwhva_->selection_controller()->GetRectBetweenBounds();
|
| + gfx::PointF anchor_point =
|
| + gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
|
| + RenderWidgetHostImpl* host =
|
| + RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
|
| + host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
|
| + ui::MENU_SOURCE_TOUCH_EDIT_MENU,
|
| + gfx::ToRoundedPoint(anchor_point)));
|
| +
|
| + // Hide selection handles after getting rect-between-bounds from touch
|
| + // selection controller; otherwise, rect would be empty and the above
|
| + // calculations would be invalid.
|
| + rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
|
| +}
|
| +
|
| +} // namespace content
|
|
|