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

Unified Diff: content/browser/web_contents/aura/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: Fixed test failures on Mac Created 5 years, 8 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/web_contents/aura/touch_selection_controller_client_aura.cc
diff --git a/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc b/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc
new file mode 100644
index 0000000000000000000000000000000000000000..23457d34be403137ae729218a930de3ca7384798
--- /dev/null
+++ b/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc
@@ -0,0 +1,325 @@
+// 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/web_contents/aura/touch_selection_controller_client_aura.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/web_contents/web_contents_impl.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
+
+class TouchSelectionControllerClientAura::EnvPreTargetHandler
+ : public ui::EventHandler {
sadrul 2015/04/29 19:55:03 Consider using a UserActivityObserver instead.
mohsen 2015/04/30 18:29:34 Apparently, UserActivityObserver mechanism is not
+ 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_;
sadrul 2015/04/29 19:55:03 DISALLOW_COPY_AND_ASSIGN
mohsen 2015/04/30 18:29:34 Done.
+};
+
+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(selection_controller_->is_insertion_active() ||
+ selection_controller_->is_selection_active());
+
+ selection_controller_->HideAndDisallowShowingAutomatically();
+}
+
+void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
+ ui::MouseEvent* event) {
+ DCHECK(selection_controller_->is_insertion_active() ||
+ selection_controller_->is_selection_active());
+
+ 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(selection_controller_->is_insertion_active() ||
+ selection_controller_->is_selection_active());
+
+ 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),
+ scroll_in_progress_(false),
+ handle_drag_in_progress_(false) {
+}
+
+TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() {
+}
+
+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) {
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
+ WebContentsImpl* wc =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
+ wc->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
+}
+
+void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
+ const gfx::PointF& base,
+ const gfx::PointF& extent) {
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
+ WebContentsImpl* wc =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
+ wc->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent));
+}
+
+void TouchSelectionControllerClientAura::OnSelectionEvent(
+ ui::SelectionEventType event) {
+ switch (event) {
+ case ui::SELECTION_SHOWN:
+ case ui::INSERTION_SHOWN:
+ UpdateQuickMenu();
+ env_pre_target_handler_.reset(new EnvPreTargetHandler(
+ rwhva_->selection_controller(), rwhva_->GetNativeView()));
+ break;
+ case ui::SELECTION_CLEARED:
+ case ui::INSERTION_CLEARED:
+ env_pre_target_handler_.reset();
+ UpdateQuickMenu();
+ break;
+ case ui::SELECTION_DRAG_STARTED:
+ case ui::INSERTION_DRAG_STARTED:
+ handle_drag_in_progress_ = true;
+ UpdateQuickMenu();
+ break;
+ case ui::SELECTION_DRAG_STOPPED:
+ case ui::INSERTION_DRAG_STOPPED:
+ handle_drag_in_progress_ = false;
+ UpdateQuickMenu();
+ break;
+ case ui::SELECTION_MOVED:
+ case ui::INSERTION_MOVED:
+ UpdateQuickMenu();
+ break;
+ case ui::INSERTION_TAPPED:
+ break;
+ };
+}
+
+scoped_ptr<ui::TouchHandleDrawable>
+TouchSelectionControllerClientAura::CreateDrawable() {
+ return scoped_ptr<ui::TouchHandleDrawable>(
+ new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
+}
+
+void TouchSelectionControllerClientAura::OnScrollStarted() {
+ rwhva_->selection_controller()->SetTemporarilyHidden(true);
+ scroll_in_progress_ = true;
+ UpdateQuickMenu();
+}
+
+void TouchSelectionControllerClientAura::OnScrollCompleted() {
+ rwhva_->selection_controller()->SetTemporarilyHidden(false);
+ scroll_in_progress_ = false;
+ UpdateQuickMenu();
+}
+
+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();
+ }
+ case IDS_APP_DELETE:
+ return editable && has_selection;
+ case IDS_APP_SELECT_ALL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
+ int event_flags) {
+ rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
+ WebContents* wc = WebContents::FromRenderViewHost(rvh);
+ switch (command_id) {
+ case IDS_APP_CUT:
+ wc->Cut();
+ break;
+ case IDS_APP_COPY:
+ wc->Copy();
+ break;
+ case IDS_APP_PASTE:
+ wc->Paste();
+ break;
+ case IDS_APP_DELETE:
+ wc->Delete();
+ break;
+ case IDS_APP_SELECT_ALL:
+ wc->SelectAll();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void TouchSelectionControllerClientAura::OpenContextMenu() {
+ rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
+ 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)));
+}
+
+bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const {
+ return !scroll_in_progress_ && !handle_drag_in_progress_;
+}
+
+void TouchSelectionControllerClientAura::ShowQuickMenu() {
+ if (!ui::TouchSelectionMenuRunner::GetInstance())
+ return;
+
+ gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds();
+
+ // Clip rect 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()->RunMenu(
+ this, ConvertRectToScreen(parent, anchor_rect),
+ gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
+}
+
+void TouchSelectionControllerClientAura::UpdateQuickMenu() {
+ // Hide quick menu if there is any.
+ if (ui::TouchSelectionMenuRunner::GetInstance() &&
+ ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()) {
+ ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
+ } else {
+ quick_menu_timer_.Stop();
+ }
+
+ // Start timer to show quick menu if necessary.
+ if (!rwhva_->selection_controller()->is_insertion_active() &&
+ !rwhva_->selection_controller()->is_selection_active())
+ return;
+
+ if (!IsQuickMenuAllowed())
+ return;
+
+ quick_menu_timer_.Reset();
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698