0

[Blink] Expose selection region bounding box to Browser

This CL adds an extra parameter to SelectionBoundsChanged() to expose
the bounds of the rectangle which encloses the selection region, i.e.
bounding box, to the browser side.

The bounding box's value should be same with the result from
Window.getSelection().

This CL is a part of the efforts to polish the multipaste's HTML preview
with knowledge of bounding box.

No visual difference should be introduced.

Bug: 1165302
Change-Id: I33dfad2b93a9580e1937b203da6d3a1874141d03
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2791842
Reviewed-by: Tommy Li <tommycli@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#868540}
This commit is contained in:
Andrew Xu
2021-04-01 15:57:40 +00:00
committed by Chromium LUCI CQ
parent 601cc26c0d
commit 4725d23b1d
13 changed files with 44 additions and 11 deletions

@ -191,6 +191,7 @@ class WebViewPlugin : public blink::WebPlugin, public blink::WebViewObserver {
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) override {}
void CreateFrameSink(
mojo::PendingReceiver<viz::mojom::CompositorFrameSink>

@ -2145,6 +2145,7 @@ void RenderWidgetHostImpl::SelectionBoundsChanged(
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) {
if (view_)
view_->SelectionBoundsChanged(anchor_rect, anchor_dir, focus_rect,

@ -301,6 +301,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) override;
void CreateFrameSink(
mojo::PendingReceiver<viz::mojom::CompositorFrameSink>

@ -60,6 +60,7 @@ void FakeRenderWidgetHost::SelectionBoundsChanged(
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) {}
void FakeRenderWidgetHost::CreateFrameSink(

@ -61,6 +61,7 @@ class FakeRenderWidgetHost : public blink::mojom::FrameWidgetHost,
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) override;
void CreateFrameSink(
mojo::PendingReceiver<viz::mojom::CompositorFrameSink>

@ -254,6 +254,7 @@ interface WidgetHost {
mojo_base.mojom.TextDirection anchor_dir,
gfx.mojom.Rect focus_rect,
mojo_base.mojom.TextDirection focus_dir,
gfx.mojom.Rect bounding_box_rect,
bool is_anchor_first);
// Create a CompositorFrameSink that is associated with this widget.

@ -869,6 +869,7 @@ void TestWebFrameWidgetHost::SelectionBoundsChanged(
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) {}
void TestWebFrameWidgetHost::CreateFrameSink(

@ -195,6 +195,7 @@ class TestWebFrameWidgetHost : public mojom::blink::WidgetHost,
base::i18n::TextDirection anchor_dir,
const gfx::Rect& focus_rect,
base::i18n::TextDirection focus_dir,
const gfx::Rect& bounding_box,
bool is_anchor_first) override;
void CreateFrameSink(
mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSink>

@ -61,6 +61,7 @@
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
@ -3013,6 +3014,7 @@ void WebFrameWidgetImpl::ResetVirtualKeyboardVisibilityRequest() {
bool WebFrameWidgetImpl::GetSelectionBoundsInWindow(
gfx::Rect* focus,
gfx::Rect* anchor,
gfx::Rect* bounding_box,
base::i18n::TextDirection* focus_dir,
base::i18n::TextDirection* anchor_dir,
bool* is_anchor_first) {
@ -3031,17 +3033,22 @@ bool WebFrameWidgetImpl::GetSelectionBoundsInWindow(
}
gfx::Rect focus_root_frame;
gfx::Rect anchor_root_frame;
CalculateSelectionBounds(focus_root_frame, anchor_root_frame);
gfx::Rect bounding_box_root_frame;
CalculateSelectionBounds(focus_root_frame, anchor_root_frame,
&bounding_box_root_frame);
gfx::Rect focus_rect_in_dips =
widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(focus_root_frame));
gfx::Rect anchor_rect_in_dips =
widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(anchor_root_frame));
gfx::Rect bounding_box_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
gfx::Rect(bounding_box_root_frame));
// if the bounds are the same return false.
if (focus_rect_in_dips == *focus && anchor_rect_in_dips == *anchor)
return false;
*focus = focus_rect_in_dips;
*anchor = anchor_rect_in_dips;
*bounding_box = bounding_box_in_dips;
WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
if (!focused_frame)
@ -3606,15 +3613,18 @@ void WebFrameWidgetImpl::ForEachRemoteFrameControlledByWidget(
callback);
}
void WebFrameWidgetImpl::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
gfx::Rect& focus_root_frame) {
void WebFrameWidgetImpl::CalculateSelectionBounds(
gfx::Rect& anchor_root_frame,
gfx::Rect& focus_root_frame,
gfx::Rect* bounding_box_in_root_frame) {
const LocalFrame* local_frame = FocusedLocalFrameInWidget();
if (!local_frame)
return;
IntRect anchor;
IntRect focus;
if (!local_frame->Selection().ComputeAbsoluteBounds(anchor, focus))
auto& selection = local_frame->Selection();
if (!selection.ComputeAbsoluteBounds(anchor, focus))
return;
// Apply the visual viewport for main frames this will apply the page scale.
@ -3625,6 +3635,15 @@ void WebFrameWidgetImpl::CalculateSelectionBounds(gfx::Rect& anchor_root_frame,
local_frame->View()->ConvertToRootFrame(anchor));
focus_root_frame = visual_viewport.RootFrameToViewport(
local_frame->View()->ConvertToRootFrame(focus));
// Calculate the bounding box of the selection area.
if (bounding_box_in_root_frame) {
const IntRect bounding_box = EnclosingIntRect(
CreateRange(selection.GetSelectionInDOMTree().ComputeRange())
->BoundingRect());
*bounding_box_in_root_frame = visual_viewport.RootFrameToViewport(
local_frame->View()->ConvertToRootFrame(bounding_box));
}
}
void WebFrameWidgetImpl::BatterySavingsChanged(BatterySavingsFlags savings) {

@ -229,6 +229,7 @@ class CORE_EXPORT WebFrameWidgetImpl
void ResetVirtualKeyboardVisibilityRequest() override;
bool GetSelectionBoundsInWindow(gfx::Rect* focus,
gfx::Rect* anchor,
gfx::Rect* bounding_box,
base::i18n::TextDirection* focus_dir,
base::i18n::TextDirection* anchor_dir,
bool* is_anchor_first) override;
@ -538,8 +539,10 @@ class CORE_EXPORT WebFrameWidgetImpl
// Calculates the selection bounds in the root frame. Returns bounds unchanged
// when there is no focused frame or no selection.
void CalculateSelectionBounds(gfx::Rect& anchor_in_root_frame,
gfx::Rect& focus_in_root_frame);
void CalculateSelectionBounds(
gfx::Rect& anchor_in_root_frame,
gfx::Rect& focus_in_root_frame,
gfx::Rect* bounding_box_in_root_frame = nullptr);
// Returns if auto resize mode is enabled.
bool AutoResizeMode();

@ -162,6 +162,7 @@ class PLATFORM_EXPORT FrameWidget {
// bounds returned were different than the passed in focus and anchor bounds.
virtual bool GetSelectionBoundsInWindow(gfx::Rect* focus,
gfx::Rect* anchor,
gfx::Rect* bounding_box,
base::i18n::TextDirection* focus_dir,
base::i18n::TextDirection* anchor_dir,
bool* is_anchor_first) = 0;

@ -1150,11 +1150,12 @@ void WidgetBase::UpdateSelectionBounds() {
if (!frame_widget)
return;
if (frame_widget->GetSelectionBoundsInWindow(
&selection_focus_rect_, &selection_anchor_rect_, &focus_dir,
&anchor_dir, &is_anchor_first)) {
widget_host_->SelectionBoundsChanged(selection_anchor_rect_, anchor_dir,
selection_focus_rect_, focus_dir,
is_anchor_first);
&selection_focus_rect_, &selection_anchor_rect_,
&selection_bounding_box_, &focus_dir, &anchor_dir,
&is_anchor_first)) {
widget_host_->SelectionBoundsChanged(
selection_anchor_rect_, anchor_dir, selection_focus_rect_, focus_dir,
selection_bounding_box_, is_anchor_first);
}
}
UpdateCompositionInfo(false /* not an immediate request */);

@ -396,6 +396,7 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
// Stores the current selection bounds.
gfx::Rect selection_focus_rect_;
gfx::Rect selection_anchor_rect_;
gfx::Rect selection_bounding_box_;
// Stores the current composition character bounds.
Vector<gfx::Rect> composition_character_bounds_;