Commit 4420a01d authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

Account for non-translation transforms when adjusting link highlight rects.

Bug: 977514

Change-Id: I3c141db1860169da3064a049796bbead93f4407b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1760536Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#688234}
parent 0f85ffc4
......@@ -68,6 +68,7 @@ class CORE_EXPORT LinkHighlights final
FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, multipleHighlights);
FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, HighlightLayerEffectNode);
FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, MultiColumn);
FRIEND_TEST_ALL_PREFIXES(LinkHighlightSquashingImplTest, SquashingLayer);
void RemoveAllHighlights();
......
......@@ -242,14 +242,13 @@ bool LinkHighlightImpl::ComputeHighlightLayerPathAndPosition(
FloatQuad transformed_quad =
paint_invalidation_container.AbsoluteToLocalQuad(
absolute_quad, kTraverseDocumentBoundaries);
PhysicalOffset offset_to_backing;
PaintLayer::MapPointInPaintInvalidationContainerToBacking(
paint_invalidation_container, offset_to_backing);
PaintLayer::MapQuadInPaintInvalidationContainerToBacking(
paint_invalidation_container, transformed_quad);
// Adjust for offset from LayoutObject.
offset_to_backing -=
PhysicalOffset(current_graphics_layer_->OffsetFromLayoutObject());
PhysicalOffset offset_to_backing =
PhysicalOffset(-current_graphics_layer_->OffsetFromLayoutObject());
transformed_quad.Move(FloatSize(offset_to_backing));
......
......@@ -425,4 +425,103 @@ TEST_P(LinkHighlightImplTest, MultiColumn) {
EXPECT_EQ(layer_count_before_highlight, ContentLayerCount());
}
class LinkHighlightSquashingImplTest : public testing::Test,
public PaintTestConfigurations {
protected:
GestureEventWithHitTestResults GetTargetedEvent(
WebGestureEvent& touch_event) {
WebGestureEvent scaled_event = TransformWebGestureEvent(
web_view_helper_.GetWebView()->MainFrameImpl()->GetFrameView(),
touch_event);
return web_view_helper_.GetWebView()
->GetPage()
->DeprecatedLocalMainFrame()
->GetEventHandler()
.TargetGestureEvent(scaled_event, true);
}
void SetUp() override {
WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
WebString::FromUTF8("test_touch_link_highlight_squashing.html"));
web_view_helper_.InitializeAndLoad(url.GetString().Utf8());
}
void TearDown() override {
Platform::Current()
->GetURLLoaderMockFactory()
->UnregisterAllURLsAndClearMemoryCache();
// Ensure we fully clean up while scoped settings are enabled. Without this,
// garbage collection would occur after Scoped[setting]ForTest is out of
// scope, so the settings would not apply in some destructors.
web_view_helper_.Reset();
ThreadState::Current()->CollectAllGarbageForTesting();
}
size_t ContentLayerCount() {
// paint_artifact_compositor()->EnableExtraDataForTesting() should be called
// before using this function.
DCHECK(paint_artifact_compositor()->GetExtraDataForTesting());
return paint_artifact_compositor()
->GetExtraDataForTesting()
->content_layers.size();
}
PaintArtifactCompositor* paint_artifact_compositor() {
auto* local_frame_view = web_view_helper_.LocalMainFrame()->GetFrameView();
return local_frame_view->GetPaintArtifactCompositor();
}
void UpdateAllLifecyclePhases() {
web_view_helper_.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
}
frame_test_helpers::WebViewHelper web_view_helper_;
};
INSTANTIATE_PAINT_TEST_SUITE_P(LinkHighlightSquashingImplTest);
TEST_P(LinkHighlightSquashingImplTest, SquashingLayer) {
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
return;
bool was_running_web_test = WebTestSupport::IsRunningWebTest();
WebTestSupport::SetIsRunningWebTest(false);
int page_width = 640;
int page_height = 480;
WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
paint_artifact_compositor()->EnableExtraDataForTesting();
UpdateAllLifecyclePhases();
size_t layer_count_before_highlight = ContentLayerCount();
WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
WebInputEvent::kNoModifiers,
WebInputEvent::GetStaticTimeStampForTests(),
WebGestureDevice::kTouchscreen);
touch_event.SetPositionInWidget(WebFloatPoint(100, 100));
GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
Node* touch_node = web_view_impl->BestTapNode(targeted_event);
ASSERT_TRUE(touch_node);
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
// The highlight should create one additional layer.
EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount());
auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
auto* highlight = highlights.link_highlights_.at(0).get();
ASSERT_TRUE(highlight);
// Check that the link highlight cc layer has a cc effect property tree node.
EXPECT_EQ(1u, highlight->FragmentCountForTesting());
auto* layer = highlight->LayerForTesting(0);
EXPECT_EQ(gfx::Size(256, 256), layer->bounds());
WebTestSupport::SetIsRunningWebTest(was_running_web_test);
}
} // namespace blink
......@@ -600,6 +600,31 @@ void PaintLayer::MapPointInPaintInvalidationContainerToBacking(
point -= PhysicalOffset(squashing_layer->GetOffsetFromTransformNode());
}
void PaintLayer::MapQuadInPaintInvalidationContainerToBacking(
const LayoutBoxModelObject& paint_invalidation_container,
FloatQuad& quad) {
PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer();
if (!paint_invalidation_layer->GroupedMapping())
return;
GraphicsLayer* squashing_layer =
paint_invalidation_layer->GroupedMapping()->SquashingLayer();
PropertyTreeState source_state =
paint_invalidation_container.FirstFragment().LocalBorderBoxProperties();
PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState();
// Move the rect into the source_state transform space, map to dest_state
// transform space, then move into squashing layer state.
quad.Move(
FloatSize(paint_invalidation_container.FirstFragment().PaintOffset()));
GeometryMapper::SourceToDestinationProjection(source_state.Transform(),
dest_state.Transform())
.MapQuad(quad);
quad.Move(
-ToFloatSize(FloatPoint(squashing_layer->GetOffsetFromTransformNode())));
}
void PaintLayer::DirtyVisibleContentStatus() {
MarkAncestorChainForFlagsUpdate();
// Non-self-painting layers paint into their ancestor layer, and count as part
......
......@@ -587,6 +587,9 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
static void MapPointInPaintInvalidationContainerToBacking(
const LayoutBoxModelObject& paint_invalidation_container,
PhysicalOffset&);
static void MapQuadInPaintInvalidationContainerToBacking(
const LayoutBoxModelObject& paint_invalidation_container,
FloatQuad&);
bool PaintsWithTransparency(GlobalPaintFlags global_paint_flags) const {
return IsTransparent() && !PaintsIntoOwnBacking(global_paint_flags);
......
<!DOCTYPE html>
<style>
.abs {
position: absolute;
top: 5;
left: 5;
width: 512px;
height: 512px;
}
#target {
display: block;
transform: scale(0.5);
transform-origin: left top;
background-color: green;
}
</style>
<div class=abs style="will-change: transform; pointer-events: none;"></div>
<a class=abs id=target href="javascript:void(0)"></a>
......@@ -68,6 +68,13 @@ class PLATFORM_EXPORT GeometryMapper {
rect = Matrix().MapRect(rect);
}
void MapQuad(FloatQuad& quad) const {
if (LIKELY(IsIdentityOr2DTranslation()))
quad.Move(Translation2D());
else
quad = Matrix().MapQuad(quad);
}
void MapFloatClipRect(FloatClipRect& rect) const {
if (LIKELY(IsIdentityOr2DTranslation()))
rect.MoveBy(FloatPoint(Translation2D()));
......
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