Bug 144647

Summary: Scroll-snap points do not handle margins and padding properly
Product: WebKit Reporter: Brent Fulgham <bfulgham>
Component: Layout and RenderingAssignee: Brent Fulgham <bfulgham>
Status: RESOLVED FIXED    
Severity: Normal CC: bfulgham, cmarcelo, commit-queue, jamesr, luiz, tonikitoo, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=144710
https://bugs.webkit.org/show_bug.cgi?id=144713
Attachments:
Description Flags
border example
none
padding example
none
Patch
none
Patch
none
Patch v3 (Removed debugging code I accidentally uploaded) simon.fraser: review+

Description Brent Fulgham 2015-05-05 17:18:24 PDT
If we decorate the container holding a scroll-snap region with padding or borders, the calculation of the snap points is not correct. See the attached example for details:

1. The initial color block fills the region and looks correct.
2. After performing a single swipe (which should move 100% to the next color block), we are off by about 2x the border width, resulting in display of the third color at the edge of the display region.
Comment 1 Brent Fulgham 2015-05-05 17:18:52 PDT
Created attachment 252422 [details]
border example
Comment 2 Brent Fulgham 2015-05-05 17:36:00 PDT
Created attachment 252423 [details]
padding example
Comment 3 Radar WebKit Bug Importer 2015-05-05 17:36:24 PDT
<rdar://problem/20829473>
Comment 4 Brent Fulgham 2015-05-06 10:50:52 PDT
Created attachment 252492 [details]
Patch
Comment 5 Simon Fraser (smfr) 2015-05-06 11:37:07 PDT
Comment on attachment 252492 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=252492&action=review

> Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp:43
> +    LayoutUnit adjustedSize = viewSize;

"size" sounds like a LayoutSize. Why not just pass a LayoutSize and pick out the right axis?

> Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp:50
> +    if (axis == ScrollEventAxis::Horizontal) {
> +        adjustedSize -= valueForLength(style.paddingLeft(), viewSize);
> +        adjustedSize -= valueForLength(style.paddingRight(), viewSize);
> +    } else {
> +        adjustedSize -= valueForLength(style.paddingTop(), viewSize);
> +        adjustedSize -= valueForLength(style.paddingBottom(), viewSize);

Isn't this just what contentBoxRect() would give you?

> Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp:59
>      for (auto& child : childrenOfType<Element>(parent)) {

Wait, why are we iterating through elements here?
Comment 6 Brent Fulgham 2015-05-06 11:51:32 PDT
Comment on attachment 252492 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=252492&action=review

>> Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp:50
>> +        adjustedSize -= valueForLength(style.paddingBottom(), viewSize);
> 
> Isn't this just what contentBoxRect() would give you?

Yes! I finally found that after writing this silly code. :-(

>> Source/WebCore/page/scrolling/AxisScrollSnapOffsets.cpp:59
>>      for (auto& child : childrenOfType<Element>(parent)) {
> 
> Wait, why are we iterating through elements here?

Bad code. I'll do a drive-by fix here.
Comment 7 Brent Fulgham 2015-05-06 15:34:55 PDT
Created attachment 252530 [details]
Patch
Comment 8 Brent Fulgham 2015-05-06 15:38:40 PDT
Created attachment 252531 [details]
Patch v3 (Removed debugging code I accidentally uploaded)
Comment 9 Simon Fraser (smfr) 2015-05-06 17:53:36 PDT
Comment on attachment 252531 [details]
Patch v3 (Removed debugging code I accidentally uploaded)

View in context: https://bugs.webkit.org/attachment.cgi?id=252531&action=review

> Source/WebCore/testing/Internals.cpp:2814
> +    RenderBox& box = *element->renderBox();
> +    const auto& scrollSnapCoordinates = box.style().scrollSnapCoordinates();
> +    if (scrollSnapCoordinates.isEmpty())
> +        return "none";
> +
> +    LayoutRect viewSize = box.contentBoxRect();
> +    LayoutUnit viewWidth = viewSize.width();
> +    LayoutUnit viewHeight = viewSize.height();
> +    
> +    StringBuilder result;
> +    result.append("{ ");
> +    for (auto& coordinate : scrollSnapCoordinates) {
> +        if (result.length() > 2)
> +            result.append(", ");
> +
> +        LayoutUnit x = valueForLength(coordinate.width(), viewWidth);
> +        LayoutUnit y = valueForLength(coordinate.height(), viewHeight);
> +        result.append("(");
> +        result.append(String::number(x.toUnsigned()));
> +        result.append(", ");
> +        result.append(String::number(y.toUnsigned()));
> +        result.append(")");
> +    }
> +    result.append(" }");

Is this code telling us anything that we don't get from computed style? Use of box.contentBoxRect() here isn't interesting, because this is test-only code.
Comment 10 Brent Fulgham 2015-05-06 19:14:29 PDT
Comment on attachment 252531 [details]
Patch v3 (Removed debugging code I accidentally uploaded)

View in context: https://bugs.webkit.org/attachment.cgi?id=252531&action=review

>> Source/WebCore/testing/Internals.cpp:2814
>> +    result.append(" }");
> 
> Is this code telling us anything that we don't get from computed style? Use of box.contentBoxRect() here isn't interesting, because this is test-only code.

OK. I'll get rid of this for now. If I discover a need for it when delving into the corrdinate/destination stuff more thoroughly I'll put it back.
Comment 11 Brent Fulgham 2015-05-06 19:54:18 PDT
Committed r183906: <http://trac.webkit.org/changeset/183906>