Closed
Bug 919144
Opened 11 years ago
Closed 11 years ago
Improve handling of nsDisplayFixedPosition and other layerizing properties that don't create stacking contexts
Categories
(Core :: Layout, defect)
Tracking
()
RESOLVED
FIXED
mozilla28
People
(Reporter: roc, Assigned: roc)
References
Details
Attachments
(10 files, 1 obsolete file)
49.01 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
1.11 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
2.92 KB,
patch
|
MatsPalmgren_bugz
:
review+
|
Details | Diff | Splinter Review |
2.40 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
2.49 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
18.16 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
21.20 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
72.77 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
20.81 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
2.15 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
CSS properties that need to set properties on layers fall into two categories: those that force their element to be a stacking context, and those that don't. The former case is relatively easy to handle: nsFrame::BuildDisplayListForChild recognizes the property as creating a stacking context and calls nsFrame::BuildDisplayListForStackingContext, which then creates a display item which returns something other than LAYER_NONE from nsDisplayItem::GetLayerState and builds a layer with the right properties set on it in nsDisplayItem::BuildLayer. The element being a stacking context means all its descendant content can be rendered as the children of a single display item.
The latter case is difficult to handle because the element's descendants may be interleaved in z-order with other content that is not affected by the CSS property, so multiple layers must be modified for a given CSS property on a given element. For position:fixed, we tried to handle this by creating multiple nsDisplayFixedPosition display items and later opportunistically merging them. This turns out to be a real pain for lots of reasons. For example it complicates invalidation, and it's complex to make sure that the right display items are created and merged. It also interacts poorly with our invariant that display item (frame, key) pairs are unique.
We already have a better way to handle the latter case, and we use it for scrolling. FrameLayerBuilder calls nsLayoutUtils::GetActiveScrolledRoot on the frame for every display item to figure out what the nearest scrolling ancestor is, and display items are clustered into ThebesLayers so that all the items in a given ThebesLayer have the same active scrolled root. Each ThebesLayer is given a transform based on the scroll position of the active scrolled root for its items. (In bug 876321 and bug 913444 I extend that so that elements with animated top/left/right/bottom and margins are also considered active scrolled roots --- and it works beautifully and simply.)
I think we can keep extending this approach to handle position:fixed, touch-action and other properties that don't create stacking contexts. Here's how it looks:
-- GetActiveScrolledRoot is generalized to compute, for each display item, a key tuple of the values that will determine properties of its ThebesLayer. The members of this tuple will be:
* The nearest geometric ancestor frame that is being scrolled, or having its position animated, or is position:fixed.
* A boolean indicating whether the display item should trigger default panning behavior when touched.
Other fields can be added as needed.
-- Items with different key tuples are forced into different layers. Thus all items in a ThebesLayer have the same key tuple.
-- FrameLayerBuilder is responsible for assigning layer properties to ThebesLayers (and other layers) based on the key tuple. These properties include a layer transform, fixed positioning properties, and some new property for touch-action.
The first thing to do here is to rework nsDisplayFixedPosition to basically get rid of the display item and generalize GetActiveScrolledRoot instead.
Assignee | ||
Comment 1•11 years ago
|
||
This isn't going to help with touch-action unless we fix 918288 somehow.
Assignee | ||
Comment 2•11 years ago
|
||
This works nicely.
Assignee | ||
Comment 3•11 years ago
|
||
Attachment #810378 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 4•11 years ago
|
||
Attachment #810380 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 5•11 years ago
|
||
Attachment #810381 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 6•11 years ago
|
||
Attachment #810382 -
Flags: review?(matspal)
Assignee | ||
Comment 7•11 years ago
|
||
Attachment #810383 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 8•11 years ago
|
||
Attachment #810384 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 9•11 years ago
|
||
This is the main patch.
Attachment #810385 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 10•11 years ago
|
||
Attachment #810386 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 11•11 years ago
|
||
Attachment #810387 -
Flags: review?(matt.woodrow)
Assignee | ||
Comment 12•11 years ago
|
||
Attachment #810388 -
Flags: review?(matt.woodrow)
Comment 13•11 years ago
|
||
Comment on attachment 810382 [details] [diff] [review]
Part 4: Create nsLayoutUtils::IsFixedPosFrameWithDisplayPort
r=mats with a few nits:
>+++ b/layout/base/nsLayoutUtils.cpp
>+ aFrame->PresContext()->GetPresShell()->GetRootScrollFrame();
s/GetPresShell/PresShell/
>+ // Treat a fixed-pos frame as an animated geometry root if it belongs to
>+ // a viewport which has a scrollframe and a displayport
End the sentence with a period.
>+++ b/layout/base/nsLayoutUtils.h
>+ * Return true if aFrame is a fixed-pos frame and its viewport (its parent) has
>+ * a displayport.
That suggests that all fixed-pos frames are children of the viewport.
Could you rephrase it so that it doesn't do that, but also make it clear that only
(fixed-pos) child frames of the viewport are considered (which I assume is what
you mean). Perhaps:
* Return true if aFrame is a fixed-pos child frame of the viewport and
* the viewport has a displayport.
Also, the method name IsFixedPosFrameWithDisplayPort is a bit confusing.
It suggests that the displayport belongs to the fixed-pos frame.
Perhaps IsFixedPosChildFrameInDisplayPort matches the description better?
Attachment #810382 -
Flags: review?(matspal) → review+
Comment 14•11 years ago
|
||
Comment on attachment 810378 [details] [diff] [review]
Part 1: Rename identifiers from 'active scroll(ed) root' to 'animated geometry root'
Review of attachment 810378 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/base/FrameLayerBuilder.cpp
@@ +2069,5 @@
> }
>
> bool isFixed;
> bool forceInactive;
> + const nsIFrame* AnimatedGeometryRoot;
animatedGeometryRoot
Attachment #810378 -
Flags: review?(matt.woodrow) → review+
Comment 15•11 years ago
|
||
Comment on attachment 810380 [details] [diff] [review]
Part 2: Force creation of a layer for every viewport with a displayport
Review of attachment 810380 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/generic/nsSubDocumentFrame.cpp
@@ +373,5 @@
> nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
> bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
> bool needsOwnLayer = constructZoomItem ||
> + presContext->IsRootContentDocument() || (sf && sf->IsScrollingActive()) ||
> + (sf && nsLayoutUtils::GetDisplayPort(presShell->GetRootScrollFrame()->GetContent()));
This is slightly different to the GetDisplayPort call a few lines further up, can we just share them instead?
Updated•11 years ago
|
Attachment #810381 -
Flags: review?(matt.woodrow) → review+
Updated•11 years ago
|
Attachment #810383 -
Flags: review?(matt.woodrow) → review+
Updated•11 years ago
|
Attachment #810384 -
Flags: review?(matt.woodrow) → review+
Updated•11 years ago
|
Attachment #810387 -
Flags: review?(matt.woodrow) → review+
Comment 16•11 years ago
|
||
Comment on attachment 810385 [details] [diff] [review]
Part 7: Make fixed-pos frames with displayports animated geometry roots, and make FrameLayerBuilder responsible for setting fixed-pos layer parameters instead of nsDisplayFixedPositio n
Review of attachment 810385 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/base/FrameLayerBuilder.cpp
@@ +2157,2 @@
> bool forceInactive;
> + const nsIFrame* animatedGeometryRoot;
Looks like this fixes my comment from earlier :)
Attachment #810385 -
Flags: review?(matt.woodrow) → review+
Comment 17•11 years ago
|
||
Comment on attachment 810386 [details] [diff] [review]
Part 8: Delete lots of code that's no longer needed
Review of attachment 810386 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/base/nsDisplayList.cpp
@@ -1678,5 @@
> - }
> -
> - // Check if this background layer is attachment-fixed
> - if (mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED) {
> - aBuilder->SetHasFixedItems();
Heh, this confused me for a while. I guess this should have been in the nsDisplayCanvasBackgroundImage constructor really, we never return true for ShouldFixToViewport for non-canvas backgrounds.
Attachment #810386 -
Flags: review?(matt.woodrow) → review+
Updated•11 years ago
|
Attachment #810388 -
Flags: review?(matt.woodrow) → review+
Assignee | ||
Comment 18•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #13)
> That suggests that all fixed-pos frames are children of the viewport.
> Could you rephrase it so that it doesn't do that, but also make it clear
> that only
> (fixed-pos) child frames of the viewport are considered (which I assume is
> what
> you mean). Perhaps:
>
> * Return true if aFrame is a fixed-pos child frame of the viewport and
> * the viewport has a displayport.
>
> Also, the method name IsFixedPosFrameWithDisplayPort is a bit confusing.
> It suggests that the displayport belongs to the fixed-pos frame.
> Perhaps IsFixedPosChildFrameInDisplayPort matches the description better?
Yes, all good ideas.
Assignee | ||
Comment 19•11 years ago
|
||
Attachment #810380 -
Attachment is obsolete: true
Attachment #810380 -
Flags: review?(matt.woodrow)
Attachment #810971 -
Flags: review?(matt.woodrow)
Updated•11 years ago
|
Attachment #810971 -
Flags: review?(matt.woodrow) → review+
Assignee | ||
Comment 20•11 years ago
|
||
https://tbpl.mozilla.org/?tree=Try&rev=4de27991a6fe
https://hg.mozilla.org/integration/mozilla-inbound/rev/9820c500c65e
https://hg.mozilla.org/integration/mozilla-inbound/rev/910b46ec2248
https://hg.mozilla.org/integration/mozilla-inbound/rev/ab45d37e8d99
https://hg.mozilla.org/integration/mozilla-inbound/rev/146367e368d0
https://hg.mozilla.org/integration/mozilla-inbound/rev/1c809ffb8d08
https://hg.mozilla.org/integration/mozilla-inbound/rev/b337478518d7
https://hg.mozilla.org/integration/mozilla-inbound/rev/c7d20f37b046
https://hg.mozilla.org/integration/mozilla-inbound/rev/b5f7ce805487
https://hg.mozilla.org/integration/mozilla-inbound/rev/e815bda6bd08
https://hg.mozilla.org/integration/mozilla-inbound/rev/ff63da70a65f
https://hg.mozilla.org/mozilla-central/rev/9820c500c65e
https://hg.mozilla.org/mozilla-central/rev/910b46ec2248
https://hg.mozilla.org/mozilla-central/rev/ab45d37e8d99
https://hg.mozilla.org/mozilla-central/rev/146367e368d0
https://hg.mozilla.org/mozilla-central/rev/1c809ffb8d08
https://hg.mozilla.org/mozilla-central/rev/b337478518d7
https://hg.mozilla.org/mozilla-central/rev/c7d20f37b046
https://hg.mozilla.org/mozilla-central/rev/b5f7ce805487
https://hg.mozilla.org/mozilla-central/rev/e815bda6bd08
https://hg.mozilla.org/mozilla-central/rev/ff63da70a65f
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla28
Comment 22•11 years ago
|
||
This has caused all fixed-position headers on mobile-websites to jank when content is scrolled; see all the duplicates.
Updated•11 years ago
|
You need to log in
before you can comment on or make changes to this bug.
Description
•