Commit 20cbbf21 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[FragmentItem] Remove |NodeForHitTest| from |NGPaintFragment|

It looks like we tried to copy the logic in |LayoutObject::
NodeForHitTest| to |NGPaintFragment|. As part of deprecating
|NGPaintFragment|, this patch moves it to |NGPhysicalFragment|,
using the existing logic in |LayoutObject|.

In future, this logic might be moved to |Node| or something
that represents the box tree. Until then, using the logic in
|LayoutObject| looks most reasonable.

Bug: 982194
Change-Id: Ib6b967dc616714eb2cb1a16585493d106c44c504
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1937953Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719562}
parent 077c539b
......@@ -3330,17 +3330,22 @@ bool LayoutObject::HitTestAllPhases(HitTestResult& result,
}
Node* LayoutObject::NodeForHitTest() const {
Node* node = GetNode();
if (Node* node = GetNode())
return node;
// If we hit the anonymous layoutObjects inside generated content we should
// actually hit the generated content so walk up to the PseudoElement.
if (!node && Parent() && Parent()->IsBeforeOrAfterContent()) {
for (LayoutObject* layout_object = Parent(); layout_object && !node;
layout_object = layout_object->Parent())
node = layout_object->GetNode();
if (const LayoutObject* parent = Parent()) {
if (parent->IsBeforeOrAfterContent() ||
parent->StyleRef().StyleType() == kPseudoIdFirstLetter) {
for (; parent; parent = parent->Parent()) {
if (Node* node = parent->GetNode())
return node;
}
}
}
return node;
return nullptr;
}
void LayoutObject::UpdateHitTestResult(HitTestResult& result,
......
......@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
......@@ -32,6 +33,21 @@ static_assert(sizeof(NGPhysicalFragment) ==
sizeof(SameSizeAsNGPhysicalFragment),
"NGPhysicalFragment should stay small");
const LayoutObject* ListMarkerFromMarkerOrMarkerContent(
const LayoutObject* object) {
if (object->IsLayoutNGListMarkerIncludingInside())
return object;
// Check if this is a marker content.
if (object->IsAnonymous()) {
const LayoutObject* parent = object->Parent();
if (parent && parent->IsLayoutNGListMarkerIncludingInside())
return parent;
}
return nullptr;
}
bool AppendFragmentOffsetAndSize(const NGPhysicalFragment* fragment,
base::Optional<PhysicalOffset> fragment_offset,
StringBuilder* builder,
......@@ -488,6 +504,22 @@ bool NGPhysicalFragment::ShouldPaintDragCaret() const {
return false;
}
Node* NGPhysicalFragment::NodeForHitTest() const {
if (Node* node = layout_object_->NodeForHitTest())
return node;
// When the fragment is a list marker, return the list item.
if (const LayoutObject* marker =
ListMarkerFromMarkerOrMarkerContent(layout_object_)) {
if (const LayoutNGListItem* list_item =
LayoutNGListItem::FromMarker(*marker))
return list_item->GetNode();
return nullptr;
}
return nullptr;
}
String NGPhysicalFragment::ToString() const {
StringBuilder output;
output.AppendFormat("Type: '%d' Size: '%s'", Type(),
......
......@@ -202,6 +202,9 @@ class CORE_EXPORT NGPhysicalFragment
Node* GeneratingNode() const {
return IsCSSBox() ? layout_object_->GeneratingNode() : nullptr;
}
// The node to return when hit-testing on this fragment. This can be different
// from GetNode() when this fragment is content of a pseudo node.
Node* NodeForHitTest() const;
// Whether there is a PaintLayer associated with the fragment.
bool HasLayer() const { return IsCSSBox() && layout_object_->HasLayer(); }
......
......@@ -178,40 +178,10 @@ base::Optional<PositionWithAffinity> PositionForPointInChild(
return base::nullopt;
}
// ::before, ::after and ::first-letter can be hit test targets.
bool CanBeHitTestTargetPseudoNode(const Node& node) {
auto* pseudo_element = DynamicTo<PseudoElement>(node);
if (!pseudo_element)
return false;
switch (pseudo_element->GetPseudoId()) {
case kPseudoIdBefore:
case kPseudoIdAfter:
case kPseudoIdFirstLetter:
return true;
default:
return false;
}
}
bool IsLastBRInPage(const LayoutObject& layout_object) {
return layout_object.IsBR() && !layout_object.NextInPreOrder();
}
const LayoutObject* ListMarkerFromMarkerOrMarkerContent(
const LayoutObject* object) {
if (object->IsLayoutNGListMarkerIncludingInside())
return object;
// Check if this is a marker content.
if (object->IsAnonymous()) {
const LayoutObject* parent = object->Parent();
if (parent && parent->IsLayoutNGListMarkerIncludingInside())
return parent;
}
return nullptr;
}
} // namespace
NGPaintFragment::NGPaintFragment(
......@@ -1152,44 +1122,6 @@ PositionWithAffinity NGPaintFragment::PositionForPoint(
return PositionForPointInInlineLevelBox(point);
}
Node* NGPaintFragment::NodeForHitTest() const {
if (GetNode())
return GetNode();
if (PhysicalFragment().IsLineBox())
return Parent()->NodeForHitTest();
// When the fragment is a list marker, return the list item.
if (const LayoutObject* object = GetLayoutObject()) {
if (const LayoutObject* marker =
ListMarkerFromMarkerOrMarkerContent(object)) {
if (const LayoutNGListItem* list_item =
LayoutNGListItem::FromMarker(*marker))
return list_item->GetNode();
return nullptr;
}
}
for (const NGPaintFragment* runner = Parent(); runner;
runner = runner->Parent()) {
// When the fragment is inside a ::first-letter, ::before or ::after pseudo
// node, return the pseudo node.
if (Node* node = runner->GetNode()) {
if (CanBeHitTestTargetPseudoNode(*node))
return node;
return nullptr;
}
// When the fragment is inside a list marker, return the list item.
if (runner->GetLayoutObject() &&
runner->GetLayoutObject()->IsLayoutNGListMarker()) {
return runner->NodeForHitTest();
}
}
return nullptr;
}
String NGPaintFragment::DebugName() const {
StringBuilder name;
......
......@@ -217,7 +217,7 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
// The node to return when hit-testing on this fragment. This can be different
// from GetNode() when this fragment is content of a pseudo node.
Node* NodeForHitTest() const;
Node* NodeForHitTest() const { return PhysicalFragment().NodeForHitTest(); }
// Returns true when associated fragment of |layout_object| has line box.
static bool TryMarkFirstLineBoxDirtyFor(const LayoutObject& layout_object);
......
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