Since bug 1524480 we set the NS_FRAME_MAY_BE_TRANSFORMED frame bit when needed
in RestyleManager::ProcessRestyledFrames so that it is now redundant to also set
it from KeyframeEffect.
Furthermore, setting frame bits from KeyframeEffect is a little fragile since it
depends on the life cycle of the KeyframeEffect which is independent of the
nsFrame. If we can avoid doing that, we probably should.
Differential Revision: https://phabricator.services.mozilla.com/D21885
For display:table content we generate two frames: a table wrapper frame and an
inner table frame. The styles are applied to the inner frame (referred to as the
style frame), whilst the wrapper frame is the primary frame for the content.
However, in order to make tables with transforms behave as a container for
abspos/fixed-pos content as required by the spec, we apply the transform to the
wrapper frame (bug 722777) by inheriting the transform from inner to wrapper and
then ignoring the transform on the inner frame (bug 722777 and bug 816458).
When handling animations on table elements we need to be careful of this
distinction. in particular, css animations[1] and web animations[2] require that
when we have an unfinished transform animation targetting an element, the
element acts as if it had `will-change: transform` applied and therefore
generates a stacking context. As a result we need to accurately detect when
a frame should be considered as having transform animations applied to it or not
for the purpose of creating a stacking context.
Previously our handling of display:table content was quite inconsistent and
contradictory. For example, `nsIFrame::HasAnimationOfTransform` would check for
a primary frame AND for animations on that frame, despite the fact that we only
ever store animations on the style frame. As a result it could never return true
for either a table wrapper or inner table frame.
This patch attempts to make this handling at least a little more consistent,
producing the following result:
Outer table frame (primary frame):
nsIFrame::IsTransformed → true
nsIFrame::IsCSSTransformed → true
nsIFrame::HasAnimationOfTransform → true
nsLayoutUtils::HasAnimationOfProperty(frame, eCSSProperty_transform) → false
Inner table frame (style frame):
nsIFrame::IsTransformed → false
nsIFrame::IsCSSTransformed → false
nsIFrame::HasAnimationOfTransform → false
nsLayoutUtils::HasAnimationOfProperty(frame, eCSSProperty_transform) → true
We maintain that the NS_FRAME_MAY_BE_TRANSFORMED bit is only set on the primary
frame whilst the mMayHaveTransformAnimation flag is only set on the style frame.
Note that we don't simply always put everything on the primary frame because for
other property types (e.g. opacity) the default setup of putting all styles and
animations on the style frame is simpler and correct. So far it is only
transforms that require special handling to apply the effect to the wrapper
frame.
This patch adds a reftest that fails without the code changes included in this
patch.
[1] https://drafts.csswg.org/css-animations/#animations
[2] https://drafts.csswg.org/web-animations-1/#side-effects-section
Differential Revision: https://phabricator.services.mozilla.com/D21883
Transform display item may have multiple properties, so it's better to
use display item type as the input.
Also, factor some code out of AddAnimationsForProperty, so we can easier
to extend this for multiple properties.
We will pass a list of layers::Animation to the compositor thread. In
this list, the animations belonging to the same property are grouped together,
so we can easily separate the animations by property and sample the animations
for each property on the compositor thread. (Will do this in Bug 1425837.)
Depends on D19628
Differential Revision: https://phabricator.services.mozilla.com/D19629
This doesn't matter yet because all the states that return a change hint are on
stylesheets, but will matter with bug 1472637.
Differential Revision: https://phabricator.services.mozilla.com/D21616
This doesn't matter yet because all the states that return a change hint are on
stylesheets, but will matter with bug 1472637.
Differential Revision: https://phabricator.services.mozilla.com/D21616
Only nsBlockFrame and its subclasses recognize the nsIFrame::eBlockFrame
flag, so we can replace the usage of the flag with either
nsIFrame::IsBlockFrameOrSubclass() or a do_QueryFrame().
Differential Revision: https://phabricator.services.mozilla.com/D20542
This is more consistent with all the other image request code, and handles
pseudo-elements properly without having to add more out-of-band calls to
UpdateStyleOfOwnedChildFrame and such.
Differential Revision: https://phabricator.services.mozilla.com/D20107
This is more consistent with what the Rust bits of the style system do, and
removes a pointer from ComputedStyle which is always nice.
This also aligns the Rust bits with the C++ bits re. not treating xul pseudos as
anonymous boxes. See the comment in nsTreeStyleCache.cpp regarding those.
Can't wait for XUL trees to die.
Depends on D19001
Differential Revision: https://phabricator.services.mozilla.com/D19002
Even less so on reframe, where it's just unsound to do so. I had to give a value
to eSetValue_Internal, since otherwise I cannot check for its presence. I can
further special-case the reframe case if you prefer.
Differential Revision: https://phabricator.services.mozilla.com/D20133
This is more consistent with all the other image request code, and handles
pseudo-elements properly without having to add more out-of-band calls to
UpdateStyleOfOwnedChildFrame and such.
Differential Revision: https://phabricator.services.mozilla.com/D20107
These assertions can happen in certain circumstances (see the referenced bug).
These assertions are not security sensitive, but they affect correctness.
They're old (from before my change), so I prefer dealing with them in a public
bug and stop crashing release for now.
Differential Revision: https://phabricator.services.mozilla.com/D20105
Just for my sanity. I think the other scroll observer is sane after a quick
look, but this will ensure we don't ship security issues.
Differential Revision: https://phabricator.services.mozilla.com/D19725
Typically we set the NS_FRAME_MAY_BE_TRANSFORMED bit on a frame when one of the
following situations arises:
a. We update the keyframes of a KeyframeEffect to include transforms or we
create a new KeyframeEffect that animates transforms (in
KeyframeEffect::SetKeyframes), or
b. We retarget a KeyframeEffect with transforms at a new element (in
KeyframeEffect::SetTarget), or
c. We create an nsFrame with transform animations applied to it (in
nsFrame::Init), or
d. We get a nsChangeHint_AddOrRemoveTransform hint in
RestyleManager::ProcessRestyledFrames and decide to update the frame bit on
the frame and its continuations accordingly.
However, there are some situations where we can have a transform animation on
a frame where none of the above are triggered.
For example, if the style frame is not unavailable (e.g. a display:none
element) when the KeyframeEffect is initialized we will fail to the frame bit in
(a) and if we never retarget the effect we will never set reach (b).
Furthermore, if we have an animation that is "not relevant" (e.g. idle) and
hence not registered with the EffectSet when the frame is initialized we will
fail to set the frame bit in (c).
Finally, if the the animation does not produce a style change that causes the
nsChangeHint_AddOrRemoveTransform bit to be set (e.g. the transform animation
begins at 'none') we will not set the frame bit in (d).
As a result, we can end up failing to set the NS_FRAME_MAY_BE_TRANSFORMED bit
for some content.
The crashtest included in this patch produces such a case and, without the code
changes in this patch, will fail the assertion in ApplyRenderingChangeToTree[1]:
NS_ASSERTION(!(aChange & nsChangeHint_UpdateTransformLayer) ||
aFrame->IsTransformed() ||
aFrame->StyleDisplay()->HasTransformStyle(),
"Unexpected UpdateTransformLayer hint");
That is because although the nsChangeHint_UpdateTransformLayer bit will be set,
aFrame->IsTransformed() will return false because the frame bit has not been
set, and aFrame->StyleDisplay()->HasTransformStyle() will return false because
the animation sets the transform to 'none'.
Not only will this assertion fail, but once we cease flushing style as part of
triggering an animation later in this patch, the reftest
layout/reftests/web-animations/stacking-context-transform-changing-effect.html
will begin to fail. That reftest produces a similar situation to the crashtest
but it currently does not fail because the style flush that happens as part of
creating an animation ensures the style frame is available at the point when the
animation is triggered and hence case (a) from above is hit.
This patch addresses this by detecting the case where we have this change hint
set but not the corresponding frame bit, and setting the frame bit.
[1] https://searchfox.org/mozilla-central/rev/9eb30227b21e0aa40d51d9f9b08bb0b113c5fadb/layout/base/RestyleManager.cpp#1191-1199
Differential Revision: https://phabricator.services.mozilla.com/D18911
This patch should make the detection of whether we should reframe in
UpdateContainingBlock exact.
It should have no behavior change, but sometimes reframing can confuse event
handling code or what not.
We don't have a reduced test-case for the event handling regression this fixes,
but I added a test to ensure we don't uselessly reframe in this case that fails
without this patch and passes with.
Differential Revision: https://phabricator.services.mozilla.com/D16333
We currently perform anchor adjustment in three spots:
1. If the target of RestyleManager::RecomputePosition is in a scroll anchor chain
2. If the reflow root is in a scroll anchor chain
3. In nsHTMLScrollFrame::DidReflow, for itself
It looks like it's possible for a scroll anchor container to be adjusted by (1)
and (2 or 3) in the same PresShell flush.
This should be okay, except that we consume mSuppressAnchorAdjustment when
performing an adjustment, and this can lead us to miss the second time that
we perform adjustments in a PresShell flush.
This commit reworks how we run anchor adjustments so that we collect all
scroll anchor containers that should be adjusted, and only perform the
adjustments once.
Differential Revision: https://phabricator.services.mozilla.com/D16407
This commit implements the second half of the heuristics to detect style changes
that could lead to feedback loops with scroll anchoring. [1]
A new change hint is added for when a style is changed from positioned to not
positioned. When this hint is applied, scroll anchor suppression is triggered in
the scroll anchor container where the frame used to be, and the new scroll
anchor container where the frame is added after reconstruction.
[1] https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers
Differential Revision: https://phabricator.services.mozilla.com/D13273
This commit implements anchor offset adjustment. When the position of a frame
that is an anchor is changed during reflow, we notify the anchor container. The
anchor container will then post a reflow callback.
Then when reflow is completed, the anchor container will perform a scroll to
keep the anchor node in the same relative position.
Differential Revision: https://phabricator.services.mozilla.com/D13270
This commit adds a mechanism for scroll anchor containers to request an anchor
node selection at a future time. Currently this is before styling so that anchor
adjustment suppression will have current anchor nodes.
Differential Revision: https://phabricator.services.mozilla.com/D13269
This commit implements the second half of the heuristics to detect style changes
that could lead to feedback loops with scroll anchoring. [1]
A new change hint is added for when a style is changed from positioned to not
positioned. When this hint is applied, scroll anchor suppression is triggered in
the scroll anchor container where the frame used to be, and the new scroll
anchor container where the frame is added after reconstruction.
[1] https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers
Differential Revision: https://phabricator.services.mozilla.com/D13273
This commit implements anchor offset adjustment. When the position of a frame
that is an anchor is changed during reflow, we notify the anchor container. The
anchor container will then post a reflow callback.
Then when reflow is completed, the anchor container will perform a scroll to
keep the anchor node in the same relative position.
Differential Revision: https://phabricator.services.mozilla.com/D13270
This commit adds a mechanism for scroll anchor containers to request an anchor
node selection at a future time. Currently this is before styling so that anchor
adjustment suppression will have current anchor nodes.
Differential Revision: https://phabricator.services.mozilla.com/D13269
Summary: Really sorry for the size of the patch. It's mostly automatic
s/nsIDocument/Document/ but I had to fix up in a bunch of places manually to
add the right namespacing and such.
Overall it's not a very interesting patch I think.
nsDocument.cpp turns into Document.cpp, nsIDocument.h into Document.h and
nsIDocumentInlines.h into DocumentInlines.h.
I also changed a bunch of nsCOMPtr usage to RefPtr, but not all of it.
While fixing up some of the bits I also removed some unneeded OwnerDoc() null
checks and such, but I didn't do anything riskier than that.
So we do it while we're still handling re-entrant changes for SVG, since SVG can
post change hints from UpdateOverflow().
Differential Revision: https://phabricator.services.mozilla.com/D12102
All of the removed includes are redundant (i.e. they're #included elsewhere in
the same file).
In most cases, I'm removing the second (redundant) copy of the
#include, except when that copy makes more sense (i.e. if it's in better sorted
order, or if it's paired alongside a closely-associated header while the
earlier copy is not).
Here's the script that I used to generate candidates here -- I ran this in
every subdirectory of layout, on my linux machine (warning, this writes two
files to your /tmp directory):
for FILE in *.h *.cpp; do
nonunique=$(grep \#include $FILE | grep -v List\.h | cut -f2 -d'"' | cut -f2- -d'/'| cut -f2- -d'/' | sort | wc -l)
unique=$( grep \#include $FILE | grep -v List\.h | cut -f2 -d'"' | cut -f2- -d'/'| cut -f2- -d'/' | sort | uniq | wc -l)
if [[ "$unique" != "$nonunique" ]]; then
echo "$FILE: $nonunique / $unique"
grep \#include $FILE | cut -f2 -d'"' | grep -v List\.h | cut -f2- -d'/'| cut -f2- -d'/' | sort > /tmp/nonunique.txt
grep \#include $FILE | cut -f2 -d'"' | grep -v List\.h | cut -f2- -d'/'| cut -f2- -d'/' | sort | uniq > /tmp/unique.txt
diff /tmp/nonunique.txt /tmp/unique.txt
echo
fi
done
Depends on D13773
Differential Revision: https://phabricator.services.mozilla.com/D13774
Just adding:
- a missing-but-needed forward-decl (in LayersLogging.h which is
included by files in layout/base).
- a 'using' decl (to provide layers::AnimationInfo).
- a missing-but-needed #include for nsCOMPtr.
Differential Revision: https://phabricator.services.mozilla.com/D12964
Bug 828240 switched the children only transform on an outer svg from applying to
each of the anonymous child's children to applying directly to the anonymous
child instead. So now when the viewBox changes on an outer svg, we need to
update (just) the overflow of the anonymous child. The children only transform
on an inner svg still applies to the children of the inner svg, so we continue
updating those children in that case.
Hit testing uses overflows as part of the testing process, so was broken by the
lack of overflow updates.
Differential Revision: https://phabricator.services.mozilla.com/D5668