Index: content/browser/web_contents/aura/touch_selection_controller_client_aura.cc |
diff --git a/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc b/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..23457d34be403137ae729218a930de3ca7384798 |
--- /dev/null |
+++ b/content/browser/web_contents/aura/touch_selection_controller_client_aura.cc |
@@ -0,0 +1,325 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/web_contents/aura/touch_selection_controller_client_aura.h" |
+ |
+#include "content/browser/renderer_host/render_widget_host_impl.h" |
+#include "content/browser/renderer_host/render_widget_host_view_aura.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
+#include "content/common/view_messages.h" |
+#include "content/public/browser/render_view_host.h" |
+#include "ui/aura/client/cursor_client.h" |
+#include "ui/aura/client/screen_position_client.h" |
+#include "ui/aura/env.h" |
+#include "ui/aura/window.h" |
+#include "ui/base/clipboard/clipboard.h" |
+#include "ui/gfx/geometry/point_conversions.h" |
+#include "ui/gfx/geometry/size_conversions.h" |
+#include "ui/strings/grit/ui_strings.h" |
+#include "ui/touch_selection/touch_handle_drawable_aura.h" |
+#include "ui/touch_selection/touch_selection_menu_runner.h" |
+ |
+namespace content { |
+namespace { |
+ |
+// Delay before showing the quick menu, in milliseconds. |
+const int kQuickMenuDelayInMs = 100; |
+ |
+gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::RectF& rect) { |
+ gfx::Point origin = gfx::ToRoundedPoint(rect.origin()); |
+ gfx::Point bottom_right = gfx::ToRoundedPoint(rect.bottom_right()); |
+ |
+ aura::Window* root_window = window->GetRootWindow(); |
+ if (root_window) { |
+ aura::client::ScreenPositionClient* screen_position_client = |
+ aura::client::GetScreenPositionClient(root_window); |
+ if (screen_position_client) { |
+ screen_position_client->ConvertPointToScreen(window, &origin); |
+ screen_position_client->ConvertPointToScreen(window, &bottom_right); |
+ } |
+ } |
+ return gfx::Rect(origin.x(), origin.y(), bottom_right.x() - origin.x(), |
+ bottom_right.y() - origin.y()); |
+} |
+ |
+} // namespace |
+ |
+class TouchSelectionControllerClientAura::EnvPreTargetHandler |
+ : public ui::EventHandler { |
sadrul
2015/04/29 19:55:03
Consider using a UserActivityObserver instead.
mohsen
2015/04/30 18:29:34
Apparently, UserActivityObserver mechanism is not
|
+ public: |
+ EnvPreTargetHandler(ui::TouchSelectionController* selection_controller, |
+ aura::Window* window); |
+ ~EnvPreTargetHandler() override; |
+ |
+ private: |
+ // EventHandler: |
+ void OnKeyEvent(ui::KeyEvent* event) override; |
+ void OnMouseEvent(ui::MouseEvent* event) override; |
+ void OnScrollEvent(ui::ScrollEvent* event) override; |
+ |
+ ui::TouchSelectionController* selection_controller_; |
+ aura::Window* window_; |
sadrul
2015/04/29 19:55:03
DISALLOW_COPY_AND_ASSIGN
mohsen
2015/04/30 18:29:34
Done.
|
+}; |
+ |
+TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler( |
+ ui::TouchSelectionController* selection_controller, |
+ aura::Window* window) |
+ : selection_controller_(selection_controller), window_(window) { |
+ aura::Env::GetInstance()->AddPreTargetHandler(this); |
+} |
+ |
+TouchSelectionControllerClientAura::EnvPreTargetHandler:: |
+ ~EnvPreTargetHandler() { |
+ aura::Env::GetInstance()->RemovePreTargetHandler(this); |
+} |
+ |
+void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent( |
+ ui::KeyEvent* event) { |
+ DCHECK(selection_controller_->is_insertion_active() || |
+ selection_controller_->is_selection_active()); |
+ |
+ selection_controller_->HideAndDisallowShowingAutomatically(); |
+} |
+ |
+void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent( |
+ ui::MouseEvent* event) { |
+ DCHECK(selection_controller_->is_insertion_active() || |
+ selection_controller_->is_selection_active()); |
+ |
+ aura::client::CursorClient* cursor_client = |
+ aura::client::GetCursorClient(window_->GetRootWindow()); |
+ if (!cursor_client || cursor_client->IsMouseEventsEnabled()) |
+ selection_controller_->HideAndDisallowShowingAutomatically(); |
+} |
+ |
+void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent( |
+ ui::ScrollEvent* event) { |
+ DCHECK(selection_controller_->is_insertion_active() || |
+ selection_controller_->is_selection_active()); |
+ |
+ selection_controller_->HideAndDisallowShowingAutomatically(); |
+} |
+ |
+TouchSelectionControllerClientAura::TouchSelectionControllerClientAura( |
+ RenderWidgetHostViewAura* rwhva) |
+ : rwhva_(rwhva), |
+ quick_menu_timer_( |
+ FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs), |
+ base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu, |
+ base::Unretained(this)), |
+ false), |
+ scroll_in_progress_(false), |
+ handle_drag_in_progress_(false) { |
+} |
+ |
+TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() { |
+} |
+ |
+bool TouchSelectionControllerClientAura::SupportsAnimation() const { |
+ return false; |
+} |
+ |
+void TouchSelectionControllerClientAura::SetNeedsAnimate() { |
+ NOTREACHED(); |
+} |
+ |
+void TouchSelectionControllerClientAura::MoveCaret( |
+ const gfx::PointF& position) { |
+ RenderWidgetHostImpl* host = |
+ RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost()); |
+ host->MoveCaret(gfx::ToRoundedPoint(position)); |
+} |
+ |
+void TouchSelectionControllerClientAura::MoveRangeSelectionExtent( |
+ const gfx::PointF& extent) { |
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost()); |
+ WebContentsImpl* wc = |
+ static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh)); |
+ wc->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent)); |
+} |
+ |
+void TouchSelectionControllerClientAura::SelectBetweenCoordinates( |
+ const gfx::PointF& base, |
+ const gfx::PointF& extent) { |
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost()); |
+ WebContentsImpl* wc = |
+ static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh)); |
+ wc->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent)); |
+} |
+ |
+void TouchSelectionControllerClientAura::OnSelectionEvent( |
+ ui::SelectionEventType event) { |
+ switch (event) { |
+ case ui::SELECTION_SHOWN: |
+ case ui::INSERTION_SHOWN: |
+ UpdateQuickMenu(); |
+ env_pre_target_handler_.reset(new EnvPreTargetHandler( |
+ rwhva_->selection_controller(), rwhva_->GetNativeView())); |
+ break; |
+ case ui::SELECTION_CLEARED: |
+ case ui::INSERTION_CLEARED: |
+ env_pre_target_handler_.reset(); |
+ UpdateQuickMenu(); |
+ break; |
+ case ui::SELECTION_DRAG_STARTED: |
+ case ui::INSERTION_DRAG_STARTED: |
+ handle_drag_in_progress_ = true; |
+ UpdateQuickMenu(); |
+ break; |
+ case ui::SELECTION_DRAG_STOPPED: |
+ case ui::INSERTION_DRAG_STOPPED: |
+ handle_drag_in_progress_ = false; |
+ UpdateQuickMenu(); |
+ break; |
+ case ui::SELECTION_MOVED: |
+ case ui::INSERTION_MOVED: |
+ UpdateQuickMenu(); |
+ break; |
+ case ui::INSERTION_TAPPED: |
+ break; |
+ }; |
+} |
+ |
+scoped_ptr<ui::TouchHandleDrawable> |
+TouchSelectionControllerClientAura::CreateDrawable() { |
+ return scoped_ptr<ui::TouchHandleDrawable>( |
+ new ui::TouchHandleDrawableAura(rwhva_->GetNativeView())); |
+} |
+ |
+void TouchSelectionControllerClientAura::OnScrollStarted() { |
+ rwhva_->selection_controller()->SetTemporarilyHidden(true); |
+ scroll_in_progress_ = true; |
+ UpdateQuickMenu(); |
+} |
+ |
+void TouchSelectionControllerClientAura::OnScrollCompleted() { |
+ rwhva_->selection_controller()->SetTemporarilyHidden(false); |
+ scroll_in_progress_ = false; |
+ UpdateQuickMenu(); |
+} |
+ |
+bool TouchSelectionControllerClientAura::IsCommandIdEnabled( |
+ int command_id) const { |
+ bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE; |
+ bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD; |
+ gfx::Range selection_range; |
+ rwhva_->GetSelectionRange(&selection_range); |
+ bool has_selection = !selection_range.is_empty(); |
+ switch (command_id) { |
+ case IDS_APP_CUT: |
+ return editable && readable && has_selection; |
+ case IDS_APP_COPY: |
+ return readable && has_selection; |
+ case IDS_APP_PASTE: { |
+ base::string16 result; |
+ ui::Clipboard::GetForCurrentThread()->ReadText( |
+ ui::CLIPBOARD_TYPE_COPY_PASTE, &result); |
+ return editable && !result.empty(); |
+ } |
+ case IDS_APP_DELETE: |
+ return editable && has_selection; |
+ case IDS_APP_SELECT_ALL: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
+void TouchSelectionControllerClientAura::ExecuteCommand(int command_id, |
+ int event_flags) { |
+ rwhva_->selection_controller()->HideAndDisallowShowingAutomatically(); |
+ RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost()); |
+ WebContents* wc = WebContents::FromRenderViewHost(rvh); |
+ switch (command_id) { |
+ case IDS_APP_CUT: |
+ wc->Cut(); |
+ break; |
+ case IDS_APP_COPY: |
+ wc->Copy(); |
+ break; |
+ case IDS_APP_PASTE: |
+ wc->Paste(); |
+ break; |
+ case IDS_APP_DELETE: |
+ wc->Delete(); |
+ break; |
+ case IDS_APP_SELECT_ALL: |
+ wc->SelectAll(); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+void TouchSelectionControllerClientAura::OpenContextMenu() { |
+ rwhva_->selection_controller()->HideAndDisallowShowingAutomatically(); |
+ gfx::RectF anchor_rect = |
+ rwhva_->selection_controller()->GetRectBetweenBounds(); |
+ gfx::PointF anchor_point = |
+ gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y()); |
+ RenderWidgetHostImpl* host = |
+ RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost()); |
+ host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(), |
+ ui::MENU_SOURCE_TOUCH_EDIT_MENU, |
+ gfx::ToRoundedPoint(anchor_point))); |
+} |
+ |
+bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const { |
+ return !scroll_in_progress_ && !handle_drag_in_progress_; |
+} |
+ |
+void TouchSelectionControllerClientAura::ShowQuickMenu() { |
+ if (!ui::TouchSelectionMenuRunner::GetInstance()) |
+ return; |
+ |
+ gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds(); |
+ |
+ // Clip rect to client bounds. |
+ gfx::PointF origin = rect.origin(); |
+ gfx::PointF bottom_right = rect.bottom_right(); |
+ gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds(); |
+ origin.SetToMax(client_bounds.origin()); |
+ bottom_right.SetToMin(client_bounds.bottom_right()); |
+ if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y()) |
+ return; |
+ |
+ gfx::Vector2dF diagonal = bottom_right - origin; |
+ gfx::SizeF size(diagonal.x(), diagonal.y()); |
+ gfx::RectF anchor_rect(origin, size); |
+ |
+ // Calculate maximum handle image size; |
+ gfx::SizeF max_handle_size = |
+ rwhva_->selection_controller()->GetStartHandleRect().size(); |
+ max_handle_size.SetToMax( |
+ rwhva_->selection_controller()->GetEndHandleRect().size()); |
+ |
+ aura::Window* parent = rwhva_->GetNativeView(); |
+ ui::TouchSelectionMenuRunner::GetInstance()->RunMenu( |
+ this, ConvertRectToScreen(parent, anchor_rect), |
+ gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow()); |
+} |
+ |
+void TouchSelectionControllerClientAura::UpdateQuickMenu() { |
+ // Hide quick menu if there is any. |
+ if (ui::TouchSelectionMenuRunner::GetInstance() && |
+ ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()) { |
+ ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu(); |
+ } else { |
+ quick_menu_timer_.Stop(); |
+ } |
+ |
+ // Start timer to show quick menu if necessary. |
+ if (!rwhva_->selection_controller()->is_insertion_active() && |
+ !rwhva_->selection_controller()->is_selection_active()) |
+ return; |
+ |
+ if (!IsQuickMenuAllowed()) |
+ return; |
+ |
+ quick_menu_timer_.Reset(); |
+} |
+ |
+} // namespace content |