WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
109100
[CSS Grid Layout] Adding or removing grid items doesn't properly recompute the track sizes
https://bugs.webkit.org/show_bug.cgi?id=109100
Summary
[CSS Grid Layout] Adding or removing grid items doesn't properly recompute th...
Julien Chaffraix
Reported
2013-02-06 15:25:49 PST
We have no coverage for removing grid items and checking that we properly recompute the tracks' breadths. This doesn't properly work currently as we miss some layout cues and our distribution algorithm is not totally right.
Attachments
Proposed patch 1: Added a beefy test that uncovered several bugs in our implementation.
(29.46 KB, patch)
2013-02-06 16:42 PST
,
Julien Chaffraix
no flags
Details
Formatted Diff
Diff
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild.
(39.87 KB, patch)
2013-02-11 16:39 PST
,
Julien Chaffraix
no flags
Details
Formatted Diff
Diff
Patch for landing
(39.78 KB, patch)
2013-02-13 11:33 PST
,
Julien Chaffraix
no flags
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Julien Chaffraix
Comment 1
2013-02-06 16:42:36 PST
Created
attachment 186944
[details]
Proposed patch 1: Added a beefy test that uncovered several bugs in our implementation.
Ojan Vafai
Comment 2
2013-02-06 17:13:31 PST
Comment on
attachment 186944
[details]
Proposed patch 1: Added a beefy test that uncovered several bugs in our implementation. View in context:
https://bugs.webkit.org/attachment.cgi?id=186944&action=review
> Source/WebCore/ChangeLog:22 > + This made us over-grow some cases in the test.
Is the overgrowing correct or incorrect? It's unclear from this description ("over" implies incorrect to me).
> Source/WebCore/rendering/RenderGrid.cpp:306 > + if (usedBreadth != oldUsedBreadth || child->style()->logicalHeight().isPercent())
I don't understand the percent case. It's definitely wrong, but I'm not sure what the right solution is. Can you explain this case to me?
> Source/WebCore/rendering/RenderGrid.cpp:333 > + // FIXME: minContentForChild will already call layout on |child|, maybe there is a way for us to avoid this second layout?
This FIXME is only for the percent case, right? The usedBreadths will be the same if minContentForChild set it. That said, we should move this second half of these functions into a helper functions since they are identical and now becoming non-trivial. Arguably they were non-trivial before. :)
> Source/WebCore/rendering/RenderGrid.cpp:409 > + for (size_t i = 0; i < tracksSize; ++i) > + updatedTrackSizes[i] = (tracks[i]->*trackGetter)();
I don't understand what this loop does. Don't we just overwrite all these values in the next loop?
> Source/WebCore/rendering/RenderGrid.cpp:433 > tracksSize = tracksForGrowthAboveMaxBreadth->size(); > for (size_t i = 0; i < tracksSize; ++i) { > - GridTrack& track = *tracksForGrowthAboveMaxBreadth->at(i); > LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i); > - (track.*trackGrowthFunction)(growthShare); > + updatedTrackSizes[i] += growthShare; > availableLogicalSpace -= growthShare; > }
You could avoid duplicate code by wrapping this code in the following and then always doing the for-loop below: if (availableLogicalSpace > 0 && tracksForGrowthAboveMaxBreadth) {
Julien Chaffraix
Comment 3
2013-02-06 18:07:18 PST
Comment on
attachment 186944
[details]
Proposed patch 1: Added a beefy test that uncovered several bugs in our implementation. View in context:
https://bugs.webkit.org/attachment.cgi?id=186944&action=review
>> Source/WebCore/ChangeLog:22 >> + This made us over-grow some cases in the test. > > Is the overgrowing correct or incorrect? It's unclear from this description ("over" implies incorrect to me).
The over-growing was wrong. Before the change, we would end up trying to grow the size based on m_maxBreadth == infinity instead of settling on the used breadth.
>> Source/WebCore/rendering/RenderGrid.cpp:306 >> + if (usedBreadth != oldUsedBreadth || child->style()->logicalHeight().isPercent()) > > I don't understand the percent case. It's definitely wrong, but I'm not sure what the right solution is. Can you explain this case to me?
Sure, in some cases, even if the column used breadth didn't change, we still need to recompute the (unconstrained) logical height to properly compute the row grid breadth. The bug it hit was to read the previous layout logical height value when the column used breadth didn't change. This wrong check was trying to be conservative instead of just always relayouting. I completely forgot the percent height descendant map which should cover this case better but not sure if it would work 100% of the time.
>> Source/WebCore/rendering/RenderGrid.cpp:333 >> + // FIXME: minContentForChild will already call layout on |child|, maybe there is a way for us to avoid this second layout? > > This FIXME is only for the percent case, right? The usedBreadths will be the same if minContentForChild set it. > > That said, we should move this second half of these functions into a helper functions since they are identical and now becoming non-trivial. Arguably they were non-trivial before. :)
Sounds good.
>> Source/WebCore/rendering/RenderGrid.cpp:409 >> + updatedTrackSizes[i] = (tracks[i]->*trackGetter)(); > > I don't understand what this loop does. Don't we just overwrite all these values in the next loop?
True, we could fold this loop into the next one.
Julien Chaffraix
Comment 4
2013-02-11 16:39:51 PST
Created
attachment 187719
[details]
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild.
Ojan Vafai
Comment 5
2013-02-11 19:01:32 PST
Comment on
attachment 187719
[details]
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild. View in context:
https://bugs.webkit.org/attachment.cgi?id=187719&action=review
> Source/WebCore/rendering/RenderGrid.cpp:297 > + if (!child->needsLayout()) > + child->setNeedsLayout(true, MarkOnlyThis);
I don't think we need this bit actually. child->layout() should unconditionally do the layout, no?
> Source/WebCore/rendering/RenderGrid.cpp:399 > + // FIXME: This should probably use a RAII pattern to ensure we always update our tracks.
I don't understand this FIXME. We always set it in the for-loop below, no?
Julien Chaffraix
Comment 6
2013-02-11 21:59:15 PST
Comment on
attachment 187719
[details]
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild. View in context:
https://bugs.webkit.org/attachment.cgi?id=187719&action=review
>> Source/WebCore/rendering/RenderGrid.cpp:297 >> + child->setNeedsLayout(true, MarkOnlyThis); > > I don't think we need this bit actually. child->layout() should unconditionally do the layout, no?
No, child->layout() will ASSERT if child doesn't need layout (see e.g. RenderBlock::layout) as you shouldn't be calling layout on a renderer that doesn't need it. This part of the change is required and matches what other renderers are doing to force a relayout on their children.
>> Source/WebCore/rendering/RenderGrid.cpp:399 >> + // FIXME: This should probably use a RAII pattern to ensure we always update our tracks. > > I don't understand this FIXME. We always set it in the for-loop below, no?
It's a stray FIXME, it should have been removed from this change.
Ojan Vafai
Comment 7
2013-02-13 10:29:24 PST
Comment on
attachment 187719
[details]
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild. View in context:
https://bugs.webkit.org/attachment.cgi?id=187719&action=review
r=me with the stray FIXME removed.
>>> Source/WebCore/rendering/RenderGrid.cpp:297 >>> + child->setNeedsLayout(true, MarkOnlyThis); >> >> I don't think we need this bit actually. child->layout() should unconditionally do the layout, no? > > No, child->layout() will ASSERT if child doesn't need layout (see e.g. RenderBlock::layout) as you shouldn't be calling layout on a renderer that doesn't need it. > > This part of the change is required and matches what other renderers are doing to force a relayout on their children.
I see. I wonder how much value we get out of that assert. Seems sort of silly.
Julien Chaffraix
Comment 8
2013-02-13 11:13:35 PST
Comment on
attachment 187719
[details]
Updated patch per discussion with Ojan: Always force a layout in minContentForChild / maxContentForChild. View in context:
https://bugs.webkit.org/attachment.cgi?id=187719&action=review
>>>> Source/WebCore/rendering/RenderGrid.cpp:297 >>>> + child->setNeedsLayout(true, MarkOnlyThis); >>> >>> I don't think we need this bit actually. child->layout() should unconditionally do the layout, no? >> >> No, child->layout() will ASSERT if child doesn't need layout (see e.g. RenderBlock::layout) as you shouldn't be calling layout on a renderer that doesn't need it. >> >> This part of the change is required and matches what other renderers are doing to force a relayout on their children. > > I see. I wonder how much value we get out of that assert. Seems sort of silly.
I strongly disagree with your comment. This is a performance ASSERT that guarantees that people don't call layout when it's not needed as layout is an already expensive operation.
Julien Chaffraix
Comment 9
2013-02-13 11:33:26 PST
Created
attachment 188130
[details]
Patch for landing
WebKit Review Bot
Comment 10
2013-02-13 14:19:29 PST
Comment on
attachment 188130
[details]
Patch for landing Clearing flags on attachment: 188130 Committed
r142798
: <
http://trac.webkit.org/changeset/142798
>
WebKit Review Bot
Comment 11
2013-02-13 14:19:34 PST
All reviewed patches have been landed. Closing bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug