summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormohsen <mohsen@chromium.org>2015-07-30 09:41:00 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-30 16:42:16 +0000
commit2a5e3624e4d0b78bfe5f5a3d40f5a98730291056 (patch)
tree6bc5339c5ac557877f6d5fe6f9575dc3c2e37799
parentc7a6ce3e5957485bb9128dd74483611c8bcfc029 (diff)
downloadchromium_src-2a5e3624e4d0b78bfe5f5a3d40f5a98730291056.zip
chromium_src-2a5e3624e4d0b78bfe5f5a3d40f5a98730291056.tar.gz
chromium_src-2a5e3624e4d0b78bfe5f5a3d40f5a98730291056.tar.bz2
Implement Aura side of unified touch text selection for contents
This is the first part of unified touch text selection for Aura which implements it using the new ui::TouchSelectionController for contents. Selection updates are now coming from swap-compositor-frame IPC message instead of selection-bounds-changed IPC message. This CL also replaces TouchEditableImplAura (owned by WebContentsViewAura) with ui::TouchSelectionController (owned by RenderWidgetHostViewAura) for which a client implementation is provided in TouchSelectionControllerClientAura. Note that at the moment we are unable to remove selection-bounds-changed IPC message completely as it is also used by IME and the new path is not yet working properly inside <webview> (which is being worked on). Next part would be using ui::TouchSelectionController to implement unified touch text selection for Views textfields. COLLABORATOR=mfomitchev BUG=399721 Review URL: https://codereview.chromium.org/698253004 Cr-Commit-Position: refs/heads/master@{#341134}
-rw-r--r--content/browser/BUILD.gn4
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller_client_aura.cc353
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller_client_aura.h80
-rw-r--r--content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc441
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc129
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h76
-rw-r--r--content/browser/web_contents/touch_editable_impl_aura.cc385
-rw-r--r--content/browser/web_contents/touch_editable_impl_aura.h116
-rw-r--r--content/browser/web_contents/touch_editable_impl_aura_browsertest.cc638
-rw-r--r--content/browser/web_contents/web_contents_view_aura.cc66
-rw-r--r--content/browser/web_contents/web_contents_view_aura.h12
-rw-r--r--content/child/runtime_features.cc5
-rw-r--r--content/content_browser.gypi8
-rw-r--r--content/content_tests.gypi16
-rw-r--r--content/renderer/render_widget.cc12
-rw-r--r--content/test/BUILD.gn18
-rw-r--r--content/test/data/touch_selection.html36
-rw-r--r--ui/touch_selection/BUILD.gn14
-rw-r--r--ui/touch_selection/touch_selection_controller_test_api.cc23
-rw-r--r--ui/touch_selection/touch_selection_controller_test_api.h33
-rw-r--r--ui/touch_selection/touch_selection_controller_unittest.cc16
-rw-r--r--ui/touch_selection/ui_touch_selection.gyp12
22 files changed, 1170 insertions, 1323 deletions
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 6281b91..dac2fb1 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -417,6 +417,8 @@ source_set("browser") {
"renderer_host/compositor_resize_lock_aura.h",
"renderer_host/input/synthetic_gesture_target_aura.cc",
"renderer_host/input/synthetic_gesture_target_aura.h",
+ "renderer_host/input/touch_selection_controller_client_aura.cc",
+ "renderer_host/input/touch_selection_controller_client_aura.h",
"renderer_host/native_web_keyboard_event_aura.cc",
"renderer_host/render_widget_host_view_aura.cc",
"renderer_host/render_widget_host_view_aura.h",
@@ -434,8 +436,6 @@ source_set("browser") {
"web_contents/aura/overscroll_window_delegate.h",
"web_contents/aura/shadow_layer_delegate.cc",
"web_contents/aura/shadow_layer_delegate.h",
- "web_contents/touch_editable_impl_aura.cc",
- "web_contents/touch_editable_impl_aura.h",
"web_contents/web_contents_view_aura.cc",
"web_contents/web_contents_view_aura.h",
]
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 0000000..ada3e9f
--- /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
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.h b/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
new file mode 100644
index 0000000..bb9dd66
--- /dev/null
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
@@ -0,0 +1,80 @@
+// 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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_CLIENT_AURA_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_CLIENT_AURA_H_
+
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "ui/touch_selection/touch_selection_controller.h"
+#include "ui/touch_selection/touch_selection_menu_runner.h"
+
+namespace content {
+class RenderWidgetHostViewAura;
+
+// An implementation of |TouchSelectionControllerClient| to be used in Aura's
+// implementation of touch selection for contents.
+class CONTENT_EXPORT TouchSelectionControllerClientAura
+ : public ui::TouchSelectionControllerClient,
+ public ui::TouchSelectionMenuClient {
+ public:
+ explicit TouchSelectionControllerClientAura(RenderWidgetHostViewAura* rwhva);
+ ~TouchSelectionControllerClientAura() override;
+
+ // Called when |rwhva_|'s window is moved, to update the quick menu's
+ // position.
+ void OnWindowMoved();
+
+ // Called on first touch down/last touch up to hide/show the quick menu.
+ void OnTouchDown();
+ void OnTouchUp();
+
+ // Called when touch scroll starts/completes to hide/show touch handles and
+ // the quick menu.
+ void OnScrollStarted();
+ void OnScrollCompleted();
+
+ private:
+ friend class TestTouchSelectionControllerClientAura;
+ class EnvPreTargetHandler;
+
+ bool IsQuickMenuAllowed() const;
+ void ShowQuickMenu();
+ void UpdateQuickMenu();
+
+ // ui::TouchSelectionControllerClient:
+ bool SupportsAnimation() const override;
+ void SetNeedsAnimate() override;
+ void MoveCaret(const gfx::PointF& position) override;
+ void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override;
+ void OnSelectionEvent(ui::SelectionEventType event) override;
+ scoped_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
+
+ // ui::TouchSelectionMenuClient:
+ bool IsCommandIdEnabled(int command_id) const override;
+ void ExecuteCommand(int command_id, int event_flags) override;
+ void RunContextMenu() override;
+
+ // Not owned, non-null for the lifetime of this object.
+ RenderWidgetHostViewAura* rwhva_;
+
+ base::Timer quick_menu_timer_;
+ bool touch_down_;
+ bool scroll_in_progress_;
+ bool handle_drag_in_progress_;
+
+ bool show_quick_menu_immediately_for_test_;
+
+ // A pre-target event handler for aura::Env which deactivates touch selection
+ // on mouse and keyboard events.
+ scoped_ptr<EnvPreTargetHandler> env_pre_target_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerClientAura);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_CLIENT_AURA_H_
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
new file mode 100644
index 0000000..999b1cd
--- /dev/null
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -0,0 +1,441 @@
+// 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 "base/json/json_reader.h"
+#include "base/run_loop.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/touch_selection/touch_selection_controller_test_api.h"
+
+namespace content {
+namespace {
+
+bool JSONToPoint(const std::string& str, gfx::PointF* point) {
+ scoped_ptr<base::Value> value = base::JSONReader::Read(str);
+ if (!value)
+ return false;
+ base::DictionaryValue* root;
+ if (!value->GetAsDictionary(&root))
+ return false;
+ double x, y;
+ if (!root->GetDouble("x", &x))
+ return false;
+ if (!root->GetDouble("y", &y))
+ return false;
+ point->set_x(x);
+ point->set_y(y);
+ return true;
+}
+
+// A mock touch selection menu runner to use whenever a default one is not
+// installed.
+class TestTouchSelectionMenuRunner : public ui::TouchSelectionMenuRunner {
+ public:
+ TestTouchSelectionMenuRunner() : menu_opened_(false) {}
+ ~TestTouchSelectionMenuRunner() override {}
+
+ private:
+ void OpenMenu(ui::TouchSelectionMenuClient* client,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
+ aura::Window* context) override {
+ menu_opened_ = true;
+ }
+
+ void CloseMenu() override { menu_opened_ = false; }
+
+ bool IsRunning() const override { return menu_opened_; }
+
+ bool menu_opened_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTouchSelectionMenuRunner);
+};
+
+} // namespace
+
+class TestTouchSelectionControllerClientAura
+ : public TouchSelectionControllerClientAura {
+ public:
+ explicit TestTouchSelectionControllerClientAura(
+ RenderWidgetHostViewAura* rwhva)
+ : TouchSelectionControllerClientAura(rwhva),
+ expected_event_(ui::SELECTION_HANDLES_SHOWN) {
+ show_quick_menu_immediately_for_test_ = true;
+ }
+
+ ~TestTouchSelectionControllerClientAura() override {}
+
+ void InitWaitForSelectionEvent(ui::SelectionEventType expected_event) {
+ DCHECK(!run_loop_);
+ expected_event_ = expected_event;
+ run_loop_.reset(new base::RunLoop());
+ }
+
+ void Wait() {
+ DCHECK(run_loop_);
+ run_loop_->Run();
+ run_loop_.reset();
+ }
+
+ private:
+ // TouchSelectionControllerClientAura:
+ void OnSelectionEvent(ui::SelectionEventType event) override {
+ TouchSelectionControllerClientAura::OnSelectionEvent(event);
+ if (run_loop_ && event == expected_event_)
+ run_loop_->Quit();
+ }
+
+ bool IsCommandIdEnabled(int command_id) const override {
+ // Return true so that quick menu has something to show.
+ return true;
+ }
+
+ ui::SelectionEventType expected_event_;
+ scoped_ptr<base::RunLoop> run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTouchSelectionControllerClientAura);
+};
+
+class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
+ public:
+ TouchSelectionControllerClientAuraTest() {}
+ ~TouchSelectionControllerClientAuraTest() override {}
+
+ protected:
+ // Starts the test server and navigates to the given url. Sets a large enough
+ // size to the root window. Returns after the navigation to the url is
+ // complete.
+ void StartTestWithPage(const std::string& url) {
+ ASSERT_TRUE(test_server()->Start());
+ GURL test_url(test_server()->GetURL(url));
+ NavigateToURL(shell(), test_url);
+ aura::Window* content = shell()->web_contents()->GetContentNativeView();
+ content->GetHost()->SetBounds(gfx::Rect(800, 600));
+ }
+
+ bool GetPointInsideText(gfx::PointF* point) {
+ std::string str;
+ if (ExecuteScriptAndExtractString(shell()->web_contents()->GetMainFrame(),
+ "get_point_inside_text()", &str)) {
+ return JSONToPoint(str, point);
+ }
+ return false;
+ }
+
+ bool GetPointInsideTextfield(gfx::PointF* point) {
+ std::string str;
+ if (ExecuteScriptAndExtractString(shell()->web_contents()->GetMainFrame(),
+ "get_point_inside_textfield()", &str)) {
+ return JSONToPoint(str, point);
+ }
+ return false;
+ }
+
+ private:
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+ if (!ui::TouchSelectionMenuRunner::GetInstance())
+ menu_runner_.reset(new TestTouchSelectionMenuRunner);
+ }
+
+ void TearDownOnMainThread() override {
+ menu_runner_ = nullptr;
+ ContentBrowserTest::TearDownOnMainThread();
+ }
+
+ scoped_ptr<TestTouchSelectionMenuRunner> menu_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerClientAuraTest);
+};
+
+// Tests if long-pressing on a text brings up selection handles and the quick
+// menu properly.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContents* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ TestTouchSelectionControllerClientAura* selection_controller_client =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client));
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Long-press on the text and wait for handles to appear.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideText(&point));
+ ui::GestureEvent long_press(
+ point.x(), point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ rwhva->OnGestureEvent(&long_press);
+
+ selection_controller_client->Wait();
+
+ // Check if selection is active and the quick menu is showing.
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
+// Tests if tapping in a textfield brings up the insertion handle and the quick
+// menu properly.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicInsertion) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContents* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ TestTouchSelectionControllerClientAura* selection_controller_client =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client));
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Tap inside the textfield and wait for the insertion handle to appear.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::INSERTION_HANDLE_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideTextfield(&point));
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
+ tap_details.set_tap_count(1);
+ ui::GestureEvent tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ tap_details);
+ rwhva->OnGestureEvent(&tap);
+
+ selection_controller_client->Wait();
+
+ // Check if insertion is active and the quick menu is showing.
+ EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
+// Tests if the quick menu is hidden whenever a touch point is active.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
+ QuickMenuHiddenOnTouch) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContents* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ TestTouchSelectionControllerClientAura* selection_controller_client =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client));
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Long-press on the text and wait for selection handles to appear.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideText(&point));
+ ui::GestureEvent long_press(
+ point.x(), point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ rwhva->OnGestureEvent(&long_press);
+
+ selection_controller_client->Wait();
+
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ ui::test::EventGenerator generator(
+ web_contents->GetContentNativeView()->GetRootWindow(),
+ web_contents->GetContentNativeView());
+
+ // Put the first finger down: the quick menu should get hidden.
+ generator.PressTouchId(0);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Put a second finger down: the quick menu should remain hidden.
+ generator.PressTouchId(1);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Lift the first finger up: the quick menu should still remain hidden.
+ generator.ReleaseTouchId(0);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Lift the second finger up: the quick menu should re-appear.
+ generator.ReleaseTouchId(1);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
+// Tests if the quick menu and touch handles are hidden during an scroll.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContents* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ TestTouchSelectionControllerClientAura* selection_controller_client =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client));
+ ui::TouchSelectionControllerTestApi selection_controller_test_api(
+ rwhva->selection_controller());
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Long-press on the text and wait for selection handles to appear.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideText(&point));
+ ui::GestureEvent long_press(
+ point.x(), point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ rwhva->OnGestureEvent(&long_press);
+
+ selection_controller_client->Wait();
+
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(selection_controller_test_api.temporarily_hidden());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Put a finger down: the quick menu should go away, while touch handles stay
+ // there.
+ ui::TouchEvent touch_down(ui::ET_TOUCH_PRESSED, gfx::PointF(10, 10), 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_down);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(selection_controller_test_api.temporarily_hidden());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Start scrolling: touch handles should get hidden, while touch selection is
+ // still active.
+ ui::GestureEvent scroll_begin(
+ 10, 10, 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
+ rwhva->OnGestureEvent(&scroll_begin);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(selection_controller_test_api.temporarily_hidden());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // End scrolling: touch handles should re-appear.
+ ui::GestureEvent scroll_end(
+ 10, 10, 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+ rwhva->OnGestureEvent(&scroll_end);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(selection_controller_test_api.temporarily_hidden());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Lift the finger up: the quick menu should re-appear.
+ ui::TouchEvent touch_up(ui::ET_TOUCH_RELEASED, gfx::PointF(10, 10), 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_up);
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(selection_controller_test_api.temporarily_hidden());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
+// Tests if touch selection gets deactivated after an overscroll completes.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
+ HiddenAfterOverscroll) {
+ // Set the page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContents* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ TestTouchSelectionControllerClientAura* selection_controller_client =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client));
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Long-press on the text and wait for touch handles to appear.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideText(&point));
+ ui::GestureEvent long_press(
+ point.x(), point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ rwhva->OnGestureEvent(&long_press);
+
+ selection_controller_client->Wait();
+
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+ // Scroll such that an overscroll is initiated and wait for it to complete:
+ // touch selection should not be active at the end.
+ selection_controller_client->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_CLEARED);
+
+ ui::GestureEvent scroll_begin(
+ 10, 10, 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
+ rwhva->OnGestureEvent(&scroll_begin);
+
+ ui::GestureEvent scroll_update(
+ 210, 10, 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 200, 0));
+ rwhva->OnGestureEvent(&scroll_update);
+
+ ui::GestureEvent scroll_end(
+ 210, 10, 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+ rwhva->OnGestureEvent(&scroll_end);
+
+ selection_controller_client->Wait();
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
+} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 3947821..2edeacf 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -30,6 +30,8 @@
#include "content/browser/renderer_host/compositor_resize_lock_aura.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
+#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
+#include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -71,6 +73,7 @@
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/display.h"
@@ -78,6 +81,7 @@
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/skia_util.h"
+#include "ui/touch_selection/touch_selection_controller.h"
#include "ui/wm/public/activation_client.h"
#include "ui/wm/public/scoped_tooltip_disabler.h"
#include "ui/wm/public/tooltip_client.h"
@@ -462,7 +466,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
showing_context_menu_(false),
#endif
has_snapped_to_boundary_(false),
- touch_editing_client_(NULL),
is_guest_view_hack_(is_guest_view_hack),
begin_frame_observer_proxy_(this),
weak_ptr_factory_(this) {
@@ -480,6 +483,10 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
SetOverscrollControllerEnabled(overscroll_enabled);
+
+ selection_controller_client_.reset(
+ new TouchSelectionControllerClientAura(this));
+ CreateSelectionController();
}
////////////////////////////////////////////////////////////////////////////////
@@ -965,8 +972,6 @@ void RenderWidgetHostViewAura::TextInputTypeChanged(
text_input_flags_ = flags;
if (GetInputMethod())
GetInputMethod()->OnTextInputTypeChanged(this);
- if (touch_editing_client_)
- touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
}
}
@@ -1083,11 +1088,6 @@ void RenderWidgetHostViewAura::SelectionBoundsChanged(
selection_focus_ = focus_bound;
if (GetInputMethod())
GetInputMethod()->OnCaretBoundsChanged(this);
-
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(
- anchor_bound, focus_bound);
- }
}
void RenderWidgetHostViewAura::CopyFromCompositingSurface(
@@ -1178,6 +1178,10 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
frame->metadata.device_scale_factor,
frame->metadata.latency_info,
&frame->metadata.satisfies_sequences);
+ SelectionUpdated(frame->metadata.selection.is_editable,
+ frame->metadata.selection.is_empty_text_form_control,
+ ConvertSelectionBound(frame->metadata.selection.start),
+ ConvertSelectionBound(frame->metadata.selection.end));
return;
}
@@ -1190,8 +1194,7 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
}
void RenderWidgetHostViewAura::DidStopFlinging() {
- if (touch_editing_client_)
- touch_editing_client_->DidStopFlinging();
+ selection_controller_client_->OnScrollCompleted();
}
#if defined(OS_WIN)
@@ -1271,9 +1274,6 @@ void RenderWidgetHostViewAura::WheelEventAck(
void RenderWidgetHostViewAura::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
- if (touch_editing_client_)
- touch_editing_client_->GestureEventAck(event.type);
-
if (overscroll_controller_) {
overscroll_controller_->ReceivedEventACK(
event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
@@ -1675,9 +1675,8 @@ gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
}
gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
- gfx::Rect rect =
- ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_);
- return ConvertRectToScreen(rect);
+ return ConvertRectToScreen(
+ ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_));
}
bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
@@ -1861,8 +1860,6 @@ bool RenderWidgetHostViewAura::CanFocus() {
void RenderWidgetHostViewAura::OnCaptureLost() {
host_->LostCapture();
- if (touch_editing_client_)
- touch_editing_client_->EndTouchEditing(false);
}
void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
@@ -1945,8 +1942,6 @@ void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
popup_child_host_view_->OnKeyEvent(event);
@@ -1993,9 +1988,6 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
-
if (mouse_locked_) {
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window_->GetRootWindow());
@@ -2159,8 +2151,6 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
if (event->type() == ui::ET_SCROLL) {
#if !defined(OS_WIN)
@@ -2189,8 +2179,8 @@ void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
- return;
+
+ bool had_no_pointer = !pointer_state_.GetPointerCount();
// Update the touch event first.
if (!pointer_state_.OnTouch(*event)) {
@@ -2198,10 +2188,24 @@ void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
return;
}
- blink::WebTouchEvent touch_event = ui::CreateWebTouchEventFromMotionEvent(
- pointer_state_, event->may_cause_scrolling());
+ blink::WebTouchEvent touch_event;
+ bool handled = selection_controller_->WillHandleTouchEvent(pointer_state_);
+ if (handled) {
+ event->SetHandled();
+ } else {
+ touch_event = ui::CreateWebTouchEventFromMotionEvent(
+ pointer_state_, event->may_cause_scrolling());
+ }
pointer_state_.CleanupRemovedTouchPoints(*event);
+ if (handled)
+ return;
+
+ if (had_no_pointer)
+ selection_controller_client_->OnTouchDown();
+ if (!pointer_state_.GetPointerCount())
+ selection_controller_client_->OnTouchUp();
+
// It is important to always mark events as being handled asynchronously when
// they are forwarded. This ensures that the current event does not get
// processed by the gesture recognizer before events currently awaiting
@@ -2216,6 +2220,7 @@ void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
+
if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
@@ -2223,7 +2228,8 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
return;
}
- if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
+ HandleGestureForTouchSelection(event);
+ if (event->handled())
return;
// Confirm existing composition text on TAP gesture, to make sure the input
@@ -2316,8 +2322,7 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
DetachFromInputMethod();
- if (touch_editing_client_)
- touch_editing_client_->EndTouchEditing(false);
+ selection_controller_->HideAndDisallowShowingAutomatically();
if (overscroll_controller_)
overscroll_controller_->Cancel();
@@ -2374,9 +2379,8 @@ void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
// RenderWidgetHostViewAura, private:
RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
- if (touch_editing_client_)
- touch_editing_client_->OnViewDestroyed();
-
+ selection_controller_.reset();
+ selection_controller_client_.reset();
delegated_frame_host_.reset();
window_observer_.reset();
if (window_->GetHost())
@@ -2553,6 +2557,12 @@ void RenderWidgetHostViewAura::OnShowContextMenu() {
#endif
}
+void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
+ scoped_ptr<TouchSelectionControllerClientAura> client) {
+ selection_controller_client_.swap(client);
+ CreateSelectionController();
+}
+
void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
SnapToPhysicalPixelBoundary();
// Don't recursively call SetBounds if this bounds update is the result of
@@ -2561,10 +2571,6 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
window_->SetBounds(rect);
host_->WasResized();
delegated_frame_host_->WasResized();
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_,
- selection_focus_);
- }
#if defined(OS_WIN)
// Create the legacy dummy window which corresponds to the bounds of the
// webcontents. This will be passed as the container window for windowless
@@ -2707,6 +2713,51 @@ void RenderWidgetHostViewAura::ForwardKeyboardEvent(
host_->ForwardKeyboardEvent(event);
}
+void RenderWidgetHostViewAura::SelectionUpdated(bool is_editable,
+ bool is_empty_text_form_control,
+ const ui::SelectionBound& start,
+ const ui::SelectionBound& end) {
+ selection_controller_->OnSelectionEditable(is_editable);
+ selection_controller_->OnSelectionEmpty(is_empty_text_form_control);
+ selection_controller_->OnSelectionBoundsChanged(start, end);
+}
+
+void RenderWidgetHostViewAura::CreateSelectionController() {
+ ui::TouchSelectionController::Config tsc_config;
+ tsc_config.tap_timeout = base::TimeDelta::FromMilliseconds(
+ ui::GestureConfiguration::GetInstance()->show_press_delay_in_ms());
+ tsc_config.tap_slop = ui::GestureConfiguration::GetInstance()
+ ->max_touch_move_in_pixels_for_click();
+ tsc_config.show_on_tap_for_empty_editable = true;
+ tsc_config.enable_longpress_drag_selection = false;
+ selection_controller_.reset(new ui::TouchSelectionController(
+ selection_controller_client_.get(), tsc_config));
+}
+
+void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
+ ui::GestureEvent* event) {
+ switch (event->type()) {
+ case ui::ET_GESTURE_LONG_PRESS:
+ if (selection_controller_->WillHandleLongPressEvent(
+ base::TimeTicks() + event->time_stamp(), event->location_f())) {
+ event->SetHandled();
+ }
+ break;
+ case ui::ET_GESTURE_TAP:
+ if (selection_controller_->WillHandleTapEvent(event->location_f()))
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ selection_controller_client_->OnScrollStarted();
+ break;
+ case ui::ET_GESTURE_SCROLL_END:
+ selection_controller_client_->OnScrollCompleted();
+ break;
+ default:
+ break;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, public:
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index e0f76f1..b3d913f 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -31,7 +31,6 @@
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/touch/selection_bound.h"
-#include "ui/base/touch/touch_editing_controller.h"
#include "ui/events/gestures/motion_event_aura.h"
#include "ui/gfx/display_observer.h"
#include "ui/gfx/geometry/insets.h"
@@ -65,6 +64,7 @@ class CompositorLock;
class InputMethod;
class LocatedEvent;
class Texture;
+class TouchSelectionController;
}
namespace content {
@@ -76,6 +76,7 @@ class OverscrollController;
class RenderFrameHostImpl;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
+class TouchSelectionControllerClientAura;
// RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
class CONTENT_EXPORT RenderWidgetHostViewAura
@@ -90,49 +91,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
public aura::client::FocusChangeObserver,
public aura::client::CursorClientObserver {
public:
- // Displays and controls touch editing elements such as selection handles.
- class TouchEditingClient {
- public:
- TouchEditingClient() {}
-
- // Tells the client to start showing touch editing handles.
- virtual void StartTouchEditing() = 0;
-
- // Notifies the client that touch editing is no longer needed. |quick|
- // determines whether the handles should fade out quickly or slowly.
- virtual void EndTouchEditing(bool quick) = 0;
-
- // Notifies the client that the selection bounds need to be updated.
- virtual void OnSelectionOrCursorChanged(
- const ui::SelectionBound& anchor,
- const ui::SelectionBound& focus) = 0;
-
- // Notifies the client that the current text input type as changed.
- virtual void OnTextInputTypeChanged(ui::TextInputType type) = 0;
-
- // Notifies the client that an input event is about to be sent to the
- // renderer. Returns true if the client wants to stop event propagation.
- virtual bool HandleInputEvent(const ui::Event* event) = 0;
-
- // Notifies the client that a gesture event ack was received.
- virtual void GestureEventAck(int gesture_event_type) = 0;
-
- // Notifies the client that the fling has ended, so it can activate touch
- // editing if needed.
- virtual void DidStopFlinging() = 0;
-
- // This is called when the view is destroyed, so that the client can
- // perform any necessary clean-up.
- virtual void OnViewDestroyed() = 0;
-
- protected:
- virtual ~TouchEditingClient() {}
- };
-
- void set_touch_editing_client(TouchEditingClient* client) {
- touch_editing_client_ = client;
- }
-
// When |is_guest_view_hack| is true, this view isn't really the view for
// the |widget|, a RenderWidgetHostViewGuest is.
//
@@ -344,6 +302,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SnapToPhysicalPixelBoundary();
+ ui::TouchSelectionController* selection_controller() const {
+ return selection_controller_.get();
+ }
+
+ TouchSelectionControllerClientAura* selection_controller_client() const {
+ return selection_controller_client_.get();
+ }
+
OverscrollController* overscroll_controller() const {
return overscroll_controller_.get();
}
@@ -351,6 +317,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Called when the context menu is about to be displayed.
void OnShowContextMenu();
+ // Used in tests to set a mock client for touch selection controller. It will
+ // create a new touch selection controller for the new client.
+ void SetSelectionControllerClientForTest(
+ scoped_ptr<TouchSelectionControllerClientAura> client);
+
protected:
~RenderWidgetHostViewAura() override;
@@ -510,6 +481,20 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Called when the parent window hierarchy for our window changes.
void ParentHierarchyChanged();
+ // Helper function to be called whenever new selection information is
+ // received. It will update selection controller.
+ void SelectionUpdated(bool is_editable,
+ bool is_empty_text_form_control,
+ const ui::SelectionBound& start,
+ const ui::SelectionBound& end);
+
+ // Helper function to create a selection controller.
+ void CreateSelectionController();
+
+ // Performs gesture handling needed for touch text selection. Sets event as
+ // handled if it should not be further processed.
+ void HandleGestureForTouchSelection(ui::GestureEvent* event);
+
// The model object.
RenderWidgetHostImpl* host_;
@@ -647,7 +632,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool has_snapped_to_boundary_;
- TouchEditingClient* touch_editing_client_;
+ scoped_ptr<TouchSelectionControllerClientAura> selection_controller_client_;
+ scoped_ptr<ui::TouchSelectionController> selection_controller_;
scoped_ptr<OverscrollController> overscroll_controller_;
diff --git a/content/browser/web_contents/touch_editable_impl_aura.cc b/content/browser/web_contents/touch_editable_impl_aura.cc
deleted file mode 100644
index 622b490..0000000
--- a/content/browser/web_contents/touch_editable_impl_aura.cc
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright (c) 2013 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/touch_editable_impl_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 "content/public/browser/render_widget_host.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/touch/selection_bound.h"
-#include "ui/base/ui_base_switches_util.h"
-#include "ui/gfx/range/range.h"
-#include "ui/strings/grit/ui_strings.h"
-#include "ui/wm/public/activation_client.h"
-
-namespace content {
-
-////////////////////////////////////////////////////////////////////////////////
-// TouchEditableImplAura, public:
-
-TouchEditableImplAura::~TouchEditableImplAura() {
- Cleanup();
-}
-
-// static
-TouchEditableImplAura* TouchEditableImplAura::Create() {
- if (switches::IsTouchEditingEnabled())
- return new TouchEditableImplAura();
- return NULL;
-}
-
-void TouchEditableImplAura::AttachToView(RenderWidgetHostViewAura* view) {
- if (rwhva_ == view)
- return;
-
- Cleanup();
- if (!view)
- return;
-
- rwhva_ = view;
- rwhva_->set_touch_editing_client(this);
-}
-
-void TouchEditableImplAura::UpdateEditingController() {
- if (!rwhva_ || !rwhva_->HasFocus())
- return;
-
- if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE ||
- selection_anchor_ != selection_focus_) {
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
- } else {
- EndTouchEditing(false);
- }
-}
-
-void TouchEditableImplAura::OverscrollStarted() {
- overscroll_in_progress_ = true;
-}
-
-void TouchEditableImplAura::OverscrollCompleted() {
- overscroll_in_progress_ = false;
- StartTouchEditingIfNecessary();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TouchEditableImplAura, RenderWidgetHostViewAura::TouchEditingClient
-// implementation:
-
-void TouchEditableImplAura::StartTouchEditing() {
- if (!rwhva_ || !rwhva_->HasFocus())
- return;
-
- if (!touch_selection_controller_) {
- touch_selection_controller_.reset(
- ui::TouchEditingControllerDeprecated::Create(this));
- }
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
-}
-
-void TouchEditableImplAura::EndTouchEditing(bool quick) {
- if (touch_selection_controller_) {
- if (touch_selection_controller_->IsHandleDragInProgress()) {
- touch_selection_controller_->SelectionChanged();
- } else {
- selection_gesture_in_process_ = false;
- touch_selection_controller_->HideHandles(quick);
- touch_selection_controller_.reset();
- }
- }
-}
-
-void TouchEditableImplAura::OnSelectionOrCursorChanged(
- const ui::SelectionBound& anchor,
- const ui::SelectionBound& focus) {
- selection_anchor_ = anchor;
- selection_focus_ = focus;
-
- // If touch editing handles were not visible, we bring them up only if the
- // current event is a gesture event, no scroll/fling/overscoll is in progress,
- // and there is non-zero selection on the page
- if (selection_gesture_in_process_ && !scroll_in_progress_ &&
- !overscroll_in_progress_ && selection_anchor_ != selection_focus_) {
- StartTouchEditing();
- selection_gesture_in_process_ = false;
- }
-
- UpdateEditingController();
-}
-
-void TouchEditableImplAura::OnTextInputTypeChanged(ui::TextInputType type) {
- text_input_type_ = type;
-}
-
-bool TouchEditableImplAura::HandleInputEvent(const ui::Event* event) {
- DCHECK(rwhva_);
- if (!event->IsGestureEvent()) {
- // Ignore all non-gesture events. Non-gesture events that can deactivate
- // touch editing are handled in TouchSelectionControllerImpl.
- return false;
- }
-
- const ui::GestureEvent* gesture_event =
- static_cast<const ui::GestureEvent*>(event);
- switch (event->type()) {
- case ui::ET_GESTURE_TAP:
- // When the user taps, we want to show touch editing handles if user
- // tapped on selected text.
- if (gesture_event->details().tap_count() == 1 &&
- selection_anchor_ != selection_focus_) {
- gfx::Rect selection_rect =
- ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_);
- // When tap is on selection, show handles and mark event as handled only
- // if handles are not present or text is not editable. Otherwise, do not
- // set event as handles so that event is forwarded to the renderer to
- // update selection/cursor.
- if (selection_rect.Contains(gesture_event->location()) &&
- (text_input_type_ == ui::TEXT_INPUT_TYPE_NONE ||
- !touch_selection_controller_)) {
- StartTouchEditing();
- return true;
- }
- }
- // For single taps, not inside selected region, we want to show handles
- // only when the tap is on an already focused textfield.
- textfield_was_focused_on_tap_ =
- gesture_event->details().tap_count() == 1 &&
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE;
- break;
- case ui::ET_GESTURE_LONG_PRESS:
- selection_gesture_in_process_ = true;
- break;
- case ui::ET_GESTURE_SCROLL_BEGIN:
- scroll_in_progress_ = true;;
- // We need to hide selection handles during scroll (including fling and
- // overscroll), but they should be re-activated after scrolling if:
- // - an existing scroll decided that handles should be shown after
- // scrolling; or
- // - the gesture in progress is going to end in selection; or
- // - selection handles are currently active.
- handles_hidden_due_to_scroll_ = handles_hidden_due_to_scroll_ ||
- selection_gesture_in_process_ ||
- touch_selection_controller_ != NULL;
- selection_gesture_in_process_ = false;
- EndTouchEditing(true);
- break;
- case ui::ET_GESTURE_SCROLL_END:
- scroll_in_progress_ = false;
- StartTouchEditingIfNecessary();
- break;
- default:
- break;
- }
- return false;
-}
-
-void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
- DCHECK(rwhva_);
- if (gesture_event_type == blink::WebInputEvent::GestureTap &&
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE &&
- textfield_was_focused_on_tap_) {
- StartTouchEditing();
- UpdateEditingController();
- }
-}
-
-void TouchEditableImplAura::DidStopFlinging() {
- scroll_in_progress_ = false;
- StartTouchEditingIfNecessary();
-}
-
-void TouchEditableImplAura::OnViewDestroyed() {
- Cleanup();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TouchEditableImplAura, ui::TouchEditable implementation:
-
-void TouchEditableImplAura::SelectRect(const gfx::Point& start,
- const gfx::Point& end) {
- RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
- RenderViewHost* rvh = RenderViewHost::From(host);
- WebContentsImpl* wc =
- static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
- wc->SelectRange(start, end);
-}
-
-void TouchEditableImplAura::MoveCaretTo(const gfx::Point& point) {
- if (!rwhva_)
- return;
-
- RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
- rwhva_->GetRenderWidgetHost());
- host->MoveCaret(point);
-}
-
-void TouchEditableImplAura::GetSelectionEndPoints(ui::SelectionBound* anchor,
- ui::SelectionBound* focus) {
- *anchor = selection_anchor_;
- *focus = selection_focus_;
-}
-
-gfx::Rect TouchEditableImplAura::GetBounds() {
- return rwhva_ ? gfx::Rect(rwhva_->GetNativeView()->bounds().size()) :
- gfx::Rect();
-}
-
-gfx::NativeView TouchEditableImplAura::GetNativeView() const {
- return rwhva_ ? rwhva_->GetNativeView()->GetToplevelWindow() : NULL;
-}
-
-void TouchEditableImplAura::ConvertPointToScreen(gfx::Point* point) {
- if (!rwhva_)
- return;
- aura::Window* window = rwhva_->GetNativeView();
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(window->GetRootWindow());
- if (screen_position_client)
- screen_position_client->ConvertPointToScreen(window, point);
-}
-
-void TouchEditableImplAura::ConvertPointFromScreen(gfx::Point* point) {
- if (!rwhva_)
- return;
- aura::Window* window = rwhva_->GetNativeView();
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(window->GetRootWindow());
- if (screen_position_client)
- screen_position_client->ConvertPointFromScreen(window, point);
-}
-
-bool TouchEditableImplAura::DrawsHandles() {
- return false;
-}
-
-void TouchEditableImplAura::OpenContextMenu(const gfx::Point& anchor) {
- if (!rwhva_)
- return;
- gfx::Point point = anchor;
- ConvertPointFromScreen(&point);
- RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
- host->Send(new ViewMsg_ShowContextMenu(
- host->GetRoutingID(), ui::MENU_SOURCE_TOUCH_EDIT_MENU, point));
- EndTouchEditing(false);
-}
-
-bool TouchEditableImplAura::IsCommandIdChecked(int command_id) const {
- NOTREACHED();
- return false;
-}
-
-bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
- if (!rwhva_)
- return false;
- 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;
- }
-}
-
-bool TouchEditableImplAura::GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) {
- return false;
-}
-
-void TouchEditableImplAura::ExecuteCommand(int command_id, int event_flags) {
- RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
- RenderViewHost* rvh = RenderViewHost::From(host);
- 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;
- }
- EndTouchEditing(false);
-}
-
-void TouchEditableImplAura::DestroyTouchSelection() {
- EndTouchEditing(false);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TouchEditableImplAura, private:
-
-TouchEditableImplAura::TouchEditableImplAura()
- : text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
- rwhva_(NULL),
- selection_gesture_in_process_(false),
- handles_hidden_due_to_scroll_(false),
- scroll_in_progress_(false),
- overscroll_in_progress_(false),
- textfield_was_focused_on_tap_(false) {
-}
-
-void TouchEditableImplAura::StartTouchEditingIfNecessary() {
- // If there is no scrolling left in progress, show selection handles if they
- // were hidden due to scroll and there is a selection.
- if (!scroll_in_progress_ && !overscroll_in_progress_ &&
- handles_hidden_due_to_scroll_ &&
- (selection_anchor_ != selection_focus_ ||
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
- StartTouchEditing();
- UpdateEditingController();
- handles_hidden_due_to_scroll_ = false;
- }
-}
-
-void TouchEditableImplAura::Cleanup() {
- if (rwhva_) {
- rwhva_->set_touch_editing_client(NULL);
- rwhva_ = NULL;
- }
- text_input_type_ = ui::TEXT_INPUT_TYPE_NONE;
- EndTouchEditing(true);
- selection_gesture_in_process_ = false;
- handles_hidden_due_to_scroll_ = false;
- scroll_in_progress_ = false;
- overscroll_in_progress_ = false;
-}
-
-} // namespace content
diff --git a/content/browser/web_contents/touch_editable_impl_aura.h b/content/browser/web_contents/touch_editable_impl_aura.h
deleted file mode 100644
index d7516f6..0000000
--- a/content/browser/web_contents/touch_editable_impl_aura.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
-#define CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
-
-#include <deque>
-#include <map>
-#include <queue>
-
-#include "content/browser/renderer_host/render_widget_host_view_aura.h"
-#include "ui/aura/window_observer.h"
-#include "ui/base/touch/touch_editing_controller.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace ui {
-class Accelerator;
-}
-
-namespace content {
-class TouchEditableImplAuraTest;
-
-// Aura specific implementation of ui::TouchEditable for a RenderWidgetHostView.
-class CONTENT_EXPORT TouchEditableImplAura
- : public ui::TouchEditable,
- public NON_EXPORTED_BASE(RenderWidgetHostViewAura::TouchEditingClient) {
- public:
- ~TouchEditableImplAura() override;
-
- static TouchEditableImplAura* Create();
-
- void AttachToView(RenderWidgetHostViewAura* view);
-
- // Updates the |touch_selection_controller_| or ends touch editing session
- // depending on the current selection and cursor state.
- void UpdateEditingController();
-
- virtual void OverscrollStarted();
- virtual void OverscrollCompleted();
-
- // Overridden from RenderWidgetHostViewAura::TouchEditingClient.
- void StartTouchEditing() override;
- void EndTouchEditing(bool quick) override;
- void OnSelectionOrCursorChanged(const ui::SelectionBound& anchor,
- const ui::SelectionBound& focus) override;
- void OnTextInputTypeChanged(ui::TextInputType type) override;
- bool HandleInputEvent(const ui::Event* event) override;
- void GestureEventAck(int gesture_event_type) override;
- void DidStopFlinging() override;
- void OnViewDestroyed() override;
-
- // Overridden from ui::TouchEditable:
- void SelectRect(const gfx::Point& start, const gfx::Point& end) override;
- void MoveCaretTo(const gfx::Point& point) override;
- void GetSelectionEndPoints(ui::SelectionBound* anchor,
- ui::SelectionBound* focus) override;
- gfx::Rect GetBounds() override;
- gfx::NativeView GetNativeView() const override;
- void ConvertPointToScreen(gfx::Point* point) override;
- void ConvertPointFromScreen(gfx::Point* point) override;
- bool DrawsHandles() override;
- void OpenContextMenu(const gfx::Point& anchor) override;
- bool IsCommandIdChecked(int command_id) const override;
- bool IsCommandIdEnabled(int command_id) const override;
- bool GetAcceleratorForCommandId(int command_id,
- ui::Accelerator* accelerator) override;
- void ExecuteCommand(int command_id, int event_flags) override;
- void DestroyTouchSelection() override;
-
- protected:
- TouchEditableImplAura();
-
- private:
- friend class TouchEditableImplAuraTest;
-
- // A convenience function that is called after scroll/fling/overscroll ends to
- // re-activate touch selection if necessary.
- void StartTouchEditingIfNecessary();
-
- void Cleanup();
-
- // Bounds for the selection.
- ui::SelectionBound selection_anchor_;
- ui::SelectionBound selection_focus_;
-
- // The current text input type.
- ui::TextInputType text_input_type_;
-
- RenderWidgetHostViewAura* rwhva_;
- scoped_ptr<ui::TouchEditingControllerDeprecated> touch_selection_controller_;
-
- // True if |rwhva_| is currently handling a gesture that could result in a
- // change in selection (long press, double tap or triple tap).
- bool selection_gesture_in_process_;
-
- // Set to true if handles are hidden when user is scrolling. Used to determine
- // whether to re-show handles after a scrolling session.
- bool handles_hidden_due_to_scroll_;
-
- // Keep track of scrolls/overscrolls in progress.
- bool scroll_in_progress_;
- bool overscroll_in_progress_;
-
- // Used to track if a textfield was focused when the current tap gesture
- // happened.
- bool textfield_was_focused_on_tap_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchEditableImplAura);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WEB_CONTENTS_TOUCH_EDITABLE_IMPL_AURA_H_
diff --git a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
deleted file mode 100644
index 9ee1bbf..0000000
--- a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
+++ /dev/null
@@ -1,638 +0,0 @@
-// Copyright (c) 2012 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/touch_editable_impl_aura.h"
-
-#include "base/command_line.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/test_timeouts.h"
-#include "base/values.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_contents/web_contents_view_aura.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/wm/core/default_screen_position_client.h"
-
-using blink::WebInputEvent;
-
-namespace content {
-
-class TestTouchEditableImplAura : public TouchEditableImplAura {
- public:
- TestTouchEditableImplAura()
- : overscroll_started_callback_arrived_(false),
- waiting_for_overscroll_started_callback_(false),
- overscroll_completed_callback_arrived_(false),
- waiting_for_overscroll_completed_callback_(false),
- selection_changed_callback_arrived_(false),
- waiting_for_selection_changed_callback_(false),
- waiting_for_gesture_ack_type_(WebInputEvent::Undefined),
- last_gesture_ack_type_(WebInputEvent::Undefined),
- fling_stop_callback_arrived_(false),
- waiting_for_fling_stop_callback_(false) {}
-
- virtual void Reset() {
- overscroll_started_callback_arrived_ = false;
- waiting_for_overscroll_started_callback_ = false;
- overscroll_completed_callback_arrived_ = false;
- waiting_for_overscroll_completed_callback_ = false;
- selection_changed_callback_arrived_ = false;
- waiting_for_selection_changed_callback_ = false;
- waiting_for_gesture_ack_type_ = WebInputEvent::Undefined;
- last_gesture_ack_type_ = WebInputEvent::Undefined;
- fling_stop_callback_arrived_ = false;
- waiting_for_fling_stop_callback_ = false;
- }
-
- void OverscrollStarted() override {
- overscroll_started_callback_arrived_ = true;
- TouchEditableImplAura::OverscrollStarted();
- if (waiting_for_overscroll_started_callback_)
- overscroll_started_wait_run_loop_->Quit();
-}
-
- void WaitForOverscrollStartedCallback() {
- // Doesn't make sense to call more that once without resetting.
- CHECK(!waiting_for_overscroll_started_callback_);
- waiting_for_overscroll_started_callback_ = true;
- if (overscroll_started_callback_arrived_)
- return;
- overscroll_started_wait_run_loop_.reset(new base::RunLoop());
- overscroll_started_wait_run_loop_->Run();
- }
-
- void OverscrollCompleted() override {
- overscroll_completed_callback_arrived_ = true;
- TouchEditableImplAura::OverscrollCompleted();
- if (waiting_for_overscroll_completed_callback_)
- overscroll_completed_wait_run_loop_->Quit();
- }
-
- void WaitForOverscrollCompletedCallback() {
- // Doesn't make sense to call more that once without resetting.
- CHECK(!waiting_for_overscroll_completed_callback_);
- waiting_for_overscroll_completed_callback_ = true;
- if (overscroll_completed_callback_arrived_)
- return;
- overscroll_completed_wait_run_loop_.reset(new base::RunLoop());
- overscroll_completed_wait_run_loop_->Run();
- }
-
- void OnSelectionOrCursorChanged(const ui::SelectionBound& anchor,
- const ui::SelectionBound& focus) override {
- selection_changed_callback_arrived_ = true;
- TouchEditableImplAura::OnSelectionOrCursorChanged(anchor, focus);
- if (waiting_for_selection_changed_callback_)
- selection_changed_wait_run_loop_->Quit();
- }
-
- void GestureEventAck(int gesture_event_type) override {
- last_gesture_ack_type_ =
- static_cast<WebInputEvent::Type>(gesture_event_type);
- TouchEditableImplAura::GestureEventAck(gesture_event_type);
- if (waiting_for_gesture_ack_type_ == gesture_event_type)
- gesture_ack_wait_run_loop_->Quit();
- }
-
- void DidStopFlinging() override {
- fling_stop_callback_arrived_ = true;
- TouchEditableImplAura::DidStopFlinging();
- if (waiting_for_fling_stop_callback_)
- fling_stop_wait_run_loop_->Quit();
- }
-
- void WaitForSelectionChangeCallback() {
- // Doesn't make sense to call more that once without resetting.
- CHECK(!waiting_for_selection_changed_callback_);
- waiting_for_selection_changed_callback_ = true;
- if (selection_changed_callback_arrived_)
- return;
- selection_changed_wait_run_loop_.reset(new base::RunLoop());
- selection_changed_wait_run_loop_->Run();
- }
-
- void WaitForGestureAck(WebInputEvent::Type gesture_event_type) {
- // Doesn't make sense to call more that once without resetting.
- CHECK_EQ(waiting_for_gesture_ack_type_, WebInputEvent::Undefined);
- waiting_for_gesture_ack_type_ = gesture_event_type;
- if (last_gesture_ack_type_ == gesture_event_type)
- return;
- gesture_ack_wait_run_loop_.reset(new base::RunLoop());
- gesture_ack_wait_run_loop_->Run();
- }
-
- void WaitForFlingStopCallback() {
- // Doesn't make sense to call more that once without resetting.
- CHECK(!waiting_for_fling_stop_callback_);
- waiting_for_fling_stop_callback_ = true;
- if (fling_stop_callback_arrived_)
- return;
- fling_stop_wait_run_loop_.reset(new base::RunLoop());
- fling_stop_wait_run_loop_->Run();
- }
-
- protected:
- ~TestTouchEditableImplAura() override {}
-
- private:
- bool overscroll_started_callback_arrived_;
- bool waiting_for_overscroll_started_callback_;
- bool overscroll_completed_callback_arrived_;
- bool waiting_for_overscroll_completed_callback_;
- bool selection_changed_callback_arrived_;
- bool waiting_for_selection_changed_callback_;
- WebInputEvent::Type waiting_for_gesture_ack_type_;
- WebInputEvent::Type last_gesture_ack_type_;
- bool fling_stop_callback_arrived_;
- bool waiting_for_fling_stop_callback_;
- scoped_ptr<base::RunLoop> overscroll_started_wait_run_loop_;
- scoped_ptr<base::RunLoop> overscroll_completed_wait_run_loop_;
- scoped_ptr<base::RunLoop> selection_changed_wait_run_loop_;
- scoped_ptr<base::RunLoop> gesture_ack_wait_run_loop_;
- scoped_ptr<base::RunLoop> fling_stop_wait_run_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAura);
-};
-
-class TouchEditableImplAuraTest : public ContentBrowserTest {
- public:
- TouchEditableImplAuraTest() {}
-
- protected:
- void SetUpOnMainThread() override {
- ContentBrowserTest::SetUpOnMainThread();
- aura::client::SetScreenPositionClient(shell()->window()->GetRootWindow(),
- &screen_position_client_);
- }
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitch(switches::kEnableTouchEditing);
- }
-
- // Executes the javascript synchronously and makes sure the returned value is
- // freed properly.
- void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(rfh, jscript);
- }
-
- // Starts the test server and navigates to the given url. Sets a large enough
- // size to the root window. Returns after the navigation to the url is
- // complete.
- void StartTestWithPage(const std::string& url) {
- ASSERT_TRUE(test_server()->Start());
- GURL test_url(test_server()->GetURL(url));
- NavigateToURL(shell(), test_url);
- aura::Window* content = shell()->web_contents()->GetContentNativeView();
- content->GetHost()->SetBounds(gfx::Rect(800, 600));
- }
-
- RenderWidgetHostViewAura* GetRenderWidgetHostViewAura(
- TouchEditableImplAura* touch_editable) {
- return touch_editable->rwhva_;
- }
-
- ui::TouchEditingControllerDeprecated* GetTouchSelectionController(
- TouchEditableImplAura* touch_editable) {
- return touch_editable->touch_selection_controller_.get();
- }
-
- ui::TextInputType GetTextInputType(TouchEditableImplAura* touch_editable) {
- return touch_editable->text_input_type_;
- }
-
- private:
- wm::DefaultScreenPositionClient screen_position_client_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchEditableImplAuraTest);
-};
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TouchSelectionOriginatingFromWebpageTest) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- aura::Window* content = web_contents->GetContentNativeView();
- ui::test::EventGenerator generator(content->GetRootWindow(), content);
- gfx::Rect bounds = content->GetBoundsInRootWindow();
-
- touch_editable->Reset();
- ExecuteSyncJSFunction(main_frame, "select_all_text()");
- touch_editable->WaitForSelectionChangeCallback();
-
- // Tap inside selection to bring up selection handles.
- generator.GestureTapAt(gfx::Point(bounds.x() + 10, bounds.y() + 10));
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
-
- // Check if selection handles are showing.
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
- EXPECT_STREQ("Some text we can select", selection.c_str());
-
- // Lets move the handles a bit to modify the selection
- touch_editable->Reset();
- ui::SelectionBound anchor, focus;
- touch_editable->GetSelectionEndPoints(&anchor, &focus);
- // The distance by which a handle image is offset from the bottom of the
- // selection/text baseline.
- const int kSelectionHandleVerticalVisualOffset = 2;
- int handle_grab_x = bounds.x() + anchor.edge_bottom_rounded().x();
- int handle_grab_y = bounds.y() + anchor.edge_bottom_rounded().y() +
- kSelectionHandleVerticalVisualOffset + 1;
- generator.GestureScrollSequence(
- gfx::Point(handle_grab_x, handle_grab_y),
- gfx::Point(handle_grab_x + 20, handle_grab_y),
- base::TimeDelta::FromMilliseconds(20),
- 5);
- touch_editable->WaitForSelectionChangeCallback();
-
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
- value = content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- value->GetAsString(&selection);
-
- // It is hard to tell what exactly the selection would be now. But it would
- // definitely be less than whatever was selected before.
- EXPECT_GT(std::strlen("Some text we can select"), selection.size());
-}
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TestTouchSelectionHiddenWhenScrolling) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- // Long press to select word.
- ui::GestureEvent long_press(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
- touch_editable->Reset();
- rwhva->OnGestureEvent(&long_press);
- touch_editable->WaitForSelectionChangeCallback();
-
- // Check if selection handles are showing.
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
- EXPECT_STREQ("Some", selection.c_str());
-
- // Start scrolling. Handles should get hidden.
- ui::GestureEvent scroll_begin(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
- rwhva->OnGestureEvent(&scroll_begin);
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // Handles should come back after scroll ends.
- ui::GestureEvent scroll_end(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- rwhva->OnGestureEvent(&scroll_end);
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-}
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TestTouchSelectionReshownAfterFling) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- // Long press to select word.
- ui::GestureEvent long_press(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
- touch_editable->Reset();
- rwhva->OnGestureEvent(&long_press);
- touch_editable->WaitForSelectionChangeCallback();
-
- // Check if selection handles are showing.
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
- EXPECT_STREQ("Some", selection.c_str());
-
- // Start scrolling. Handles should get hidden.
- ui::GestureEvent scroll_begin(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0));
- rwhva->OnGestureEvent(&scroll_begin);
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // Start a fling. Handles should come back after fling stops.
- ui::GestureEvent fling_start(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 1, 0));
- rwhva->OnGestureEvent(&fling_start);
- touch_editable->WaitForFlingStopCallback();
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-}
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TestTouchSelectionWhenOverscrolling) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- // Long press to select word.
- ui::GestureEvent long_press(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
- touch_editable->Reset();
- rwhva->OnGestureEvent(&long_press);
- touch_editable->WaitForSelectionChangeCallback();
-
- // Check if selection handles are showing.
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
- EXPECT_STREQ("Some", selection.c_str());
-
- ui::GestureEvent scroll_begin(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0));
- rwhva->OnGestureEvent(&scroll_begin);
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // Then overscroll starts. OverscrollStarted callback should be called and
- // handles should remain hidden.
- ui::GestureEvent scroll_update(
- 210,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 200, 0));
- rwhva->OnGestureEvent(&scroll_update);
- touch_editable->WaitForOverscrollStartedCallback();
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // We might have multiple overscroll-starts in one overscroll session. Handles
- // should still remain hidden.
- touch_editable->OverscrollStarted();
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // And, finally a scroll-end. An OverscrollCompleted callback should be
- // called and handles should come back.
- ui::GestureEvent scroll_end(
- 10,
- 210,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- rwhva->OnGestureEvent(&scroll_end);
- touch_editable->WaitForOverscrollCompletedCallback();
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- // Now repeat the same sequence, but abort the overscroll by scrolling back
- // before ending the scroll.
- touch_editable->Reset();
- scroll_begin = ui::GestureEvent(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0));
- rwhva->OnGestureEvent(&scroll_begin);
-
- scroll_update = ui::GestureEvent(
- 210,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 200, 0));
- rwhva->OnGestureEvent(&scroll_update);
- touch_editable->WaitForOverscrollStartedCallback();
-
- // Scroll back.
- ui::GestureEvent scroll_update2(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, -200, 0));
- rwhva->OnGestureEvent(&scroll_update2);
- // Handles should remain hidden.
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- // End the scroll - the overscroll should be cancelled, and we should still
- // receive OverscrollCompleted callback
- scroll_end = ui::GestureEvent(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- rwhva->OnGestureEvent(&scroll_end);
- touch_editable->WaitForOverscrollCompletedCallback();
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-}
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TouchSelectionOnLongPressTest) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- // Long press to select word.
- ui::GestureEvent long_press(
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
- touch_editable->Reset();
- rwhva->OnGestureEvent(&long_press);
- touch_editable->WaitForSelectionChangeCallback();
-
- // Check if selection handles are showing.
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
- EXPECT_STREQ("Some", selection.c_str());
-}
-
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- NoTouchSelectionOnDoubleTapTest) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura =
- static_cast<WebContentsViewAura*>(web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- // Double-tap to select word.
- ui::GestureEventDetails details(ui::ET_GESTURE_TAP);
- details.set_tap_count(2);
- ui::GestureEvent double_tap(10, 10, 0, ui::EventTimeForNow(), details);
- touch_editable->Reset();
- rwhva->OnGestureEvent(&double_tap);
- touch_editable->WaitForSelectionChangeCallback();
-
- // Make sure touch selection handles are not showing.
- EXPECT_FALSE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
- std::string selection;
- value->GetAsString(&selection);
- EXPECT_STREQ("Some", selection.c_str());
-}
-
-#if defined(OS_CHROMEOS)
-// http://crbug.com/396509
-#define MAYBE_TouchCursorInTextfieldTest DISABLED_TouchCursorInTextfieldTest
-#else
-#define MAYBE_TouchCursorInTextfieldTest TouchCursorInTextfieldTest
-#endif
-IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- MAYBE_TouchCursorInTextfieldTest) {
- ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHost* main_frame = web_contents->GetMainFrame();
- WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
- web_contents->GetView());
- TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
- view_aura->SetTouchEditableForTest(touch_editable);
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- aura::Window* content = web_contents->GetContentNativeView();
- ui::test::EventGenerator generator(content->GetRootWindow(), content);
- gfx::Rect bounds = content->GetBoundsInRootWindow();
- EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
-
- ExecuteSyncJSFunction(main_frame, "focus_textfield()");
- touch_editable->WaitForSelectionChangeCallback();
-
- // Tap textfield
- touch_editable->Reset();
- generator.GestureTapAt(gfx::Point(bounds.x() + 50, bounds.y() + 40));
- // Tap Down acks are sent synchronously, while Tap acks are asynchronous.
- touch_editable->WaitForGestureAck(WebInputEvent::GestureTap);
- touch_editable->WaitForSelectionChangeCallback();
- touch_editable->Reset();
-
- // Check if cursor handle is showing.
- EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType(touch_editable));
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
-
- scoped_ptr<base::Value> value =
- content::ExecuteScriptAndGetValue(main_frame, "get_cursor_position()");
- int cursor_pos = -1;
- value->GetAsInteger(&cursor_pos);
- EXPECT_NE(-1, cursor_pos);
-
- // Move the cursor handle.
- generator.GestureScrollSequence(
- gfx::Point(50, 59),
- gfx::Point(10, 59),
- base::TimeDelta::FromMilliseconds(20),
- 1);
- touch_editable->WaitForSelectionChangeCallback();
- EXPECT_TRUE(GetTouchSelectionController(touch_editable));
- value = content::ExecuteScriptAndGetValue(main_frame,
- "get_cursor_position()");
- int new_cursor_pos = -1;
- value->GetAsInteger(&new_cursor_pos);
- EXPECT_NE(-1, new_cursor_pos);
- // Cursor should have moved.
- EXPECT_NE(new_cursor_pos, cursor_pos);
-}
-
-} // namespace content
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 39a2388..49618ee 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -13,6 +13,7 @@
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -21,7 +22,6 @@
#include "content/browser/renderer_host/web_input_event_aura.h"
#include "content/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
-#include "content/browser/web_contents/touch_editable_impl_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_observer.h"
@@ -63,6 +63,7 @@
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
+#include "ui/touch_selection/touch_selection_controller.h"
#include "ui/wm/public/drag_drop_client.h"
#include "ui/wm/public/drag_drop_delegate.h"
@@ -530,8 +531,12 @@ class WebContentsViewAura::WindowObserver
const gfx::Rect& new_bounds) override {
if (window == host_window_ || window == view_->window_) {
SendScreenRects();
- if (view_->touch_editable_)
- view_->touch_editable_->UpdateEditingController();
+ if (old_bounds.origin() != new_bounds.origin()) {
+ TouchSelectionControllerClientAura* selection_controller_client =
+ view_->GetSelectionControllerClient();
+ if (selection_controller_client)
+ selection_controller_client->OnWindowMoved();
+ }
#if defined(OS_WIN)
} else {
UpdateConstrainedWindows(NULL);
@@ -649,7 +654,6 @@ WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
current_overscroll_gesture_(OVERSCROLL_NONE),
completed_overscroll_gesture_(OVERSCROLL_NONE),
navigation_overlay_(nullptr),
- touch_editable_(TouchEditableImplAura::Create()),
is_or_was_visible_(false) {
}
@@ -668,12 +672,6 @@ WebContentsViewAura::~WebContentsViewAura() {
window_.reset();
}
-void WebContentsViewAura::SetTouchEditableForTest(
- TouchEditableImplAura* touch_editable) {
- touch_editable_.reset(touch_editable);
- AttachTouchEditableToRenderView();
-}
-
void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
if (web_contents_->GetInterstitialPage())
web_contents_->GetInterstitialPage()->SetSize(size);
@@ -723,16 +721,9 @@ void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
if (!web_contents_->GetRenderWidgetHostView())
return;
navigation_overlay_->relay_delegate()->OnOverscrollComplete(mode);
- if (touch_editable_)
- touch_editable_->OverscrollCompleted();
-}
-
-void WebContentsViewAura::AttachTouchEditableToRenderView() {
- if (!touch_editable_)
- return;
- RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
- web_contents_->GetRenderWidgetHostView());
- touch_editable_->AttachToView(rwhva);
+ ui::TouchSelectionController* selection_controller = GetSelectionController();
+ if (selection_controller)
+ selection_controller->HideAndDisallowShowingAutomatically();
}
void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
@@ -741,6 +732,20 @@ void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
}
+ui::TouchSelectionController* WebContentsViewAura::GetSelectionController()
+ const {
+ RenderWidgetHostViewAura* view =
+ ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
+ return view ? view->selection_controller() : nullptr;
+}
+
+TouchSelectionControllerClientAura*
+WebContentsViewAura::GetSelectionControllerClient() const {
+ RenderWidgetHostViewAura* view =
+ ToRenderWidgetHostViewAura(web_contents_->GetRenderWidgetHostView());
+ return view ? view->selection_controller_client() : nullptr;
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, WebContentsView implementation:
@@ -898,7 +903,6 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
InstallOverscrollControllerDelegate(view);
}
- AttachTouchEditableToRenderView();
return view;
}
@@ -915,7 +919,6 @@ void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
}
void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
- AttachTouchEditableToRenderView();
}
void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
@@ -940,9 +943,9 @@ void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
const ContextMenuParams& params) {
- if (touch_editable_) {
- touch_editable_->EndTouchEditing(false);
- }
+ ui::TouchSelectionController* selection_controller = GetSelectionController();
+ if (selection_controller)
+ selection_controller->HideAndDisallowShowingAutomatically();
if (delegate_) {
RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
web_contents_->GetRenderWidgetHostView());
@@ -966,9 +969,9 @@ void WebContentsViewAura::StartDragging(
return;
}
- if (touch_editable_)
- touch_editable_->EndTouchEditing(false);
-
+ ui::TouchSelectionController* selection_controller = GetSelectionController();
+ if (selection_controller)
+ selection_controller->HideAndDisallowShowingAutomatically();
ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
PrepareDragData(drop_data, provider, web_contents_);
@@ -1080,13 +1083,6 @@ void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
OverscrollUpdateForWebContentsDelegate(0);
- if (touch_editable_) {
- if (new_mode == OVERSCROLL_NONE)
- touch_editable_->OverscrollCompleted();
- else
- touch_editable_->OverscrollStarted();
- }
-
current_overscroll_gesture_ = new_mode;
navigation_overlay_->relay_delegate()->OnOverscrollModeChange(old_mode,
new_mode);
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index 4516181..0d84b5a 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -24,6 +24,7 @@ class Window;
namespace ui {
class DropTargetEvent;
+class TouchSelectionController;
}
namespace content {
@@ -32,7 +33,7 @@ class OverscrollNavigationOverlay;
class RenderWidgetHostImpl;
class RenderWidgetHostViewAura;
class ShadowLayerDelegate;
-class TouchEditableImplAura;
+class TouchSelectionControllerClientAura;
class WebContentsViewDelegate;
class WebContentsImpl;
class WebDragDestDelegate;
@@ -48,9 +49,6 @@ class WebContentsViewAura
WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate);
- CONTENT_EXPORT void SetTouchEditableForTest(
- TouchEditableImplAura* touch_editable);
-
private:
class WindowObserver;
@@ -71,10 +69,11 @@ class WebContentsViewAura
// animates in, or the content window animates out).
void CompleteOverscrollNavigation(OverscrollMode mode);
- void AttachTouchEditableToRenderView();
-
void OverscrollUpdateForWebContentsDelegate(float delta_y);
+ ui::TouchSelectionController* GetSelectionController() const;
+ TouchSelectionControllerClientAura* GetSelectionControllerClient() const;
+
// Overridden from WebContentsView:
gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override;
@@ -194,7 +193,6 @@ class WebContentsViewAura
// navigation triggered by the overscroll gesture.
scoped_ptr<OverscrollNavigationOverlay> navigation_overlay_;
- scoped_ptr<TouchEditableImplAura> touch_editable_;
scoped_ptr<GestureNavSimple> gesture_nav_simple_;
// On Windows we can run into problems if resources get released within the
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 4a75f4f..2eb04a4 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -59,7 +59,6 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::enableOrientationEvent(true);
WebRuntimeFeatures::enableFastMobileScrolling(true);
WebRuntimeFeatures::enableMediaCapture(true);
- WebRuntimeFeatures::enableCompositedSelectionUpdate(true);
// Android won't be able to reliably support non-persistent notifications, the
// intended behavior for which is in flux by itself.
WebRuntimeFeatures::enableNotificationConstructor(false);
@@ -67,6 +66,10 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::enableNavigatorContentUtils(true);
#endif // defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(USE_AURA)
+ WebRuntimeFeatures::enableCompositedSelectionUpdate(true);
+#endif
+
#if !(defined OS_ANDROID || defined OS_CHROMEOS || defined OS_IOS)
// Only Android, ChromeOS, and IOS support NetInfo right now.
WebRuntimeFeatures::enableNetworkInformation(false);
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 1d9cf9a..0c23b4f 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1208,6 +1208,8 @@
'browser/renderer_host/input/touch_emulator_client.h',
'browser/renderer_host/input/touch_event_queue.cc',
'browser/renderer_host/input/touch_event_queue.h',
+ 'browser/renderer_host/input/touch_selection_controller_client_aura.cc',
+ 'browser/renderer_host/input/touch_selection_controller_client_aura.h',
'browser/renderer_host/input/touchpad_tap_suppression_controller.cc',
'browser/renderer_host/input/touchpad_tap_suppression_controller.h',
'browser/renderer_host/input/touchscreen_tap_suppression_controller.cc',
@@ -1521,8 +1523,6 @@
'browser/web_contents/aura/overscroll_window_delegate.h',
'browser/web_contents/aura/shadow_layer_delegate.cc',
'browser/web_contents/aura/shadow_layer_delegate.h',
- 'browser/web_contents/touch_editable_impl_aura.cc',
- 'browser/web_contents/touch_editable_impl_aura.h',
'browser/web_contents/web_contents_android.cc',
'browser/web_contents/web_contents_android.h',
'browser/web_contents/web_contents_impl.cc',
@@ -2063,10 +2063,10 @@
],
}, {
'sources/': [
+ ['exclude', '^browser/renderer_host/input/touch_selection_controller_client_aura.cc'],
+ ['exclude', '^browser/renderer_host/input/touch_selection_controller_client_aura.h'],
['exclude', '^browser/renderer_host/render_widget_host_view_aura.cc'],
['exclude', '^browser/renderer_host/render_widget_host_view_aura.h'],
- ['exclude', '^browser/web_contents/touch_editable_impl_aura.cc'],
- ['exclude', '^browser/web_contents/touch_editable_impl_aura.h'],
['exclude', '^browser/renderer_host/ui_events_helper.cc'],
['exclude', '^browser/renderer_host/ui_events_helper.h'],
],
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index ed1a156..9095f33 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -232,6 +232,7 @@
'browser/net_info_browsertest.cc',
'browser/renderer_host/input/touch_action_browsertest.cc',
'browser/renderer_host/input/touch_input_browsertest.cc',
+ 'browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc',
'browser/renderer_host/render_message_filter_browsertest.cc',
'browser/renderer_host/render_process_host_browsertest.cc',
'browser/renderer_host/render_view_host_browsertest.cc',
@@ -246,7 +247,6 @@
'browser/tracing/background_tracing_manager_browsertest.cc',
'browser/tracing/tracing_controller_browsertest.cc',
'browser/web_contents/opened_by_dom_browsertest.cc',
- 'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
'browser/web_contents/web_contents_impl_browsertest.cc',
'browser/web_contents/web_contents_view_aura_browsertest.cc',
'browser/webkit_browsertest.cc',
@@ -1441,11 +1441,6 @@
],
'sources': [ '<@(content_browsertests_sources)' ],
'conditions': [
- ['chromeos==0', {
- 'sources!': [
- 'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
- ],
- }],
['OS=="win"', {
'resource_include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/webkit',
@@ -1521,6 +1516,15 @@
'browser/compositor/image_transport_factory_browsertest.cc',
],
}],
+ ['use_aura==1', {
+ 'dependencies': [
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection',
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_test_support',
+ ]}, {
+ 'sources!': [
+ 'browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc',
+ ],
+ }],
['enable_webrtc==1', {
'sources': [ '<@(content_browsertests_webrtc_sources)' ],
'dependencies': [
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index d38cdc1..73aa11e 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -2006,10 +2006,20 @@ void RenderWidget::UpdateSelectionBounds() {
if (handling_ime_event_)
return;
+#if defined(USE_AURA)
+ // TODO(mohsen): For now, always send explicit selection IPC notifications for
+ // Aura beucause composited selection updates are not working for webview tags
+ // which regresses IME inside webview. Remove this when composited selection
+ // updates are fixed for webviews. See, http://crbug.com/510568.
+ bool send_ipc = true;
+#else
// With composited selection updates, the selection bounds will be reported
// directly by the compositor, in which case explicit IPC selection
// notifications should be suppressed.
- if (!blink::WebRuntimeFeatures::isCompositedSelectionUpdateEnabled()) {
+ bool send_ipc =
+ !blink::WebRuntimeFeatures::isCompositedSelectionUpdateEnabled();
+#endif
+ if (send_ipc) {
ViewHostMsg_SelectionBounds_Params params;
GetSelectionBounds(&params.anchor_rect, &params.focus_rect);
if (selection_anchor_rect_ != params.anchor_rect ||
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 07ee03f..d17a7dc 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -374,11 +374,6 @@ if (!is_mac) {
"//third_party/mesa:osmesa",
]
- if (!is_chromeos) {
- sources -=
- [ "../browser/web_contents/touch_editable_impl_aura_browsertest.cc" ]
- }
-
if (is_win) {
sources += rebase_path(
content_tests_gypi_values.content_browsertests_win_sources,
@@ -464,9 +459,16 @@ if (!is_mac) {
"//content")
}
- if (!use_aura) {
- sources -=
- [ "../browser/web_contents/web_contents_view_aura_browsertest.cc" ]
+ if (use_aura) {
+ deps += [
+ "//ui/touch_selection:test_support",
+ "//ui/touch_selection:touch_selection",
+ ]
+ } else {
+ sources -= [
+ "../browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc",
+ "../browser/web_contents/web_contents_view_aura_browsertest.cc",
+ ]
}
}
}
diff --git a/content/test/data/touch_selection.html b/content/test/data/touch_selection.html
index 89d76831..7bf8644 100644
--- a/content/test/data/touch_selection.html
+++ b/content/test/data/touch_selection.html
@@ -3,33 +3,27 @@
<input id='textfield' type="text" value="Text in a textfield">
<script>
-function select_all_text() {
- var div = document.getElementById("textDiv");
- var range = document.createRange();
- range.selectNodeContents(div);
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(range);
-}
-
-function get_selection() {
- return (window.getSelection() + "");
-}
-
function focus_textfield() {
document.getElementById("textfield").focus();
// Focusing the textfiled selects its text. Collapse selection to a cursor.
window.getSelection().collapseToStart();
}
-function get_cursor_position() {
- var div = document.getElementById("textfield");
- var start = div.selectionStart;
- var end = div.selectionEnd;
- if (start == end)
- return start;
- else
- return -1;
+function get_point_inside(element) {
+ var rect = element.getBoundingClientRect();
+ var point = {
+ x: rect.left + 8,
+ y: (rect.top + rect.bottom) / 2
+ };
+ window.domAutomationController.send(JSON.stringify(point));
+}
+
+function get_point_inside_text() {
+ get_point_inside(document.getElementById('textDiv'));
+}
+
+function get_point_inside_textfield() {
+ get_point_inside(document.getElementById('textfield'));
}
</script>
diff --git a/ui/touch_selection/BUILD.gn b/ui/touch_selection/BUILD.gn
index 3f98ea0..f5f2825 100644
--- a/ui/touch_selection/BUILD.gn
+++ b/ui/touch_selection/BUILD.gn
@@ -53,6 +53,19 @@ component("touch_selection") {
}
}
+static_library("test_support") {
+ testonly = true
+
+ sources = [
+ "touch_selection_controller_test_api.cc",
+ "touch_selection_controller_test_api.h",
+ ]
+
+ deps = [
+ ":touch_selection",
+ ]
+}
+
# TODO(GYP): Delete this after we've converted everything to GN.
# The _run targets exist only for compatibility w/ GYP.
group("ui_touch_selection_unittests_run") {
@@ -70,6 +83,7 @@ test("ui_touch_selection_unittests") {
]
deps = [
+ ":test_support",
":touch_selection",
"//base/test:run_all_unittests",
"//testing/gmock:gmock",
diff --git a/ui/touch_selection/touch_selection_controller_test_api.cc b/ui/touch_selection/touch_selection_controller_test_api.cc
new file mode 100644
index 0000000..abe89de
--- /dev/null
+++ b/ui/touch_selection/touch_selection_controller_test_api.cc
@@ -0,0 +1,23 @@
+// 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_test_api.h"
+
+namespace ui {
+
+TouchSelectionControllerTestApi::TouchSelectionControllerTestApi(
+ TouchSelectionController* controller)
+ : controller_(controller) {}
+
+TouchSelectionControllerTestApi::~TouchSelectionControllerTestApi() {}
+
+bool TouchSelectionControllerTestApi::GetStartVisible() const {
+ return controller_->GetStartVisible();
+}
+
+bool TouchSelectionControllerTestApi::GetEndVisible() const {
+ return controller_->GetEndVisible();
+}
+
+} // namespace ui
diff --git a/ui/touch_selection/touch_selection_controller_test_api.h b/ui/touch_selection/touch_selection_controller_test_api.h
new file mode 100644
index 0000000..b55b2628
--- /dev/null
+++ b/ui/touch_selection/touch_selection_controller_test_api.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_TEST_API_H_
+#define UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_TEST_API_H_
+
+#include "ui/touch_selection/touch_selection_controller.h"
+
+namespace ui {
+
+// Test api class to access internals of |ui::TouchSelectionController| in
+// tests.
+class TouchSelectionControllerTestApi {
+ public:
+ explicit TouchSelectionControllerTestApi(
+ TouchSelectionController* controller);
+ ~TouchSelectionControllerTestApi();
+
+ bool GetStartVisible() const;
+ bool GetEndVisible() const;
+
+ bool temporarily_hidden() const { return controller_->temporarily_hidden_; }
+
+ private:
+ TouchSelectionController* const controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerTestApi);
+};
+
+} // namespace ui
+
+#endif // UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_TEST_API_H_
diff --git a/ui/touch_selection/touch_selection_controller_unittest.cc b/ui/touch_selection/touch_selection_controller_unittest.cc
index adb09c7..b0f0576 100644
--- a/ui/touch_selection/touch_selection_controller_unittest.cc
+++ b/ui/touch_selection/touch_selection_controller_unittest.cc
@@ -9,6 +9,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/test/motion_event_test_utils.h"
+#include "ui/touch_selection/touch_selection_controller_test_api.h"
using testing::ElementsAre;
using testing::IsEmpty;
@@ -43,21 +44,6 @@ class MockTouchHandleDrawable : public TouchHandleDrawable {
} // namespace
-class TouchSelectionControllerTestApi {
- public:
- explicit TouchSelectionControllerTestApi(TouchSelectionController* controller)
- : controller_(controller) {}
- ~TouchSelectionControllerTestApi() {}
-
- bool GetStartVisible() const { return controller_->GetStartVisible(); }
- bool GetEndVisible() const { return controller_->GetEndVisible(); }
-
- private:
- TouchSelectionController* controller_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerTestApi);
-};
-
class TouchSelectionControllerTest : public testing::Test,
public TouchSelectionControllerClient {
public:
diff --git a/ui/touch_selection/ui_touch_selection.gyp b/ui/touch_selection/ui_touch_selection.gyp
index 6289bd0..76308e592 100644
--- a/ui/touch_selection/ui_touch_selection.gyp
+++ b/ui/touch_selection/ui_touch_selection.gyp
@@ -63,6 +63,17 @@
],
},
{
+ 'target_name': 'ui_touch_selection_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'ui_touch_selection',
+ ],
+ 'sources': [
+ 'touch_selection_controller_test_api.cc',
+ 'touch_selection_controller_test_api.h',
+ ],
+ },
+ {
'target_name': 'ui_touch_selection_unittests',
'type': '<(gtest_target_type)',
'dependencies': [
@@ -76,6 +87,7 @@
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_test_support',
'ui_touch_selection',
+ 'ui_touch_selection_test_support',
],
'sources': [
'longpress_drag_selector_unittest.cc',