Commit b6276908 authored by Navid Zolghadr's avatar Navid Zolghadr Committed by Commit Bot

Add hit-test API for scroll begin on main thread

Refactor the current frame sink id hit test API and
reuse it to scroller target finding to be used in
compositor.
This will be used in the scroll targeting in
scroll unification project in the follow up CLs.
For more information look at:
https://docs.google.com/document/d/1smLAXs-DSLLmkEt4FIPP7PVglJXOcwRc7A5G0SEwxaY/edit#heading=h.hykhktoizkjj

Bug: 1047179
Change-Id: Ie7001e5342a99eff85dc078c65a958a4c65f1120
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2070383Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Navid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754976}
parent 5d9ef524
...@@ -256,24 +256,23 @@ RenderWidgetInputHandler::RenderWidgetInputHandler( ...@@ -256,24 +256,23 @@ RenderWidgetInputHandler::RenderWidgetInputHandler(
delegate->SetInputHandler(this); delegate->SetInputHandler(this);
} }
RenderWidgetInputHandler::~RenderWidgetInputHandler() {} RenderWidgetInputHandler::~RenderWidgetInputHandler() = default;
viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint( blink::WebHitTestResult RenderWidgetInputHandler::GetHitTestResultAtPoint(
const gfx::PointF& point, const gfx::PointF& point) {
gfx::PointF* local_point) {
// This method must only be called on a local root, which is guaranteed to
// have a WebWidget.
// TODO(https://crbug.com/995981): Eventually we should be able to remove this
// DCHECK, since RenderWidget's lifetime [and thus this instance's] will be
// synchronized with the WebWidget.
DCHECK(widget_->GetWebWidget());
gfx::PointF point_in_pixel(point); gfx::PointF point_in_pixel(point);
if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) {
point_in_pixel = gfx::ConvertPointToPixel( point_in_pixel = gfx::ConvertPointToPixel(
widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel); widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel);
} }
blink::WebHitTestResult result = return widget_->GetWebWidget()->HitTestResultAt(
widget_->GetWebWidget()->HitTestResultAt(ToRoundedPoint(point_in_pixel)); ToRoundedPoint(point_in_pixel));
}
viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint(
const gfx::PointF& point,
gfx::PointF* local_point) {
blink::WebHitTestResult result = GetHitTestResultAtPoint(point);
blink::WebNode result_node = result.GetNode(); blink::WebNode result_node = result.GetNode();
*local_point = gfx::PointF(point); *local_point = gfx::PointF(point);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "content/common/input/input_event_dispatch_type.h" #include "content/common/input/input_event_dispatch_type.h"
#include "content/renderer/input/main_thread_event_queue.h" #include "content/renderer/input/main_thread_event_queue.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h" #include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
#include "ui/base/ui_base_types.h" #include "ui/base/ui_base_types.h"
#include "ui/events/blink/did_overscroll_params.h" #include "ui/events/blink/did_overscroll_params.h"
#include "ui/events/types/scroll_types.h" #include "ui/events/types/scroll_types.h"
...@@ -83,6 +84,9 @@ class CONTENT_EXPORT RenderWidgetInputHandler { ...@@ -83,6 +84,9 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
// cursor. // cursor.
bool DidChangeCursor(const WebCursor& cursor); bool DidChangeCursor(const WebCursor& cursor);
// Do a hit test for a given point in viewport coordinate.
blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point);
private: private:
class HandlingState; class HandlingState;
struct InjectScrollGestureParams { struct InjectScrollGestureParams {
......
...@@ -221,6 +221,18 @@ void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( ...@@ -221,6 +221,18 @@ void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread(
INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING, HandledEventCallback()); INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING, HandledEventCallback());
} }
void WidgetInputHandlerManager::FindScrollTargetOnMainThread(
const gfx::PointF& point,
ElementAtPointCallback callback) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
uint64_t element_id =
render_widget_->GetHitTestResultAtPoint(point).GetScrollableContainerId();
InputThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), element_id));
}
void WidgetInputHandlerManager::DidOverscroll( void WidgetInputHandlerManager::DidOverscroll(
const gfx::Vector2dF& accumulated_overscroll, const gfx::Vector2dF& accumulated_overscroll,
const gfx::Vector2dF& latest_overscroll_delta, const gfx::Vector2dF& latest_overscroll_delta,
......
...@@ -139,6 +139,13 @@ class CONTENT_EXPORT WidgetInputHandlerManager final ...@@ -139,6 +139,13 @@ class CONTENT_EXPORT WidgetInputHandlerManager final
// hit test regions. // hit test regions.
void AllowPreCommitInput() { allow_pre_commit_input_ = true; } void AllowPreCommitInput() { allow_pre_commit_input_ = true; }
// Called on the main thread. Finds the matching element under the given
// point in visual viewport coordinates and runs the callback with the
// found element id on input thread task runner.
using ElementAtPointCallback = base::OnceCallback<void(uint64_t)>;
void FindScrollTargetOnMainThread(const gfx::PointF& point,
ElementAtPointCallback callback);
protected: protected:
friend class base::RefCountedThreadSafe<WidgetInputHandlerManager>; friend class base::RefCountedThreadSafe<WidgetInputHandlerManager>;
~WidgetInputHandlerManager() override; ~WidgetInputHandlerManager() override;
......
...@@ -3391,6 +3391,11 @@ void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) { ...@@ -3391,6 +3391,11 @@ void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) {
synchronous_resize_mode_for_testing_ = enable; synchronous_resize_mode_for_testing_ = enable;
} }
blink::WebHitTestResult RenderWidget::GetHitTestResultAtPoint(
const gfx::PointF& point) {
return input_handler_->GetHitTestResultAtPoint(point);
}
void RenderWidget::SetDeviceScaleFactorForTesting(float factor) { void RenderWidget::SetDeviceScaleFactorForTesting(float factor) {
DCHECK_GT(factor, 0.f); DCHECK_GT(factor, 0.f);
......
...@@ -598,12 +598,14 @@ class CONTENT_EXPORT RenderWidget ...@@ -598,12 +598,14 @@ class CONTENT_EXPORT RenderWidget
void SetZoomLevelForTesting(double zoom_level); void SetZoomLevelForTesting(double zoom_level);
void ResetZoomLevelForTesting(); void ResetZoomLevelForTesting();
void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space); void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
void SetPageZoomLevelForTesting(double zoom_level);
void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect); void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
void EnableAutoResizeForTesting(const gfx::Size& min_size, void EnableAutoResizeForTesting(const gfx::Size& min_size,
const gfx::Size& max_size); const gfx::Size& max_size);
void DisableAutoResizeForTesting(const gfx::Size& new_size); void DisableAutoResizeForTesting(const gfx::Size& new_size);
// Do a hit test for a given point in viewport coordinate.
blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point);
// Forces a redraw and invokes the callback once the frame's been displayed // Forces a redraw and invokes the callback once the frame's been displayed
// to the user. // to the user.
using PresentationTimeCallback = using PresentationTimeCallback =
......
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h" #include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget.h" #include "content/renderer/render_widget.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_input_method_controller.h" #include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_range.h" #include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_view.h"
#include "ui/base/ime/text_input_type.h" #include "ui/base/ime/text_input_type.h"
namespace content { namespace content {
...@@ -52,6 +54,23 @@ class RenderWidgetTest : public RenderViewTest { ...@@ -52,6 +54,23 @@ class RenderWidgetTest : public RenderViewTest {
ui::TextInputType GetTextInputType() { return widget()->GetTextInputType(); } ui::TextInputType GetTextInputType() { return widget()->GetTextInputType(); }
void SetFocus(bool focused) { widget()->OnSetFocus(focused); } void SetFocus(bool focused) { widget()->OnSetFocus(focused); }
gfx::PointF GetCenterPointOfElement(const blink::WebString& id) {
auto rect =
GetMainFrame()->GetDocument().GetElementById(id).BoundsInViewport();
return gfx::PointF(rect.x + rect.width / 2, rect.y + rect.height / 2);
}
// Returns Compositor scrolling ElementId for a given id. If id is empty it
// returns the document scrolling ElementId.
uint64_t GetCompositorElementId(const blink::WebString& id = "") {
blink::WebNode node;
if (id.IsEmpty())
node = GetMainFrame()->GetDocument();
else
node = GetMainFrame()->GetDocument().GetElementById(id);
return node.ScrollingElementIdForTesting();
}
}; };
TEST_F(RenderWidgetTest, OnSynchronizeVisualProperties) { TEST_F(RenderWidgetTest, OnSynchronizeVisualProperties) {
...@@ -118,7 +137,114 @@ class RenderWidgetInitialSizeTest : public RenderWidgetTest { ...@@ -118,7 +137,114 @@ class RenderWidgetInitialSizeTest : public RenderWidgetTest {
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
}; };
TEST_F(RenderWidgetTest, HitTestAPI) { TEST_F(RenderWidgetTest, CompositorIdHitTestAPI) {
LoadHTML(
R"HTML(
<style>
body { padding: 0; margin: 0; }
</style>
<div id='green' style='background:green; height:50px; margin-top:50px;'>
</div>
<div id='red' style='background:red; height:50px; overflow-y:scroll'>
<div style='height:200px'>long content</div>
</div>
<div id='blue' style='background:blue; height:50px; overflow:hidden'>
<div style='height:200px'>long content</div>
</div>
<div style='height:50px; overflow-y:scroll'>
<div id='yellow' style='height:50px; width:200px; position:fixed;
background:yellow;'>position fixed</div>
<div style='height:200px; background: black'>long content</div>
</div>
<div id='cyan-parent' style='height:50px; overflow:scroll'>
<div id='cyan' style='background:cyan; height:100px; overflow:scroll'>
<div style='height:200px'>long content</div>
</div>
</div>
)HTML");
float scale_factors[] = {1, 1.5, 2};
for (float factor : scale_factors) {
view_->GetWebView()->SetPageScaleFactor(factor);
// Hit the root
EXPECT_EQ(GetCompositorElementId(),
widget()
->GetHitTestResultAtPoint(gfx::PointF(10, 10))
.GetScrollableContainerId());
// Hit non-scrollable div
EXPECT_EQ(GetCompositorElementId(),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("green"))
.GetScrollableContainerId());
// Hit scrollable div
EXPECT_EQ(GetCompositorElementId("red"),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("red"))
.GetScrollableContainerId());
// Hit overflow:hidden div
EXPECT_EQ(GetCompositorElementId(),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("blue"))
.GetScrollableContainerId());
// Hit position fixed div
EXPECT_EQ(GetCompositorElementId(),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("yellow"))
.GetScrollableContainerId());
// Hit inner scroller inside another scroller
EXPECT_EQ(
GetCompositorElementId("cyan"),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("cyan-parent"))
.GetScrollableContainerId());
}
}
TEST_F(RenderWidgetTest, CompositorIdHitTestAPIWithImplicitRootScroller) {
blink::WebRuntimeFeatures::EnableOverlayScrollbars(true);
blink::WebRuntimeFeatures::EnableImplicitRootScroller(true);
LoadHTML(
R"HTML(
<style>
html,body {
width: 100%;
height: 100%;
margin: 0px;
}
#scroller {
width: 100%;
height: 100%;
overflow: auto;
}
</style>
<div id='scroller'>
<div style='height:3000px; background:red;'>very long content</div>
</div>
<div id='white' style='position:absolute; top:100px; left:50px;
height:50px; background:white;'>some more content</div>
)HTML");
// Hit sibling of a implicit root scroller node
EXPECT_EQ(GetMainFrame()->GetDocument().GetVisualViewportScrollingElementId(),
widget()
->GetHitTestResultAtPoint(GetCenterPointOfElement("white"))
.GetScrollableContainerId());
}
TEST_F(RenderWidgetTest, FrameSinkIdHitTestAPI) {
LoadHTML( LoadHTML(
"<body style='padding: 0px; margin: 0px'>" "<body style='padding: 0px; margin: 0px'>"
"<div style='background: green; padding: 100px; margin: 0px;'>" "<div style='background: green; padding: 100px; margin: 0px;'>"
......
...@@ -131,6 +131,9 @@ class WebDocument : public WebNode { ...@@ -131,6 +131,9 @@ class WebDocument : public WebNode {
BLINK_EXPORT void SetShowBeforeUnloadDialog(bool show_dialog); BLINK_EXPORT void SetShowBeforeUnloadDialog(bool show_dialog);
// See cc/paint/element_id.h for the definition of these id.
BLINK_EXPORT uint64_t GetVisualViewportScrollingElementId();
#if INSIDE_BLINK #if INSIDE_BLINK
BLINK_EXPORT WebDocument(Document*); BLINK_EXPORT WebDocument(Document*);
BLINK_EXPORT WebDocument& operator=(Document*); BLINK_EXPORT WebDocument& operator=(Document*);
......
...@@ -76,6 +76,10 @@ class WebHitTestResult { ...@@ -76,6 +76,10 @@ class WebHitTestResult {
// Return whether an editable input element was hit. // Return whether an editable input element was hit.
BLINK_EXPORT bool IsContentEditable() const; BLINK_EXPORT bool IsContentEditable() const;
// Return the ElementId of the first scrollable containing block ancestor
// of the target, including the target itself if it is scrollable
BLINK_EXPORT uint64_t GetScrollableContainerId() const;
#if INSIDE_BLINK #if INSIDE_BLINK
BLINK_EXPORT WebHitTestResult(const HitTestResult&); BLINK_EXPORT WebHitTestResult(const HitTestResult&);
BLINK_EXPORT WebHitTestResult& operator=(const HitTestResult&); BLINK_EXPORT WebHitTestResult& operator=(const HitTestResult&);
......
...@@ -86,6 +86,9 @@ class BLINK_EXPORT WebNode { ...@@ -86,6 +86,9 @@ class BLINK_EXPORT WebNode {
bool IsElementNode() const; bool IsElementNode() const;
void SimulateClick(); void SimulateClick();
// See cc/paint/element_id.h for the definition of these ids.
uint64_t ScrollingElementIdForTesting() const;
// The argument should be lower-cased. // The argument should be lower-cased.
WebElementCollection GetElementsByHTMLTagName(const WebString&) const; WebElementCollection GetElementsByHTMLTagName(const WebString&) const;
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h" #include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/html_all_collection.h" #include "third_party/blink/renderer/core/html/html_all_collection.h"
...@@ -61,6 +62,7 @@ ...@@ -61,6 +62,7 @@
#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/casting.h"
...@@ -274,6 +276,14 @@ void WebDocument::SetShowBeforeUnloadDialog(bool show_dialog) { ...@@ -274,6 +276,14 @@ void WebDocument::SetShowBeforeUnloadDialog(bool show_dialog) {
doc->SetShowBeforeUnloadDialog(show_dialog); doc->SetShowBeforeUnloadDialog(show_dialog);
} }
uint64_t WebDocument::GetVisualViewportScrollingElementId() {
return blink::To<Document>(private_.Get())
->GetPage()
->GetVisualViewport()
.GetScrollElementId()
.GetStableId();
}
WebDocument::WebDocument(Document* elem) : WebNode(elem) {} WebDocument::WebDocument(Document* elem) : WebNode(elem) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebDocument, ConstUnwrap<Node>()->IsDocumentNode()) DEFINE_WEB_NODE_TYPE_CASTS(WebDocument, ConstUnwrap<Node>()->IsDocumentNode())
......
...@@ -101,6 +101,10 @@ bool WebHitTestResult::IsContentEditable() const { ...@@ -101,6 +101,10 @@ bool WebHitTestResult::IsContentEditable() const {
return private_->Result().IsContentEditable(); return private_->Result().IsContentEditable();
} }
uint64_t WebHitTestResult::GetScrollableContainerId() const {
return private_->Result().GetScrollableContainer().GetStableId();
}
WebHitTestResult::WebHitTestResult(const HitTestResult& result) WebHitTestResult::WebHitTestResult(const HitTestResult& result)
: private_(MakeGarbageCollected<WebHitTestResultPrivate>(result)) {} : private_(MakeGarbageCollected<WebHitTestResultPrivate>(result)) {}
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink { namespace blink {
...@@ -209,6 +210,13 @@ bool WebNode::Focused() const { ...@@ -209,6 +210,13 @@ bool WebNode::Focused() const {
return private_->IsFocused(); return private_->IsFocused();
} }
uint64_t WebNode::ScrollingElementIdForTesting() const {
return private_->GetLayoutBox()
->GetScrollableArea()
->GetScrollElementId()
.GetStableId();
}
WebPluginContainer* WebNode::PluginContainer() const { WebPluginContainer* WebNode::PluginContainer() const {
return private_->GetWebPluginContainer(); return private_->GetWebPluginContainer();
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/editing/position_with_affinity.h" #include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/html_area_element.h" #include "third_party/blink/renderer/core/html/html_area_element.h"
...@@ -38,7 +39,10 @@ ...@@ -38,7 +39,10 @@
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h" #include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_image.h" #include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h" #include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/core/svg/svg_element.h" #include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/geometry/region.h" #include "third_party/blink/renderer/platform/geometry/region.h"
...@@ -174,6 +178,31 @@ void HitTestResult::SetToShadowHostIfInRestrictedShadowRoot() { ...@@ -174,6 +178,31 @@ void HitTestResult::SetToShadowHostIfInRestrictedShadowRoot() {
SetInnerNode(shadow_host); SetInnerNode(shadow_host);
} }
CompositorElementId HitTestResult::GetScrollableContainer() const {
DCHECK(InnerNode());
LayoutBox* cur_box = InnerNode()->GetLayoutObject()->EnclosingBox();
// Scrolling propagates along the containing block chain and ends at the
// RootScroller node. The RootScroller node will have a custom applyScroll
// callback that performs scrolling as well as associated "root" actions like
// browser control movement and overscroll glow.
while (cur_box) {
if (cur_box->IsGlobalRootScroller() ||
cur_box->NeedsScrollNode(CompositingReason::kNone)) {
return CompositorElementIdFromUniqueObjectId(
cur_box->UniqueId(), CompositorElementIdNamespace::kScroll);
}
cur_box = cur_box->ContainingBlock();
}
return InnerNode()
->GetDocument()
.GetPage()
->GetVisualViewport()
.GetScrollElementId();
}
HTMLAreaElement* HitTestResult::ImageAreaForImage() const { HTMLAreaElement* HitTestResult::ImageAreaForImage() const {
DCHECK(inner_node_); DCHECK(inner_node_);
auto* image_element = DynamicTo<HTMLImageElement>(inner_node_.Get()); auto* image_element = DynamicTo<HTMLImageElement>(inner_node_.Get());
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h" #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h" #include "third_party/blink/renderer/core/layout/hit_test_location.h"
#include "third_party/blink/renderer/core/layout/hit_test_request.h" #include "third_party/blink/renderer/core/layout/hit_test_request.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h" #include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
...@@ -86,6 +87,7 @@ class CORE_EXPORT HitTestResult { ...@@ -86,6 +87,7 @@ class CORE_EXPORT HitTestResult {
Node* InnerPossiblyPseudoNode() const { Node* InnerPossiblyPseudoNode() const {
return inner_possibly_pseudo_node_.Get(); return inner_possibly_pseudo_node_.Get();
} }
CompositorElementId GetScrollableContainer() const;
Element* InnerElement() const { return inner_element_.Get(); } Element* InnerElement() const { return inner_element_.Get(); }
// If innerNode is an image map or image map area, return the associated image // If innerNode is an image map or image map area, return the associated image
......
...@@ -6578,4 +6578,15 @@ TextDirection LayoutBox::ResolvedDirection() const { ...@@ -6578,4 +6578,15 @@ TextDirection LayoutBox::ResolvedDirection() const {
return StyleRef().Direction(); return StyleRef().Direction();
} }
bool LayoutBox::NeedsScrollNode(
CompositingReasons direct_compositing_reasons) const {
if (!HasOverflowClip())
return false;
if (direct_compositing_reasons & CompositingReason::kRootScroller)
return true;
return GetScrollableArea()->ScrollsOverflow();
}
} // namespace blink } // namespace blink
...@@ -223,6 +223,11 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject { ...@@ -223,6 +223,11 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
virtual bool BackgroundShouldAlwaysBeClipped() const { return false; } virtual bool BackgroundShouldAlwaysBeClipped() const { return false; }
// Returns whether this object needs a scroll paint property tree node. These
// are a requirement for composited scrolling but are also created for
// non-composited scrollers.
bool NeedsScrollNode(CompositingReasons direct_compositing_reasons) const;
// Use this with caution! No type checking is done! // Use this with caution! No type checking is done!
LayoutBox* FirstChildBox() const; LayoutBox* FirstChildBox() const;
LayoutBox* FirstInFlowChildBox() const; LayoutBox* FirstInFlowChildBox() const;
......
...@@ -279,17 +279,6 @@ class FragmentPaintPropertyTreeBuilder { ...@@ -279,17 +279,6 @@ class FragmentPaintPropertyTreeBuilder {
PaintPropertyChangeType::kUnchanged; PaintPropertyChangeType::kUnchanged;
}; };
static bool NeedsScrollNode(const LayoutObject& object,
CompositingReasons direct_compositing_reasons) {
if (!object.HasOverflowClip())
return false;
if (direct_compositing_reasons & CompositingReason::kRootScroller)
return true;
return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow();
}
// True if a scroll translation is needed for static scroll offset (e.g., // True if a scroll translation is needed for static scroll offset (e.g.,
// overflow hidden with scroll), or if a scroll node is needed for composited // overflow hidden with scroll), or if a scroll node is needed for composited
// scrolling. // scrolling.
...@@ -305,7 +294,7 @@ static bool NeedsScrollOrScrollTranslation( ...@@ -305,7 +294,7 @@ static bool NeedsScrollOrScrollTranslation(
ScrollOffset scroll_offset = box.GetScrollableArea()->GetScrollOffset(); ScrollOffset scroll_offset = box.GetScrollableArea()->GetScrollOffset();
return !scroll_offset.IsZero() || return !scroll_offset.IsZero() ||
NeedsScrollNode(object, direct_compositing_reasons); box.NeedsScrollNode(direct_compositing_reasons);
} }
static bool NeedsReplacedContentTransform(const LayoutObject& object) { static bool NeedsReplacedContentTransform(const LayoutObject& object) {
...@@ -1872,7 +1861,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() { ...@@ -1872,7 +1861,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
DCHECK(properties_); DCHECK(properties_);
if (NeedsPaintPropertyUpdate()) { if (NeedsPaintPropertyUpdate()) {
if (NeedsScrollNode(object_, full_context_.direct_compositing_reasons)) { if (object_.IsBox() && ToLayoutBox(object_).NeedsScrollNode(
full_context_.direct_compositing_reasons)) {
const LayoutBox& box = ToLayoutBox(object_); const LayoutBox& box = ToLayoutBox(object_);
PaintLayerScrollableArea* scrollable_area = box.GetScrollableArea(); PaintLayerScrollableArea* scrollable_area = box.GetScrollableArea();
ScrollPaintPropertyNode::State state; ScrollPaintPropertyNode::State state;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment