blob: 420fd4f5636fd0e5c855e67ebb460ab597c51c76 [file] [log] [blame]
// Copyright 2017 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_child_frame.h"
#include "base/logging.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_child_frame.h"
#include "content/common/widget_messages.h"
#include "content/public/browser/touch_selection_controller_client_manager.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/strings/grit/ui_strings.h"
namespace content {
TouchSelectionControllerClientChildFrame::
TouchSelectionControllerClientChildFrame(
RenderWidgetHostViewChildFrame* rwhv,
TouchSelectionControllerClientManager* manager)
: rwhv_(rwhv), manager_(manager) {
DCHECK(rwhv);
DCHECK(manager_);
}
TouchSelectionControllerClientChildFrame::
~TouchSelectionControllerClientChildFrame() {
// If the manager doesn't outlive us, our owning view sill detach us.
manager_->InvalidateClient(this);
}
void TouchSelectionControllerClientChildFrame::DidStopFlinging() {
manager_->DidStopFlinging();
}
void TouchSelectionControllerClientChildFrame::
TransformSelectionBoundsAndUpdate() {
gfx::SelectionBound transformed_selection_start(selection_start_);
gfx::SelectionBound transformed_selection_end(selection_end_);
// TODO(wjmaclean): Get the transform between the views to lower the
// overhead here, instead of calling the transform functions four times.
transformed_selection_start.SetEdge(
rwhv_->TransformPointToRootCoordSpaceF(selection_start_.edge_top()),
rwhv_->TransformPointToRootCoordSpaceF(selection_start_.edge_bottom()));
transformed_selection_end.SetEdge(
rwhv_->TransformPointToRootCoordSpaceF(selection_end_.edge_top()),
rwhv_->TransformPointToRootCoordSpaceF(selection_end_.edge_bottom()));
manager_->UpdateClientSelectionBounds(transformed_selection_start,
transformed_selection_end, this, this);
}
void TouchSelectionControllerClientChildFrame::UpdateSelectionBoundsIfNeeded(
const viz::Selection<gfx::SelectionBound>& selection,
float device_scale_factor) {
if (selection.start != selection_start_ || selection.end != selection_end_) {
selection_start_ = selection.start;
selection_end_ = selection.end;
TransformSelectionBoundsAndUpdate();
}
}
// Since an active touch selection in a child frame can have its screen position
// changed by a scroll in a containing frame (and thus without the child frame
// sending a new compositor frame), we must manually recompute the screen
// position if requested to do so and it has changed.
void TouchSelectionControllerClientChildFrame::DidScroll() {
TransformSelectionBoundsAndUpdate();
}
gfx::Point TouchSelectionControllerClientChildFrame::ConvertFromRoot(
const gfx::PointF& point_f) const {
gfx::PointF transformed_point(point_f);
RenderWidgetHostViewBase* root_view = rwhv_->GetRootRenderWidgetHostView();
if (root_view) {
root_view->TransformPointToCoordSpaceForView(point_f, rwhv_,
&transformed_point);
}
return gfx::ToRoundedPoint(transformed_point);
}
bool TouchSelectionControllerClientChildFrame::SupportsAnimation() const {
NOTREACHED();
return false;
}
void TouchSelectionControllerClientChildFrame::SetNeedsAnimate() {
NOTREACHED();
}
void TouchSelectionControllerClientChildFrame::MoveCaret(
const gfx::PointF& position) {
RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
if (host_delegate)
host_delegate->MoveCaret(ConvertFromRoot(position));
}
void TouchSelectionControllerClientChildFrame::MoveRangeSelectionExtent(
const gfx::PointF& extent) {
RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
if (host_delegate)
host_delegate->MoveRangeSelectionExtent(ConvertFromRoot(extent));
}
void TouchSelectionControllerClientChildFrame::SelectBetweenCoordinates(
const gfx::PointF& base,
const gfx::PointF& extent) {
RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
if (host_delegate) {
host_delegate->SelectRange(ConvertFromRoot(base), ConvertFromRoot(extent));
}
}
void TouchSelectionControllerClientChildFrame::OnSelectionEvent(
ui::SelectionEventType event) {
NOTREACHED();
}
void TouchSelectionControllerClientChildFrame::OnDragUpdate(
const gfx::PointF& position) {
NOTREACHED();
}
std::unique_ptr<ui::TouchHandleDrawable>
TouchSelectionControllerClientChildFrame::CreateDrawable() {
NOTREACHED();
return std::unique_ptr<ui::TouchHandleDrawable>();
}
bool TouchSelectionControllerClientChildFrame::IsCommandIdEnabled(
int command_id) const {
bool editable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
bool readable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
bool has_selection = !rwhv_->GetSelectedText().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 TouchSelectionControllerClientChildFrame::ExecuteCommand(int command_id,
int event_flags) {
manager_->GetTouchSelectionController()
->HideAndDisallowShowingAutomatically();
RenderWidgetHostDelegate* host_delegate = rwhv_->host()->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 TouchSelectionControllerClientChildFrame::RunContextMenu() {
gfx::RectF anchor_rect =
manager_->GetTouchSelectionController()->GetRectBetweenBounds();
gfx::PointF anchor_point =
gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
gfx::PointF origin = rwhv_->TransformPointToRootCoordSpaceF(gfx::PointF());
anchor_point.Offset(-origin.x(), -origin.y());
RenderWidgetHostImpl* host = rwhv_->host();
host->Send(new WidgetMsg_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.
manager_->GetTouchSelectionController()
->HideAndDisallowShowingAutomatically();
}
bool TouchSelectionControllerClientChildFrame::ShouldShowQuickMenu() {
NOTREACHED();
return false;
}
base::string16 TouchSelectionControllerClientChildFrame::GetSelectedText() {
NOTREACHED();
return base::string16();
}
} // namespace content