Commit f566298c authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

[LayoutNG] Replicate most inline hit test behavior to NG

Legacy hit tests inline elements and nodes in the way that:
- Enter inline boxes from block flow only when HitTestAction is
  kHitTestForeground (LineBoxList::HitTest)
- When entering atomic inline from an inline box, hit test all phases
  regardless of the HitTestAction for parent (InlineBox::NodeAtPoint)
- After hit testing the children of an InlineFlowBox, the InlineFlowBox
  itself is also hit tested (InlineFlowBox::NodeAtPoint). This applies
  even when the the InlineFlowBox is a RootInlineBox (i.e., line box).

This patch replicates the above behaviors in NG. Since NG treats line
boxes differently from normal inline boxes, this patch introduces
NGBoxFragmentPainter::HitTestLineBoxFragment() for relevant handling.

Note: this patch doesn't handled culled inlines.

One test related to vertical-rl writing mode is regressed due to passing
incorrect accumulated offset to legacy. This will be fixed later.

Bug: 851075
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I5eceb4fe5c8270bc17407212ae2fe7c3841daf90
Reviewed-on: https://chromium-review.googlesource.com/1093577
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567814}
parent d0a1c9e3
......@@ -24,6 +24,9 @@ crbug.com/591099 fast/block/child-not-removed-from-parent-lineboxes-crash.html [
# https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_block.cc?l=1372&rcl=0e081149ecd6a83f6289e3aee5797936008a1e10
crbug.com/591099 fast/block/marquee-width-shrinks-to-fit-in-fixed-size-container.html [ Failure ]
# Hit test failure due to vertical-rl writing mode
crbug.com/851075 fast/writing-mode/vertical-inline-block-hittest.html [ Failure ]
# New passes
crbug.com/774229 editing/pasteboard/copy-paste-white-space.html [ Pass ]
crbug.com/591099 external/wpt/css/CSS2/floats-clear/no-clearance-adjoining-opposite-float.html [ Pass ]
......@@ -485,7 +488,6 @@ crbug.com/714962 fast/dom/elementsFromPoint/elementsFromPoint-inline.html [ Fail
crbug.com/591099 fast/dom/elementsFromPoint/elementsFromPoint-svg.html [ Failure ]
crbug.com/714962 fast/dom/inert/inert-inlines.html [ Failure ]
crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ]
crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-child-frame-scrolled-content.html [ Failure ]
crbug.com/714962 fast/dom/nodesFromRect/nodesFromRect-culled-inline-with-linebreak.html [ Failure ]
crbug.com/714962 fast/dom/nodesFromRect/nodesFromRect-culled-inlines.html [ Failure ]
crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-inline-image.html [ Failure ]
......@@ -507,7 +509,6 @@ crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pas
crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
crbug.com/591099 fast/forms/fieldset/fieldset-with-float.html [ Failure ]
crbug.com/591099 fast/forms/form-hides-table.html [ Failure ]
crbug.com/714962 fast/forms/label/continous-click-on-label.html [ Failure ]
crbug.com/591099 fast/forms/select/select-initial-position.html [ Failure ]
crbug.com/591099 fast/forms/select/select-style.html [ Failure ]
crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Timeout ]
......
......@@ -482,6 +482,7 @@ crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/border-vertical-lr.
crbug.com/714962 [ Mac Win ] virtual/layout_ng/fast/writing-mode/english-lr-text.html [ Failure ]
crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/japanese-rl-text.html [ Failure ]
crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/text-orientation-basic.html [ Failure ]
crbug.com/851075 virtual/layout_ng/fast/writing-mode/vertical-inline-block-hittest.html [ Failure ]
# Crashes/asserts due to inline item reuse.
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-block-from-content-after-spanner.html [ Failure Crash Timeout ]
......
......@@ -962,6 +962,57 @@ bool NGBoxFragmentPainter::HitTestTextFragment(
return false;
}
// Replicates logic in legacy InlineFlowBox::NodeAtPoint().
bool NGBoxFragmentPainter::HitTestLineBoxFragment(
HitTestResult& result,
const NGPaintFragment& fragment,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction action) {
if (action != kHitTestForeground)
return false;
const LayoutPoint adjusted_offset =
accumulated_offset + fragment.Offset().ToLayoutPoint();
const LayoutSize size = fragment.Size().ToLayoutSize();
// TODO(xiaochengh): Hit test ellipsis box.
if (HitTestChildren(result, fragment.Children(), location_in_container,
adjusted_offset, action))
return true;
if (!VisibleToHitTestRequest(result.GetHitTestRequest()))
return false;
const LayoutPoint overflow_location =
fragment.SelfInkOverflow().Location() + adjusted_offset;
if (HitTestClippedOutByBorder(location_in_container, overflow_location))
return false;
const LayoutRect bounds_rect(adjusted_offset, size);
const ComputedStyle& containing_box_style = box_fragment_.Style();
if (containing_box_style.HasBorderRadius() &&
!location_in_container.Intersects(
containing_box_style.GetRoundedBorderFor(bounds_rect))) {
return false;
}
// Now hit test ourselves.
if (!location_in_container.Intersects(bounds_rect))
return false;
Node* node = fragment.NodeForHitTest();
if (!result.InnerNode() && node) {
const LayoutPoint point =
location_in_container.Point() - ToLayoutSize(adjusted_offset) +
fragment.InlineOffsetToContainerBox().ToLayoutPoint();
result.SetNodeAndPosition(node, point);
}
return result.AddNodeToListBasedTestResult(node, location_in_container,
bounds_rect) == kStopHitTesting;
}
bool NGBoxFragmentPainter::HitTestChildren(
HitTestResult& result,
const Vector<std::unique_ptr<NGPaintFragment>>& children,
......@@ -977,22 +1028,30 @@ bool NGBoxFragmentPainter::HitTestChildren(
bool stop_hit_testing = false;
if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
if (FragmentRequiresLegacyFallback(fragment)) {
// Hit test all phases of an inline-block/table or replaced element
// atomically, as if it created its own stacking context. (See Appendix
// E.2, section 7.4 on inline block/table elements in CSS2.2 spec)
bool should_hit_test_all_phases = fragment.IsAtomicInline();
LayoutPoint fallback_accumulated_offset =
FallbackAccumulatedOffset(*child, accumulated_offset);
stop_hit_testing = fragment.GetLayoutObject()->NodeAtPoint(
result, location_in_container, fallback_accumulated_offset, action);
if (should_hit_test_all_phases) {
stop_hit_testing = fragment.GetLayoutObject()->HitTestAllPhases(
result, location_in_container, fallback_accumulated_offset);
} else {
stop_hit_testing = fragment.GetLayoutObject()->NodeAtPoint(
result, location_in_container, fallback_accumulated_offset,
action);
}
} else {
// TODO(layout-dev): Implement HitTestAllPhases in NG after we stop
// falling back to legacy for atomic inlines.
stop_hit_testing = NGBoxFragmentPainter(*child).NodeAtPoint(
result, location_in_container, accumulated_offset, action);
}
} else if (fragment.Type() == NGPhysicalFragment::kFragmentLineBox) {
const LayoutSize line_box_offset(fragment.Offset().left,
fragment.Offset().top);
const LayoutPoint adjusted_offset = accumulated_offset + line_box_offset;
stop_hit_testing =
HitTestChildren(result, child->Children(), location_in_container,
adjusted_offset, action);
stop_hit_testing = HitTestLineBoxFragment(
result, *child, location_in_container, accumulated_offset, action);
} else if (fragment.Type() == NGPhysicalFragment::kFragmentText) {
// TODO(eae): Should this hit test on the text itself or the containing
......
......@@ -122,6 +122,11 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const NGPaintFragment&,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset);
bool HitTestLineBoxFragment(HitTestResult&,
const NGPaintFragment&,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction);
bool HitTestClippedOutByBorder(const HitTestLocation&,
const LayoutPoint& border_box_location) const;
LayoutPoint FlipForWritingModeForChild(
......
......@@ -593,6 +593,9 @@ Node* NGPaintFragment::NodeForHitTest() const {
if (GetNode())
return GetNode();
if (PhysicalFragment().IsLineBox())
return Parent()->NodeForHitTest();
// When the fragment is inside a ::first-letter, ::before or ::after pseudo
// node, return the pseudo node.
for (const NGPaintFragment* runner = Parent(); runner;
......
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