Bug 1374761 part 1. Properly restyle the viewport and its child anonymous box when we do a restyle. r?heycam
The child anon box may be an nsHTMLScrollFrame, a nsRootBoxFrame, or a
nsSimplePageSequenceFrame. nsHTMLScrollFrame already knows how to deal with
its anonymous box kids, nsRootBoxFrame doesn't have any, and the next changeset
will deal with anon box kids of nsSimplePageSequenceFrame.
MozReview-Commit-ID: 2ZV061EhRmc
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ServoRestyleManager.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/Unused.h"
+#include "mozilla/ViewportFrame.h"
#include "mozilla/dom/ChildIterator.h"
#include "mozilla/dom/ElementInlines.h"
#include "nsBlockFrame.h"
#include "nsBulletFrame.h"
#include "nsPlaceholderFrame.h"
#include "nsContentUtils.h"
#include "nsCSSFrameConstructor.h"
#include "nsPrintfCString.h"
@@ -424,16 +425,25 @@ ServoRestyleManager::ProcessPostTraversa
displayContentsNode->mStyle = newContext;
}
if (styleFrame) {
styleFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeList, changeHint);
UpdateFramePseudoElementStyles(styleFrame, *aStyleSet, aChangeList);
}
+ if (!aElement->GetParent()) {
+ // This is the root. Update styles on the viewport as needed.
+ ViewportFrame* viewport =
+ do_QueryFrame(mPresContext->PresShell()->GetRootFrame());
+ if (viewport) {
+ viewport->UpdateStyle(*aStyleSet, aChangeList);
+ }
+ }
+
// Some changes to animations don't affect the computed style and yet still
// require the layer to be updated. For example, pausing an animation via
// the Web Animations API won't affect an element's style but still
// requires to update the animation on the layer.
//
// We can sometimes reach this when the animated style is being removed.
// Since AddLayerChangesForAnimation checks if |styleFrame| has a transform
// style or not, we need to call it *after* setting |newContext| to
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2754,16 +2754,18 @@ nsCSSFrameConstructor::ConstructRootFram
ViewportFrame* viewportFrame =
NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
// XXXbz do we _have_ to pass a null content pointer to that frame?
// Would it really kill us to pass in the root element or something?
// What would that break?
viewportFrame->Init(nullptr, nullptr, nullptr);
+ viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
+
// Bind the viewport frame to the root view
nsView* rootView = mPresShell->GetViewManager()->GetRootView();
viewportFrame->SetView(rootView);
viewportFrame->SyncFrameViewProperties(rootView);
nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
rootView, nullptr, nsContainerFrame::SET_ASYNC);
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -410,15 +410,44 @@ ViewportFrame::ComputeCustomOverflow(nsO
PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
return false;
}
return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
}
+void
+ViewportFrame::UpdateStyle(ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList)
+{
+ nsStyleContext* oldContext = StyleContext();
+ nsIAtom* pseudo = oldContext->GetPseudo();
+ RefPtr<nsStyleContext> newContext =
+ aStyleSet.ResolveInheritingAnonymousBoxStyle(pseudo, nullptr);
+
+ // We're special because we have a null GetContent(), so don't call things
+ // like UpdateStyleOfOwnedChildFrame that try to append changes for the
+ // content to the change list. Nor do we computed a changehint, since we have
+ // no way to apply it anyway.
+ newContext->EnsureSameStructsCached(oldContext);
+
+ MOZ_ASSERT(!GetNextContinuation(), "Viewport has continuations?");
+ SetStyleContext(newContext);
+
+ UpdateStyleOfOwnedAnonBoxes(aStyleSet, aChangeList, nsChangeHint_Empty);
+}
+
+void
+ViewportFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
+{
+ if (mFrames.NotEmpty()) {
+ aResult.AppendElement(mFrames.FirstChild());
+ }
+}
+
#ifdef DEBUG_FRAME_DUMP
nsresult
ViewportFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("Viewport"), aResult);
}
#endif
--- a/layout/generic/ViewportFrame.h
+++ b/layout/generic/ViewportFrame.h
@@ -67,16 +67,27 @@ public:
/**
* Adjust aReflowInput to account for scrollbars and pres shell
* GetScrollPositionClampingScrollPortSizeSet and
* GetContentDocumentFixedPositionMargins adjustments.
* @return the rect to use as containing block rect
*/
nsRect AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) const;
+ /**
+ * Update our style (and recursively the styles of any anonymous boxes we
+ * might own)
+ */
+ void UpdateStyle(ServoStyleSet& aStyleSet, nsStyleChangeList& aChangeList);
+
+ /**
+ * Return our single anonymous box child.
+ */
+ void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
+
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
ViewportFrame(nsStyleContext* aContext, ClassID aID)
: nsContainerFrame(aContext, aID)
, mView(nullptr)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10203,17 +10203,18 @@ nsFrame::BoxMetrics() const
void
nsIFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
MOZ_ASSERT(aChildFrame->GetParent() == this,
"This should only be used for children!");
- MOZ_ASSERT(aChildFrame->GetContent() == GetContent(),
+ MOZ_ASSERT((!GetContent() && IsViewportFrame()) ||
+ aChildFrame->GetContent() == GetContent(),
"What content node is it a frame for?");
MOZ_ASSERT(!aChildFrame->GetPrevContinuation(),
"Only first continuations should end up here");
// We could force the caller to pass in the pseudo, since some callers know it
// statically... But this API is a bit nicer.
nsIAtom* pseudo = aChildFrame->StyleContext()->GetPseudo();
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(pseudo), "Child is not an anon box?");