Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(646)

Unified Diff: content/browser/renderer_host/input/touch_selection_controller_client_aura.cc

Issue 698253004: Reland: Implement Aura side of unified touch text selection for contents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased after blink issue fixed: r200194 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698