import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1251797 - Don't fault struct out of rule tree if all of the potential physical property destinations already have a winning value in the cascade. r=heycam (b64f25ae75)
- Bug 1257688 part 0: Add an "IsLegacyBox" accessor to nsFlexContainerFrame, to enable special handling of display:-webkit-box & display:-webkit-inline-box. r=mats (f728070412)
- Bug 1257688 part 1: Change "-webkit-box-pack" & "-webkit-box-align" to alias their -moz equivalents, & change nsFlexContainerFrame to respect them in a -webkit-box. r=mats (fda7e641bb)
- Bug 1174248 - Apply RTL resizer failure only to GTK2. r=karlt (5f264b52bc)
- Bug 1234941 part 1: Add reftests for "-webkit-box" rendering, with -webkit-box-orient unset. r=heycam (bbdb2737a0)
- Bug 1234941 part 2: Add reftests for "-webkit-box" rendering, with -webkit-box-orient:horizontal. r=heycam (815f24f010)
- Bug 1234941 part 3: Add reftests for "-webkit-box" rendering, with -webkit-box-orient:vertical. r=heycam (a4f71266b9)
- Bug 1257688 part 2: Enable "-webkit-box-pack: justify" sections of -webkit-box reftests, & fix reference cases to use 'space-between' (the modern equivalent). (no review) (7641615ec0)
- Bug 1257688 part 3: Change "-webkit-box-ordinal-group" to alias its -moz equivalent, & change nsFlexContainerFrame to respect it in a -webkit-box. r=mats (90797264fe)
- Bug 1257688 part 4: Add reftests for -webkit-box-ordinal-group inside of display:-webkit-box. r=mats (7623b7a5dd)
- Bug 1257688 part 5: Change "-webkit-box-flex" to alias its -moz equivalent, & change nsFlexContainerFrame to use it instead of flex-shrink & flex-grow in a -webkit-box. r=mats (dabf0415f3)
- Bug 1257688 part 6: Add reftest for -webkit-box-flex inside of display:-webkit-box. r=mats (06d1384d0b)
- Bug 1257688 followup: Fix typo in <title>s in webkit-box-ordinal-group reftests. (no review, test-metadata only) (b8753af073)
- Bug 1262049 part 1: Back out bug 1208344 in its entirety, and mark -webkit-box-orient:vertical reftests as failing (for now). (no review) (fd3890a164)
- Bug 1262049 part 2: Add -webkit-box-orient & -webkit-box-direction as aliases for -moz versions, in the style system (but not yet honored by flexbox layout). r=mats (33e137427f)
- Bug 1262049 part 3: Refactor FlexboxAxisTracker constructor to take pointer to nsFlexContainerFrame. r=mats (0e9a26b85d)
- Bug 1262049 part 4: Refactor some of FlexboxAxisTracker constructor's logic into a helper method. r=mats (c298827ed2)
- Bug 1264837 Part 1 - Remove nsTextBoxFrameSuper. r=dholbert (dc64371da6)
- Bug 1264837 Part 2 - Remove nsColorControlFrameSuper. r=dholbert (166c5c13c3)
- Bug 1264837 Part 3 - Remove nsFormControlFrameSuper. r=dholbert (70c4c13c79)
- Bug 1264837 Part 4 - Remove nsImageControlFrameSuper. r=dholbert (68af4648e6)
- Bug 1264837 Part 5 - Remove nsFlexContainerFrameSuper. r=dholbert (ef7b1a912e)
- Bug 1261553 - Don't return from OnVisibilityChanged implementations without calling the superclass implementation. r=mstange (033d4cdf72)
- Bug 1264837 Part 6 - Remove ImageFrameSuper. r=dholbert (cbf002ba56)
- Bug 1264837 Part 7 - Remove nsInlineFrameBase r=dholbert (42e277593f)
- Bug 1262049 part 5: Honor -webkit-box-orient & -webkit-box-direction when determining axes for a -webkit-box flexbox. r=mats (a4f03722ed)
- Bug 1262049 part 6: Add reftest for -webkit-box-direction. (no review) (d41936d107)
- Bug 1266248 part 1: Rename MapSinglePropertyInto() args, to make src-vs-target distinctions clearer. r=heycam (2d46c21c34)
- Bug 1266248 part 2: Add assertion to verify that MapSinglePropertyInto() isn't called with a logical target-property. r=heycam (c51b780a2b)
- Bug 1264837 Part 8 - Remove nsPluginFrameSuper. r=dholbert (615738f0f0)
- Bug 1264837 Part 9 - Remove nsRubyBaseFrameSuper. r=dholbert (0fb30cf0a3)
- Bug 1264837 Part 10 - Remove nsRubyContentFrameSuper. r=dholbert (df02f9983c)
- Bug 1264837 Part 11 - Remove nsRubyFrameSuper. r=dholbert (684a20009b)
- Bug 1264837 Part 12 - Remove nsRubyTextContainerFrameSuper. r=dholbert (4961565c4b)
- Bug 1264837 Part 13 - Remove nsRubyTextFrameSuper. r=dholbert (aa9e863378)
- bits of  1261230 (cffbacd922)
- Bug 1264837 Part 14 - Remove nsSubDocumentFrameSuper. r=dholbert (2ddc0b2028)
- Bug 1264837 Part 15 - Remove nsVideoFrameBase r=dholbert (c1246fd0bc)
- Bug 1264837 Part 16 - Remove ViewportFrame::Super. r=dholbert (dff457b117)
- Bug 1264837 Part 17 - Remove nsSVGAFrameBase. r=dholbert (0df66e92c5)
- Bug 1253590, part 1 - Generalize AutoReferenceLoopDetector to allow it to be used to limit reference chain lengths. r=longsonr (e1673d2e9e)
- Bug 1253590, part 2 - Use the new AutoReferenceLimiter helper to limit clip path reference chain lengths. r=longsonr (4e03ec9001)
- Bug 1253590, part 3 - Crashtest for long clipPath reference chains. r=longsonr (c4da0e1dc4)
- Bug 1253590, part 4 - Follow-up to return the correct type. r=bustage (61c7fd965a)
- Bug 1264837 Part 18 - Remove nsSVGClipPathFrameBase. r=dholbert (ec78340590)
- Bug 1264837 Part 19 - Remove nsSVGContainerFrameBase. r=dholbert (57c5c44826)
- Bug 1264837 Part 20 - Remove nsSVGFilterFrameBase. r=dholbert (5f41a15a86)
- Bug 1264837 Part 21 - Remove nsSVGForeignObjectFrameBase. r=dholbert (c9aeb556ce)
- Bug 1264837 Part 22 - Remove nsSVGGenericContainerFrameBase. r=dholbert (bd4e21975d)
- Bug 1264837 Part 23 - Remove nsSVGGFrameBase. r=dholbert (bed40424fd)
- Bug 1264837 Part 24 - Remove nsSVGGradientFrameBase. r=dholbert (a9a7d3e0d4)
- Bug 1264837 Part 25 - Remove nsSVGLinearGradientFrameBase. r=dholbert (a48ed6b6b2)
- Bug 1264837 Part 26 - Remove nsSVGRadialGradientFrameBase. r=dholbert (76181ad3b2)
- Bug 1264837 Part 27 - Remove nsSVGImageFrameBase. r=dholbert (5aaa32517d)
- Bug 1242256 - ensure images in patterns and masks animate properly. r=jwatt,seth (cc40ee9520)
- Bug 1264837 Part 28 - Remove nsSVGInnerSVGFrameBase. r=dholbert (04b9d9b5fb)
- Bug 1264837 Part 29 - Remove nsSVGMarkerFrameBase. r=dholbert (bc28eca472)
- Bug 1264837 Part 30 - Remove nsSVGMarkerAnonChildFrameBase. r=dholbert (6898a93a31)
- Bug 1264837 Part 31 - Remove nsSVGMaskFrameBase. r=dholbert (26d0e7a5e1)
- Bug 1264837 Part 32 - Remove nsSVGOuterSVGFrameBase. r=dholbert (a473ae8be3)
- Bug 1264837 Part 33 - Remove nsSVGOuterSVGAnonChildFrameBase. r=dholbert (8c6cca5e9b)
- Bug 1264837 Part 34 - Remove nsSVGPaintServerFrameBase. r=dholbert (eab458bfab)
- Bug 1264837 Part 35 - Remove nsSVGPathGeometryFrameBase. r=dholbert (e5245d2be0)
- Bug 1264837 Part 36 - Remove nsSVGPatternFrameBase. r=dholbert (2df37d4056)
- Bug 1264837 Part 37 - Remove nsSVGStopFrameBase. r=dholbert (e367dba151)
- Bug 1264837 Part 38 - Remove nsSVGSwitchFrameBase. r=dholbert (7ffe7a731a)
- Bug 1264837 Part 39 - Remove nsSVGUseFrameBase. r=dholbert (b4445728e3)
- Bug 1264837 Part 40 - Remove SVGFEContainerFrameBase. r=dholbert (ee08ef9caf)
- Bug 1264837 Part 41 - Remove SVGFEImageFrameBase. r=dholbert (010f79b418)
- Bug 1264837 Part 42 - Remove SVGFELeafFrameBase. r=dholbert (949aeba02d)
- Bug 1264837 Part 44 - Remove SVGTextFrameBase. r=dholbert (bfd0603d44)
- Bug 1264837 Part 45 - Remove SVGViewFrameBase. r=dholbert (151f3c95b2)
- Bug 1265591 patch 1 - Remove Internal/External versions of ReconstructStyleData. r=heycam (a91f96e3b3)
- Bug 1265591 patch 2 - Rename nsIPresShell::ReconstructStyleData to RestyleForCSSRuleChanges. r=heycam (8ad2bc3021)
- Bug 1265591 patch 3 - Make the comment describing RestyleForCSSRuleChanges match reality. r=heycam (2ef053622d)
- Bug 1251150. Add crash annotations if image visibility is re-entering. r=mats (975a3e98d7)
- Bug 1261554 (Part 1) - Prepare for implementing in-displayport visibility tracking. r=mstange (b139489249)
- Bug 1261554 (Part 2) - Mark frames which are added to the display list when painting to the window as having Visibility::IN_DISPLAYPORT. r=mstange (4c8185bf0e)
- Bug 1259529 - Clean up the APZ minimap rendering code a bit. No functional changes. r=BenWa (9b99c27777)
- Bug 1256532 - Show the critical displayport in the APZ minimap as well. r=BenWa (9b131616a0)
- Bug 1251886 - Correct inputFrameID selection when using e10s r=daoshengmu (9e042f6af3)
- Bug 1261554 (Part 3) - Visualize Visibility::IN_DISPLAYPORT regions in the APZ minimap visibility debugger. r=botond (f9b72319e1)
- Bug 1261554 (Followup) - Fix memory reporting for PresShell::mVisibleRegions. r=me (6fc953c1de)
- Bug 1259529 - Ensure that the APZ minimap for subframes remains scaled to the visible portion of the composition bounds. r=BenWa (9f156773cf)
- Bug 1251150. Back out crash annotations used to try to diagnose crash. (db6ba80214)
- missing bits of Bug 1258476 - Optimize CreateRangePaintInfo by generating display lists for the minimum amount of range subtrees rather than for the range common ancestor. r=tn (2ded969082)
- Bug 1237821. Use displayport getter for image visibility in the (unused) display list builder based image visibility code. r=botond (a634182065)
- Bug 1253995 - Display stale image in nsImageFrame if we have a new src but haven't decoded it yet - r=seth (6add357448)
- Bug 1261703. When moving flex frame, position its view as well as any child views. r=dholbert (abd586f55f)
- bug 1246772 - work around x87 floating point truncation issues in gecko r=dholbert (de38865a9f)
- missing bits of 1202908 (4a254234f7)
- Bug 1249134: Remove support for -webkit-appearance as an alias for -moz-appearance, since the two prefixed properties behave differently in practice. r=heycam (7fd6826fb0)
- Bug 1249937 - Rename LayerComposite::SetShadowTransform to SetShadowBaseTransform. r=botond (c91f175b8d)
- Bug 1260335 - On perspective ContainerLayers, the clip deferred from their child layer needs to be affected by the perspective layer's async transforms. r=botond (ee1a19e113)
- Bug 1260335 - Add a comment that explains why the perspective child can't have more than one frame metrics. r=mattwoodrow (639d9ede24)
- Bug 1148978 - Remove plugin window update composition deferment. r=mattwoodrow (01e7da3570)
- Bug 1263515 - Destroy the compositor earlier in RecvWillStop when it still has a valid widget. r=jnicol (c14135bf7c)
- Bug 1258440 - Don't attempt to hide plugin windows when switching trees if the previous remote layer tree didn't contain plugin windows. Fixes a tpaint regression. r=mconley (929db2fdf2)
- Bug 1260976 - Make nsTransitionManager use Keyframe objects to set up transitions; r=heycam (3b8ef91fe9)
- Bug 1265611 - Make TransitionProperty() and ToValue() safe when mProperties is not set; r=heycam (37d234aad4)
- Bug 1259675 - Clean up InternalTransitionEvent r=masayuki (f6526d4dfa)
- Bug 1260976 - Remove some references to properties within nsTransitionManager; r=heycam (6c0f84fb17)
- Bug 1182856 - Part 4: Refactor code in nsTransitionManager::StyleContextChanged(). r=heycam (ee0f4d76fd)
- Bug 1182856 - Part 5: Avoid unnecessary transition update if display:none. r=heycam (5e01fff5cc)
- Bug 1182856 - Part 6: Revise tests for display:none in test_transitions.html. r=heycam (ac2dfe8e47)
- Bug 1182856 - Part 7: Test. r=cam (2aed7d5ae6)
- Bug 1265611 - Don't trigger transitions for properties that are disabled; r=heycam (dabf201421)
- Bug 1247533 - Annotate intentional switch fallthrough to suppress -Wimplicit-fallthrough warning in layout/style/. r=dbaron (a0b748bea2)
- Bug 1264830 - Part 1: Add an nsStyleAutoArray array type, similar to AutoTArray<...,1> but memmovable. r=bholley (ad4eb0692c)
- Bug 1264830 - Part 2: Change nsStyleImageLayers::mLayers to use nsStyleAutoArray. r=bholley (963a9e4033)
- Bug 1264830 - Part 3: Change nsStyleDisplay::{mTransitions,mAnimations} to use nsStyleAutoArray. r=bholley (396812da9d)
- Bug 1264830 - Part 4: Change nsStyleDisplay::mWillChange to use nsTArray. r=bholley (7dead8570f)
- Bug 1264830 - Part 5: Require all style structs be memmovable. r=bholley (8fdd844d1c)
- Bug 1244628: compare nsStyleImageLayers::mAttachmentCount in nsStyleImageLayers::CalcDifference. r=dbaron. (11e2bb1665)
- Bug 1252739 - nsStyleImageLayers::HasLayerWithImage should return true when we have mask-image:<element-reference> | <gradient>; r=dbaron (904b65a0e5)
- cleanup empty line (8263e0793e)
- Bug 1261392 - Define gettid for all Linux builds. r=bgirard (781ae95acc)
This commit is contained in:
2024-06-13 11:26:16 +08:00
parent a916628ef3
commit 28eae10bc7
144 changed files with 4705 additions and 1545 deletions
@@ -7,4 +7,3 @@
/ssltunnel
/xpcshell
/XUL
+9 -9
View File
@@ -285,9 +285,8 @@ nsImageLoadingContent::OnUnlockedDraw()
return;
}
if (frame->GetVisibility() == Visibility::APPROXIMATELY_VISIBLE) {
// This frame is already marked visible; there's nothing to do.
return;
if (frame->IsVisibleOrMayBecomeVisibleSoon()) {
return; // Nothing to do.
}
nsPresContext* presContext = frame->PresContext();
@@ -300,7 +299,7 @@ nsImageLoadingContent::OnUnlockedDraw()
return;
}
presShell->EnsureFrameInApproximatelyVisibleList(frame);
presShell->MarkFrameVisibleInDisplayPort(frame);
}
nsresult
@@ -527,7 +526,7 @@ nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
nsIPresShell* presShell = presContext ? presContext->GetPresShell() : nullptr;
if (presShell) {
presShell->RemoveFrameFromApproximatelyVisibleList(aFrame);
presShell->MarkFrameNonvisible(aFrame);
}
}
@@ -1423,12 +1422,13 @@ nsImageLoadingContent::OnVisibilityChange(Visibility aNewVisibility,
const Maybe<OnNonvisible>& aNonvisibleAction)
{
switch (aNewVisibility) {
case Visibility::APPROXIMATELY_VISIBLE:
case Visibility::MAY_BECOME_VISIBLE:
case Visibility::IN_DISPLAYPORT:
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
break;
case Visibility::APPROXIMATELY_NONVISIBLE:
case Visibility::NONVISIBLE:
UntrackImage(mCurrentRequest, aNonvisibleAction);
UntrackImage(mPendingRequest, aNonvisibleAction);
break;
@@ -1454,11 +1454,11 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage)
}
// We only want to track this request if we're visible. Ordinarily we check
// the visible count, but that requires a frame; in cases where
// whether our frame considers itself visible, but in cases where
// GetOurPrimaryFrame() cannot obtain a frame (e.g. <feImage>), we assume
// we're visible if FrameCreated() was called.
nsIFrame* frame = GetOurPrimaryFrame();
if ((frame && frame->GetVisibility() == Visibility::APPROXIMATELY_NONVISIBLE) ||
if ((frame && !frame->IsVisibleOrMayBecomeVisibleSoon()) ||
(!frame && !mFrameCreateCalled)) {
return;
}
+6 -6
View File
@@ -47,9 +47,9 @@ TransitionEvent::Constructor(const GlobalObject& aGlobal,
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
InternalTransitionEvent* internalEvent = e->mEvent->AsTransitionEvent();
internalEvent->propertyName = aParam.mPropertyName;
internalEvent->elapsedTime = aParam.mElapsedTime;
internalEvent->pseudoElement = aParam.mPseudoElement;
internalEvent->mPropertyName = aParam.mPropertyName;
internalEvent->mElapsedTime = aParam.mElapsedTime;
internalEvent->mPseudoElement = aParam.mPseudoElement;
e->SetTrusted(trusted);
return e.forget();
@@ -58,7 +58,7 @@ TransitionEvent::Constructor(const GlobalObject& aGlobal,
NS_IMETHODIMP
TransitionEvent::GetPropertyName(nsAString& aPropertyName)
{
aPropertyName = mEvent->AsTransitionEvent()->propertyName;
aPropertyName = mEvent->AsTransitionEvent()->mPropertyName;
return NS_OK;
}
@@ -72,13 +72,13 @@ TransitionEvent::GetElapsedTime(float* aElapsedTime)
float
TransitionEvent::ElapsedTime()
{
return mEvent->AsTransitionEvent()->elapsedTime;
return mEvent->AsTransitionEvent()->mElapsedTime;
}
NS_IMETHODIMP
TransitionEvent::GetPseudoElement(nsAString& aPseudoElement)
{
aPseudoElement = mEvent->AsTransitionEvent()->pseudoElement;
aPseudoElement = mEvent->AsTransitionEvent()->mPseudoElement;
return NS_OK;
}
+2 -2
View File
@@ -2657,7 +2657,7 @@ nsHTMLDocument::TearingDownEditor(nsIEditor *aEditor)
presShell->SetAgentStyleSheets(agentSheets);
presShell->ReconstructStyleData();
presShell->RestyleForCSSRuleChanges();
}
}
@@ -2821,7 +2821,7 @@ nsHTMLDocument::EditingStateChanged()
rv = presShell->SetAgentStyleSheets(agentSheets);
NS_ENSURE_SUCCESS(rv, rv);
presShell->ReconstructStyleData();
presShell->RestyleForCSSRuleChanges();
// Adjust focused element with new style but blur event shouldn't be fired
// until mEditingState is modified with newState.
+2
View File
@@ -72,3 +72,5 @@ load 880544-3.svg
load 880544-4.svg
load 880544-5.svg
load 898915-1.svg
# Disabled for now due to it taking a very long time to run - bug 1259356
#load long-clipPath-reference-chain.svg
@@ -0,0 +1,53 @@
<svg xmlns="http://www.w3.org/2000/svg">
<title>Test very long clipPath chain - MAY CRASH</title>
<script><![CDATA[
// This script creates a very long chain of clipPath elements to test whether
// that causes a stack overflow that crashes the UA. The first clipPath clips
// to a 50x100 rect, the last to a 25x100 rect. If a UA was to apply the
// entire clipPath chain (unlikely) a rect 25x100 would be rendered.
//
// At the time of writing, Firefox would treat the entire chain of clipPaths as
// invalid due to its excessive length, and refuse to render the referencing
// element at all. One alternative would be to ignore the clipPath reference
// and render the referencing element without any clipping. Another
// alternative would be to break the chain and clip the referencing element,
// but only using the first X clipPaths in the chain (in which case a 50x100
// rect would be rendered).
var chainLength = 100000;
var SVG_NS = "http://www.w3.org/2000/svg";
var template = document.createElementNS(SVG_NS, "clipPath");
var templatesRect = document.createElementNS(SVG_NS, "rect");
templatesRect.setAttribute("width", "100");
templatesRect.setAttribute("height", "100");
template.appendChild(templatesRect);
function createClipPath(index) {
var cp = template.cloneNode(true);
cp.id = "c" + index;
cp.setAttribute("clip-path", "url(#c" + (index + 1) + ")");
return cp;
}
var de = document.documentElement;
for (var i = chainLength; i > 0; --i) {
var cp = createClipPath(i);
if (i == chainLength) {
cp.firstChild.setAttribute("width", "25");
}
else if (i == 1) {
cp.firstChild.setAttribute("width", "50");
}
de.appendChild(cp);
}
]]></script>
<rect width="100%" height="100%" fill="lime"/>
<!-- We don't expect the following element to render at all -->
<rect width="500" height="500" clip-path="url(#c1)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+2 -2
View File
@@ -2879,7 +2879,7 @@ nsHTMLEditor::AddOverrideStyleSheet(const nsAString& aURL)
// (This checks if already exists)
ps->AddOverrideStyleSheet(sheet);
ps->ReconstructStyleData();
ps->RestyleForCSSRuleChanges();
// Save as the last-loaded sheet
mLastOverrideStyleSheetURL = aURL;
@@ -2924,7 +2924,7 @@ nsHTMLEditor::RemoveOverrideStyleSheet(const nsAString &aURL)
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
ps->RemoveOverrideStyleSheet(sheet);
ps->ReconstructStyleData();
ps->RestyleForCSSRuleChanges();
// Remove it from our internal list
return rv;
@@ -234,7 +234,7 @@ SetShadowTransform(Layer* aLayer, LayerToParentLayerMatrix4x4 aTransform)
aTransform.PostScale(1.0f / aLayer->GetPostXScale(),
1.0f / aLayer->GetPostYScale(),
1);
aLayer->AsLayerComposite()->SetShadowTransform(aTransform.ToUnknownMatrix());
aLayer->AsLayerComposite()->SetShadowBaseTransform(aTransform.ToUnknownMatrix());
}
static void
@@ -642,7 +642,7 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
if (ContainerLayer* c = aLayer->AsContainerLayer()) {
matrix.PostScale(c->GetInheritedXScale(), c->GetInheritedYScale(), 1);
}
layerComposite->SetShadowTransform(matrix);
layerComposite->SetShadowBaseTransform(matrix);
layerComposite->SetShadowTransformSetByAnimation(true);
break;
}
@@ -811,6 +811,11 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// The final clip for the layer is the intersection of these clips.
Maybe<ParentLayerIntRect> asyncClip = aLayer->GetClipRect();
// If we are a perspective transform ContainerLayer, apply the clip deferred
// from our child (if there is any) before we iterate over our frame metrics,
// because this clip is subject to all async transforms of this layer.
asyncClip = IntersectMaybeRects(asyncClip, clipDeferredFromChildren);
// The transform of a mask layer is relative to the masked layer's parent
// layer. So whenever we apply an async transform to a layer, we need to
// apply that same transform to the layer's own mask layer.
@@ -934,6 +939,12 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// our scroll clip to it instead of to this layer (see bug 1168263).
// A layer with a perspective transform shouldn't have multiple
// children with FrameMetrics, nor a child with multiple FrameMetrics.
// (A child with multiple FrameMetrics would mean that there's *another*
// scrollable element between the one with the CSS perspective and the
// transformed element. But you'd have to use preserve-3d on the inner
// scrollable element in order to have the perspective apply to the
// transformed child, and preserve-3d is not supported on scrollable
// elements, so this case can't occur.)
MOZ_ASSERT(!aClipDeferredToParent);
aClipDeferredToParent = Some(clip);
} else {
@@ -958,8 +969,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
}
if (hasAsyncTransform || clipDeferredFromChildren) {
aLayer->AsLayerComposite()->SetShadowClipRect(
IntersectMaybeRects(asyncClip, clipDeferredFromChildren));
aLayer->AsLayerComposite()->SetShadowClipRect(asyncClip);
}
if (hasAsyncTransform) {
@@ -1426,7 +1436,7 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame,
gfx::Matrix4x4 trans = rootComposite->GetShadowBaseTransform();
trans *= gfx::Matrix4x4::From2D(mWorldTransform);
rootComposite->SetShadowTransform(trans);
rootComposite->SetShadowBaseTransform(trans);
if (gfxPrefs::CollectScrollTransforms()) {
RecordShadowTransforms(root);
@@ -141,8 +141,7 @@ template<class ContainerT> void
ContainerRenderVR(ContainerT* aContainer,
LayerManagerComposite* aManager,
const gfx::IntRect& aClipRect,
RefPtr<gfx::VRHMDInfo> aHMD,
int32_t aInputFrameID)
RefPtr<gfx::VRHMDInfo> aHMD)
{
int32_t inputFrameID = -1;
@@ -273,11 +272,29 @@ ContainerRenderVR(ContainerT* aContainer,
surfaceRect.width, surfaceRect.height));
layerToRender->RenderLayer(surfaceRect);
CompositableHost *ch = layerToRender->GetCompositableHost();
if (ch) {
int32_t compositableInputFrameID = ch->GetLastInputFrameID();
if (compositableInputFrameID != -1) {
inputFrameID = compositableInputFrameID;
// Search all children recursively until we find the canvas with
// an inputFrameID
std::stack<LayerComposite*> searchLayers;
searchLayers.push(layerToRender);
while (!searchLayers.empty() && inputFrameID == -1) {
LayerComposite* searchLayer = searchLayers.top();
searchLayers.pop();
if (searchLayer) {
searchLayers.push(searchLayer->GetFirstChildComposite());
Layer* sibling = searchLayer->GetLayer();
if (sibling) {
sibling = sibling->GetNextSibling();
}
if (sibling) {
searchLayers.push(sibling->AsLayerComposite());
}
CompositableHost *ch = searchLayer->GetCompositableHost();
if (ch) {
int32_t compositableInputFrameID = ch->GetLastInputFrameID();
if (compositableInputFrameID != -1) {
inputFrameID = compositableInputFrameID;
}
}
}
}
@@ -457,6 +474,22 @@ ContainerPrepare(ContainerT* aContainer,
}
}
template <typename RectPainter> void
DrawRegion(CSSIntRegion* aRegion,
gfx::Color aColor,
const RectPainter& aRectPainter)
{
MOZ_ASSERT(aRegion);
// Iterate through and draw the rects in the region using the provided lambda.
for (CSSIntRegion::RectIterator iterator = aRegion->RectIter();
!iterator.Done();
iterator.Next())
{
aRectPainter(iterator.Get(), aColor);
}
}
template<class ContainerT> void
RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
const RenderTargetIntRect& aClipRect, Layer* aLayer)
@@ -481,9 +514,11 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
gfx::Color tileActiveColor(1, 1, 1, 0.4f);
gfx::Color tileBorderColor(0, 0, 0, 0.1f);
gfx::Color pageBorderColor(0, 0, 0);
gfx::Color criticalDisplayPortColor(1.f, 1.f, 0);
gfx::Color displayPortColor(0, 1.f, 0);
gfx::Color viewPortColor(0, 0, 1.f, 0.3f);
gfx::Color visibilityColor(1.f, 0, 0);
gfx::Color approxVisibilityColor(1.f, 0, 0);
gfx::Color inDisplayPortVisibilityColor(1.f, 1.f, 0);
// Rects
const FrameMetrics& fm = aLayer->GetFrameMetrics(0);
@@ -491,6 +526,10 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
LayerRect scrollRect = fm.GetScrollableRect() * fm.LayersPixelsPerCSSPixel();
LayerRect viewRect = ParentLayerRect(scrollOffset, compositionBounds.Size()) / LayerToParentLayerScale(1);
LayerRect dp = (fm.GetDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel();
Maybe<LayerRect> cdp;
if (!fm.GetCriticalDisplayPort().IsEmpty()) {
cdp = Some((fm.GetCriticalDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel());
}
// Don't render trivial minimap. They can show up from textboxes and other tiny frames.
if (viewRect.width < 64 && viewRect.height < 64) {
@@ -502,41 +541,32 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
float scaleFactor;
float scaleFactorX;
float scaleFactorY;
scaleFactorX = 100.f / scrollRect.width;
scaleFactorY = ((viewRect.height) - 2 * verticalPadding) / scrollRect.height;
Rect dest = Rect(aClipRect.ToUnknownRect());
if (aLayer->GetEffectiveClipRect()) {
dest = Rect(aLayer->GetEffectiveClipRect().value().ToUnknownRect());
} else {
dest = aContainer->GetEffectiveTransform().Inverse().TransformBounds(dest);
}
dest = dest.Intersect(compositionBounds.ToUnknownRect());
scaleFactorX = std::min(100.f, dest.width - (2 * horizontalPadding)) / scrollRect.width;
scaleFactorY = (dest.height - (2 * verticalPadding)) / scrollRect.height;
scaleFactor = std::min(scaleFactorX, scaleFactorY);
if (scaleFactor <= 0) {
return;
}
Matrix4x4 transform = Matrix4x4::Scaling(scaleFactor, scaleFactor, 1);
transform.PostTranslate(horizontalPadding + compositionBounds.x, verticalPadding + compositionBounds.y, 0);
transform.PostTranslate(horizontalPadding + dest.x, verticalPadding + dest.y, 0);
Rect clipRect = aContainer->GetEffectiveTransform().TransformBounds(
transform.TransformBounds(scrollRect.ToUnknownRect()));
Rect transformedScrollRect = transform.TransformBounds(scrollRect.ToUnknownRect());
Rect clipRect = aContainer->GetEffectiveTransform().TransformBounds(transformedScrollRect);
clipRect.width++;
clipRect.height++;
Rect r;
r = transform.TransformBounds(scrollRect.ToUnknownRect());
compositor->FillRect(r, backgroundColor, clipRect, aContainer->GetEffectiveTransform());
/* Disabled because on long pages SlowDrawRect becomes a bottleneck.
int tileW = gfxPrefs::LayersTileWidth();
int tileH = gfxPrefs::LayersTileHeight();
for (int x = scrollRect.x; x < scrollRect.XMost(); x += tileW) {
for (int y = scrollRect.y; y < scrollRect.YMost(); y += tileH) {
LayerRect tileRect = LayerRect(x - x % tileW, y - y % tileH, tileW, tileH);
r = transform.TransformBounds(tileRect.ToUnknownRect());
if (tileRect.Intersects(dp)) {
compositor->FillRect(r, tileActiveColor, clipRect, aContainer->GetEffectiveTransform());
}
compositor->SlowDrawRect(r, tileBorderColor, clipRect, aContainer->GetEffectiveTransform());
}
}
*/
// Render the scrollable area.
r = transform.TransformBounds(scrollRect.ToUnknownRect());
compositor->SlowDrawRect(r, pageBorderColor, clipRect, aContainer->GetEffectiveTransform());
compositor->FillRect(transformedScrollRect, backgroundColor, clipRect, aContainer->GetEffectiveTransform());
compositor->SlowDrawRect(transformedScrollRect, pageBorderColor, clipRect, aContainer->GetEffectiveTransform());
// If enabled, render information about visibility.
if (gfxPrefs::APZMinimapVisibilityEnabled()) {
@@ -547,31 +577,34 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
ScrollableLayerGuid guid = controller->GetGuid();
// Get the approximately visible region.
static CSSIntRegion emptyRegion;
CSSIntRegion* visibleRegion = aManager->GetApproximatelyVisibleRegion(guid);
if (!visibleRegion) {
visibleRegion = &emptyRegion;
}
// Iterate through and draw the rects in the region.
for (CSSIntRegion::RectIterator iterator = visibleRegion->RectIter();
!iterator.Done();
iterator.Next())
{
CSSIntRect rect = iterator.Get();
LayerRect scaledRect = rect * fm.LayersPixelsPerCSSPixel();
auto rectPainter = [&](const CSSIntRect& aRect, const gfx::Color& aColor) {
LayerRect scaledRect = aRect * fm.LayersPixelsPerCSSPixel();
Rect r = transform.TransformBounds(scaledRect.ToUnknownRect());
compositor->FillRect(r, visibilityColor, clipRect, aContainer->GetEffectiveTransform());
}
compositor->FillRect(r, aColor, clipRect, aContainer->GetEffectiveTransform());
};
// Draw the approximately visible region.
CSSIntRegion* approxVisibleRegion =
aManager->GetVisibleRegion(VisibilityCounter::MAY_BECOME_VISIBLE, guid);
DrawRegion(approxVisibleRegion, approxVisibilityColor, rectPainter);
// Draw the in-displayport visible region.
CSSIntRegion* inDisplayPortVisibleRegion =
aManager->GetVisibleRegion(VisibilityCounter::IN_DISPLAYPORT, guid);
DrawRegion(inDisplayPortVisibleRegion, inDisplayPortVisibilityColor, rectPainter);
}
// Render the displayport.
r = transform.TransformBounds(dp.ToUnknownRect());
Rect r = transform.TransformBounds(dp.ToUnknownRect());
compositor->FillRect(r, tileActiveColor, clipRect, aContainer->GetEffectiveTransform());
r = transform.TransformBounds(dp.ToUnknownRect());
compositor->SlowDrawRect(r, displayPortColor, clipRect, aContainer->GetEffectiveTransform());
// Render the critical displayport if there is one
if (cdp) {
r = transform.TransformBounds(cdp->ToUnknownRect());
compositor->SlowDrawRect(r, criticalDisplayPortColor, clipRect, aContainer->GetEffectiveTransform());
}
// Render the viewport.
r = transform.TransformBounds(viewRect.ToUnknownRect());
compositor->SlowDrawRect(r, viewPortColor, clipRect, aContainer->GetEffectiveTransform(), 2);
@@ -750,7 +783,7 @@ ContainerRender(ContainerT* aContainer,
RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDeviceID());
if (hmdInfo && hmdInfo->GetConfiguration().IsValid()) {
ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo, aContainer->GetInputFrameID());
ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo);
aContainer->mPrepared = nullptr;
return;
}
+36 -10
View File
@@ -33,6 +33,7 @@
#include "nsRegion.h" // for nsIntRegion
#include "nscore.h" // for nsAString, etc
#include "LayerTreeInvalidation.h"
#include "Visibility.h"
class gfxContext;
@@ -219,10 +220,17 @@ public:
mInvalidRegion.Or(mInvalidRegion, aRegion);
}
void ClearApproximatelyVisibleRegions(uint64_t aLayersId,
const Maybe<uint32_t>& aPresShellId)
void ClearVisibleRegions(uint64_t aLayersId,
const Maybe<uint32_t>& aPresShellId)
{
for (auto iter = mVisibleRegions.Iter(); !iter.Done(); iter.Next()) {
for (auto iter = mApproximatelyVisibleRegions.Iter(); !iter.Done(); iter.Next()) {
if (iter.Key().mLayersId == aLayersId &&
(!aPresShellId || iter.Key().mPresShellId == *aPresShellId)) {
iter.Remove();
}
}
for (auto iter = mInDisplayPortVisibleRegions.Iter(); !iter.Done(); iter.Next()) {
if (iter.Key().mLayersId == aLayersId &&
(!aPresShellId || iter.Key().mPresShellId == *aPresShellId)) {
iter.Remove();
@@ -230,18 +238,35 @@ public:
}
}
void UpdateApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
void UpdateVisibleRegion(VisibilityCounter aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
{
CSSIntRegion* regionForScrollFrame = mVisibleRegions.LookupOrAdd(aGuid);
VisibleRegions& regions = aCounter == VisibilityCounter::MAY_BECOME_VISIBLE
? mApproximatelyVisibleRegions
: mInDisplayPortVisibleRegions;
CSSIntRegion* regionForScrollFrame = regions.LookupOrAdd(aGuid);
MOZ_ASSERT(regionForScrollFrame);
*regionForScrollFrame = aRegion;
}
CSSIntRegion* GetApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid)
CSSIntRegion* GetVisibleRegion(VisibilityCounter aCounter,
const ScrollableLayerGuid& aGuid)
{
return mVisibleRegions.Get(aGuid);
static CSSIntRegion emptyRegion;
VisibleRegions& regions = aCounter == VisibilityCounter::MAY_BECOME_VISIBLE
? mApproximatelyVisibleRegions
: mInDisplayPortVisibleRegions;
CSSIntRegion* region = regions.Get(aGuid);
if (!region) {
region = &emptyRegion;
}
return region;
}
Compositor* GetCompositor() const
@@ -382,7 +407,8 @@ private:
typedef nsClassHashtable<nsGenericHashKey<ScrollableLayerGuid>,
CSSIntRegion> VisibleRegions;
VisibleRegions mVisibleRegions;
VisibleRegions mApproximatelyVisibleRegions;
VisibleRegions mInDisplayPortVisibleRegions;
UniquePtr<FPSState> mFPS;
@@ -491,7 +517,7 @@ public:
mShadowClipRect = aRect;
}
void SetShadowTransform(const gfx::Matrix4x4& aMatrix)
void SetShadowBaseTransform(const gfx::Matrix4x4& aMatrix)
{
mShadowTransform = aMatrix;
}
+7 -8
View File
@@ -727,29 +727,28 @@ CompositorBridgeChild::SendRequestNotifyAfterRemotePaint()
}
bool
CompositorBridgeChild::SendClearApproximatelyVisibleRegions(uint64_t aLayersId,
uint32_t aPresShellId)
CompositorBridgeChild::SendClearVisibleRegions(uint64_t aLayersId,
uint32_t aPresShellId)
{
MOZ_ASSERT(mCanSend);
if (!mCanSend) {
return true;
}
return PCompositorBridgeChild::SendClearApproximatelyVisibleRegions(aLayersId,
aPresShellId);
return PCompositorBridgeChild::SendClearVisibleRegions(aLayersId, aPresShellId);
}
bool
CompositorBridgeChild::SendNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
CompositorBridgeChild::SendUpdateVisibleRegion(VisibilityCounter aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
{
MOZ_ASSERT(mCanSend);
if (!mCanSend) {
return true;
}
return PCompositorBridgeChild::SendNotifyApproximatelyVisibleRegion(aGuid, aRegion);
return PCompositorBridgeChild::SendUpdateVisibleRegion(aCounter, aGuid, aRegion);
}
} // namespace layers
} // namespace mozilla
+4 -3
View File
@@ -126,9 +126,10 @@ public:
bool SendStopFrameTimeRecording(const uint32_t& startIndex, nsTArray<float>* intervals);
bool SendNotifyRegionInvalidated(const nsIntRegion& region);
bool SendRequestNotifyAfterRemotePaint();
bool SendClearApproximatelyVisibleRegions(uint64_t aLayersId, uint32_t aPresShellId);
bool SendNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const mozilla::CSSIntRegion& aRegion);
bool SendClearVisibleRegions(uint64_t aLayersId, uint32_t aPresShellId);
bool SendUpdateVisibleRegion(VisibilityCounter aCounter,
const ScrollableLayerGuid& aGuid,
const mozilla::CSSIntRegion& aRegion);
bool IsSameProcess() const;
static void ShutDown();
+49 -50
View File
@@ -701,7 +701,6 @@ CompositorBridgeParent::CompositorBridgeParent(nsIWidget* aWidget,
, mCompositorScheduler(nullptr)
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
, mLastPluginUpdateLayerTreeId(0)
, mPluginUpdateResponsePending(false)
, mDeferPluginWindows(false)
, mPluginWindowsHidden(false)
#endif
@@ -785,6 +784,8 @@ CompositorBridgeParent::RecvWillClose()
if (mCompositor) {
mCompositor->DetachWidget();
mCompositor->Destroy();
mCompositor = nullptr;
}
return true;
@@ -897,19 +898,19 @@ CompositorBridgeParent::RecvStopFrameTimeRecording(const uint32_t& aStartIndex,
}
bool
CompositorBridgeParent::RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId)
CompositorBridgeParent::RecvClearVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId)
{
ClearApproximatelyVisibleRegions(aLayersId, Some(aPresShellId));
ClearVisibleRegions(aLayersId, Some(aPresShellId));
return true;
}
void
CompositorBridgeParent::ClearApproximatelyVisibleRegions(const uint64_t& aLayersId,
const Maybe<uint32_t>& aPresShellId)
CompositorBridgeParent::ClearVisibleRegions(const uint64_t& aLayersId,
const Maybe<uint32_t>& aPresShellId)
{
if (mLayerManager) {
mLayerManager->ClearApproximatelyVisibleRegions(aLayersId, aPresShellId);
mLayerManager->ClearVisibleRegions(aLayersId, aPresShellId);
// We need to recomposite to update the minimap.
ScheduleComposition();
@@ -917,16 +918,25 @@ CompositorBridgeParent::ClearApproximatelyVisibleRegions(const uint64_t& aLayers
}
bool
CompositorBridgeParent::RecvNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
CompositorBridgeParent::RecvUpdateVisibleRegion(const VisibilityCounter& aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
{
UpdateVisibleRegion(aCounter, aGuid, aRegion);
return true;
}
void
CompositorBridgeParent::UpdateVisibleRegion(const VisibilityCounter& aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion)
{
if (mLayerManager) {
mLayerManager->UpdateApproximatelyVisibleRegion(aGuid, aRegion);
mLayerManager->UpdateVisibleRegion(aCounter, aGuid, aRegion);
// We need to recomposite to update the minimap.
ScheduleComposition();
}
return true;
}
void
@@ -1175,7 +1185,7 @@ CompositorBridgeParent::SetShadowProperties(Layer* aLayer)
// FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
LayerComposite* layerComposite = aLayer->AsLayerComposite();
// Set the layerComposite's base transform to the layer's base transform.
layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
layerComposite->SetShadowBaseTransform(aLayer->GetBaseTransform());
layerComposite->SetShadowTransformSetByAnimation(false);
layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
layerComposite->SetShadowClipRect(aLayer->GetClipRect());
@@ -1213,20 +1223,6 @@ CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRec
return;
}
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
// Still waiting on plugin update confirmation
if (mPluginUpdateResponsePending) {
return;
}
#endif
bool hasRemoteContent = false;
bool pluginsUpdatedFlag = true;
AutoResolveRefLayers resolve(mCompositionManager, this,
&hasRemoteContent,
&pluginsUpdatedFlag);
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
/*
* AutoResolveRefLayers handles two tasks related to Windows and Linux
* plugin window management:
@@ -1239,27 +1235,20 @@ CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRec
* since plugin clipping can depend on chrome (for example, due to tab modal
* prompts). Updates in step 2 are applied via an async ipc message sent
* to the main thread.
* Windows specific: The compositor will wait for confirmation that plugin
* updates have been applied before painting. Deferment of painting is
* indicated by the mPluginUpdateResponsePending flag. The main thread
* messages back using the RemotePluginsReady async ipc message.
* This is neccessary since plugin windows can leave remnants of window
* content if moved after the underlying window paints.
*/
if (pluginsUpdatedFlag) {
mPluginUpdateResponsePending = true;
return;
}
bool hasRemoteContent = false;
bool updatePluginsFlag = true;
AutoResolveRefLayers resolve(mCompositionManager, this,
&hasRemoteContent,
&updatePluginsFlag);
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
// We do not support plugins in local content. When switching tabs
// to local pages, hide every plugin associated with the window.
if (!hasRemoteContent && BrowserTabsRemoteAutostart() &&
mCachedPluginData.Length()) {
Unused << SendHideAllPlugins((uintptr_t)GetWidget());
mCachedPluginData.Clear();
// Wait for confirmation the hide operation is complete.
mPluginUpdateResponsePending = true;
return;
}
#endif
@@ -1343,7 +1332,6 @@ bool
CompositorBridgeParent::RecvRemotePluginsReady()
{
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
mPluginUpdateResponsePending = false;
ScheduleComposition();
return true;
#else
@@ -1770,7 +1758,7 @@ EraseLayerState(uint64_t aId)
if (iter != sIndirectLayerTrees.end()) {
CompositorBridgeParent* parent = iter->second.mParent;
if (parent) {
parent->ClearApproximatelyVisibleRegions(aId, Nothing());
parent->ClearVisibleRegions(aId, Nothing());
}
sIndirectLayerTrees.erase(iter);
@@ -1953,31 +1941,38 @@ public:
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; }
virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) override { return true; }
virtual bool RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId) override
virtual bool RecvClearVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId) override
{
CompositorBridgeParent* parent;
{ // scope lock
MonitorAutoLock lock(*sIndirectLayerTreesLock);
parent = sIndirectLayerTrees[aLayersId].mParent;
}
if (parent) {
parent->ClearApproximatelyVisibleRegions(aLayersId, Some(aPresShellId));
if (!parent) {
return false;
}
parent->ClearVisibleRegions(aLayersId, Some(aPresShellId));
return true;
}
virtual bool RecvNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion) override
virtual bool RecvUpdateVisibleRegion(const VisibilityCounter& aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion) override
{
CompositorBridgeParent* parent;
{ // scope lock
MonitorAutoLock lock(*sIndirectLayerTreesLock);
parent = sIndirectLayerTrees[aGuid.mLayersId].mParent;
}
if (parent) {
return parent->RecvNotifyApproximatelyVisibleRegion(aGuid, aRegion);
if (!parent) {
return false;
}
parent->UpdateVisibleRegion(aCounter, aGuid, aRegion);
return true;
}
@@ -2474,6 +2469,11 @@ CompositorBridgeParent::UpdatePluginWindowState(uint64_t aId)
}
if (!lts.mPluginData.Length()) {
// Don't hide plugins if the previous remote layer tree didn't contain any.
if (!mCachedPluginData.Length()) {
PLUGINS_LOG("[%" PRIu64 "] nothing to hide", aId);
return false;
}
// We will pass through here in cases where the previous shadow layer
// tree contained visible plugins and the new tree does not. All we need
// to do here is hide the plugins for the old tree, so don't waste time
@@ -2562,7 +2562,6 @@ CompositorBridgeParent::HideAllPluginWindows()
return;
}
mDeferPluginWindows = true;
mPluginUpdateResponsePending = true;
mPluginWindowsHidden = true;
Unused << SendHideAllPlugins((uintptr_t)GetWidget());
ScheduleComposition();
+10 -9
View File
@@ -258,12 +258,16 @@ public:
// @see CrossProcessCompositorBridgeParent::RecvRequestNotifyAfterRemotePaint
virtual bool RecvRequestNotifyAfterRemotePaint() override { return true; };
virtual bool RecvClearApproximatelyVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId) override;
void ClearApproximatelyVisibleRegions(const uint64_t& aLayersId,
const Maybe<uint32_t>& aPresShellId);
virtual bool RecvNotifyApproximatelyVisibleRegion(const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion) override;
virtual bool RecvClearVisibleRegions(const uint64_t& aLayersId,
const uint32_t& aPresShellId) override;
void ClearVisibleRegions(const uint64_t& aLayersId,
const Maybe<uint32_t>& aPresShellId);
virtual bool RecvUpdateVisibleRegion(const VisibilityCounter& aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion) override;
void UpdateVisibleRegion(const VisibilityCounter& aCounter,
const ScrollableLayerGuid& aGuid,
const CSSIntRegion& aRegion);
virtual void ActorDestroy(ActorDestroyReason why) override;
@@ -599,9 +603,6 @@ protected:
nsIntPoint mPluginsLayerOffset;
nsIntRegion mPluginsLayerVisibleRegion;
nsTArray<PluginWindowData> mCachedPluginData;
// indicates if we are currently waiting on a plugin update confirmation.
// When this is true, composition is currently on hold.
bool mPluginUpdateResponsePending;
// indicates if plugin window visibility and metric updates are currently
// being defered due to a scroll operation.
bool mDeferPluginWindows;
+10 -6
View File
@@ -25,6 +25,7 @@ using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasi
using mozilla::CSSIntRegion from "Units.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";
using mozilla::LayoutDeviceIntRegion from "Units.h";
using mozilla::VisibilityCounter from "VisibilityIPC.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using class mozilla::layers::FrameUniformityData from "mozilla/layers/FrameUniformityData.h";
@@ -173,15 +174,18 @@ parent:
*/
async RequestNotifyAfterRemotePaint();
// The child clears the 'approximately visible' regions associated with the
// provided layers ID and pres shell ID (i.e., the regions for all view IDs
// associated with those IDs).
async ClearApproximatelyVisibleRegions(uint64_t layersId, uint32_t presShellId);
// The child sends a request to clear the visible regions (approximate,
// in-displayport, etc.) associated with the provided layers ID and pres shell
// ID (i.e., the regions for all view IDs associated with those IDs).
async ClearVisibleRegions(uint64_t layersId, uint32_t presShellId);
// The child sends a region containing rects associated with the provided
// scrollable layer GUID that the child considers 'approximately visible'.
// scrollable layer GUID that the child considers visible in the sense
// specified by |counter|.
// We visualize this information in the APZ minimap.
async NotifyApproximatelyVisibleRegion(ScrollableLayerGuid guid, CSSIntRegion region);
async UpdateVisibleRegion(VisibilityCounter counter,
ScrollableLayerGuid guid,
CSSIntRegion region);
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can
+8
View File
@@ -526,6 +526,12 @@ HMDInfoOculus::SubmitFrame(RenderTargetSet *aRTSet, int32_t aInputFrameID)
RenderTargetSetOculus *rts = static_cast<RenderTargetSetOculus*>(aRTSet);
MOZ_ASSERT(rts->hmd != nullptr);
MOZ_ASSERT(rts->textureSet != nullptr);
MOZ_ASSERT(aInputFrameID >= 0);
if (aInputFrameID < 0) {
// Sanity check to prevent invalid memory access on builds with assertions
// disabled.
aInputFrameID = 0;
}
VRHMDSensorState sensorState = mLastSensorState[aInputFrameID % kMaxLatencyFrames];
// It is possible to get a cache miss on mLastSensorState if latency is
@@ -535,6 +541,7 @@ HMDInfoOculus::SubmitFrame(RenderTargetSet *aRTSet, int32_t aInputFrameID)
// un-viewable and a more accurate pose prediction is not likely to
// compensate.
ovrLayerEyeFov layer;
memset(&layer, 0, sizeof(layer));
layer.Header.Type = ovrLayerType_EyeFov;
layer.Header.Flags = 0;
layer.ColorTexture[0] = rts->textureSet;
@@ -607,6 +614,7 @@ VRHMDManagerOculus::Init()
mOculusThread = already_AddRefed<nsIThread>(thread);
ovrInitParams params;
memset(&params, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = OVR_MINOR_VERSION;
params.LogCallback = nullptr;
+1
View File
@@ -543,6 +543,7 @@ VRHMDManagerOculus050::Init()
mOculusThread = already_AddRefed<nsIThread>(thread);
ovrInitParams params;
memset(&params, 0, sizeof(params));
params.Flags = ovrInit_RequestVersion;
params.RequestedMinorVersion = LIBOVR_MINOR_VERSION;
params.LogCallback = nullptr;
+20 -17
View File
@@ -45,7 +45,6 @@
#include "nsRefPtrHashtable.h"
#include "nsClassHashtable.h"
#include "nsPresArena.h"
#include "nsIImageLoadingContent.h"
#include "nsMargin.h"
#include "nsFrameState.h"
@@ -358,22 +357,25 @@ public:
bool GetAuthorStyleDisabled() const;
/*
* Called when stylesheets are added/removed/enabled/disabled to rebuild
* all style data for a given pres shell without necessarily reconstructing
* all of the frames. This will not reconstruct style synchronously; if
* you need to do that, call FlushPendingNotifications to flush out style
* reresolves.
* Called when stylesheets are added/removed/enabled/disabled to
* recompute style and clear other cached data as needed. This will
* not reconstruct style synchronously; if you need to do that, call
* FlushPendingNotifications to flush out style reresolves.
*
* This handles the the addition and removal of the various types of
* style rules that can be in CSS style sheets, such as @font-face
* rules and @counter-style rules.
*
* It requires that StyleSheetAdded, StyleSheetRemoved,
* StyleSheetApplicableStateChanged, StyleRuleAdded, StyleRuleRemoved,
* or StyleRuleChanged has been called on the style sheets that have
* changed.
*
* // XXXbz why do we have this on the interface anyway? The only consumer
* is calling AddOverrideStyleSheet/RemoveOverrideStyleSheet, and I think
* those should just handle reconstructing style data...
*/
virtual void ReconstructStyleDataExternal();
void ReconstructStyleDataInternal();
#ifdef MOZILLA_INTERNAL_API
void ReconstructStyleData() { ReconstructStyleDataInternal(); }
#else
void ReconstructStyleData() { ReconstructStyleDataExternal(); }
#endif
void RestyleForCSSRuleChanges();
/**
* Update the style set somehow to take into account changed prefs which
@@ -1588,11 +1590,12 @@ public:
virtual void RebuildApproximateFrameVisibility(nsRect* aRect = nullptr,
bool aRemoveOnly = false) = 0;
/// Ensures @aFrame is in the list of approximately visible frames.
virtual void EnsureFrameInApproximatelyVisibleList(nsIFrame* aFrame) = 0;
/// Adds @aFrame to the list of frames which were visible within the
/// displayport during the last paint.
virtual void MarkFrameVisibleInDisplayPort(nsIFrame* aFrame) = 0;
/// Removes @aFrame from the list of approximately visible frames if present.
virtual void RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame) = 0;
/// Marks @aFrame nonvisible and removes it from all lists of visible frames.
virtual void MarkFrameNonvisible(nsIFrame* aFrame) = 0;
/// Whether we should assume all frames are visible.
virtual bool AssumeAllFramesVisible() = 0;
+219 -209
View File
@@ -1184,8 +1184,9 @@ PresShell::Destroy()
mSynthMouseMoveEvent.Revoke();
mUpdateApproximateFrameVisibilityEvent.Revoke();
mNotifyCompositorOfVisibleRegionsChangeEvent.Revoke();
ClearApproximatelyVisibleFramesList(Some(OnNonvisible::DISCARD_IMAGES));
ClearVisibleFramesSets(Some(OnNonvisible::DISCARD_IMAGES));
if (mCaret) {
mCaret->Terminate();
@@ -1343,7 +1344,7 @@ nsIPresShell::SetAuthorStyleDisabled(bool aStyleDisabled)
{
if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) {
mStyleSet->SetAuthorStyleDisabled(aStyleDisabled);
ReconstructStyleData();
RestyleForCSSRuleChanges();
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
@@ -1452,7 +1453,7 @@ PresShell::AddUserSheet(nsISupports* aSheet)
mStyleSet->EndUpdate();
ReconstructStyleData();
RestyleForCSSRuleChanges();
}
void
@@ -1468,7 +1469,7 @@ PresShell::AddAgentSheet(nsISupports* aSheet)
}
mStyleSet->AppendStyleSheet(SheetType::Agent, sheet);
ReconstructStyleData();
RestyleForCSSRuleChanges();
}
void
@@ -1491,7 +1492,7 @@ PresShell::AddAuthorSheet(nsISupports* aSheet)
mStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
}
ReconstructStyleData();
RestyleForCSSRuleChanges();
}
void
@@ -1504,7 +1505,7 @@ PresShell::RemoveSheet(SheetType aType, nsISupports* aSheet)
}
mStyleSet->RemoveStyleSheet(aType, sheet);
ReconstructStyleData();
RestyleForCSSRuleChanges();
}
NS_IMETHODIMP
@@ -2407,7 +2408,7 @@ PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
if (aUpdateType & UPDATE_STYLE) {
mStyleSet->EndUpdate();
if (mStylesHaveChanged || !mChangedScopeStyleRoots.IsEmpty())
ReconstructStyleData();
RestyleForCSSRuleChanges();
}
mFrameConstructor->EndUpdate();
@@ -4440,7 +4441,7 @@ PresShell::ReconstructFrames(void)
}
void
nsIPresShell::ReconstructStyleDataInternal()
nsIPresShell::RestyleForCSSRuleChanges()
{
AutoTArray<RefPtr<mozilla::dom::Element>,1> scopeRoots;
mChangedScopeStyleRoots.SwapElements(scopeRoots);
@@ -4490,12 +4491,6 @@ nsIPresShell::ReconstructStyleDataInternal()
}
}
void
nsIPresShell::ReconstructStyleDataExternal()
{
ReconstructStyleDataInternal();
}
void
PresShell::RecordStyleSheetChange(StyleSheetHandle aStyleSheet)
{
@@ -4575,6 +4570,71 @@ PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame) const
return mFrameConstructor->GetPlaceholderFrameFor(aFrame);
}
void
PresShell::NotifyCompositorOfVisibleRegionsChange()
{
mNotifyCompositorOfVisibleRegionsChangeEvent.Revoke();
if (!mVisibleRegions) {
return;
}
// Retrieve the layers ID and pres shell ID.
TabChild* tabChild = TabChild::GetFrom(this);
if (!tabChild) {
return;
}
const uint64_t layersId = tabChild->LayersId();
const uint32_t presShellId = GetPresShellId();
// Retrieve the CompositorBridgeChild.
LayerManager* layerManager = GetLayerManager();
if (!layerManager) {
return;
}
ClientLayerManager* clientLayerManager = layerManager->AsClientLayerManager();
if (!clientLayerManager) {
return;
}
CompositorBridgeChild* compositorChild = clientLayerManager->GetCompositorBridgeChild();
if (!compositorChild) {
return;
}
// Clear the old visible regions associated with this document.
compositorChild->SendClearVisibleRegions(layersId, presShellId);
// Send the new visible regions to the compositor.
for (auto iter = mVisibleRegions->mApproximate.ConstIter();
!iter.Done();
iter.Next()) {
const ViewID viewId = iter.Key();
const CSSIntRegion* region = iter.UserData();
MOZ_ASSERT(region);
const ScrollableLayerGuid guid(layersId, presShellId, viewId);
compositorChild->SendUpdateVisibleRegion(VisibilityCounter::MAY_BECOME_VISIBLE,
guid, *region);
}
for (auto iter = mVisibleRegions->mInDisplayPort.ConstIter();
!iter.Done();
iter.Next()) {
const ViewID viewId = iter.Key();
const CSSIntRegion* region = iter.UserData();
MOZ_ASSERT(region);
const ScrollableLayerGuid guid(layersId, presShellId, viewId);
compositorChild->SendUpdateVisibleRegion(VisibilityCounter::IN_DISPLAYPORT,
guid, *region);
}
}
nsresult
PresShell::RenderDocument(const nsRect& aRect, uint32_t aFlags,
nscolor aBackgroundColor,
@@ -4686,6 +4746,9 @@ PresShell::RenderDocument(const nsRect& aRect, uint32_t aFlags,
nsLayoutUtils::PaintFrame(&rc, rootFrame, nsRegion(aRect),
aBackgroundColor, flags);
// We don't call NotifyCompositorOfVisibleRegionsChange here because we're
// not painting to the window, and hence there should be no change.
return NS_OK;
}
@@ -4838,12 +4901,12 @@ PresShell::CreateRangePaintInfo(nsIDOMRange* aRange,
ancestorFrame = ancestorFrame->GetParent();
}
if (!ancestorFrame)
if (!ancestorFrame) {
return nullptr;
auto info = MakeUnique<RangePaintInfo>(range, ancestorFrame);
}
// get a display list containing the range
auto info = MakeUnique<RangePaintInfo>(range, ancestorFrame);
info->mBuilder.SetIncludeAllOutOfFlows();
if (aForPrimarySelection) {
info->mBuilder.SetSelectedFramesOnly();
@@ -5576,17 +5639,14 @@ PresShell::ProcessSynthMouseMoveEvent(bool aFromScroll)
}
}
static void
AddFrameToVisibleRegions(nsIFrame* aFrame,
nsViewManager* aViewManager,
Maybe<VisibleRegions>& aVisibleRegions)
void
PresShell::AddFrameToVisibleRegions(nsIFrame* aFrame, VisibilityCounter aForCounter)
{
if (!aVisibleRegions) {
if (!mVisibleRegions) {
return;
}
MOZ_ASSERT(aFrame);
MOZ_ASSERT(aViewManager);
// Retrieve the view ID for this frame (which we obtain from the enclosing
// scrollable frame).
@@ -5621,20 +5681,22 @@ AddFrameToVisibleRegions(nsIFrame* aFrame,
return;
}
CSSIntRegion* regionForView = aVisibleRegions->LookupOrAdd(viewID);
VisibleRegions& regions = aForCounter == VisibilityCounter::MAY_BECOME_VISIBLE
? mVisibleRegions->mApproximate
: mVisibleRegions->mInDisplayPort;
CSSIntRegion* regionForView = regions.LookupOrAdd(viewID);
MOZ_ASSERT(regionForView);
regionForView->OrWith(CSSPixel::FromAppUnitsRounded(frameRectInScrolledFrameSpace));
}
/* static */ void
PresShell::MarkFramesInListApproximatelyVisible(const nsDisplayList& aList,
Maybe<VisibleRegions>& aVisibleRegions)
PresShell::MarkFramesInListApproximatelyVisible(const nsDisplayList& aList)
{
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
nsDisplayList* sublist = item->GetChildren();
if (sublist) {
MarkFramesInListApproximatelyVisible(*sublist, aVisibleRegions);
MarkFramesInListApproximatelyVisible(*sublist);
continue;
}
@@ -5652,128 +5714,56 @@ PresShell::MarkFramesInListApproximatelyVisible(const nsDisplayList& aList,
presShell->mApproximatelyVisibleFrames.PutEntry(frame);
if (presShell->mApproximatelyVisibleFrames.Count() > count) {
// The frame was added to mApproximatelyVisibleFrames, so increment its visible count.
frame->IncApproximateVisibleCount();
frame->IncVisibilityCount(VisibilityCounter::MAY_BECOME_VISIBLE);
}
AddFrameToVisibleRegions(frame, presShell->mViewManager, aVisibleRegions);
}
}
void
PresShell::ReportBadStateDuringVisibilityUpdate()
{
if (!NS_IsMainThread()) {
gfxCriticalNote << "Got null frame in frame visibility: off-main-thread";
}
if (mIsZombie) {
gfxCriticalNote << "Got null frame in frame visibility: mIsZombie";
}
if (mIsDestroying) {
gfxCriticalNote << "Got null frame in frame visibility: mIsDestroying";
}
if (mIsReflowing) {
gfxCriticalNote << "Got null frame in frame visibility: mIsReflowing";
}
if (mPaintingIsFrozen) {
gfxCriticalNote << "Got null frame in frame visibility: mPaintingIsFrozen";
}
if (mForwardingContainer) {
gfxCriticalNote << "Got null frame in frame visibility: mForwardingContainer";
}
if (mIsNeverPainting) {
gfxCriticalNote << "Got null frame in frame visibility: mIsNeverPainting";
}
if (mIsDocumentGone) {
gfxCriticalNote << "Got null frame in frame visibility: mIsDocumentGone";
}
if (!nsContentUtils::IsSafeToRunScript()) {
gfxCriticalNote << "Got null frame in frame visibility: not safe to run script";
}
}
void
PresShell::SetInFrameVisibilityUpdate(bool aState)
{
mInFrameVisibilityUpdate = aState;
}
static void
NotifyCompositorOfVisibleRegionsChange(PresShell* aPresShell,
const Maybe<VisibleRegions>& aRegions)
{
if (!aRegions) {
return;
}
MOZ_ASSERT(aPresShell);
// Retrieve the layers ID and pres shell ID.
TabChild* tabChild = TabChild::GetFrom(aPresShell);
if (!tabChild) {
return;
}
const uint64_t layersId = tabChild->LayersId();
const uint32_t presShellId = aPresShell->GetPresShellId();
// Retrieve the CompositorBridgeChild.
LayerManager* layerManager = aPresShell->GetLayerManager();
if (!layerManager) {
return;
}
ClientLayerManager* clientLayerManager = layerManager->AsClientLayerManager();
if (!clientLayerManager) {
return;
}
CompositorBridgeChild* compositorChild = clientLayerManager->GetCompositorBridgeChild();
if (!compositorChild) {
return;
}
// Clear the old approximately visible regions associated with this document.
compositorChild->SendClearApproximatelyVisibleRegions(layersId, presShellId);
// Send the new approximately visible regions to the compositor.
for (auto iter = aRegions->ConstIter(); !iter.Done(); iter.Next()) {
const ViewID viewId = iter.Key();
const CSSIntRegion* region = iter.UserData();
MOZ_ASSERT(region);
const ScrollableLayerGuid guid(layersId, presShellId, viewId);
compositorChild->SendNotifyApproximatelyVisibleRegion(guid, *region);
presShell->AddFrameToVisibleRegions(frame, VisibilityCounter::MAY_BECOME_VISIBLE);
}
}
/* static */ void
PresShell::DecApproximateVisibleCount(VisibleFrames& aFrames,
Maybe<OnNonvisible> aNonvisibleAction
/* = Nothing() */)
PresShell::DecVisibleCount(const VisibleFrames& aFrames,
VisibilityCounter aCounter,
Maybe<OnNonvisible> aNonvisibleAction /* = Nothing() */)
{
for (auto iter = aFrames.Iter(); !iter.Done(); iter.Next()) {
for (auto iter = aFrames.ConstIter(); !iter.Done(); iter.Next()) {
nsIFrame* frame = iter.Get()->GetKey();
if (MOZ_UNLIKELY(!frame)) {
// We are about to crash, annotate crash report with some info that might
// help debug the crash (bug 1251150)
ReportBadStateDuringVisibilityUpdate();
}
SetInFrameVisibilityUpdate(true);
// Decrement the frame's visible count if we're still tracking its
// visibility. (We may not be, if the frame disabled visibility tracking
// after we added it to the visible frames list.)
if (frame->TrackingVisibility()) {
frame->DecApproximateVisibleCount(aNonvisibleAction);
frame->DecVisibilityCount(aCounter, aNonvisibleAction);
}
SetInFrameVisibilityUpdate(false);
}
}
void
PresShell::InitVisibleRegionsIfVisualizationEnabled(VisibilityCounter aForCounter)
{
// If we're visualizing visible regions, initialize a
// VisibleRegionsContainer to store them. Visibility-related functions we
// call will only do the work of populating this object and sending it to
// the compositor if we've created it, so we don't need to check the prefs
// everywhere.
if (!gfxPrefs::APZMinimap() ||
!gfxPrefs::APZMinimapVisibilityEnabled()) {
mVisibleRegions = nullptr;
return;
}
if (mVisibleRegions) {
// Clear the regions we're about to update. We don't want to clear both,
// or the two visibility tracking methods will interfere with each other.
VisibleRegions& regions = aForCounter == VisibilityCounter::MAY_BECOME_VISIBLE
? mVisibleRegions->mApproximate
: mVisibleRegions->mInDisplayPort;
regions.Clear();
return;
}
mVisibleRegions = MakeUnique<VisibleRegionsContainer>();
}
void
PresShell::RebuildApproximateFrameVisibilityDisplayList(const nsDisplayList& aList)
{
@@ -5785,70 +5775,72 @@ PresShell::RebuildApproximateFrameVisibilityDisplayList(const nsDisplayList& aLi
VisibleFrames oldApproximatelyVisibleFrames;
mApproximatelyVisibleFrames.SwapElements(oldApproximatelyVisibleFrames);
// If we're visualizing visible regions, create a VisibleRegions object to
// store information about them. The functions we call will populate this
// object and send it to the compositor only if it's Some(), so we don't
// need to check the prefs everywhere.
Maybe<VisibleRegions> visibleRegions;
if (gfxPrefs::APZMinimap() && gfxPrefs::APZMinimapVisibilityEnabled()) {
visibleRegions.emplace();
}
InitVisibleRegionsIfVisualizationEnabled(VisibilityCounter::MAY_BECOME_VISIBLE);
MarkFramesInListApproximatelyVisible(aList, visibleRegions);
MarkFramesInListApproximatelyVisible(aList);
DecApproximateVisibleCount(oldApproximatelyVisibleFrames);
DecVisibleCount(oldApproximatelyVisibleFrames,
VisibilityCounter::MAY_BECOME_VISIBLE);
NotifyCompositorOfVisibleRegionsChange(this, visibleRegions);
NotifyCompositorOfVisibleRegionsChange();
}
/* static */ void
PresShell::ClearApproximateFrameVisibilityVisited(nsView* aView, bool aClear)
PresShell::ClearVisibleFramesForUnvisitedPresShells(nsView* aView, bool aClear)
{
nsViewManager* vm = aView->GetViewManager();
if (aClear) {
PresShell* presShell = static_cast<PresShell*>(vm->GetPresShell());
if (!presShell->mApproximateFrameVisibilityVisited) {
presShell->ClearApproximatelyVisibleFramesList();
presShell->ClearVisibleFramesSets();
}
presShell->mApproximateFrameVisibilityVisited = false;
}
for (nsView* v = aView->GetFirstChild(); v; v = v->GetNextSibling()) {
ClearApproximateFrameVisibilityVisited(v, v->GetViewManager() != vm);
ClearVisibleFramesForUnvisitedPresShells(v, v->GetViewManager() != vm);
}
}
void
PresShell::ClearApproximatelyVisibleFramesList(Maybe<OnNonvisible> aNonvisibleAction
/* = Nothing() */)
PresShell::ClearVisibleFramesSets(Maybe<OnNonvisible> aNonvisibleAction
/* = Nothing() */)
{
if (mInFrameVisibilityUpdate) {
gfxCriticalNoteOnce << "ClearApproximatelyVisibleFramesList is re-entering on "
<< (NS_IsMainThread() ? "" : "non-") << "main thread";
}
DecApproximateVisibleCount(mApproximatelyVisibleFrames, aNonvisibleAction);
DecVisibleCount(mApproximatelyVisibleFrames,
VisibilityCounter::MAY_BECOME_VISIBLE,
aNonvisibleAction);
mApproximatelyVisibleFrames.Clear();
DecVisibleCount(mInDisplayPortFrames,
VisibilityCounter::IN_DISPLAYPORT,
aNonvisibleAction);
mInDisplayPortFrames.Clear();
if (mVisibleRegions) {
mVisibleRegions->mApproximate.Clear();
mVisibleRegions->mInDisplayPort.Clear();
NotifyCompositorOfVisibleRegionsChange();
}
}
void
PresShell::MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
const nsRect& aRect,
Maybe<VisibleRegions>& aVisibleRegions,
bool aRemoveOnly /* = false */)
{
MOZ_ASSERT(aFrame->PresContext()->PresShell() == this, "wrong presshell");
if (aFrame->TrackingVisibility() &&
aFrame->StyleVisibility()->IsVisible() &&
(!aRemoveOnly || aFrame->GetVisibility() == Visibility::APPROXIMATELY_VISIBLE)) {
(!aRemoveOnly || aFrame->IsVisibleOrMayBecomeVisibleSoon())) {
MOZ_ASSERT(!AssumeAllFramesVisible());
uint32_t count = mApproximatelyVisibleFrames.Count();
mApproximatelyVisibleFrames.PutEntry(aFrame);
if (mApproximatelyVisibleFrames.Count() > count) {
// The frame was added to mApproximatelyVisibleFrames, so increment its visible count.
aFrame->IncApproximateVisibleCount();
aFrame->IncVisibilityCount(VisibilityCounter::MAY_BECOME_VISIBLE);
}
AddFrameToVisibleRegions(aFrame, mViewManager, aVisibleRegions);
AddFrameToVisibleRegions(aFrame, VisibilityCounter::MAY_BECOME_VISIBLE);
}
nsSubDocumentFrame* subdocFrame = do_QueryFrame(aFrame);
@@ -5917,7 +5909,7 @@ PresShell::MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
}
}
}
MarkFramesInSubtreeApproximatelyVisible(child, r, aVisibleRegions);
MarkFramesInSubtreeApproximatelyVisible(child, r);
}
}
}
@@ -5934,35 +5926,24 @@ PresShell::RebuildApproximateFrameVisibility(nsRect* aRect,
return;
}
if (mInFrameVisibilityUpdate) {
gfxCriticalNoteOnce << "RebuildApproximateFrameVisibility is re-entering on "
<< (NS_IsMainThread() ? "" : "non-") << "main thread";
}
// Remove the entries of the mApproximatelyVisibleFrames hashtable and put
// them in oldApproximatelyVisibleFrames.
VisibleFrames oldApproximatelyVisibleFrames;
mApproximatelyVisibleFrames.SwapElements(oldApproximatelyVisibleFrames);
// If we're visualizing visible regions, create a VisibleRegions object to
// store information about them. The functions we call will populate this
// object and send it to the compositor only if it's Some(), so we don't
// need to check the prefs everywhere.
Maybe<VisibleRegions> visibleRegions;
if (gfxPrefs::APZMinimap() && gfxPrefs::APZMinimapVisibilityEnabled()) {
visibleRegions.emplace();
}
InitVisibleRegionsIfVisualizationEnabled(VisibilityCounter::MAY_BECOME_VISIBLE);
nsRect vis(nsPoint(0, 0), rootFrame->GetSize());
if (aRect) {
vis = *aRect;
}
MarkFramesInSubtreeApproximatelyVisible(rootFrame, vis, visibleRegions, aRemoveOnly);
MarkFramesInSubtreeApproximatelyVisible(rootFrame, vis, aRemoveOnly);
DecApproximateVisibleCount(oldApproximatelyVisibleFrames);
DecVisibleCount(oldApproximatelyVisibleFrames,
VisibilityCounter::MAY_BECOME_VISIBLE);
NotifyCompositorOfVisibleRegionsChange(this, visibleRegions);
NotifyCompositorOfVisibleRegionsChange();
}
void
@@ -5986,12 +5967,12 @@ PresShell::DoUpdateApproximateFrameVisibility(bool aRemoveOnly)
// call update on that frame
nsIFrame* rootFrame = GetRootFrame();
if (!rootFrame) {
ClearApproximatelyVisibleFramesList(Some(OnNonvisible::DISCARD_IMAGES));
ClearVisibleFramesSets(Some(OnNonvisible::DISCARD_IMAGES));
return;
}
RebuildApproximateFrameVisibility(/* aRect = */ nullptr, aRemoveOnly);
ClearApproximateFrameVisibilityVisited(rootFrame->GetView(), true);
ClearVisibleFramesForUnvisitedPresShells(rootFrame->GetView(), true);
#ifdef DEBUG_FRAME_VISIBILITY_DISPLAY_LIST
// This can be used to debug the frame walker by comparing beforeFrameList
@@ -6005,7 +5986,8 @@ PresShell::DoUpdateApproximateFrameVisibility(bool aRemoveOnly)
if (rootScroll) {
nsIContent* content = rootScroll->GetContent();
if (content) {
Unused << nsLayoutUtils::GetDisplayPort(content, &updateRect, RelativeTo::ScrollFrame);
Unused << nsLayoutUtils::GetDisplayPortForVisibilityTesting(content, &updateRect,
RelativeTo::ScrollFrame);
}
if (IgnoringViewportScrolling()) {
@@ -6020,7 +6002,7 @@ PresShell::DoUpdateApproximateFrameVisibility(bool aRemoveOnly)
RebuildApproximateFrameVisibilityDisplayList(list);
ClearApproximateFrameVisibilityVisited(rootFrame->GetView(), true);
ClearVisibleFramesForUnvisitedPresShells(rootFrame->GetView(), true);
list.DeleteAll();
#endif
@@ -6125,14 +6107,16 @@ PresShell::ScheduleApproximateFrameVisibilityUpdateNow()
}
void
PresShell::EnsureFrameInApproximatelyVisibleList(nsIFrame* aFrame)
PresShell::MarkFrameVisibleInDisplayPort(nsIFrame* aFrame)
{
if (!aFrame->TrackingVisibility()) {
return;
}
if (AssumeAllFramesVisible()) {
aFrame->IncApproximateVisibleCount();
if (aFrame->GetVisibility() != Visibility::IN_DISPLAYPORT) {
aFrame->IncVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
return;
}
@@ -6145,20 +6129,31 @@ PresShell::EnsureFrameInApproximatelyVisibleList(nsIFrame* aFrame)
}
#endif
if (mInFrameVisibilityUpdate) {
gfxCriticalNoteOnce << "EnsureFrameInApproximatelyVisibleList is re-entering on "
<< (NS_IsMainThread() ? "" : "non-") << "main thread";
if (!mInDisplayPortFrames.Contains(aFrame)) {
MOZ_ASSERT(!AssumeAllFramesVisible());
mInDisplayPortFrames.PutEntry(aFrame);
aFrame->IncVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
if (!mApproximatelyVisibleFrames.Contains(aFrame)) {
MOZ_ASSERT(!AssumeAllFramesVisible());
mApproximatelyVisibleFrames.PutEntry(aFrame);
aFrame->IncApproximateVisibleCount();
AddFrameToVisibleRegions(aFrame, VisibilityCounter::IN_DISPLAYPORT);
}
static void
RemoveFrameFromVisibleSet(nsIFrame* aFrame,
VisibleFrames& aSet,
VisibilityCounter aCounter)
{
uint32_t count = aSet.Count();
aSet.RemoveEntry(aFrame);
if (aFrame->TrackingVisibility() && aSet.Count() < count) {
aFrame->DecVisibilityCount(aCounter);
}
}
void
PresShell::RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame)
PresShell::MarkFrameNonvisible(nsIFrame* aFrame)
{
#ifdef DEBUG
// Make sure it's in this pres shell.
@@ -6171,24 +6166,16 @@ PresShell::RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame)
if (AssumeAllFramesVisible()) {
MOZ_ASSERT(mApproximatelyVisibleFrames.Count() == 0,
"Shouldn't have any frames in the table");
"Shouldn't have any frames in the approximate visibility set");
MOZ_ASSERT(mInDisplayPortFrames.Count() == 0,
"Shouldn't have any frames in the in-displayport visibility set");
return;
}
if (mInFrameVisibilityUpdate) {
gfxCriticalNoteOnce << "RemoveFrameFromApproximatelyVisibleList is re-entering on "
<< (NS_IsMainThread() ? "" : "non-") << "main thread";
}
uint32_t count = mApproximatelyVisibleFrames.Count();
mApproximatelyVisibleFrames.RemoveEntry(aFrame);
if (aFrame->TrackingVisibility() &&
mApproximatelyVisibleFrames.Count() < count) {
// aFrame was in the hashtable, and we're still tracking its visibility,
// so we need to decrement its visible count.
aFrame->DecApproximateVisibleCount();
}
RemoveFrameFromVisibleSet(aFrame, mApproximatelyVisibleFrames,
VisibilityCounter::MAY_BECOME_VISIBLE);
RemoveFrameFromVisibleSet(aFrame, mInDisplayPortFrames,
VisibilityCounter::IN_DISPLAYPORT);
}
class nsAutoNotifyDidPaint
@@ -6376,8 +6363,30 @@ PresShell::Paint(nsView* aViewToPaint,
}
if (frame) {
// Remove the entries of the mInDisplayPortFrames hashtable and put them
// in oldInDisplayPortFrames.
VisibleFrames oldInDisplayPortFrames;
mInDisplayPortFrames.SwapElements(oldInDisplayPortFrames);
InitVisibleRegionsIfVisualizationEnabled(VisibilityCounter::IN_DISPLAYPORT);
// We can paint directly into the widget using its layer manager.
nsLayoutUtils::PaintFrame(nullptr, frame, aDirtyRegion, bgcolor, flags);
DecVisibleCount(oldInDisplayPortFrames, VisibilityCounter::IN_DISPLAYPORT);
if (mVisibleRegions &&
!mNotifyCompositorOfVisibleRegionsChangeEvent.IsPending()) {
// Asynchronously notify the compositor of the new visible regions,
// since this is happening during a paint and updating the visible
// regions triggers a recomposite.
RefPtr<nsRunnableMethod<PresShell>> event =
NS_NewRunnableMethod(this, &PresShell::NotifyCompositorOfVisibleRegionsChange);
if (NS_SUCCEEDED(NS_DispatchToMainThread(event))) {
mNotifyCompositorOfVisibleRegionsChangeEvent = event;
}
}
return;
}
@@ -9024,6 +9033,7 @@ void
PresShell::Freeze()
{
mUpdateApproximateFrameVisibilityEvent.Revoke();
mNotifyCompositorOfVisibleRegionsChangeEvent.Revoke();
MaybeReleaseCapturingContent();
@@ -11047,11 +11057,6 @@ PresShell::UpdateImageLockingState()
nsresult rv = mDocument->SetImageLockingState(locked);
if (locked) {
if (mInFrameVisibilityUpdate) {
gfxCriticalNoteOnce << "UpdateImageLockingState is re-entering on "
<< (NS_IsMainThread() ? "" : "non-") << "main thread";
}
// Request decodes for visible image frames; we want to start decoding as
// quickly as possible when we get foregrounded to minimize flashing.
for (auto iter = mApproximatelyVisibleFrames.Iter(); !iter.Done(); iter.Next()) {
@@ -11091,6 +11096,11 @@ PresShell::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
*aPresShellSize += mCaret->SizeOfIncludingThis(aMallocSizeOf);
}
*aPresShellSize += mApproximatelyVisibleFrames.ShallowSizeOfExcludingThis(aMallocSizeOf);
*aPresShellSize += mInDisplayPortFrames.ShallowSizeOfExcludingThis(aMallocSizeOf);
*aPresShellSize += mVisibleRegions
? mVisibleRegions->mApproximate.ShallowSizeOfIncludingThis(aMallocSizeOf) +
mVisibleRegions->mInDisplayPort.ShallowSizeOfIncludingThis(aMallocSizeOf)
: 0;
*aPresShellSize += mFramesToDirty.ShallowSizeOfExcludingThis(aMallocSizeOf);
*aPresShellSize += aArenaObjectsSize->mOther;
+34 -14
View File
@@ -38,6 +38,7 @@
#include "mozilla/StyleSetHandle.h"
#include "mozilla/UniquePtr.h"
#include "MobileViewportManager.h"
#include "Visibility.h"
#include "ZoomConstraintsClient.h"
class nsRange;
@@ -79,6 +80,8 @@ class PresShell final : public nsIPresShell,
template <typename T> using Maybe = mozilla::Maybe<T>;
using Nothing = mozilla::Nothing;
using OnNonvisible = mozilla::OnNonvisible;
template <typename T> using UniquePtr = mozilla::UniquePtr<T>;
using VisibilityCounter = mozilla::VisibilityCounter;
using VisibleFrames = mozilla::VisibleFrames;
using VisibleRegions = mozilla::VisibleRegions;
@@ -402,8 +405,8 @@ public:
void RebuildApproximateFrameVisibility(nsRect* aRect = nullptr,
bool aRemoveOnly = false) override;
void EnsureFrameInApproximatelyVisibleList(nsIFrame* aFrame) override;
void RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame) override;
void MarkFrameVisibleInDisplayPort(nsIFrame* aFrame) override;
void MarkFrameNonvisible(nsIFrame* aFrame) override;
bool AssumeAllFramesVisible() override;
@@ -765,27 +768,46 @@ protected:
void UpdateApproximateFrameVisibility();
void DoUpdateApproximateFrameVisibility(bool aRemoveOnly);
void ClearApproximatelyVisibleFramesList(Maybe<mozilla::OnNonvisible> aNonvisibleAction
= Nothing());
static void ClearApproximateFrameVisibilityVisited(nsView* aView, bool aClear);
static void MarkFramesInListApproximatelyVisible(const nsDisplayList& aList,
Maybe<VisibleRegions>& aVisibleRegions);
void ClearVisibleFramesSets(Maybe<OnNonvisible> aNonvisibleAction = Nothing());
static void ClearVisibleFramesForUnvisitedPresShells(nsView* aView, bool aClear);
static void MarkFramesInListApproximatelyVisible(const nsDisplayList& aList);
void MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
const nsRect& aRect,
Maybe<VisibleRegions>& aVisibleRegions,
bool aRemoveOnly = false);
void DecApproximateVisibleCount(VisibleFrames& aFrames,
Maybe<OnNonvisible> aNonvisibleAction = Nothing());
void ReportBadStateDuringVisibilityUpdate();
void SetInFrameVisibilityUpdate(bool aState);
void DecVisibleCount(const VisibleFrames& aFrames,
VisibilityCounter aCounter,
Maybe<OnNonvisible> aNonvisibleAction = Nothing());
void InitVisibleRegionsIfVisualizationEnabled(VisibilityCounter aForCounter);
void AddFrameToVisibleRegions(nsIFrame* aFrame, VisibilityCounter aForCounter);
void NotifyCompositorOfVisibleRegionsChange();
nsRevocableEventPtr<nsRunnableMethod<PresShell>> mUpdateApproximateFrameVisibilityEvent;
nsRevocableEventPtr<nsRunnableMethod<PresShell>> mNotifyCompositorOfVisibleRegionsChangeEvent;
// A set of frames that were visible or could be visible soon at the time
// that we last did an approximate frame visibility update.
VisibleFrames mApproximatelyVisibleFrames;
// A set of frames that were visible in the displayport the last time we painted.
VisibleFrames mInDisplayPortFrames;
struct VisibleRegionsContainer
{
// The approximately visible regions calculated during the last update to
// approximate frame visibility.
VisibleRegions mApproximate;
// The in-displayport visible regions calculated during the last paint.
VisibleRegions mInDisplayPort;
};
// The most recent visible regions we've computed. Only non-null if the APZ
// minimap visibility visualization was enabled during the last visibility
// update.
UniquePtr<VisibleRegionsContainer> mVisibleRegions;
//////////////////////////////////////////////////////////////////////////////
// Methods for dispatching KeyboardEvent and BeforeAfterKeyboardEvent.
@@ -952,8 +974,6 @@ protected:
// Whether the widget has received a paint message yet.
bool mHasReceivedPaintMessage : 1;
bool mInFrameVisibilityUpdate : 1;
static bool sDisableNonTestMouseEvents;
};
+5 -5
View File
@@ -20,8 +20,8 @@
using mozilla::dom::Element;
nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext):
nsColorControlFrameSuper(aContext)
nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext)
: nsHTMLButtonControlFrame(aContext)
{
}
@@ -36,14 +36,14 @@ NS_IMPL_FRAMEARENA_HELPERS(nsColorControlFrame)
NS_QUERYFRAME_HEAD(nsColorControlFrame)
NS_QUERYFRAME_ENTRY(nsColorControlFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsColorControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)
void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
nsContentUtils::DestroyAnonymousContent(&mColorContent);
nsColorControlFrameSuper::DestroyFrom(aDestructRoot);
nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
}
nsIAtom*
@@ -126,7 +126,7 @@ nsColorControlFrame::AttributeChanged(int32_t aNameSpaceID,
aNameSpaceID == kNameSpaceID_None && nsGkAtoms::value == aAttribute) {
UpdateColor();
}
return nsColorControlFrameSuper::AttributeChanged(aNameSpaceID, aAttribute,
return nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}
+1 -3
View File
@@ -14,11 +14,9 @@ namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
} // namespace mozilla
typedef nsHTMLButtonControlFrame nsColorControlFrameSuper;
// Class which implements the input type=color
class nsColorControlFrame final : public nsColorControlFrameSuper,
class nsColorControlFrame final : public nsHTMLButtonControlFrame,
public nsIAnonymousContentCreator
{
typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
+5 -5
View File
@@ -17,8 +17,8 @@ using namespace mozilla;
//#define FCF_NOISY
nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext) :
nsFormControlFrameSuper(aContext)
nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext)
: nsAtomicContainerFrame(aContext)
{
}
@@ -29,7 +29,7 @@ nsFormControlFrame::~nsFormControlFrame()
nsIAtom*
nsFormControlFrame::GetType() const
{
return nsGkAtoms::formControlFrame;
return nsGkAtoms::formControlFrame;
}
void
@@ -37,12 +37,12 @@ nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
// Unregister the access key registered in reflow
nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
nsFormControlFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
NS_QUERYFRAME_HEAD(nsFormControlFrame)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsFormControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
/* virtual */ nscoord
nsFormControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)
+6 -8
View File
@@ -11,14 +11,12 @@
#include "nsAtomicContainerFrame.h"
#include "nsDisplayList.h"
typedef nsAtomicContainerFrame nsFormControlFrameSuper;
/**
/**
* nsFormControlFrame is the base class for radio buttons and
* checkboxes. It also has two static methods (RegUnRegAccessKey and
* GetScreenHeight) that are used by other form controls.
*/
class nsFormControlFrame : public nsFormControlFrameSuper,
class nsFormControlFrame : public nsAtomicContainerFrame,
public nsIFormControlFrame
{
public:
@@ -33,7 +31,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsFormControlFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
@@ -68,11 +66,11 @@ public:
const mozilla::LogicalSize& aPadding,
bool aShrinkWrap) override;
/**
/**
* Respond to a gui event
* @see nsIFrame::HandleEvent
*/
virtual nsresult HandleEvent(nsPresContext* aPresContext,
virtual nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
@@ -117,7 +115,7 @@ protected:
//-------------------------------------------------------------------------------------
// Utility methods for managing checkboxes and radiobuttons
//-------------------------------------------------------------------------------------
//
//
/**
* Get the state of the checked attribute.
* @param aState set to true if the checked attribute is set,
+13 -15
View File
@@ -15,8 +15,7 @@
using namespace mozilla;
typedef nsImageFrame nsImageControlFrameSuper;
class nsImageControlFrame : public nsImageControlFrameSuper,
class nsImageControlFrame : public nsImageFrame,
public nsIFormControlFrame
{
public:
@@ -56,13 +55,13 @@ public:
nsIFrame::Cursor& aCursor) override;
// nsIFormContromFrame
virtual void SetFocus(bool aOn, bool aRepaint) override;
virtual nsresult SetFormProperty(nsIAtom* aName,
virtual nsresult SetFormProperty(nsIAtom* aName,
const nsAString& aValue) override;
};
nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext):
nsImageControlFrameSuper(aContext)
nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext)
: nsImageFrame(aContext)
{
}
@@ -76,7 +75,7 @@ nsImageControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
if (!GetPrevInFlow()) {
nsFormControlFrame::RegUnRegAccessKey(this, false);
}
nsImageControlFrameSuper::DestroyFrom(aDestructRoot);
nsImageFrame::DestroyFrom(aDestructRoot);
}
nsIFrame*
@@ -92,12 +91,12 @@ nsImageControlFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
nsImageControlFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsImageFrame::Init(aContent, aParent, aPrevInFlow);
if (aPrevInFlow) {
return;
}
mContent->SetProperty(nsGkAtoms::imageClickedPoint,
new nsIntPoint(0, 0),
nsINode::DeleteProperty<nsIntPoint>);
@@ -105,7 +104,7 @@ nsImageControlFrame::Init(nsIContent* aContent,
NS_QUERYFRAME_HEAD(nsImageControlFrame)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsImageControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsImageFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@@ -122,7 +121,7 @@ nsImageControlFrame::AccessibleType()
nsIAtom*
nsImageControlFrame::GetType() const
{
return nsGkAtoms::imageControlFrame;
return nsGkAtoms::imageControlFrame;
}
void
@@ -136,10 +135,10 @@ nsImageControlFrame::Reflow(nsPresContext* aPresContext,
if (!GetPrevInFlow() && (mState & NS_FRAME_FIRST_REFLOW)) {
nsFormControlFrame::RegUnRegAccessKey(this, true);
}
return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
return nsImageFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
nsresult
nsresult
nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus)
@@ -175,11 +174,10 @@ nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
TranslateEventCoords(pt, *lastClickPoint);
}
}
return nsImageControlFrameSuper::HandleEvent(aPresContext, aEvent,
aEventStatus);
return nsImageFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
void
void
nsImageControlFrame::SetFocus(bool aOn, bool aRepaint)
{
}
+28 -12
View File
@@ -8,6 +8,8 @@
* possible visibility states of a frame. @OnNonvisible is an enumeration that
* allows callers to request a specific action when a frame transitions from
* visible to nonvisible.
*
* IPC serializers are available in VisibilityIPC.h.
*/
#ifndef mozilla_layout_generic_Visibility_h
@@ -18,21 +20,35 @@ namespace mozilla {
// Visibility states for frames.
enum class Visibility : uint8_t
{
// Indicates that we're not tracking visibility for this frame.
// We're not tracking visibility for this frame.
UNTRACKED,
// Indicates that the frame is probably nonvisible. Visible frames *may* be
// APPROXIMATELY_NONVISIBLE because approximate visibility is not updated
// synchronously. Some truly nonvisible frames may be marked
// APPROXIMATELY_VISIBLE instead if our heuristics lead us to think they may
// be visible soon.
APPROXIMATELY_NONVISIBLE,
// This frame is nonvisible - i.e., it was not within the displayport as of
// the last paint (in which case it'd be IN_DISPLAYPORT) and our heuristics
// aren't telling us that it may become visible soon (in which case it'd be
// MAY_BECOME_VISIBLE).
NONVISIBLE,
// Indicates that the frame is either visible now or is likely to be visible
// soon according to our heuristics. As with APPROXIMATELY_NONVISIBLE, it's
// important to note that approximately visibility is not updated
// synchronously, so this information may be out of date.
APPROXIMATELY_VISIBLE
// This frame is nonvisible now, but our heuristics tell us it may become
// visible soon. These heuristics are updated on a relatively slow timer, so a
// frame being marked MAY_BECOME_VISIBLE does not imply any particular
// relationship between the frame and the displayport.
MAY_BECOME_VISIBLE,
// This frame was within the displayport as of the last paint. That doesn't
// necessarily mean that the frame is visible - it may still lie outside the
// viewport - but it does mean that the user may scroll the frame into view
// asynchronously at any time (due to APZ), so for most purposes such a frame
// should be treated as truly visible.
IN_DISPLAYPORT
};
// The subset of the states in @Visibility which have a per-frame counter. This
// is used in the implementation of visibility tracking.
enum class VisibilityCounter : uint8_t
{
MAY_BECOME_VISIBLE,
IN_DISPLAYPORT
};
// Requested actions when frames transition to the nonvisible state.
+45
View File
@@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Declares IPC serializers for the visibility-related types in Visibility.h.
* These are separated out to reduce the number of moz.build files that need to
* include chromium IPC headers, since Visibility.h is included from nsIFrame.h
* which is widely included.
*/
#ifndef mozilla_layout_generic_VisibilityIPC_h
#define mozilla_layout_generic_VisibilityIPC_h
#include "ipc/IPCMessageUtils.h"
#include "Visibility.h"
namespace IPC {
template<>
struct ParamTraits<mozilla::VisibilityCounter>
{
typedef mozilla::VisibilityCounter paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, uint8_t(aParam));
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
uint8_t valueAsByte;
if (ReadParam(aMsg, aIter, &valueAsByte)) {
*aResult = paramType(valueAsByte);
return true;
}
return false;
}
};
} // namespace IPC
#endif // mozilla_layout_generic_VisibilityIPC_h
+1
View File
@@ -98,6 +98,7 @@ EXPORTS += [
'ScrollbarActivity.h',
'ScrollSnap.h',
'Visibility.h',
'VisibilityIPC.h',
]
EXPORTS.mozilla += [
+255 -45
View File
@@ -78,6 +78,89 @@ kAxisOrientationToSidesMap[eNumAxisOrientationTypes][eNumAxisEdges] = {
// Helper structs / classes / methods
// ==================================
// Returns true iff the given nsStyleDisplay has display:-webkit-{inline-}-box.
static inline bool
IsDisplayValueLegacyBox(const nsStyleDisplay* aStyleDisp)
{
return aStyleDisp->mDisplay == NS_STYLE_DISPLAY_WEBKIT_BOX ||
aStyleDisp->mDisplay == NS_STYLE_DISPLAY_WEBKIT_INLINE_BOX;
}
// Helper to check whether our nsFlexContainerFrame is emulating a legacy
// -webkit-{inline-}box, in which case we should use legacy CSS properties
// instead of the modern ones. The params are are the nsStyleDisplay and the
// nsStyleContext associated with the nsFlexContainerFrame itself.
static inline bool
IsLegacyBox(const nsStyleDisplay* aStyleDisp,
nsStyleContext* aStyleContext)
{
// Trivial case: just check "display" directly.
if (IsDisplayValueLegacyBox(aStyleDisp)) {
return true;
}
// If this frame is for a scrollable element, then it will actually have
// "display:block", and its *parent* will have the real flex-flavored display
// value. So in that case, check the parent to find out if we're legacy.
if (aStyleDisp->mDisplay == NS_STYLE_DISPLAY_BLOCK) {
nsStyleContext* parentStyleContext = aStyleContext->GetParent();
NS_ASSERTION(parentStyleContext &&
aStyleContext->GetPseudo() == nsCSSAnonBoxes::scrolledContent,
"The only way a nsFlexContainerFrame can have 'display:block' "
"should be if it's the inner part of a scrollable element");
if (IsDisplayValueLegacyBox(parentStyleContext->StyleDisplay())) {
return true;
}
}
return false;
}
// Returns the "align-items" value that's equivalent to the legacy "box-align"
// value in the given style struct.
static uint8_t
ConvertLegacyStyleToAlignItems(const nsStyleXUL* aStyleXUL)
{
// -[moz|webkit]-box-align corresponds to modern "align-items"
switch (aStyleXUL->mBoxAlign) {
case NS_STYLE_BOX_ALIGN_STRETCH:
return NS_STYLE_ALIGN_STRETCH;
case NS_STYLE_BOX_ALIGN_START:
return NS_STYLE_ALIGN_FLEX_START;
case NS_STYLE_BOX_ALIGN_CENTER:
return NS_STYLE_ALIGN_CENTER;
case NS_STYLE_BOX_ALIGN_BASELINE:
return NS_STYLE_ALIGN_BASELINE;
case NS_STYLE_BOX_ALIGN_END:
return NS_STYLE_ALIGN_FLEX_END;
}
MOZ_ASSERT_UNREACHABLE("Unrecognized mBoxAlign enum value");
// Fall back to default value of "align-items" property:
return NS_STYLE_ALIGN_STRETCH;
}
// Returns the "justify-content" value that's equivalent to the legacy
// "box-pack" value in the given style struct.
static uint8_t
ConvertLegacyStyleToJustifyContent(const nsStyleXUL* aStyleXUL)
{
// -[moz|webkit]-box-pack corresponds to modern "justify-content"
switch (aStyleXUL->mBoxPack) {
case NS_STYLE_BOX_PACK_START:
return NS_STYLE_ALIGN_FLEX_START;
case NS_STYLE_BOX_PACK_CENTER:
return NS_STYLE_ALIGN_CENTER;
case NS_STYLE_BOX_PACK_END:
return NS_STYLE_ALIGN_FLEX_END;
case NS_STYLE_BOX_PACK_JUSTIFY:
return NS_STYLE_ALIGN_SPACE_BETWEEN;
}
MOZ_ASSERT_UNREACHABLE("Unrecognized mBoxPack enum value");
// Fall back to default value of "justify-content" property:
return NS_STYLE_ALIGN_FLEX_START;
}
// Indicates whether advancing along the given axis is equivalent to
// increasing our X or Y position (as opposed to decreasing it).
@@ -156,7 +239,7 @@ PhysicalCoordFromFlexRelativeCoord(nscoord aFlexRelativeCoord,
// Encapsulates our flex container's main & cross axes.
class MOZ_STACK_CLASS nsFlexContainerFrame::FlexboxAxisTracker {
public:
FlexboxAxisTracker(const nsStylePosition* aStylePosition,
FlexboxAxisTracker(const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM);
// Accessors:
@@ -287,6 +370,15 @@ private:
FlexboxAxisTracker(const FlexboxAxisTracker&) = delete;
FlexboxAxisTracker& operator=(const FlexboxAxisTracker&) = delete;
// Helpers for constructor which determine the orientation of our axes, based
// on legacy box properties (-webkit-box-orient, -webkit-box-direction) or
// modern flexbox properties (flex-direction, flex-wrap) depending on whether
// the flex container is a "legacy box" (as determined by IsLegacyBox).
void InitAxesFromLegacyProps(const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM);
void InitAxesFromModernProps(const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM);
// XXXdholbert [BEGIN DEPRECATED]
AxisOrientationType mMainAxis;
AxisOrientationType mCrossAxis;
@@ -890,6 +982,29 @@ BuildStrutInfoFromCollapsedItems(const FlexLine* aFirstLine,
}
}
// Convenience function to get either the "order" or the "box-ordinal-group"
// property-value for a flex item (depending on whether the container is a
// modern flex container or a legacy box).
static int32_t
GetOrderOrBoxOrdinalGroup(nsIFrame* aFlexItem, bool aIsLegacyBox)
{
if (aIsLegacyBox) {
// We'll be using mBoxOrdinal, which has type uint32_t. However, the modern
// 'order' property (whose functionality we're co-opting) has type int32_t.
// So: if we happen to have a uint32_t value that's greater than INT32_MAX,
// we clamp it rather than letting it overflow. Chances are, this is just
// an author using BIG_VALUE anyway, so the clamped value should be fine.
// (particularly since sufficiently-huge values are busted in Chrome/WebKit
// per https://bugs.chromium.org/p/chromium/issues/detail?id=599645 )
uint32_t clampedBoxOrdinal = std::min(aFlexItem->StyleXUL()->mBoxOrdinal,
static_cast<uint32_t>(INT32_MAX));
return static_cast<int32_t>(clampedBoxOrdinal);
}
// Normal case: just use modern 'order' property.
return aFlexItem->StylePosition()->mOrder;
}
// Helper-function to find the first non-anonymous-box descendent of aFrame.
static nsIFrame*
GetFirstNonAnonBoxDescendant(nsIFrame* aFrame)
@@ -954,6 +1069,11 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFrame1,
{
MOZ_ASSERT(aFrame1->IsFlexItem() && aFrame2->IsFlexItem(),
"this method only intended for comparing flex items");
MOZ_ASSERT(aFrame1->GetParent() == aFrame2->GetParent(),
"this method only intended for comparing siblings");
nsStyleContext* parentFrameSC = aFrame1->GetParent()->StyleContext();
bool isInLegacyBox = IsLegacyBox(parentFrameSC->StyleDisplay(),
parentFrameSC);
if (aFrame1 == aFrame2) {
// Anything is trivially LEQ itself, so we return "true" here... but it's
@@ -967,8 +1087,8 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFrame1,
nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
int32_t order1 = aRealFrame1->StylePosition()->mOrder;
int32_t order2 = aRealFrame2->StylePosition()->mOrder;
int32_t order1 = GetOrderOrBoxOrdinalGroup(aRealFrame1, isInLegacyBox);
int32_t order2 = GetOrderOrBoxOrdinalGroup(aRealFrame2, isInLegacyBox);
if (order1 != order2) {
return order1 < order2;
@@ -1035,13 +1155,18 @@ IsOrderLEQ(nsIFrame* aFrame1,
{
MOZ_ASSERT(aFrame1->IsFlexItem() && aFrame2->IsFlexItem(),
"this method only intended for comparing flex items");
MOZ_ASSERT(aFrame1->GetParent() == aFrame2->GetParent(),
"this method only intended for comparing siblings");
nsStyleContext* parentFrameSC = aFrame1->GetParent()->StyleContext();
bool isInLegacyBox = IsLegacyBox(parentFrameSC->StyleDisplay(),
parentFrameSC);
// If we've got a placeholder frame, use its out-of-flow frame's 'order' val.
nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
int32_t order1 = aRealFrame1->StylePosition()->mOrder;
int32_t order2 = aRealFrame2->StylePosition()->mOrder;
int32_t order1 = GetOrderOrBoxOrdinalGroup(aRealFrame1, isInLegacyBox);
int32_t order2 = GetOrderOrBoxOrdinalGroup(aRealFrame2, isInLegacyBox);
return order1 <= order2;
}
@@ -1049,7 +1174,7 @@ IsOrderLEQ(nsIFrame* aFrame1,
bool
nsFlexContainerFrame::IsHorizontal()
{
const FlexboxAxisTracker axisTracker(StylePosition(), GetWritingMode());
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
return axisTracker.IsMainAxisHorizontal();
}
@@ -1069,9 +1194,15 @@ nsFlexContainerFrame::GenerateFlexItemForChild(
// FLEX GROW & SHRINK WEIGHTS
// --------------------------
const nsStylePosition* stylePos = aChildFrame->StylePosition();
float flexGrow = stylePos->mFlexGrow;
float flexShrink = stylePos->mFlexShrink;
float flexGrow, flexShrink;
if (IsLegacyBox(aParentReflowState.mStyleDisplay, mStyleContext)) {
flexGrow = flexShrink = aChildFrame->StyleXUL()->mBoxFlex;
} else {
const nsStylePosition* stylePos = aChildFrame->StylePosition();
flexGrow = stylePos->mFlexGrow;
flexShrink = stylePos->mFlexShrink;
}
WritingMode childWM = childRS.GetWritingMode();
// MAIN SIZES (flex base size, min/max size)
@@ -1576,14 +1707,28 @@ FlexItem::FlexItem(nsHTMLReflowState& aFlexItemReflowState,
MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
"out-of-flow frames should not be treated as flex items");
mAlignSelf = aFlexItemReflowState.mStylePosition->ComputedAlignSelf(
mFrame->StyleContext()->GetParent());
if (MOZ_LIKELY(mAlignSelf == NS_STYLE_ALIGN_NORMAL)) {
mAlignSelf = NS_STYLE_ALIGN_STRETCH;
}
const nsHTMLReflowState* containerRS = aFlexItemReflowState.parentReflowState;
if (IsLegacyBox(containerRS->mStyleDisplay,
containerRS->frame->StyleContext())) {
// For -webkit-box/-webkit-inline-box, we need to:
// (1) Use "-webkit-box-align" instead of "align-items" to determine the
// container's cross-axis alignment behavior.
// (2) Suppress the ability for flex items to override that with their own
// cross-axis alignment. (The legacy box model doesn't support this.)
// So, each FlexItem simply copies the container's converted "align-items"
// value and disregards their own "align-self" property.
const nsStyleXUL* containerStyleXUL = containerRS->frame->StyleXUL();
mAlignSelf = ConvertLegacyStyleToAlignItems(containerStyleXUL);
} else {
mAlignSelf = aFlexItemReflowState.mStylePosition->ComputedAlignSelf(
mFrame->StyleContext()->GetParent());
if (MOZ_LIKELY(mAlignSelf == NS_STYLE_ALIGN_NORMAL)) {
mAlignSelf = NS_STYLE_ALIGN_STRETCH;
}
// XXX strip off the <overflow-position> bit until we implement that
mAlignSelf &= ~NS_STYLE_ALIGN_FLAG_BITS;
// XXX strip off the <overflow-position> bit until we implement that
mAlignSelf &= ~NS_STYLE_ALIGN_FLAG_BITS;
}
SetFlexBaseSizeAndMainSize(aFlexBaseSize);
CheckForMinSizeAuto(aFlexItemReflowState, aAxisTracker);
@@ -1940,7 +2085,7 @@ public:
NS_QUERYFRAME_HEAD(nsFlexContainerFrame)
NS_QUERYFRAME_ENTRY(nsFlexContainerFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsFlexContainerFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsFlexContainerFrame)
@@ -3058,12 +3203,92 @@ BlockDirToAxisOrientation(WritingMode::BlockDir aBlockDir)
return eAxis_TB; // in case of unforseen error, assume English TTB block-flow
}
FlexboxAxisTracker::FlexboxAxisTracker(const nsStylePosition* aStylePosition,
const WritingMode& aWM)
FlexboxAxisTracker::FlexboxAxisTracker(
const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM)
: mWM(aWM),
mAreAxesInternallyReversed(false)
{
uint32_t flexDirection = aStylePosition->mFlexDirection;
if (IsLegacyBox(aFlexContainer->StyleDisplay(),
aFlexContainer->StyleContext())) {
InitAxesFromLegacyProps(aFlexContainer, aWM);
} else {
InitAxesFromModernProps(aFlexContainer, aWM);
}
// Master switch to enable/disable bug 983427's code for reversing our axes
// and reversing some logic, to avoid reflowing children in bottom-to-top
// order. (This switch can be removed eventually, but for now, it allows
// this special-case code path to be compared against the normal code path.)
static bool sPreventBottomToTopChildOrdering = true;
if (sPreventBottomToTopChildOrdering) {
// If either axis is bottom-to-top, we flip both axes (and set a flag
// so that we can flip some logic to make the reversal transparent).
if (eAxis_BT == mMainAxis || eAxis_BT == mCrossAxis) {
mMainAxis = GetReverseAxis(mMainAxis);
mCrossAxis = GetReverseAxis(mCrossAxis);
mAreAxesInternallyReversed = true;
mIsMainAxisReversed = !mIsMainAxisReversed;
mIsCrossAxisReversed = !mIsCrossAxisReversed;
}
}
}
void
FlexboxAxisTracker::InitAxesFromLegacyProps(
const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM)
{
const nsStyleXUL* styleXUL = aFlexContainer->StyleXUL();
const bool boxOrientIsVertical = (styleXUL->mBoxOrient ==
NS_STYLE_BOX_ORIENT_VERTICAL);
const bool wmIsVertical = aWM.IsVertical();
// If box-orient agrees with our writing-mode, then we're "row-oriented"
// (i.e. the flexbox main axis is the same as our writing mode's inline
// direction). Otherwise, we're column-oriented (i.e. the flexbox's main
// axis is perpendicular to the writing-mode's inline direction).
mIsRowOriented = (boxOrientIsVertical == wmIsVertical);
// XXXdholbert BEGIN CODE TO SET DEPRECATED MEMBER-VARS
if (boxOrientIsVertical) {
mMainAxis = eAxis_TB;
mCrossAxis = eAxis_LR;
} else {
mMainAxis = eAxis_LR;
mCrossAxis = eAxis_TB;
}
// "direction: rtl" (in a horizontal -webkit-box) reverses the main axis.
// (Note this we don't toggle "mIsMainAxisReversed" for this condition,
// because the main axis will still match aWM's inline direction.)
if (aWM.IsBidiLTR()) {
mMainAxis = GetReverseAxis(mMainAxis);
}
// XXXdholbert END CODE TO SET DEPRECATED MEMBER-VARS
// Legacy flexbox can use "-webkit-box-direction: reverse" to reverse the
// main axis (so it runs in the reverse direction of the inline axis):
if (styleXUL->mBoxDirection == NS_STYLE_BOX_DIRECTION_REVERSE) {
mMainAxis = GetReverseAxis(mMainAxis);
mIsMainAxisReversed = true;
} else {
mIsMainAxisReversed = false;
}
// Legacy flexbox does not support reversing the cross axis -- it has no
// equivalent of modern flexbox's "flex-wrap: wrap-reverse".
mIsCrossAxisReversed = false;
}
void
FlexboxAxisTracker::InitAxesFromModernProps(
const nsFlexContainerFrame* aFlexContainer,
const WritingMode& aWM)
{
const nsStylePosition* stylePos = aFlexContainer->StylePosition();
uint32_t flexDirection = stylePos->mFlexDirection;
// Inline dimension ("start-to-end"):
// (NOTE: I'm intentionally not calling these "inlineAxis"/"blockAxis", since
@@ -3111,30 +3336,12 @@ FlexboxAxisTracker::FlexboxAxisTracker(const nsStylePosition* aStylePosition,
}
// "flex-wrap: wrap-reverse" reverses our cross axis.
if (aStylePosition->mFlexWrap == NS_STYLE_FLEX_WRAP_WRAP_REVERSE) {
if (stylePos->mFlexWrap == NS_STYLE_FLEX_WRAP_WRAP_REVERSE) {
mCrossAxis = GetReverseAxis(mCrossAxis);
mIsCrossAxisReversed = true;
} else {
mIsCrossAxisReversed = false;
}
// Master switch to enable/disable bug 983427's code for reversing our axes
// and reversing some logic, to avoid reflowing children in bottom-to-top
// order. (This switch can be removed eventually, but for now, it allows
// this special-case code path to be compared against the normal code path.)
static bool sPreventBottomToTopChildOrdering = true;
if (sPreventBottomToTopChildOrdering) {
// If either axis is bottom-to-top, we flip both axes (and set a flag
// so that we can flip some logic to make the reversal transparent).
if (eAxis_BT == mMainAxis || eAxis_BT == mCrossAxis) {
mMainAxis = GetReverseAxis(mMainAxis);
mCrossAxis = GetReverseAxis(mCrossAxis);
mAreAxesInternallyReversed = true;
mIsMainAxisReversed = !mIsMainAxisReversed;
mIsCrossAxisReversed = !mIsCrossAxisReversed;
}
}
}
// Allocates a new FlexLine, adds it to the given LinkedList (at the front or
@@ -3647,8 +3854,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
SortChildrenIfNeeded<IsOrderLEQWithDOMFallback>();
}
const FlexboxAxisTracker axisTracker(aReflowState.mStylePosition,
aReflowState.GetWritingMode());
const FlexboxAxisTracker axisTracker(this, aReflowState.GetWritingMode());
// If we're being fragmented into a constrained BSize, then subtract off
// borderpadding BStart from that constrained BSize, to get the available
@@ -3858,11 +4064,14 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
}
}
for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
const auto justifyContent = IsLegacyBox(aReflowState.mStyleDisplay,
mStyleContext) ?
ConvertLegacyStyleToJustifyContent(StyleXUL()) :
aReflowState.mStylePosition->ComputedJustifyContent();
for (FlexLine* line = lines.getFirst(); line; line = line->getNext()) {
// Main-Axis Alignment - Flexbox spec section 9.5
// ==============================================
auto justifyContent = aReflowState.mStylePosition->ComputedJustifyContent();
line->PositionItemsInMainAxis(justifyContent,
aContentBoxMainSize,
aAxisTracker);
@@ -4069,6 +4278,7 @@ nsFlexContainerFrame::MoveFlexItemToFinalPosition(
logicalOffsets, &aFramePos,
aContainerSize);
aItem.Frame()->SetPosition(outerWM, aFramePos, aContainerSize);
PositionFrameView(aItem.Frame());
PositionChildViews(aItem.Frame());
}
@@ -4186,7 +4396,7 @@ nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext)
DISPLAY_MIN_WIDTH(this, minWidth);
const nsStylePosition* stylePos = StylePosition();
const FlexboxAxisTracker axisTracker(stylePos, GetWritingMode());
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
for (nsIFrame* childFrame : mFrames) {
nscoord childMinWidth =
@@ -4217,7 +4427,7 @@ nsFlexContainerFrame::GetPrefISize(nsRenderingContext* aRenderingContext)
// Whenever anything happens that might change it, set it to
// NS_INTRINSIC_WIDTH_UNKNOWN (like nsBlockFrame::MarkIntrinsicISizesDirty
// does)
const FlexboxAxisTracker axisTracker(StylePosition(), GetWritingMode());
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
for (nsIFrame* childFrame : mFrames) {
nscoord childPrefWidth =
+23 -5
View File
@@ -5,7 +5,7 @@
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/. */
/* rendering object for CSS "display: flex" */
/* rendering object for CSS "display: flex" and "display: -webkit-box" */
#ifndef nsFlexContainerFrame_h___
#define nsFlexContainerFrame_h___
@@ -20,9 +20,27 @@ class LogicalPoint;
nsContainerFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
typedef nsContainerFrame nsFlexContainerFrameSuper;
class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
/**
* This is the rendering object used for laying out elements with
* "display: flex" or "display: inline-flex".
*
* We also use this class for elements with "display: -webkit-box" or
* "display: -webkit-inline-box" (but not "-moz-box" / "-moz-inline-box" --
* those are rendered with old-school XUL frame classes).
*
* Note: we represent the -webkit-box family of properties (-webkit-box-orient,
* -webkit-box-flex, etc.) as aliases for their -moz equivalents. And for
* -webkit-{inline-}box containers, nsFlexContainerFrame will honor those
* "legacy" properties for alignment/flexibility/etc. *instead of* honoring the
* modern flexbox & alignment properties. For brevity, many comments in
* nsFlexContainerFrame.cpp simply refer to these properties using their
* "-webkit" versions, since we're mostly expecting to encounter them in that
* form. (Technically, the "-moz" versions of these properties *can* influence
* layout here as well (since that's what the -webkit versions are aliased to)
* -- but only inside of a "display:-webkit-{inline-}box" container.)
*/
class nsFlexContainerFrame : public nsContainerFrame {
public:
NS_DECL_FRAMEARENA_HELPERS
NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame)
@@ -62,8 +80,8 @@ public:
protected:
// Protected constructor & destructor
explicit nsFlexContainerFrame(nsStyleContext* aContext) :
nsFlexContainerFrameSuper(aContext)
explicit nsFlexContainerFrame(nsStyleContext* aContext)
: nsContainerFrame(aContext)
{}
virtual ~nsFlexContainerFrame();
+77 -38
View File
@@ -414,7 +414,7 @@ nsFrame::~nsFrame()
{
MOZ_COUNT_DTOR(nsFrame);
MOZ_ASSERT(GetVisibility() != Visibility::APPROXIMATELY_VISIBLE,
MOZ_ASSERT(!IsVisibleOrMayBecomeVisibleSoon(),
"Visible nsFrame is being destroyed");
NS_IF_RELEASE(mContent);
@@ -553,7 +553,7 @@ nsFrame::Init(nsIContent* aContent,
if (HasAnyStateBits(NS_FRAME_IN_POPUP) && TrackingVisibility()) {
// Assume all frames in popups are visible.
IncApproximateVisibleCount();
IncVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
}
const nsStyleDisplay *disp = StyleDisplay();
@@ -606,7 +606,7 @@ nsFrame::Init(nsIContent* aContent,
if (PresContext()->PresShell()->AssumeAllFramesVisible() &&
TrackingVisibility()) {
IncApproximateVisibleCount();
IncVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
DidSetStyleContext(nullptr);
@@ -733,8 +733,8 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
// frame reconstruction induced by style changes.
DisableVisibilityTracking();
// Ensure that we're not in the approximately visible list anymore.
PresContext()->GetPresShell()->RemoveFrameFromApproximatelyVisibleList(this);
// Ensure that we're not in the visible list anymore.
PresContext()->GetPresShell()->MarkFrameNonvisible(this);
shell->NotifyDestroyingFrame(this);
@@ -1476,6 +1476,18 @@ nsIFrame::GetCrossDocChildLists(nsTArray<ChildList>* aLists)
GetChildLists(aLists);
}
static Visibility
VisibilityStateAsVisibility(const nsIFrame::VisibilityState& aState)
{
if (aState.mInDisplayPortCounter > 0) {
return Visibility::IN_DISPLAYPORT; // Takes priority over MAY_BECOME_VISIBLE.
}
if (aState.mApproximateCounter > 0) {
return Visibility::MAY_BECOME_VISIBLE;
}
return Visibility::NONVISIBLE;
}
Visibility
nsIFrame::GetVisibility() const
{
@@ -1485,14 +1497,12 @@ nsIFrame::GetVisibility() const
bool isSet = false;
FrameProperties props = Properties();
uint32_t visibleCount = props.Get(VisibilityStateProperty(), &isSet);
VisibilityState state = props.Get(VisibilityStateProperty(), &isSet);
MOZ_ASSERT(isSet, "Should have a VisibilityStateProperty value "
"if NS_FRAME_VISIBILITY_IS_TRACKED is set");
return visibleCount > 0
? Visibility::APPROXIMATELY_VISIBLE
: Visibility::APPROXIMATELY_NONVISIBLE;
return VisibilityStateAsVisibility(state);
}
void
@@ -1504,7 +1514,7 @@ nsIFrame::UpdateVisibilitySynchronously()
}
if (presShell->AssumeAllFramesVisible()) {
presShell->EnsureFrameInApproximatelyVisibleList(this);
presShell->MarkFrameVisibleInDisplayPort(this);
return;
}
@@ -1545,9 +1555,9 @@ nsIFrame::UpdateVisibilitySynchronously()
}
if (visible) {
presShell->EnsureFrameInApproximatelyVisibleList(this);
presShell->MarkFrameVisibleInDisplayPort(this);
} else {
presShell->RemoveFrameFromApproximatelyVisibleList(this);
presShell->MarkFrameNonvisible(this);
}
}
@@ -1566,7 +1576,7 @@ nsIFrame::EnableVisibilityTracking()
// Add the state bit so we know to track visibility for this frame, and
// initialize the frame property.
AddStateBits(NS_FRAME_VISIBILITY_IS_TRACKED);
props.Set(VisibilityStateProperty(), 0);
props.Set(VisibilityStateProperty(), VisibilityState{0, 0});
nsIPresShell* presShell = PresContext()->PresShell();
if (!presShell) {
@@ -1589,66 +1599,87 @@ nsIFrame::DisableVisibilityTracking()
bool isSet = false;
FrameProperties props = Properties();
uint32_t visibleCount = props.Remove(VisibilityStateProperty(), &isSet);
VisibilityState state = props.Remove(VisibilityStateProperty(), &isSet);
MOZ_ASSERT(isSet, "Should have a VisibilityStateProperty value "
"if NS_FRAME_VISIBILITY_IS_TRACKED is set");
RemoveStateBits(NS_FRAME_VISIBILITY_IS_TRACKED);
if (visibleCount == 0) {
return; // We were nonvisible.
Visibility previousVisibility = VisibilityStateAsVisibility(state);
if (previousVisibility == Visibility::NONVISIBLE) {
return; // We were already nonvisible.
}
// We were visible, so send an OnVisibilityChange() notification.
OnVisibilityChange(Visibility::APPROXIMATELY_NONVISIBLE);
OnVisibilityChange(Visibility::NONVISIBLE);
}
void
nsIFrame::DecApproximateVisibleCount(Maybe<OnNonvisible> aNonvisibleAction
/* = Nothing() */)
nsIFrame::DecVisibilityCount(VisibilityCounter aCounter,
Maybe<OnNonvisible> aNonvisibleAction /* = Nothing() */)
{
MOZ_ASSERT(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
bool isSet = false;
FrameProperties props = Properties();
uint32_t visibleCount = props.Get(VisibilityStateProperty(), &isSet);
VisibilityState state = props.Get(VisibilityStateProperty(), &isSet);
MOZ_ASSERT(isSet, "Should have a VisibilityStateProperty value "
"if NS_FRAME_VISIBILITY_IS_TRACKED is set");
MOZ_ASSERT(visibleCount > 0, "Frame is already nonvisible and we're "
"decrementing its visible count?");
MOZ_ASSERT_IF(aCounter == VisibilityCounter::MAY_BECOME_VISIBLE,
state.mApproximateCounter > 0);
MOZ_ASSERT_IF(aCounter == VisibilityCounter::IN_DISPLAYPORT,
state.mInDisplayPortCounter > 0);
visibleCount--;
props.Set(VisibilityStateProperty(), visibleCount);
if (visibleCount > 0) {
return;
Visibility previousVisibility = VisibilityStateAsVisibility(state);
if (aCounter == VisibilityCounter::MAY_BECOME_VISIBLE) {
state.mApproximateCounter--;
} else {
state.mInDisplayPortCounter--;
}
// We just became nonvisible, so send an OnVisibilityChange() notification.
OnVisibilityChange(Visibility::APPROXIMATELY_NONVISIBLE, aNonvisibleAction);
props.Set(VisibilityStateProperty(), state);
Visibility newVisibility = VisibilityStateAsVisibility(state);
if (newVisibility == previousVisibility) {
return; // Nothing changed.
}
// Our visibility just changed, so send an OnVisibilityChange() notification.
OnVisibilityChange(newVisibility, aNonvisibleAction);
}
void
nsIFrame::IncApproximateVisibleCount()
nsIFrame::IncVisibilityCount(VisibilityCounter aCounter)
{
MOZ_ASSERT(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
bool isSet = false;
FrameProperties props = Properties();
uint32_t visibleCount = props.Get(VisibilityStateProperty(), &isSet);
VisibilityState state = props.Get(VisibilityStateProperty(), &isSet);
MOZ_ASSERT(isSet, "Should have a VisibilityStateProperty value "
"if NS_FRAME_VISIBILITY_IS_TRACKED is set");
visibleCount++;
props.Set(VisibilityStateProperty(), visibleCount);
if (visibleCount > 1) {
return;
Visibility previousVisibility = VisibilityStateAsVisibility(state);
if (aCounter == VisibilityCounter::MAY_BECOME_VISIBLE) {
state.mApproximateCounter++;
} else {
state.mInDisplayPortCounter++;
}
// We just became visible, so send an OnVisibilityChange() notification.
OnVisibilityChange(Visibility::APPROXIMATELY_VISIBLE);
props.Set(VisibilityStateProperty(), state);
Visibility newVisibility = VisibilityStateAsVisibility(state);
if (newVisibility == previousVisibility) {
return; // Nothing changed.
}
// Our visibility just changed, so send an OnVisibilityChange() notification.
OnVisibilityChange(newVisibility);
}
void
@@ -2683,6 +2714,14 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
!PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
return;
// Since we're now sure that we're adding this frame to the display list
// (which means we're painting it, modulo occlusion), mark it as visible
// within the displayport.
if (aBuilder->IsPaintingToWindow() && child->TrackingVisibility()) {
nsIPresShell* shell = child->PresContext()->PresShell();
shell->MarkFrameVisibleInDisplayPort(child);
}
// Child is composited if it's transformed, partially transparent, or has
// SVG effects or a blend mode..
const nsStyleDisplay* disp = child->StyleDisplay();
@@ -9166,7 +9205,7 @@ nsIFrame::AddInPopupStateBitToDescendants(nsIFrame* aFrame)
if (!aFrame->HasAnyStateBits(NS_FRAME_IN_POPUP) &&
aFrame->TrackingVisibility()) {
// Assume all frames in popups are visible.
aFrame->IncApproximateVisibleCount();
aFrame->IncVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
aFrame->AddStateBits(NS_FRAME_IN_POPUP);
@@ -9196,7 +9235,7 @@ nsIFrame::RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame)
if (aFrame->TrackingVisibility()) {
// We assume all frames in popups are visible, so this decrement balances
// out the increment in AddInPopupStateBitToDescendants above.
aFrame->DecApproximateVisibleCount();
aFrame->DecVisibilityCount(VisibilityCounter::IN_DISPLAYPORT);
}
AutoTArray<nsIFrame::ChildList,4> childListArray;
+35 -11
View File
@@ -424,6 +424,7 @@ public:
template<typename T=void>
using PropertyDescriptor = const mozilla::FramePropertyDescriptor<T>*;
using Visibility = mozilla::Visibility;
using VisibilityCounter = mozilla::VisibilityCounter;
typedef mozilla::FrameProperties FrameProperties;
typedef mozilla::layers::Layer Layer;
@@ -1106,6 +1107,15 @@ public:
/// for the possible return values and their meanings.
Visibility GetVisibility() const;
/// @return true if this frame is either in the displayport now or may
/// become visible soon.
bool IsVisibleOrMayBecomeVisibleSoon() const
{
Visibility visibility = GetVisibility();
return visibility == Visibility::MAY_BECOME_VISIBLE ||
visibility == Visibility::IN_DISPLAYPORT;
}
/// Update the visibility state of this frame synchronously.
/// XXX(seth): Avoid using this method; we should be relying on the refresh
/// driver for visibility updates. This method, which replaces
@@ -1114,11 +1124,17 @@ public:
/// the old image visibility code.
void UpdateVisibilitySynchronously();
// A frame property which stores the visibility state of this frame. Right
// now that consists of an approximate visibility counter represented as a
// uint32_t. When the visibility of this frame is not being tracked, this
// property is absent.
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
struct VisibilityState
{
unsigned int mApproximateCounter : 16;
unsigned int mInDisplayPortCounter : 16;
};
// A frame property which stores the visibility state of this frame, which
// consists of a VisibilityState value that stores counters for each type of
// visibility we track. When the visibility of this frame is not being
// tracked, this property is absent.
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, VisibilityState);
protected:
@@ -1163,12 +1179,19 @@ public:
///////////////////////////////////////////////////////////////////////////////
/**
* We track the approximate visibility of frames using a counter; if it's
* non-zero, then the frame is considered visible. Using a counter allows us
* to account for situations where the frame may be visible in more than one
* place (for example, via -moz-element), and it simplifies the
* We track the visibility of frames using counters; if any of the counters
* are non-zero, then the frame is considered visible. Using counters allows
* us to account for situations where the frame may be visible in more than
* one place (for example, via -moz-element), and it simplifies the
* implementation of our approximate visibility tracking algorithms.
*
* There are two visibility counters for each frame: the approximate counter
* (which is based on our heuristics for which frames may become visible
* "soon"), and the in-displayport counter (which records if the frame was
* within the displayport at the last paint).
*
*
* @param aCounter Which counter to increment or decrement.
* @param aNonvisibleAction A requested action if the frame has become
* nonvisible. If Nothing(), no action is
* requested. If DISCARD_IMAGES is specified, the
@@ -1176,8 +1199,9 @@ public:
* associated with to discard their surfaces if
* possible.
*/
void DecApproximateVisibleCount(Maybe<OnNonvisible> aNonvisibleAction = Nothing());
void IncApproximateVisibleCount();
void DecVisibilityCount(VisibilityCounter aCounter,
Maybe<OnNonvisible> aNonvisibleAction = Nothing());
void IncVisibilityCount(VisibilityCounter aCounter);
/**
+40 -16
View File
@@ -136,7 +136,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
ImageFrameSuper(aContext),
nsAtomicContainerFrame(aContext),
mComputedSize(0, 0),
mIntrinsicRatio(0, 0),
mDisplayingIcon(false),
@@ -158,7 +158,7 @@ nsImageFrame::~nsImageFrame()
NS_QUERYFRAME_HEAD(nsImageFrame)
NS_QUERYFRAME_ENTRY(nsImageFrame)
NS_QUERYFRAME_TAIL_INHERITING(ImageFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@@ -222,13 +222,13 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
if (mDisplayingIcon)
gIconLoad->RemoveIconObserver(this);
ImageFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
void
nsImageFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
{
ImageFrameSuper::DidSetStyleContext(aOldStyleContext);
nsAtomicContainerFrame::DidSetStyleContext(aOldStyleContext);
if (!mImage) {
// We'll pick this change up whenever we do get an image.
@@ -258,7 +258,7 @@ nsImageFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
ImageFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
mListener = new nsImageListener(this);
@@ -557,12 +557,12 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
// This is valid and for the current request, so update our stored image
// container, orienting according to our style.
mImage = nsLayoutUtils::OrientImage(aImage, StyleVisibility()->mImageOrientation);
intrinsicSizeChanged = UpdateIntrinsicSize(mImage);
intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged;
} else {
// We no longer have a valid image, so release our stored image container.
mImage = nullptr;
mImage = mPrevImage = nullptr;
// Have to size to 0,0 so that GetDesiredSize recalculates the size.
mIntrinsicSize.width.SetCoordValue(0);
@@ -586,6 +586,8 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage)
// so we're ready to request a decode.
MaybeDecodeForPredictedSize();
}
mPrevImage = nullptr;
}
return NS_OK;
@@ -675,7 +677,7 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest,
intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged;
} else {
// We no longer have a valid image, so release our stored image container.
mImage = nullptr;
mImage = mPrevImage = nullptr;
// Have to size to 0,0 so that GetDesiredSize recalculates the size
mIntrinsicSize.width.SetCoordValue(0);
@@ -696,6 +698,8 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest,
// so we're ready to request a decode.
MaybeDecodeForPredictedSize();
}
mPrevImage = nullptr;
}
// Update border+content to account for image change
InvalidateFrame();
@@ -714,7 +718,7 @@ nsImageFrame::MaybeDecodeForPredictedSize()
return; // We won't draw anything, so no point in decoding.
}
if (GetVisibility() != Visibility::APPROXIMATELY_VISIBLE) {
if (!IsVisibleOrMayBecomeVisibleSoon()) {
return; // We're not visible, so don't decode.
}
@@ -1486,7 +1490,8 @@ static void PaintDebugImageMap(nsIFrame* aFrame, DrawTarget* aDrawTarget,
void
nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) {
nsRenderingContext* aCtx)
{
uint32_t flags = imgIContainer::FLAG_NONE;
if (aBuilder->ShouldSyncDecodeImages()) {
flags |= imgIContainer::FLAG_SYNC_DECODE;
@@ -1498,6 +1503,17 @@ nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
DrawResult result = static_cast<nsImageFrame*>(mFrame)->
PaintImage(*aCtx, ToReferenceFrame(), mVisibleRect, mImage, flags);
if (result == DrawResult::NOT_READY ||
result == DrawResult::INCOMPLETE ||
result == DrawResult::TEMPORARY_ERROR) {
// If the current image failed to paint because it's still loading or
// decoding, try painting the previous image.
if (mPrevImage) {
result = static_cast<nsImageFrame*>(mFrame)->
PaintImage(*aCtx, ToReferenceFrame(), mVisibleRect, mPrevImage, flags);
}
}
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
@@ -1692,6 +1708,12 @@ nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
map->Draw(this, *drawTarget, black, strokeOptions);
}
if (result == DrawResult::SUCCESS) {
mPrevImage = aImage;
} else if (result == DrawResult::BAD_IMAGE) {
mPrevImage = nullptr;
}
return result;
}
@@ -1746,7 +1768,7 @@ nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
} else {
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayImage(aBuilder, this, mImage));
nsDisplayImage(aBuilder, this, mImage, mPrevImage));
// If we were previously displaying an icon, we're not anymore
if (mDisplayingIcon) {
@@ -1998,7 +2020,7 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext,
}
}
return ImageFrameSuper::HandleEvent(aPresContext, aEvent, aEventStatus);
return nsAtomicContainerFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
nsresult
@@ -2035,8 +2057,8 @@ nsImageFrame::AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
{
nsresult rv = ImageFrameSuper::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
nsresult rv = nsAtomicContainerFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
if (NS_FAILED(rv)) {
return rv;
}
@@ -2057,16 +2079,18 @@ nsImageFrame::OnVisibilityChange(Visibility aNewVisibility,
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
if (!imageLoader) {
MOZ_ASSERT_UNREACHABLE("Should have an nsIImageLoadingContent");
nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
return;
}
imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
if (aNewVisibility == Visibility::APPROXIMATELY_VISIBLE) {
if (aNewVisibility == Visibility::MAY_BECOME_VISIBLE ||
aNewVisibility == Visibility::IN_DISPLAYPORT) {
MaybeDecodeForPredictedSize();
}
ImageFrameSuper::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
}
nsIAtom*
+10 -7
View File
@@ -58,10 +58,8 @@ private:
nsImageFrame *mFrame;
};
typedef nsAtomicContainerFrame ImageFrameSuper;
class nsImageFrame : public ImageFrameSuper,
public nsIReflowCallback {
class nsImageFrame : public nsAtomicContainerFrame
, public nsIReflowCallback {
public:
template <typename T> using Maybe = mozilla::Maybe<T>;
using Nothing = mozilla::Nothing;
@@ -119,7 +117,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return ImageFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
}
@@ -333,6 +331,7 @@ private:
nsCOMPtr<imgINotificationObserver> mListener;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgIContainer> mPrevImage;
nsSize mComputedSize;
mozilla::IntrinsicSize mIntrinsicSize;
nsSize mIntrinsicRatio;
@@ -413,8 +412,11 @@ public:
typedef mozilla::layers::LayerManager LayerManager;
nsDisplayImage(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame,
imgIContainer* aImage)
: nsDisplayImageContainer(aBuilder, aFrame), mImage(aImage) {
imgIContainer* aImage, imgIContainer* aPrevImage)
: nsDisplayImageContainer(aBuilder, aFrame)
, mImage(aImage)
, mPrevImage(aPrevImage)
{
MOZ_COUNT_CTOR(nsDisplayImage);
}
virtual ~nsDisplayImage() {
@@ -463,6 +465,7 @@ public:
NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgIContainer> mPrevImage;
};
#endif /* nsImageFrame_h___ */
+3 -3
View File
@@ -71,7 +71,7 @@ nsInlineFrame::InvalidateFrame(uint32_t aDisplayItemKey)
svgTextFrame->InvalidateFrame();
return;
}
nsInlineFrameBase::InvalidateFrame(aDisplayItemKey);
nsContainerFrame::InvalidateFrame(aDisplayItemKey);
}
void
@@ -84,7 +84,7 @@ nsInlineFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayIte
svgTextFrame->InvalidateFrame();
return;
}
nsInlineFrameBase::InvalidateFrameWithRect(aRect, aDisplayItemKey);
nsContainerFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
}
static inline bool
@@ -482,7 +482,7 @@ nsInlineFrame::AttributeChanged(int32_t aNameSpaceID,
int32_t aModType)
{
nsresult rv =
nsInlineFrameBase::AttributeChanged(aNameSpaceID, aAttribute, aModType);
nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
if (NS_FAILED(rv)) {
return rv;
+1 -3
View File
@@ -13,15 +13,13 @@
class nsLineLayout;
typedef nsContainerFrame nsInlineFrameBase;
/**
* Inline frame class.
*
* This class manages a list of child frames that are inline frames. Working with
* nsLineLayout, the class will reflow and place inline frames on a line.
*/
class nsInlineFrame : public nsInlineFrameBase
class nsInlineFrame : public nsContainerFrame
{
public:
NS_DECL_QUERYFRAME_TARGET(nsInlineFrame)
+11 -11
View File
@@ -150,7 +150,7 @@ protected:
};
nsPluginFrame::nsPluginFrame(nsStyleContext* aContext)
: nsPluginFrameSuper(aContext)
: nsFrame(aContext)
, mInstanceOwner(nullptr)
, mReflowCallbackPosted(false)
, mIsHiddenDueToScroll(false)
@@ -168,7 +168,7 @@ nsPluginFrame::~nsPluginFrame()
NS_QUERYFRAME_HEAD(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsIObjectFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsPluginFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@@ -194,7 +194,7 @@ nsPluginFrame::Init(nsIContent* aContent,
MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
("Initializing nsPluginFrame %p for content %p\n", this, aContent));
nsPluginFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsFrame::Init(aContent, aParent, aPrevInFlow);
}
void
@@ -223,7 +223,7 @@ nsPluginFrame::DestroyFrom(nsIFrame* aDestructRoot)
mBackgroundSink->Destroy();
}
nsPluginFrameSuper::DestroyFrom(aDestructRoot);
nsFrame::DestroyFrom(aDestructRoot);
}
/* virtual */ void
@@ -239,7 +239,7 @@ nsPluginFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
}
}
nsPluginFrameSuper::DidSetStyleContext(aOldStyleContext);
nsFrame::DidSetStyleContext(aOldStyleContext);
}
nsIAtom*
@@ -737,7 +737,7 @@ nsPluginFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
{
if (aTabIndex)
*aTabIndex = -1;
return nsPluginFrameSuper::IsFocusable(aTabIndex, aWithMouse);
return nsFrame::IsFocusable(aTabIndex, aWithMouse);
}
bool
@@ -853,7 +853,7 @@ nsPluginFrame::DidReflow(nsPresContext* aPresContext,
objContent->HasNewFrame(this);
}
nsPluginFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
// The view is created hidden; once we have reflowed it and it has been
// positioned then we show it.
@@ -1674,7 +1674,7 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
}
#ifdef XP_WIN
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
return rv;
#endif
@@ -1698,10 +1698,10 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
}
#endif
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
// We need to be careful from this point because the call to
// nsPluginFrameSuper::HandleEvent() might have killed us.
// nsFrame::HandleEvent() might have killed us.
#ifdef XP_MACOSX
if (anEvent->mMessage == eMouseUp) {
@@ -1786,7 +1786,7 @@ nsPluginFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
return NS_ERROR_FAILURE;
}
return nsPluginFrameSuper::GetCursor(aPoint, aCursor);
return nsFrame::GetCursor(aPoint, aCursor);
}
void
+4 -6
View File
@@ -42,13 +42,11 @@ class LayerManager;
} // namespace layers
} // namespace mozilla
typedef nsFrame nsPluginFrameSuper;
class PluginFrameDidCompositeObserver;
class nsPluginFrame : public nsPluginFrameSuper,
public nsIObjectFrame,
public nsIReflowCallback
class nsPluginFrame : public nsFrame
, public nsIObjectFrame
, public nsIReflowCallback
{
public:
typedef mozilla::LayerState LayerState;
@@ -91,7 +89,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsPluginFrameSuper::IsFrameOfType(aFlags &
return nsFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
}
+1 -1
View File
@@ -22,7 +22,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyBaseFrame)
NS_QUERYFRAME_ENTRY(nsRubyBaseFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyBaseFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyContentFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyBaseFrame)
+2 -4
View File
@@ -11,8 +11,6 @@
#include "nsRubyContentFrame.h"
typedef nsRubyContentFrame nsRubyBaseFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyBaseFrame (infallible)
@@ -20,7 +18,7 @@ typedef nsRubyContentFrame nsRubyBaseFrameSuper;
nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyBaseFrame final : public nsRubyBaseFrameSuper
class nsRubyBaseFrame final : public nsRubyContentFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@@ -38,7 +36,7 @@ protected:
friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyBaseFrame(nsStyleContext* aContext)
: nsRubyBaseFrameSuper(aContext) {}
: nsRubyContentFrame(aContext) {}
};
#endif /* nsRubyBaseFrame_h___ */
+1 -1
View File
@@ -24,7 +24,7 @@ nsRubyContentFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eBidiInlineContainer) {
return false;
}
return nsRubyContentFrameSuper::IsFrameOfType(aFlags);
return nsInlineFrame::IsFrameOfType(aFlags);
}
bool
+2 -4
View File
@@ -11,9 +11,7 @@
#include "nsInlineFrame.h"
typedef nsInlineFrame nsRubyContentFrameSuper;
class nsRubyContentFrame : public nsRubyContentFrameSuper
class nsRubyContentFrame : public nsInlineFrame
{
public:
NS_DECL_ABSTRACT_FRAME(nsRubyContentFrame)
@@ -30,7 +28,7 @@ public:
protected:
explicit nsRubyContentFrame(nsStyleContext* aContext)
: nsRubyContentFrameSuper(aContext) {}
: nsInlineFrame(aContext) {}
};
#endif /* nsRubyContentFrame_h___ */
+2 -2
View File
@@ -26,7 +26,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyFrame)
NS_QUERYFRAME_ENTRY(nsRubyFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyFrame)
@@ -54,7 +54,7 @@ nsRubyFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eBidiInlineContainer) {
return false;
}
return nsRubyFrameSuper::IsFrameOfType(aFlags);
return nsInlineFrame::IsFrameOfType(aFlags);
}
#ifdef DEBUG_FRAME_DUMP
+2 -4
View File
@@ -13,8 +13,6 @@
class nsRubyBaseContainerFrame;
typedef nsInlineFrame nsRubyFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyFrame (infallible)
@@ -22,7 +20,7 @@ typedef nsInlineFrame nsRubyFrameSuper;
nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyFrame final : public nsRubyFrameSuper
class nsRubyFrame final : public nsInlineFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@@ -55,7 +53,7 @@ protected:
friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyFrame(nsStyleContext* aContext)
: nsRubyFrameSuper(aContext) {}
: nsInlineFrame(aContext) {}
void ReflowSegment(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
+5 -5
View File
@@ -60,14 +60,14 @@ nsRubyTextContainerFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eSupportsCSSTransforms) {
return false;
}
return nsRubyTextContainerFrameSuper::IsFrameOfType(aFlags);
return nsContainerFrame::IsFrameOfType(aFlags);
}
/* virtual */ void
nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
{
nsRubyTextContainerFrameSuper::SetInitialChildList(aListID, aChildList);
nsContainerFrame::SetInitialChildList(aListID, aChildList);
if (aListID == kPrincipalList) {
UpdateSpanFlag();
}
@@ -77,7 +77,7 @@ nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
nsRubyTextContainerFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
nsRubyTextContainerFrameSuper::AppendFrames(aListID, aFrameList);
nsContainerFrame::AppendFrames(aListID, aFrameList);
UpdateSpanFlag();
}
@@ -86,7 +86,7 @@ nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
nsFrameList& aFrameList)
{
nsRubyTextContainerFrameSuper::InsertFrames(aListID, aPrevFrame, aFrameList);
nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
UpdateSpanFlag();
}
@@ -94,7 +94,7 @@ nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
nsRubyTextContainerFrame::RemoveFrame(ChildListID aListID,
nsIFrame* aOldFrame)
{
nsRubyTextContainerFrameSuper::RemoveFrame(aListID, aOldFrame);
nsContainerFrame::RemoveFrame(aListID, aOldFrame);
UpdateSpanFlag();
}
+2 -4
View File
@@ -11,8 +11,6 @@
#include "nsBlockFrame.h"
typedef nsContainerFrame nsRubyTextContainerFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyTextContainerFrame (infallible)
@@ -20,7 +18,7 @@ typedef nsContainerFrame nsRubyTextContainerFrameSuper;
nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextContainerFrame final : public nsRubyTextContainerFrameSuper
class nsRubyTextContainerFrame final : public nsContainerFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@@ -59,7 +57,7 @@ protected:
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextContainerFrame(nsStyleContext* aContext)
: nsRubyTextContainerFrameSuper(aContext)
: nsContainerFrame(aContext)
, mISize(0) {}
void UpdateSpanFlag();
+3 -4
View File
@@ -22,7 +22,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyTextFrame)
NS_QUERYFRAME_ENTRY(nsRubyTextFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyTextFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyContentFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextFrame)
@@ -70,7 +70,7 @@ nsRubyTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
return;
}
nsRubyTextFrameSuper::BuildDisplayList(aBuilder, aDirtyRect, aLists);
nsRubyContentFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
/* virtual */ void
@@ -85,8 +85,7 @@ nsRubyTextFrame::Reflow(nsPresContext* aPresContext,
// the content is no longer the same, until next reflow triggered by
// some other change. In general, we always reflow all the frames we
// created. There might be other problems if we don't do that.
nsRubyTextFrameSuper::Reflow(aPresContext, aDesiredSize,
aReflowState, aStatus);
nsRubyContentFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
if (IsAutoHidden()) {
// Reset the ISize. The BSize is not changed so that it won't
+2 -4
View File
@@ -11,8 +11,6 @@
#include "nsRubyContentFrame.h"
typedef nsRubyContentFrame nsRubyTextFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyTextFrame (infallible)
@@ -20,7 +18,7 @@ typedef nsRubyContentFrame nsRubyTextFrameSuper;
nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextFrame final : public nsRubyTextFrameSuper
class nsRubyTextFrame final : public nsRubyContentFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@@ -53,7 +51,7 @@ protected:
friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextFrame(nsStyleContext* aContext)
: nsRubyTextFrameSuper(aContext) {}
: nsRubyContentFrame(aContext) {}
};
#endif /* nsRubyTextFrame_h___ */
+14 -16
View File
@@ -57,7 +57,7 @@ GetDocumentFromView(nsView* aView)
}
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
: nsSubDocumentFrameSuper(aContext)
: nsAtomicContainerFrame(aContext)
, mIsInline(false)
, mPostedReflowCallback(false)
, mDidCreateDoc(false)
@@ -75,7 +75,7 @@ nsSubDocumentFrame::AccessibleType()
NS_QUERYFRAME_HEAD(nsSubDocumentFrame)
NS_QUERYFRAME_ENTRY(nsSubDocumentFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsSubDocumentFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
class AsyncFrameInit : public nsRunnable
{
@@ -108,7 +108,7 @@ nsSubDocumentFrame::Init(nsIContent* aContent,
nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = do_QueryInterface(aContent);
mIsInline = frameElem ? false : true;
nsSubDocumentFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
// We are going to create an inner view. If we need a view for the
// OuterFrame but we wait for the normal view creation path in
@@ -689,7 +689,7 @@ nsSubDocumentFrame::GetIntrinsicSize()
if (subDocRoot) {
return subDocRoot->GetIntrinsicSize();
}
return nsSubDocumentFrameSuper::GetIntrinsicSize();
return nsAtomicContainerFrame::GetIntrinsicSize();
}
/* virtual */ nsSize
@@ -699,7 +699,7 @@ nsSubDocumentFrame::GetIntrinsicRatio()
if (subDocRoot) {
return subDocRoot->GetIntrinsicRatio();
}
return nsSubDocumentFrameSuper::GetIntrinsicRatio();
return nsAtomicContainerFrame::GetIntrinsicRatio();
}
/* virtual */
@@ -747,10 +747,10 @@ nsSubDocumentFrame::ComputeSize(nsRenderingContext *aRenderingContext,
aBorder,
aPadding);
}
return nsSubDocumentFrameSuper::ComputeSize(aRenderingContext, aWM,
aCBSize, aAvailableISize,
aMargin, aBorder, aPadding,
aFlags);
return nsAtomicContainerFrame::ComputeSize(aRenderingContext, aWM,
aCBSize, aAvailableISize,
aMargin, aBorder, aPadding,
aFlags);
}
void
@@ -955,18 +955,16 @@ public:
if (!mPresShell->IsDestroying() && mFrameElement->IsInComposedDoc()) {
mPresShell->FlushPendingNotifications(Flush_Frames);
}
// Either the frame has been constructed by now, or it never will be.
// Either way, we want to clear the stashed views.
// Either the frame has been constructed by now, or it never will be,
// either way we want to clear the stashed views.
mFrameLoader->SetDetachedSubdocFrame(nullptr, nullptr);
nsSubDocumentFrame* frame = do_QueryFrame(mFrameElement->GetPrimaryFrame());
if ((!frame && mHideViewerIfFrameless) ||
mPresShell->IsDestroying()) {
// Either the frame element has no nsIFrame or the presshell is being
// destroyed. Hide the nsFrameLoader, which destroys the presentation,
// and clear our references to the stashed presentation.
// destroyed. Hide the nsFrameLoader, which destroys the presentation.
mFrameLoader->Hide();
}
return NS_OK;
@@ -1015,7 +1013,7 @@ nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
}
}
nsSubDocumentFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
CSSIntSize
+2 -4
View File
@@ -12,12 +12,10 @@
#include "nsFrameLoader.h"
#include "Units.h"
typedef nsAtomicContainerFrame nsSubDocumentFrameSuper;
/******************************************************************************
* nsSubDocumentFrame
*****************************************************************************/
class nsSubDocumentFrame : public nsSubDocumentFrameSuper,
class nsSubDocumentFrame : public nsAtomicContainerFrame,
public nsIReflowCallback
{
public:
@@ -37,7 +35,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsSubDocumentFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced |
nsIFrame::eReplacedSizing |
nsIFrame::eReplacedContainsBlock));
+6 -5
View File
@@ -75,7 +75,7 @@ SwapScaleWidthHeightForRotation(IntSize& aSize, VideoInfo::Rotation aDegrees)
}
nsVideoFrame::nsVideoFrame(nsStyleContext* aContext)
: nsVideoFrameBase(aContext)
: nsContainerFrame(aContext)
{
EnableVisibilityTracking();
}
@@ -87,7 +87,7 @@ nsVideoFrame::~nsVideoFrame()
NS_QUERYFRAME_HEAD(nsVideoFrame)
NS_QUERYFRAME_ENTRY(nsVideoFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsVideoFrameBase)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsresult
nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
@@ -178,7 +178,7 @@ nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot)
nsContentUtils::DestroyAnonymousContent(&mCaptionDiv);
nsContentUtils::DestroyAnonymousContent(&mVideoControls);
nsContentUtils::DestroyAnonymousContent(&mPosterImage);
nsVideoFrameBase::DestroyFrom(aDestructRoot);
nsContainerFrame::DestroyFrom(aDestructRoot);
}
bool
@@ -655,7 +655,7 @@ nsVideoFrame::AttributeChanged(int32_t aNameSpaceID,
if (aAttribute == nsGkAtoms::poster && HasVideoElement()) {
UpdatePosterSource(true);
}
return nsVideoFrameBase::AttributeChanged(aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID,
aAttribute,
aModType);
}
@@ -666,12 +666,13 @@ nsVideoFrame::OnVisibilityChange(Visibility aNewVisibility,
{
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mPosterImage);
if (!imageLoader) {
nsContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
return;
}
imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsVideoFrameBase::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
}
bool nsVideoFrame::HasVideoElement() {
+2 -3
View File
@@ -26,9 +26,8 @@ class nsAString;
class nsPresContext;
class nsDisplayItem;
typedef nsContainerFrame nsVideoFrameBase;
class nsVideoFrame : public nsVideoFrameBase, public nsIAnonymousContentCreator
class nsVideoFrame : public nsContainerFrame
, public nsIAnonymousContentCreator
{
public:
template <typename T> using Maybe = mozilla::Maybe<T>;
+1 -1
View File
@@ -36,7 +36,7 @@ ViewportFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
Super::Init(aContent, aParent, aPrevInFlow);
nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
if (parent) {
-2
View File
@@ -27,8 +27,6 @@ public:
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS
typedef nsContainerFrame Super;
explicit ViewportFrame(nsStyleContext* aContext)
: nsContainerFrame(aContext)
{}
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<title>Reference: Perspective scrolling with nested clips</title>
<style>
html {
padding: 50px 0 3000px;
}
body {
margin: 0;
}
.scrollbox {
width: 600px;
height: 500px;
perspective: 1px;
overflow: auto;
}
.transformed {
will-change: transform;
width: 200px;
height: 200px;
margin: 200px 100px;
border: 10px solid black;
}
.spacer {
height: 4000px;
}
</style>
<div class="scrollbox">
<div class="transformed"></div>
<div class="spacer"></div>
</div>
<script>
document.scrollingElement.scrollTop = 250;
</script>
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en"
reftest-async-scroll
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="800" reftest-displayport-h="1000"
reftest-async-scroll-x="0" reftest-async-scroll-y="250">
<meta charset="utf-8">
<title>Perspective scrolling with nested clips</title>
<style>
html {
padding: 50px 0 3000px;
}
body {
margin: 0;
}
.scrollbox {
width: 600px;
height: 500px;
perspective: 1px;
overflow: auto;
}
.transformed {
will-change: transform;
width: 200px;
height: 200px;
margin: 200px 100px;
border: 10px solid black;
}
.spacer {
height: 4000px;
}
</style>
<div class="scrollbox"
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="600" reftest-displayport-h="2000"
reftest-async-scroll-x="0" reftest-async-scroll-y="0">
<div class="transformed"></div>
<div class="spacer"></div>
</div>
@@ -30,6 +30,7 @@ skip-if(!asyncPan) == position-fixed-iframe-2.html position-fixed-iframe-2-ref.h
skip-if(!asyncPan) == position-fixed-in-scroll-container.html position-fixed-in-scroll-container-ref.html
fuzzy(1,60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
fuzzy-if(Android,7,4) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html
# for the following tests, we want to disable the low-precision buffer
# as it will expand the displayport beyond what the test specifies in
+7 -7
View File
@@ -1,11 +1,11 @@
skip-if(B2G||Mulet) fails-if(Android) == resize.html resize-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) == resize.html resize-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
# an offset seems to apply to the native resizer on windows so skip this test for now
skip-if(B2G||Mulet) fails-if(Android) skip-if(winWidget) fuzzy-if(cocoaWidget,1,33) == resize-background.html resize-background-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) != ltr.html rtl.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) != ltr-scrollbar.html rtl-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) != in-ltr-doc-scrollbar.html in-rtl-doc-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) != ltr.html no-resize.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) fails-if(gtkWidget) != rtl.html no-resize.html # bug 834724 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) skip-if(winWidget) fuzzy-if(cocoaWidget,1,33) == resize-background.html resize-background-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) != ltr.html rtl.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) != ltr-scrollbar.html rtl-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) != in-ltr-doc-scrollbar.html in-rtl-doc-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) != ltr.html no-resize.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) fails-if(xulRuntime.widgetToolkit=="gtk2") != rtl.html no-resize.html # bug 834724 # Initial mulet triage: parity with B2G/B2G Desktop
== rtl.html rtl-dynamic-attr.html
== rtl.html rtl-dynamic-style.html
== rtl.html in-dynamic-rtl-doc.html
+9 -8
View File
@@ -1,10 +1,11 @@
# access-key tests are no use on OS X because access keys are not indicated visually
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) != accesskey-1.xul accesskey-1-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) == accesskey-2.xul accesskey-2-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
# no real XUL theme on Android so we just skip
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) != accesskey-1.xul accesskey-1-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) == accesskey-2.xul accesskey-2-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
# accesskey-3 fails because of defects in XUL bidi support
fails-if(!cocoaWidget) skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) == accesskey-3.xul accesskey-3-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) != accesskey-3.xul accesskey-3-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) == accesskey-4.xul accesskey-4-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)) != accesskey-4.xul accesskey-4-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet) == align-baseline-1.xul align-baseline-1-ref.xul # test for bug 494901 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android) skip-if(B2G||Mulet) == setsize.xul setsize-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(!cocoaWidget) skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) == accesskey-3.xul accesskey-3-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) != accesskey-3.xul accesskey-3-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) == accesskey-4.xul accesskey-4-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(cocoaWidget||((B2G&&browserIsRemote)||Mulet)||Android) != accesskey-4.xul accesskey-4-notref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if((B2G&&browserIsRemote)||Mulet||Android) == align-baseline-1.xul align-baseline-1-ref.xul # test for bug 494901 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet||Android) == setsize.xul setsize-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
+12 -9
View File
@@ -246,7 +246,7 @@ include marquee/reftest.list
# native-theme/
# skipping for B2G since something around radio-nonnative.html makes the whole suite hang
skip-if(B2G||Mulet) include native-theme/reftest.list # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Android||Mulet) include native-theme/reftest.list # Initial mulet triage: parity with B2G/B2G Desktop
# netwerk/
include ../../netwerk/test/reftest/reftest.list
@@ -373,17 +373,20 @@ include ../../widget/reftests/reftest.list
# xml-stylesheet/
include ../../content/test/reftest/xml-stylesheet/reftest.list
# xul-document-load/
include xul-document-load/reftest.list
# xul-document-load/ (no XUL theme on Android)
skip-if(Android) include xul-document-load/reftest.list
# xul/
include xul/reftest.list
# xul/ (no XUL theme on Android)
skip-if(Android) include xul/reftest.list
# xul
include ../xul/reftest/reftest.list
# xul (no XUL theme on Android)
skip-if(Android) include ../xul/reftest/reftest.list
# xul grid
include ../xul/grid/reftests/reftest.list
# xul grid (no XUL theme on Android)
skip-if(Android) include ../xul/grid/reftests/reftest.list
# -webkit-box & associated properties (mapped to modern flexbox)
include webkit-box/reftest.list
# -webkit-gradient expressions
include webkit-gradient/reftest.list
+16
View File
@@ -19,6 +19,22 @@ fails == webkit-box-anon-flex-items-3.html webkit-box-anon-flex-items-3-ref.html
== webkit-box-align-horiz-1b.html webkit-box-align-horiz-1-ref.html
== webkit-box-align-vert-1.html webkit-box-align-vert-1-ref.html
# Tests for "-webkit-box-direction":
== webkit-box-direction-1.html webkit-box-direction-1-ref.html
# Tests for "-webkit-box-flex" (flexibility of items)
== webkit-box-flex-1.html webkit-box-flex-1-ref.html
# Tests for "-webkit-box-ordinal-group"
== webkit-box-ordinal-group-1.html webkit-box-ordinal-group-1-ref.html
# XXXdholbert The following test fails because we accept "0" as a valid value
# for -webkit-box-ordinal-group (unlike Chrome/Blink), because that's simply
# how its aliased property (-moz-box-ordinal-group) behaves. This shouldn't
# matter in practice; it could only cause trouble if sites accidentally depend
# on the "0" value being rejected.
fails == webkit-box-ordinal-group-2.html webkit-box-ordinal-group-2-ref.html
== webkit-box-ordinal-group-3.html webkit-box-ordinal-group-3-ref.html
# Tests for "-webkit-box-pack" (main-axis alignment):
== webkit-box-pack-horiz-1a.html webkit-box-pack-horiz-1-ref.html
== webkit-box-pack-horiz-1b.html webkit-box-pack-horiz-1-ref.html
@@ -0,0 +1,172 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bastart { align-items: flex-start; }
.bacenter { align-items: center; }
.baend { align-items: flex-end; }
.babaseline { align-items: baseline; }
.bastretch { align-items: stretch; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-align -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-align: start -->
<!-- intrinsically sized -->
<div class="box bastart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-align: center -->
<!-- intrinsically sized -->
<div class="box bacenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bacenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bacenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bacenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-align: end -->
<!-- intrinsically sized -->
<div class="box baend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box baend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box baend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box baend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-align: baseline -->
<!-- intrinsically sized -->
<div class="box babaseline">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box babaseline" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box babaseline" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box babaseline" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SIXTH ROW: -webkit-box-align: stretch -->
<!-- intrinsically sized -->
<div class="box bastretch">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastretch" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastretch" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastretch" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: horizontally-oriented "display: -webkit-box" container,
with all the various -webkit-box-align values.
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bastart { -webkit-box-align: start; }
.bacenter { -webkit-box-align: center; }
.baend { -webkit-box-align: end; }
.babaseline { -webkit-box-align: baseline; }
.bastretch { -webkit-box-align: stretch; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-align -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-align: start -->
<!-- intrinsically sized -->
<div class="box bastart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-align: center -->
<!-- intrinsically sized -->
<div class="box bacenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bacenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bacenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bacenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-align: end -->
<!-- intrinsically sized -->
<div class="box baend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box baend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box baend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box baend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-align: baseline -->
<!-- intrinsically sized -->
<div class="box babaseline">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box babaseline" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box babaseline" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box babaseline" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SIXTH ROW: -webkit-box-align: stretch -->
<!-- intrinsically sized -->
<div class="box bastretch">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastretch" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastretch" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastretch" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,174 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: horizontally-oriented "display: -webkit-box" container,
with all the various -webkit-box-align values.
</title>
<style>
.box {
display: -webkit-box;
-webkit-box-orient: horizontal;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bastart { -webkit-box-align: start; }
.bacenter { -webkit-box-align: center; }
.baend { -webkit-box-align: end; }
.babaseline { -webkit-box-align: baseline; }
.bastretch { -webkit-box-align: stretch; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-align -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-align: start -->
<!-- intrinsically sized -->
<div class="box bastart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-align: center -->
<!-- intrinsically sized -->
<div class="box bacenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bacenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bacenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bacenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-align: end -->
<!-- intrinsically sized -->
<div class="box baend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box baend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box baend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box baend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-align: baseline -->
<!-- intrinsically sized -->
<div class="box babaseline">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box babaseline" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box babaseline" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box babaseline" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SIXTH ROW: -webkit-box-align: stretch -->
<!-- intrinsically sized -->
<div class="box bastretch">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastretch" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastretch" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastretch" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
flex-direction: column;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bastart { align-items: flex-start; }
.bacenter { align-items: center; }
.baend { align-items: flex-end; }
.babaseline { align-items: baseline; }
.bastretch { align-items: stretch; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-align -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-align: start -->
<!-- intrinsically sized -->
<div class="box bastart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-align: center -->
<!-- intrinsically sized -->
<div class="box bacenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bacenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bacenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bacenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-align: end -->
<!-- intrinsically sized -->
<div class="box baend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box baend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box baend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box baend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-align: baseline -->
<!-- intrinsically sized -->
<div class="box babaseline">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box babaseline" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box babaseline" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box babaseline" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SIXTH ROW: -webkit-box-align: stretch -->
<!-- intrinsically sized -->
<div class="box bastretch">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastretch" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastretch" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastretch" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,174 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: vertically-oriented "display: -webkit-box" container,
with all the various -webkit-box-align values.
</title>
<style>
.box {
display: -webkit-box;
-webkit-box-orient: vertical;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bastart { -webkit-box-align: start; }
.bacenter { -webkit-box-align: center; }
.baend { -webkit-box-align: end; }
.babaseline { -webkit-box-align: baseline; }
.bastretch { -webkit-box-align: stretch; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-align -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-align: start -->
<!-- intrinsically sized -->
<div class="box bastart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-align: center -->
<!-- intrinsically sized -->
<div class="box bacenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bacenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bacenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bacenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-align: end -->
<!-- intrinsically sized -->
<div class="box baend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box baend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box baend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box baend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-align: baseline -->
<!-- intrinsically sized -->
<div class="box babaseline">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box babaseline" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box babaseline" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box babaseline" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SIXTH ROW: -webkit-box-align: stretch -->
<!-- intrinsically sized -->
<div class="box bastretch">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bastretch" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bastretch" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bastretch" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
}
.box > *:nth-child(2) {
background: salmon;
}
.rtl { direction: rtl; }
.horizNormal {
flex-direction: row;
}
.horizReverse {
flex-direction: row-reverse;
}
.vertNormal {
flex-direction: column;
}
.vertReverse {
flex-direction: column-reverse;
}
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: '-webkit-box-orient: horizontal', default 'direction' -->
<div class="box horizNormal">
<div>a</div><div>b</div>
</div>
<div class="box horizReverse">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: '-webkit-box-orient: horizontal', 'direction: rtl' -->
<div class="box horizNormal rtl">
<div>a</div><div>b</div>
</div>
<div class="box horizReverse rtl">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: '-webkit-box-orient: vertical', default 'direction' -->
<div class="box vertNormal">
<div>a</div><div>b</div>
</div>
<div class="box vertReverse">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: '-webkit-box-orient: vertical', 'direction: rtl' -->
<div class="box vertNormal rtl">
<div>a</div><div>b</div>
</div>
<div class="box vertReverse rtl">
<div>a</div><div>b</div>
</div>
</body>
</html>
@@ -0,0 +1,87 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: "-webkit-box-direction" property
in a -webkit-box with default writing-mode
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
}
.box > *:nth-child(2) {
background: salmon;
}
.rtl { direction: rtl; }
.horizNormal {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
}
.horizReverse {
-webkit-box-orient: horizontal;
-webkit-box-direction: reverse;
}
.vertNormal {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
}
.vertReverse {
-webkit-box-orient: vertical;
-webkit-box-direction: reverse;
}
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: '-webkit-box-orient: horizontal', default 'direction' -->
<div class="box horizNormal">
<div>a</div><div>b</div>
</div>
<div class="box horizReverse">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: '-webkit-box-orient: horizontal', 'direction: rtl' -->
<div class="box horizNormal rtl">
<div>a</div><div>b</div>
</div>
<div class="box horizReverse rtl">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: '-webkit-box-orient: vertical', default 'direction' -->
<div class="box vertNormal">
<div>a</div><div>b</div>
</div>
<div class="box vertReverse">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: '-webkit-box-orient: vertical', 'direction: rtl' -->
<div class="box vertNormal rtl">
<div>a</div><div>b</div>
</div>
<div class="box vertReverse rtl">
<div>a</div><div>b</div>
</div>
</body>
</html>
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
width: 100px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > * {
/* Modern flexbox (used in this reference case) allows everything to
shrink by default, but -webkit-box does not, so we have to turn that
feature off to make an accurate reference case. */
flex-shrink: 0;
}
.box > *:nth-child(1) { background: turquoise; }
.box > *:nth-child(2) { background: salmon; }
.box > *:nth-child(3) { background: yellow; }
.huge { width: 120px }
.bf1 { flex: 1 1 auto }
.bf3 { flex: 3 3 auto }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-flex -->
<div class="box">
<div>a</div>
</div>
<div class="box">
<div>a</div><div>b</div>
</div>
<div class="box">
<div class="huge">a</div>
</div>
<br>
<!-- SECOND ROW: One item has nonzero -webkit-box-flex -->
<div class="box">
<div class="bf1">a</div>
</div>
<div class="box">
<div>a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
</div>
<br>
<!-- THIRD ROW: Two items have nonzero (equal) -webkit-box-flex -->
<div class="box">
<div class="bf1">a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="bf1">a</div><div>b</div><div class="bf1">c</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
<div>b</div>
<div class="huge bf1">c</div>
</div>
<br>
<!-- FOURTH ROW: Non-equal nonzero -webkit-box-flex values -->
<div class="box">
<div class="bf1">a</div><div class="bf3">b</div>
</div>
<div class="box">
<div class="bf3">a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
<div class="huge bf3">b</div>
</div>
</body>
</html>
@@ -0,0 +1,94 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: "-webkit-box-flex" in a "display: -webkit-box" container
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
width: 100px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) { background: turquoise; }
.box > *:nth-child(2) { background: salmon; }
.box > *:nth-child(3) { background: yellow; }
.huge { width: 120px }
.bf1 { -webkit-box-flex: 1 }
.bf3 { -webkit-box-flex: 3 }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-flex -->
<div class="box">
<div>a</div>
</div>
<div class="box">
<div>a</div><div>b</div>
</div>
<div class="box">
<div class="huge">a</div>
</div>
<br>
<!-- SECOND ROW: One item has nonzero -webkit-box-flex -->
<div class="box">
<div class="bf1">a</div>
</div>
<div class="box">
<div>a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
</div>
<br>
<!-- THIRD ROW: Two items have nonzero (equal) -webkit-box-flex -->
<div class="box">
<div class="bf1">a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="bf1">a</div><div>b</div><div class="bf1">c</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
<div>b</div>
<div class="huge bf1">c</div>
</div>
<br>
<!-- FOURTH ROW: Non-equal nonzero -webkit-box-flex values -->
<div class="box">
<div class="bf1">a</div><div class="bf3">b</div>
</div>
<div class="box">
<div class="bf3">a</div><div class="bf1">b</div>
</div>
<div class="box">
<div class="huge bf1">a</div>
<div class="huge bf3">b</div>
</div>
</body>
</html>
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
}
br { clear: both; }
.box > * {
border: 1px dotted purple;
}
</style>
</head>
<body>
<!-- First row: initial value mixed with single specified values -->
<div class="box">
<div>*</div>
<div class="bogOne">1a</div>
<div>*</div>
<div class="bogOne">1b</div>
<div>*</div>
</div>
<div class="box">
<div>*</div>
<div>*</div>
<div>*</div>
<div class="bogTwo">2a</div>
<div class="bogTwo">2b</div>
</div>
<div class="box">
<div>*</div>
<div>*</div>
<div>*</div>
<div class="bogNine">9a</div>
<div class="bogNine">9b</div>
</div>
<br>
<!-- Second row: various mixes of specified values -->
<div class="box">
<div>*</div>
<div class="bogOne">1</div>
<div class="bogTwo">2</div>
<div class="bogNine">9</div>
</div>
<div class="box">
<div class="bogOne">1</div>
<div>*</div>
<div class="bogTwo">2</div>
<div class="bogNine">9</div>
</div>
<div class="box">
<div class="bogOne">1</div>
<div>*</div>
<div class="bogTwo">2a</div>
<div class="bogTwo">2b</div>
<div class="bogNine">9</div>
</div>
<div class="box">
<div class="bogOne">1</div>
<div class="bogTwo">2a</div>
<div class="bogTwo">2b</div>
<div class="bogNine">9a</div>
<div class="bogNine">9b</div>
</div>
</body>
</html>
@@ -0,0 +1,88 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: -webkit-box-ordinal-group inside a -webkit-box
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
}
br { clear: both; }
.box > * {
border: 1px dotted purple;
}
.bogOne { -webkit-box-ordinal-group: 1; }
.bogTwo { -webkit-box-ordinal-group: 2; }
.bogNine { -webkit-box-ordinal-group: 9; }
</style>
</head>
<body>
<!-- First row: initial value mixed with single specified values -->
<div class="box">
<div>*</div>
<div class="bogOne">1a</div>
<div>*</div>
<div class="bogOne">1b</div>
<div>*</div>
</div>
<div class="box">
<div>*</div>
<div class="bogTwo">2a</div>
<div>*</div>
<div class="bogTwo">2b</div>
<div>*</div>
</div>
<div class="box">
<div>*</div>
<div class="bogNine">9a</div>
<div>*</div>
<div class="bogNine">9b</div>
<div>*</div>
</div>
<br>
<!-- Second row: various mixes of specified values -->
<div class="box">
<div>*</div>
<div class="bogOne">1</div>
<div class="bogTwo">2</div>
<div class="bogNine">9</div>
</div>
<div class="box">
<div class="bogNine">9</div>
<div class="bogTwo">2</div>
<div class="bogOne">1</div>
<div>*</div>
</div>
<div class="box">
<div class="bogTwo">2a</div>
<div class="bogNine">9</div>
<div class="bogTwo">2b</div>
<div class="bogOne">1</div>
<div>*</div>
</div>
<div class="box">
<div class="bogTwo">2a</div>
<div class="bogNine">9a</div>
<div class="bogNine">9b</div>
<div class="bogTwo">2b</div>
<div class="bogOne">1</div>
</div>
</body>
</html>
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
}
.box > * {
border: 1px dotted purple;
}
</style>
</head>
<body>
<div class="box">
<div>1</div>
<div>0</div>
</div>
</body>
</html>
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: -webkit-box-ordinal-group:0 inside a -webkit-box
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
}
.box > * {
border: 1px dotted purple;
}
.bogZero { -webkit-box-ordinal-group: 0; }
.bogOne { -webkit-box-ordinal-group: 1; }
</style>
</head>
<body>
<!-- -webkit-box-ordinal-group is strictly positive in Blink & WebKit. 0 is
rejected as an invalid value. So, the bogZero element below should
end up with the initial value (1) and should *not* be sorted out of its
DOM position in the final rendering. -->
<div class="box">
<div class="bogOne">1</div>
<div class="bogZero">0</div>
</div>
</body>
</html>
@@ -0,0 +1,83 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
}
br { clear: both; }
.box > * {
border: 1px dotted purple;
}
</style>
</head>
<body>
<div class="box">
<div>*</div>
<div>10</div>
<div>A</div>
</div>
<div class="box">
<div>*</div>
<div>10</div>
<div>B</div>
</div>
<div class="box">
<div>*</div>
<div>10</div>
<div>C</div>
</div>
<br>
<div class="box">
<div>*</div>
<div>10</div>
<div>D</div>
</div>
<div class="box">
<div>*</div>
<div>10</div>
<div>E</div>
</div>
<div class="box">
<div>*</div>
<div>10</div>
<div>F</div>
</div>
<br>
<div class="box">
<div>A</div>
<div>B</div>
</div>
<div class="box">
<div>A</div>
<div>C</div>
</div>
<div class="box">
<div>A</div>
<div>D</div>
</div>
<div class="box">
<div>A</div>
<div>E</div>
</div>
<div class="box">
<div>A</div>
<div>F</div>
</div>
</body>
</html>
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: -webkit-box-ordinal-group with huge values inside a -webkit-box
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
}
br { clear: both; }
.box > * {
border: 1px dotted purple;
}
.bogTen { -webkit-box-ordinal-group: 10; }
.bogHugeA { -webkit-box-ordinal-group: 2147483646; /* 2^31 - 2 */ }
.bogHugeB {
/* NOTE: This is INT32_MAX, so we may not be able to distinguish this
from anything larger than it (if we represent it internally in a
32-bit signed integer). However, it's still worth testing larger
values against e.g. 10 to be sure they don't overflow into
negative territory. */
-webkit-box-ordinal-group: 2147483647; /* 2^31 - 1 */ }
.bogHugeC { -webkit-box-ordinal-group: 4294967294; /* 2^32 - 2 */ }
.bogHugeD { -webkit-box-ordinal-group: 4294967295; /* 2^32 - 1 */ }
.bogHugeE { -webkit-box-ordinal-group: 4294967296; /* 2^32 */ }
.bogHugeF { -webkit-box-ordinal-group: 8589934592; /* 2^33 */ }
</style>
</head>
<body>
<!-- Test each huge value to see if it sorts after smaller values.
(The divs with huge values should sort to the right.) -->
<div class="box">
<div class="bogHugeA">A</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<div class="box">
<div class="bogHugeB">B</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<div class="box">
<div class="bogHugeC">C</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<br>
<div class="box">
<div class="bogHugeD">D</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<div class="box">
<div class="bogHugeE">E</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<div class="box">
<div class="bogHugeE">F</div>
<div class="bogTen">10</div>
<div>*</div>
</div>
<br>
<!-- Test that 'bogHugeA' sorts to the left of larger huge values. It's
less than INT32_MAX, so it's reasonable to expect that it can be
compared correctly against (possibly-clamped) larger values) -->
<div class="box">
<div class="bogHugeB">B</div>
<div class="bogHugeA">A</div>
</div>
<div class="box">
<div class="bogHugeC">C</div>
<div class="bogHugeA">A</div>
</div>
<div class="box">
<div class="bogHugeD">D</div>
<div class="bogHugeA">A</div>
</div>
<div class="box">
<div class="bogHugeE">E</div>
<div class="bogHugeA">A</div>
</div>
<div class="box">
<div class="bogHugeF">F</div>
<div class="bogHugeA">A</div>
</div>
</body>
</html>
@@ -0,0 +1,150 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bpstart { justify-content: flex-start; }
.bpcenter { justify-content: center; }
.bpend { justify-content: flex-end; }
.bpjustify { justify-content: space-between; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-pack -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-pack: start -->
<!-- intrinsically sized -->
<div class="box bpstart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpstart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpstart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpstart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-pack: center -->
<!-- intrinsically sized -->
<div class="box bpcenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpcenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpcenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpcenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-pack: end -->
<!-- intrinsically sized -->
<div class="box bpend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-pack: justify -->
<!-- intrinsically sized -->
<div class="box bpjustify">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpjustify" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpjustify" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpjustify" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: horizontally-oriented "display: -webkit-box" container,
with all the various -webkit-box-pack values.
</title>
<style>
.box {
display: -webkit-box;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bpstart { -webkit-box-pack: start; }
.bpcenter { -webkit-box-pack: center; }
.bpend { -webkit-box-pack: end; }
.bpjustify { -webkit-box-pack: justify; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-pack -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-pack: start -->
<!-- intrinsically sized -->
<div class="box bpstart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpstart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpstart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpstart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-pack: center -->
<!-- intrinsically sized -->
<div class="box bpcenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpcenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpcenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpcenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-pack: end -->
<!-- intrinsically sized -->
<div class="box bpend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-pack: justify -->
<!-- intrinsically sized -->
<div class="box bpjustify">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpjustify" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpjustify" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpjustify" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,152 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: horizontally-oriented "display: -webkit-box" container,
with all the various -webkit-box-pack values.
</title>
<style>
.box {
display: -webkit-box;
-webkit-box-orient: horizontal;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bpstart { -webkit-box-pack: start; }
.bpcenter { -webkit-box-pack: center; }
.bpend { -webkit-box-pack: end; }
.bpjustify { -webkit-box-pack: justify; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-pack -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-pack: start -->
<!-- intrinsically sized -->
<div class="box bpstart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpstart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpstart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpstart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-pack: center -->
<!-- intrinsically sized -->
<div class="box bpcenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpcenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpcenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpcenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-pack: end -->
<!-- intrinsically sized -->
<div class="box bpend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-pack: justify -->
<!-- intrinsically sized -->
<div class="box bpjustify">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpjustify" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpjustify" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpjustify" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Reference
</title>
<style>
.box {
display: flex;
flex-direction: column;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bpstart { justify-content: flex-start; }
.bpcenter { justify-content: center; }
.bpend { justify-content: flex-end; }
.bpjustify { justify-content: space-between; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-pack -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-pack: start -->
<!-- intrinsically sized -->
<div class="box bpstart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpstart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpstart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpstart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-pack: center -->
<!-- intrinsically sized -->
<div class="box bpcenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpcenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpcenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpcenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-pack: end -->
<!-- intrinsically sized -->
<div class="box bpend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-pack: justify -->
<!-- intrinsically sized -->
<div class="box bpjustify">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpjustify" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpjustify" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpjustify" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
@@ -0,0 +1,152 @@
<!DOCTYPE html>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>
CSS Test: vertically-oriented "display: -webkit-box" container,
with all the various -webkit-box-pack values.
</title>
<style>
.box {
display: -webkit-box;
-webkit-box-orient: vertical;
border: 1px solid black;
margin: 5px 20px;
float: left; /* For testing in "rows" */
font: 10px serif;
}
.box > *:nth-child(1) {
background: turquoise;
/* auto width */
height: 1em;
}
.box > *:nth-child(2) {
background: salmon;
font-size: 50%;
width: 2em;
/* auto height */
}
.bpstart { -webkit-box-pack: start; }
.bpcenter { -webkit-box-pack: center; }
.bpend { -webkit-box-pack: end; }
.bpjustify { -webkit-box-pack: justify; }
br { clear: both; }
</style>
</head>
<body>
<!-- FIRST ROW: Default -webkit-box-pack -->
<!-- intrinsically sized -->
<div class="box">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- SECOND ROW: -webkit-box-pack: start -->
<!-- intrinsically sized -->
<div class="box bpstart">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpstart" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpstart" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpstart" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- THIRD ROW: -webkit-box-pack: center -->
<!-- intrinsically sized -->
<div class="box bpcenter">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpcenter" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpcenter" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpcenter" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FOURTH ROW: -webkit-box-pack: end -->
<!-- intrinsically sized -->
<div class="box bpend">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpend" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpend" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpend" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
<!-- FIFTH ROW: -webkit-box-pack: justify -->
<!-- intrinsically sized -->
<div class="box bpjustify">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra width -->
<div class="box bpjustify" style="width: 36px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height -->
<div class="box bpjustify" style="height: 40px">
<div>a</div><div>b</div>
</div>
<!-- explicit size, extra height and width -->
<div class="box bpjustify" style="width: 36px; height: 40px">
<div>a</div><div>b</div>
</div>
<br>
</body>
</html>
+45 -100
View File
@@ -14,7 +14,6 @@
#include "CSSVariableImageTable.h"
#include "mozilla/css/Declaration.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/WritingModes.h"
#include "nsIDocument.h"
@@ -41,50 +40,6 @@ MoveValue(nsCSSValue* aSource, nsCSSValue* aDest)
return changed;
}
/**
* This function maps "-webkit-box-orient" values to "flex-direction" values,
* for a given writing-mode (taken from aRuleData).
*
* Specifically:
* - If aBoxOrientVal is an enumerated value (representing a physical axis),
* then we'll map it to the appropriate logical "flex-direction" value, using
* the writing mode. The converted value will be emplace()'d into in the
* outparam aConvertedValStorage, and we'll return a pointer to that value.
* - Otherwise (e.g. if we have "inherit" or "initial"), we won't do any
* mapping, and we'll directly return the passed-in aBoxOrientVal.
*
* Either way, the idea is that our caller can treat the returned value as if
* it were a value for "flex-direction".
*/
static const nsCSSValue*
ConvertBoxOrientToFlexDirection(const nsCSSValue* aBoxOrientVal,
const nsRuleData* aRuleData,
Maybe<nsCSSValue>& aConvertedValStorage)
{
MOZ_ASSERT(aBoxOrientVal, "expecting a non-null value to convert");
MOZ_ASSERT(aConvertedValStorage.isNothing(),
"expecting outparam for converted-value to be initially empty");
if (aBoxOrientVal->GetUnit() != eCSSUnit_Enumerated) {
// We probably have "inherit" or "initial" -- just return that & have the
// caller directly use it as a "flex-direction" value.
return aBoxOrientVal;
}
// OK, we have an enumerated value -- "horizontal" or "vertical".
WritingMode wm(aRuleData->mStyleContext);
// In a horizontal writing-mode, "horizontal" maps to "row".
// In a vertical writing-mode, "horizontal" maps to "column".
bool isRow = wm.IsVertical() !=
(aBoxOrientVal->GetIntValue() == NS_STYLE_BOX_ORIENT_HORIZONTAL);
aConvertedValStorage.emplace(isRow ? NS_STYLE_FLEX_DIRECTION_ROW :
NS_STYLE_FLEX_DIRECTION_COLUMN,
eCSSUnit_Enumerated);
return aConvertedValStorage.ptr();
}
static bool
ShouldIgnoreColors(nsRuleData *aRuleData)
{
@@ -170,32 +125,15 @@ ShouldStartImageLoads(nsRuleData *aRuleData, nsCSSProperty aProperty)
}
static void
MapSinglePropertyInto(nsCSSProperty aSrcProp,
MapSinglePropertyInto(nsCSSProperty aTargetProp,
const nsCSSValue* aSrcValue,
nsCSSProperty aTargetProp,
nsCSSValue* aTargetValue,
nsRuleData* aRuleData)
{
MOZ_ASSERT(!nsCSSProps::PropHasFlags(aTargetProp, CSS_PROPERTY_LOGICAL),
"Can't map into a logical property");
MOZ_ASSERT(aSrcProp == aTargetProp ||
nsCSSProps::PropHasFlags(aSrcProp, CSS_PROPERTY_LOGICAL),
"Source & target property must be the same, except when we're "
"doing a logical-to-physical property mapping");
MOZ_ASSERT(aSrcValue->GetUnit() != eCSSUnit_Null, "oops");
// Handle logical properties that have custom value-mapping behavior:
Maybe<nsCSSValue> convertedVal; // storage for converted value, if needed
bool hasCustomValMapping =
nsCSSProps::PropHasFlags(aSrcProp,
CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING);
if (hasCustomValMapping) {
if (aSrcProp == eCSSProperty_webkit_box_orient) {
aSrcValue = ConvertBoxOrientToFlexDirection(aSrcValue, aRuleData,
convertedVal);
}
}
// Although aTargetValue is the nsCSSValue we are going to write into,
// we also look at its value before writing into it. This is done
// when aTargetValue is a token stream value, which is the case when we
@@ -234,20 +172,13 @@ MapSinglePropertyInto(nsCSSProperty aSrcProp,
}
/**
* If aProperty is a logical property, returns the equivalent physical
* If aProperty is a logical property, converts it to the equivalent physical
* property based on writing mode information obtained from aRuleData's
* style context.
*/
static inline nsCSSProperty
EnsurePhysicalProperty(nsCSSProperty aProperty, nsRuleData* aRuleData)
static inline void
EnsurePhysicalProperty(nsCSSProperty& aProperty, nsRuleData* aRuleData)
{
if (!nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_LOGICAL)) {
return aProperty;
}
bool isSingleProperty =
nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING);
bool isAxisProperty =
nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_LOGICAL_AXIS);
bool isBlock =
@@ -255,9 +186,7 @@ EnsurePhysicalProperty(nsCSSProperty aProperty, nsRuleData* aRuleData)
int index;
if (isSingleProperty) {
index = 0; // We always map to the same physical property.
} else if (isAxisProperty) {
if (isAxisProperty) {
LogicalAxis logicalAxis = isBlock ? eLogicalAxisBlock : eLogicalAxisInline;
uint8_t wm = aRuleData->mStyleContext->StyleVisibility()->mWritingMode;
PhysicalAxis axis =
@@ -295,19 +224,43 @@ EnsurePhysicalProperty(nsCSSProperty aProperty, nsRuleData* aRuleData)
}
const nsCSSProperty* props = nsCSSProps::LogicalGroup(aProperty);
size_t len = isAxisProperty ? 2 : 4;
#ifdef DEBUG
{
// Table-length is 1 for single prop, 2 for axis prop, 4 for block prop.
size_t len = isSingleProperty ? 1 : (isAxisProperty ? 2 : 4);
for (size_t i = 0; i < len; i++) {
MOZ_ASSERT(props[i] != eCSSProperty_UNKNOWN,
"unexpected logical group length");
}
MOZ_ASSERT(props[len] == eCSSProperty_UNKNOWN,
MOZ_ASSERT(props[i] != eCSSProperty_UNKNOWN,
"unexpected logical group length");
}
MOZ_ASSERT(props[len] == eCSSProperty_UNKNOWN,
"unexpected logical group length");
#endif
return props[index];
for (size_t i = 0; i < len; i++) {
if (aRuleData->ValueFor(props[i])->GetUnit() == eCSSUnit_Null) {
// A declaration of one of the logical properties in this logical
// group (but maybe not aProperty) would be the winning
// declaration in the cascade. This means that it's reasonably
// likely that this logical property could be the winning
// declaration in the cascade for some values of writing-mode,
// direction, and text-orientation. (It doesn't mean that for
// sure, though. For example, if this is a block-start logical
// property, and all but the bottom physical property were set.
// But the common case we want to hit here is logical declarations
// that are completely overridden by a shorthand.)
//
// If this logical property could be the winning declaration in
// the cascade for some values of writing-mode, direction, and
// text-orientation, then we have to fault the resulting style
// struct out of the rule tree. We can't cache anything on the
// rule tree if it depends on data from the style context, since
// data cached in the rule tree could be used with a style context
// with a different value of the depended-upon data.
uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits();
aRuleData->mConditions.SetWritingModeDependency(wm);
break;
}
}
aProperty = props[index];
}
void
@@ -327,16 +280,10 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
nsCSSProperty iProp = PropertyAtIndex(i);
if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) &
aRuleData->mSIDs) {
nsCSSProperty physicalProp = EnsurePhysicalProperty(iProp,
aRuleData);
if (physicalProp != iProp) {
// We can't cache anything on the rule tree if we use any data from
// the style context, since data cached in the rule tree could be
// used with a style context with a different value.
uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits();
aRuleData->mConditions.SetWritingModeDependency(wm);
if (nsCSSProps::PropHasFlags(iProp, CSS_PROPERTY_LOGICAL)) {
EnsurePhysicalProperty(iProp, aRuleData);
}
nsCSSValue* target = aRuleData->ValueFor(physicalProp);
nsCSSValue* target = aRuleData->ValueFor(iProp);
if (target->GetUnit() == eCSSUnit_Null) {
const nsCSSValue *val = ValueAtIndex(i);
// In order for variable resolution to have the right information
@@ -348,8 +295,7 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
if (val->GetUnit() == eCSSUnit_TokenStream) {
val->GetTokenStreamValue()->mLevel = aRuleData->mLevel;
}
MapSinglePropertyInto(iProp, val, physicalProp, target,
aRuleData);
MapSinglePropertyInto(iProp, val, target, aRuleData);
}
}
}
@@ -791,10 +737,9 @@ nsCSSExpandedDataBlock::MapRuleInfoInto(nsCSSProperty aPropID,
const nsCSSValue* src = PropertyAt(aPropID);
MOZ_ASSERT(src->GetUnit() != eCSSUnit_Null);
nsCSSProperty physicalProp = EnsurePhysicalProperty(aPropID, aRuleData);
if (physicalProp != aPropID) {
uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits();
aRuleData->mConditions.SetWritingModeDependency(wm);
nsCSSProperty physicalProp = aPropID;
if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_LOGICAL)) {
EnsurePhysicalProperty(physicalProp, aRuleData);
}
nsCSSValue* dest = aRuleData->ValueFor(physicalProp);
@@ -802,7 +747,7 @@ nsCSSExpandedDataBlock::MapRuleInfoInto(nsCSSProperty aPropID,
dest->GetTokenStreamValue()->mPropertyID == aPropID);
CSSVariableImageTable::ReplaceAll(aRuleData->mStyleContext, aPropID, [=] {
MapSinglePropertyInto(aPropID, src, physicalProp, dest, aRuleData);
MapSinglePropertyInto(physicalProp, src, dest, aRuleData);
});
}
+17 -9
View File
@@ -296,10 +296,6 @@ CSS_PROP_ALIAS(-webkit-border-bottom-right-radius,
WebkitBorderBottomRightRadius, // really no dom property
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-appearance,
appearance,
WebkitAppearance,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-background-clip,
background_clip,
WebkitBackgroundClip,
@@ -327,21 +323,33 @@ CSS_PROP_ALIAS(-webkit-box-sizing,
WebkitBoxSizing,
WEBKIT_PREFIX_PREF)
// Alias old flexbox properties to modern flexbox pseudo-equivalents:
// Alias -webkit-box properties to their -moz-box equivalents.
// (NOTE: Even though they're aliases, in practice these -webkit properties
// will behave a bit differently from their -moz versions, if they're
// accompanied by "display:-webkit-box", because we generate a different frame
// for those two display values.)
CSS_PROP_ALIAS(-webkit-box-flex,
flex_grow,
box_flex,
WebkitBoxFlex,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-ordinal-group,
order,
box_ordinal_group,
WebkitBoxOrdinalGroup,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-orient,
box_orient,
WebkitBoxOrient,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-direction,
box_direction,
WebkitBoxDirection,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-align,
align_items,
box_align,
WebkitBoxAlign,
WEBKIT_PREFIX_PREF)
CSS_PROP_ALIAS(-webkit-box-pack,
justify_content,
box_pack,
WebkitBoxPack,
WEBKIT_PREFIX_PREF)
-16
View File
@@ -1330,22 +1330,6 @@ CSS_PROP_XUL(
kBoxOrientKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None) // XXX bug 3935
/* We treat -webkit-box-orient as a writing-mode-aware logical alias
* for "flex-direction": */
CSS_PROP_LOGICAL(
-webkit-box-orient,
webkit_box_orient,
WebkitBoxOrient,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_LOGICAL |
CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING,
"layout.css.prefixes.webkit",
VARIANT_HK,
kBoxOrientKTable,
WebkitBoxOrient,
Position,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_XUL(
-moz-box-pack,
box_pack,
-12
View File
@@ -44,17 +44,6 @@
// defined in nCSSProps.cpp named g<name_>LogicalGroupTable
// containing the two physical properties in vertical/horizontal
// order, followed by an nsCSSProperty_UNKNOWN entry.
//
// CSS_PROP_LOGICAL_GROUP_SINGLE(name_)
// Defines a logical property group in which the logical property always
// maps to the same physical property. For such properties, the
// "logicalness" is in the value-mapping, not in the property-mapping. For
// example, the logical property "-webkit-box-orient" is always mapped to
// "flex-direction", but its values ("horizontal", "vertical") map to
// different flex-direction values ("row", "column") depending on the
// writing-mode. A table must be defined in nsCSSProps.cpp named
// g<name_>LogicalGroupTable containing the one physical property,
// followed by an nsCSSProperty_UNKNOWN entry.
CSS_PROP_LOGICAL_GROUP_SHORTHAND(BorderColor)
CSS_PROP_LOGICAL_GROUP_SHORTHAND(BorderStyle)
@@ -65,4 +54,3 @@ CSS_PROP_LOGICAL_GROUP_BOX(Offset)
CSS_PROP_LOGICAL_GROUP_SHORTHAND(Padding)
CSS_PROP_LOGICAL_GROUP_AXIS(MinSize)
CSS_PROP_LOGICAL_GROUP_AXIS(Size)
CSS_PROP_LOGICAL_GROUP_SINGLE(WebkitBoxOrient)
-3
View File
@@ -103,13 +103,10 @@ enum nsCSSPropertyLogicalGroup {
eCSSPropertyLogicalGroup_##name_,
#define CSS_PROP_LOGICAL_GROUP_BOX(name_) \
eCSSPropertyLogicalGroup_##name_,
#define CSS_PROP_LOGICAL_GROUP_SINGLE(name_) \
eCSSPropertyLogicalGroup_##name_,
#define CSS_PROP_LOGICAL_GROUP_SHORTHAND(name_) \
eCSSPropertyLogicalGroup_##name_,
#include "nsCSSPropLogicalGroupList.h"
#undef CSS_PROP_LOGICAL_GROUP_SHORTHAND
#undef CSS_PROP_LOGICAL_GROUP_SINGLE
#undef CSS_PROP_LOGICAL_GROUP_BOX
#undef CSS_PROP_LOGICAL_GROUP_AXIS
eCSSPropertyLogicalGroup_COUNT
+2 -26
View File
@@ -3026,19 +3026,12 @@ static const nsCSSProperty gSizeLogicalGroupTable[] = {
eCSSProperty_UNKNOWN
};
static const nsCSSProperty gWebkitBoxOrientLogicalGroupTable[] = {
eCSSProperty_flex_direction,
eCSSProperty_UNKNOWN
};
const nsCSSProperty* const
nsCSSProps::kLogicalGroupTable[eCSSPropertyLogicalGroup_COUNT] = {
#define CSS_PROP_LOGICAL_GROUP_SHORTHAND(id_) g##id_##SubpropTable,
#define CSS_PROP_LOGICAL_GROUP_AXIS(name_) g##name_##LogicalGroupTable,
#define CSS_PROP_LOGICAL_GROUP_BOX(name_) g##name_##LogicalGroupTable,
#define CSS_PROP_LOGICAL_GROUP_SINGLE(name_) g##name_##LogicalGroupTable,
#include "nsCSSPropLogicalGroupList.h"
#undef CSS_PROP_LOGICAL_GROUP_SINGLE
#undef CSS_PROP_LOGICAL_GROUP_BOX
#undef CSS_PROP_LOGICAL_GROUP_AXIS
#undef CSS_PROP_LOGICAL_GROUP_SHORTHAND
@@ -3339,10 +3332,7 @@ nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = {
"the CSS_PROPERTY_LOGICAL_BLOCK_AXIS flag"); \
static_assert(!((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE), \
"only properties defined with CSS_PROP_LOGICAL can use " \
"the CSS_PROPERTY_LOGICAL_END_EDGE flag"); \
static_assert(!((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING),\
"only properties defined with CSS_PROP_LOGICAL can use " \
"the CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING flag");
"the CSS_PROPERTY_LOGICAL_END_EDGE flag");
#define CSS_PROP_LOGICAL(name_, id_, method_, flags_, pref_, parsevariant_, \
kwtable_, group_, stylestruct_, \
stylestructoffset_, animtype_) \
@@ -3355,21 +3345,7 @@ nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = {
static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_AXIS) && \
((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE)), \
"CSS_PROPERTY_LOGICAL_END_EDGE makes no sense when used " \
"with CSS_PROPERTY_LOGICAL_AXIS"); \
/* Make sure CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING isn't used */ \
/* with other mutually-exclusive flags: */ \
static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_AXIS) && \
((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\
"CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \
"sense when used with CSS_PROPERTY_LOGICAL_AXIS"); \
static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_BLOCK_AXIS) && \
((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\
"CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \
"sense when used with CSS_PROPERTY_LOGICAL_BLOCK_AXIS"); \
static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE) && \
((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\
"CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \
"sense when used with CSS_PROPERTY_LOGICAL_END_EDGE");
"with CSS_PROPERTY_LOGICAL_AXIS");
#include "nsCSSPropList.h"
#undef CSS_PROP_LOGICAL
#undef CSS_PROP
+10 -18
View File
@@ -226,6 +226,10 @@ static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK &
// wrapped in "#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL".
// Note that, these flags have no effect on the use of aliases of this
// property.
// Furthermore, for the purposes of animation (including triggering
// transitions) these flags are ignored. That is, if the property is disabled
// by a pref, we will *not* run animations or transitions on it even in
// UA sheets or chrome.
#define CSS_PROPERTY_ENABLED_MASK (3<<22)
#define CSS_PROPERTY_ENABLED_IN_UA_SHEETS (1<<22)
#define CSS_PROPERTY_ENABLED_IN_CHROME (1<<23)
@@ -250,26 +254,20 @@ static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK &
// margin-block-start or margin-inline-start).
#define CSS_PROPERTY_LOGICAL_END_EDGE (1<<26)
// This property is a logical property which always maps to the same physical
// property, and its values have some custom processing when being mapped to
// the physical property's values. Must not be used in conjunction with
// CSS_PROPERTY_LOGICAL_{AXIS,BLOCK_AXIS,END_EDGE}.
#define CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING (1<<27)
// This property can be animated on the compositor.
#define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR (1<<28)
#define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR (1<<27)
// This property is an internal property that is not represented
// in the DOM. Properties with this flag must be defined in an #ifndef
// CSS_PROP_LIST_EXCLUDE_INTERNAL section of nsCSSPropList.h.
#define CSS_PROPERTY_INTERNAL (1<<29)
#define CSS_PROPERTY_INTERNAL (1<<28)
// This property has values that can establish a containing block for
// fixed positioned and absolutely positioned elements.
// This should be set for any properties that can cause an element to be
// such a containing block, as implemented in
// nsStyleDisplay::IsFixedPosContainingBlock.
#define CSS_PROPERTY_FIXPOS_CB (1<<30)
#define CSS_PROPERTY_FIXPOS_CB (1<<29)
// This property has values that can establish a containing block for
// absolutely positioned elements.
@@ -278,10 +276,7 @@ static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK &
// nsStyleDisplay::IsAbsPosContainingBlock.
// It does not need to be set for properties that also have
// CSS_PROPERTY_FIXPOS_CB set.
#define CSS_PROPERTY_ABSPOS_CB (1u<<31)
// NOTE: Before adding any new CSS_PROPERTY_* flags here, we'll need to
// upgrade kFlagsTable to 64-bits -- see bug 1231384.
#define CSS_PROPERTY_ABSPOS_CB (1<<30)
/**
* Types of animatable values.
@@ -555,11 +550,8 @@ public:
* by the sentinel.
*
* When called with a property that has the CSS_PROPERTY_LOGICAL_AXIS
* flag, the returned array will have two values preceding the sentinel.
* When called with a property that has the
* CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING flag, the returned array
* will have one value preceding the sentinel.
* Otherwise it will have four values preceding the sentinel.
* flag, the returned array will have two values preceding the sentinel;
* otherwise it will have four.
*
* (Note that the running time of this function is proportional to the
* number of logical longhand properties that exist. If we start
+1 -1
View File
@@ -3209,7 +3209,7 @@ nsCSSRuleProcessor::ClearRuleCascades()
// We rely on our caller (perhaps indirectly) to do something that
// will rebuild style data and the user font set (either
// nsIPresShell::ReconstructStyleData or
// nsIPresShell::RestyleForCSSRuleChanges or
// nsPresContext::RebuildAllStyleData).
RuleCascadeData *data = mRuleCascades;
mRuleCascades = nullptr;
+10 -10
View File
@@ -5303,7 +5303,7 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
display, parentDisplay, aRuleData,
conditions);
display->mTransitions.SetLength(numTransitions);
display->mTransitions.SetLengthNonZero(numTransitions);
FOR_ALL_TRANSITION_PROPS(p) {
const TransitionPropInfo& i = transitionPropInfo[p];
@@ -5460,7 +5460,7 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
display, parentDisplay, aRuleData,
conditions);
display->mAnimations.SetLength(numAnimations);
display->mAnimations.SetLengthNonZero(numAnimations);
FOR_ALL_ANIMATION_PROPS(p) {
const TransitionPropInfo& i = animationPropInfo[p];
@@ -6779,8 +6779,8 @@ template <class ComputedValueItem>
static void
SetImageLayerList(nsStyleContext* aStyleContext,
const nsCSSValue& aValue,
AutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
const AutoTArray<nsStyleImageLayers::Layer, 1> &aParentLayers,
nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
ComputedValueItem aInitialValue,
uint32_t aParentItemCount,
@@ -6844,9 +6844,8 @@ template <class ComputedValueItem>
static void
SetImageLayerPairList(nsStyleContext* aStyleContext,
const nsCSSValue& aValue,
AutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
const AutoTArray<nsStyleImageLayers::Layer, 1>
&aParentLayers,
nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
ComputedValueItem nsStyleImageLayers::Layer::*
aResultLocation,
ComputedValueItem aInitialValue,
@@ -6911,7 +6910,8 @@ SetImageLayerPairList(nsStyleContext* aStyleContext,
template <class ComputedValueItem>
static void
FillBackgroundList(AutoTArray< nsStyleImageLayers::Layer, 1> &aLayers,
FillBackgroundList(
nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
uint32_t aItemCount, uint32_t aFillCount)
{
@@ -7033,7 +7033,7 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
if (rebuild) {
// Delete any extra items. We need to keep layers in which any
// property was specified.
bg->mImage.mLayers.TruncateLength(maxItemCount);
bg->mImage.mLayers.TruncateLengthNonZero(maxItemCount);
uint32_t fillCount = bg->mImage.mImageCount;
FillBackgroundList(bg->mImage.mLayers,
@@ -9852,7 +9852,7 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
if (rebuild) {
// Delete any extra items. We need to keep layers in which any
// property was specified.
svgReset->mMask.mLayers.TruncateLength(maxItemCount);
svgReset->mMask.mLayers.TruncateLengthNonZero(maxItemCount);
uint32_t fillCount = svgReset->mMask.mImageCount;
+11 -10
View File
@@ -2317,10 +2317,9 @@ nsStyleImageLayers::nsStyleImageLayers()
, mMaskModeCount(1)
, mBlendModeCount(1)
, mCompositeCount(1)
, mLayers(nsStyleAutoArray<Layer>::WITH_SINGLE_INITIAL_ELEMENT)
{
MOZ_COUNT_CTOR(nsStyleImageLayers);
mLayers.AppendElement();
NS_ASSERTION(mLayers.Length() == 1, "auto array must have room for 1 element");
}
nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
@@ -2388,7 +2387,8 @@ nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aOther) const
return hint;
}
if (mBlendModeCount != aOther.mBlendModeCount ||
if (mAttachmentCount != aOther.mAttachmentCount ||
mBlendModeCount != aOther.mBlendModeCount ||
mClipCount != aOther.mClipCount ||
mCompositeCount != aOther.mCompositeCount ||
mMaskModeCount != aOther.mMaskModeCount ||
@@ -2406,7 +2406,12 @@ bool
nsStyleImageLayers::HasLayerWithImage() const
{
for (uint32_t i = 0; i < mImageCount; i++) {
if (mLayers[i].mSourceURI) {
// mLayers[i].mSourceURI can be nullptr if mask-image prop value is
// <element-reference> or <gradient>
// mLayers[i].mImage can be empty if mask-image prop value is a reference
// to SVG mask element.
// So we need to test both mSourceURI and mImage.
if (mLayers[i].mSourceURI || !mLayers[i].mImage.IsEmpty()) {
return true;
}
}
@@ -2832,6 +2837,8 @@ mozilla::StyleAnimation::operator==(const mozilla::StyleAnimation& aOther) const
nsStyleDisplay::nsStyleDisplay(StyleStructContext aContext)
: mWillChangeBitField(0)
, mTransitions(nsStyleAutoArray<StyleTransition>::WITH_SINGLE_INITIAL_ELEMENT)
, mAnimations(nsStyleAutoArray<StyleAnimation>::WITH_SINGLE_INITIAL_ELEMENT)
{
MOZ_COUNT_CTOR(nsStyleDisplay);
mAppearance = NS_THEME_NONE;
@@ -2872,18 +2879,12 @@ nsStyleDisplay::nsStyleDisplay(StyleStructContext aContext)
// Initial value for mScrollSnapDestination is "0px 0px"
mScrollSnapDestination.SetInitialZeroValues();
mTransitions.AppendElement();
MOZ_ASSERT(mTransitions.Length() == 1,
"appending within auto buffer should never fail");
mTransitions[0].SetInitialValues();
mTransitionTimingFunctionCount = 1;
mTransitionDurationCount = 1;
mTransitionDelayCount = 1;
mTransitionPropertyCount = 1;
mAnimations.AppendElement();
MOZ_ASSERT(mAnimations.Length() == 1,
"appending within auto buffer should never fail");
mAnimations[0].SetInitialValues();
mAnimationTimingFunctionCount = 1;
mAnimationDurationCount = 1;
+87 -28
View File
@@ -152,7 +152,7 @@ static_assert(offsetof(nsRect_Simple, width) == offsetof(nsRect, width), "Wrong
static_assert(offsetof(nsRect_Simple, height) == offsetof(nsRect, height), "Wrong nsRect_Simple member alignment");
// The lifetime of these objects is managed by the presshell's arena.
struct nsStyleFont
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
{
nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
nsStyleFont(const nsStyleFont& aStyleFont);
@@ -421,7 +421,7 @@ private:
#endif
};
struct nsStyleColor
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
{
explicit nsStyleColor(StyleStructContext aContext);
nsStyleColor(const nsStyleColor& aOther);
@@ -455,6 +455,65 @@ struct nsStyleColor
nscolor mColor; // [inherited]
};
/**
* An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
* always has length >= 1.
*/
template<typename T>
class nsStyleAutoArray
{
public:
// This constructor places a single element in mFirstElement.
enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT };
explicit nsStyleAutoArray(WithSingleInitialElement) {}
nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; }
nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) {
mFirstElement = aOther.mFirstElement;
mOtherElements = aOther.mOtherElements;
return *this;
}
bool operator==(const nsStyleAutoArray& aOther) const {
return Length() == aOther.Length() &&
mFirstElement == aOther.mFirstElement &&
mOtherElements == aOther.mOtherElements;
}
bool operator!=(const nsStyleAutoArray& aOther) const {
return !(*this == aOther);
}
size_t Length() const {
return mOtherElements.Length() + 1;
}
const T& operator[](size_t aIndex) const {
return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
}
T& operator[](size_t aIndex) {
return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
}
void EnsureLengthAtLeast(size_t aMinLen) {
if (aMinLen > 0) {
mOtherElements.EnsureLengthAtLeast(aMinLen - 1);
}
}
void SetLengthNonZero(size_t aNewLen) {
MOZ_ASSERT(aNewLen > 0);
mOtherElements.SetLength(aNewLen - 1);
}
void TruncateLengthNonZero(size_t aNewLen) {
MOZ_ASSERT(aNewLen > 0);
MOZ_ASSERT(aNewLen <= Length());
mOtherElements.TruncateLength(aNewLen - 1);
}
private:
T mFirstElement;
nsTArray<T> mOtherElements;
};
struct nsStyleImageLayers {
nsStyleImageLayers();
nsStyleImageLayers(const nsStyleImageLayers &aSource);
@@ -695,7 +754,7 @@ struct nsStyleImageLayers {
// layer. In layers below the bottom layer, properties will be
// uninitialized unless their count, above, indicates that they are
// present.
AutoTArray<Layer, 1> mLayers;
nsStyleAutoArray<Layer> mLayers;
const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
@@ -724,7 +783,7 @@ struct nsStyleImageLayers {
for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
};
struct nsStyleBackground {
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
explicit nsStyleBackground(StyleStructContext aContext);
nsStyleBackground(const nsStyleBackground& aOther);
~nsStyleBackground();
@@ -777,7 +836,7 @@ struct nsStyleBackground {
#define NS_SPACING_BORDER 2
struct nsStyleMargin
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
{
explicit nsStyleMargin(StyleStructContext aContext);
nsStyleMargin(const nsStyleMargin& aMargin);
@@ -823,7 +882,7 @@ protected:
};
struct nsStylePadding
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
{
explicit nsStylePadding(StyleStructContext aContext);
nsStylePadding(const nsStylePadding& aPadding);
@@ -1026,7 +1085,7 @@ static bool IsVisibleBorderStyle(uint8_t aStyle)
aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
}
struct nsStyleBorder
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
{
explicit nsStyleBorder(StyleStructContext aContext);
nsStyleBorder(const nsStyleBorder& aBorder);
@@ -1253,7 +1312,7 @@ private:
};
struct nsStyleOutline
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
{
explicit nsStyleOutline(StyleStructContext aContext);
nsStyleOutline(const nsStyleOutline& aOutline);
@@ -1364,7 +1423,7 @@ private:
~nsStyleQuoteValues() {}
};
struct nsStyleList
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
{
explicit nsStyleList(StyleStructContext aContext);
nsStyleList(const nsStyleList& aStyleList);
@@ -1570,7 +1629,7 @@ struct nsStyleTextOverflow
bool mLogicalDirections; // true when only one value was specified
};
struct nsStyleTextReset
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
{
explicit nsStyleTextReset(StyleStructContext aContext);
nsStyleTextReset(const nsStyleTextReset& aOther);
@@ -1655,7 +1714,7 @@ protected:
nscolor mTextDecorationColor; // [reset] the colors to use for a decoration lines, not used at currentColor
};
struct nsStyleText
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
{
explicit nsStyleText(StyleStructContext aContext);
nsStyleText(const nsStyleText& aOther);
@@ -1872,7 +1931,7 @@ protected:
uint8_t mOrientation;
};
struct nsStyleVisibility
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
{
explicit nsStyleVisibility(StyleStructContext aContext);
nsStyleVisibility(const nsStyleVisibility& aVisibility);
@@ -2153,7 +2212,7 @@ private:
} // namespace mozilla
struct nsStyleDisplay
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
{
explicit nsStyleDisplay(StyleStructContext aContext);
nsStyleDisplay(const nsStyleDisplay& aOther);
@@ -2224,7 +2283,7 @@ struct nsStyleDisplay
// match mWillChange. Also tracks if any of the
// properties in the will-change list require
// a stacking context.
AutoTArray<nsString, 1> mWillChange;
nsTArray<nsString> mWillChange;
uint8_t mTouchAction; // [reset] see nsStyleConsts.h
uint8_t mScrollBehavior; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_BEHAVIOR_*
@@ -2249,7 +2308,7 @@ struct nsStyleDisplay
nsStyleCoord mVerticalAlign; // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
AutoTArray<mozilla::StyleTransition, 1> mTransitions; // [reset]
nsStyleAutoArray<mozilla::StyleTransition> mTransitions; // [reset]
// The number of elements in mTransitions that are not from repeating
// a list due to another property being longer.
uint32_t mTransitionTimingFunctionCount,
@@ -2257,7 +2316,7 @@ struct nsStyleDisplay
mTransitionDelayCount,
mTransitionPropertyCount;
AutoTArray<mozilla::StyleAnimation, 1> mAnimations; // [reset]
nsStyleAutoArray<mozilla::StyleAnimation> mAnimations; // [reset]
// The number of elements in mAnimations that are not from repeating
// a list due to another property being longer.
uint32_t mAnimationTimingFunctionCount,
@@ -2425,7 +2484,7 @@ struct nsStyleDisplay
inline uint8_t PhysicalBreakType(mozilla::WritingMode aWM) const;
};
struct nsStyleTable
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
{
explicit nsStyleTable(StyleStructContext aContext);
nsStyleTable(const nsStyleTable& aOther);
@@ -2536,7 +2595,7 @@ struct nsStyleGridTemplate
}
};
struct nsStylePosition
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
{
explicit nsStylePosition(StyleStructContext aContext);
nsStylePosition(const nsStylePosition& aOther);
@@ -2730,7 +2789,7 @@ private:
};
struct nsStyleTableBorder
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
{
explicit nsStyleTableBorder(StyleStructContext aContext);
nsStyleTableBorder(const nsStyleTableBorder& aOther);
@@ -2830,7 +2889,7 @@ struct nsStyleCounterData
#define DELETE_ARRAY_IF(array) if (array) { delete[] array; array = nullptr; }
struct nsStyleContent
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
{
explicit nsStyleContent(StyleStructContext aContext);
nsStyleContent(const nsStyleContent& aContent);
@@ -2941,7 +3000,7 @@ protected:
uint32_t mResetCount;
};
struct nsStyleUIReset
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
{
explicit nsStyleUIReset(StyleStructContext aContext);
nsStyleUIReset(const nsStyleUIReset& aOther);
@@ -3007,7 +3066,7 @@ private:
nsCOMPtr<imgIRequest> mImage;
};
struct nsStyleUserInterface
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
{
explicit nsStyleUserInterface(StyleStructContext aContext);
nsStyleUserInterface(const nsStyleUserInterface& aOther);
@@ -3058,7 +3117,7 @@ struct nsStyleUserInterface
inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
};
struct nsStyleXUL
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
{
explicit nsStyleXUL(StyleStructContext aContext);
nsStyleXUL(const nsStyleXUL& aSource);
@@ -3096,7 +3155,7 @@ struct nsStyleXUL
bool mStretchStack; // [reset] see nsStyleConsts.h
};
struct nsStyleColumn
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
{
explicit nsStyleColumn(StyleStructContext aContext);
nsStyleColumn(const nsStyleColumn& aSource);
@@ -3191,7 +3250,7 @@ struct nsStyleSVGPaint
}
};
struct nsStyleSVG
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
{
explicit nsStyleSVG(StyleStructContext aContext);
nsStyleSVG(const nsStyleSVG& aSource);
@@ -3477,7 +3536,7 @@ struct nsTArray_CopyChooser<nsStyleFilter>
typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
};
struct nsStyleSVGReset
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
{
explicit nsStyleSVGReset(StyleStructContext aContext);
nsStyleSVGReset(const nsStyleSVGReset& aSource);
@@ -3527,7 +3586,7 @@ struct nsStyleSVGReset
uint8_t mMaskType; // [reset] see nsStyleConsts.h
};
struct nsStyleVariables
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
{
explicit nsStyleVariables(StyleStructContext aContext);
nsStyleVariables(const nsStyleVariables& aSource);
@@ -3557,7 +3616,7 @@ struct nsStyleVariables
mozilla::CSSVariableValues mVariables;
};
struct nsStyleEffects
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
{
explicit nsStyleEffects(StyleStructContext aContext);
nsStyleEffects(const nsStyleEffects& aSource);
+1
View File
@@ -639,6 +639,7 @@ MatrixForTransformFunction(Matrix4x4& aMatrix,
break;
case eCSSKeyword_rotatez:
*aContains3dTransform = true;
MOZ_FALLTHROUGH;
case eCSSKeyword_rotate:
ProcessRotateZ(aMatrix, aData);
break;
+212 -166
View File
@@ -63,13 +63,11 @@ ElementPropertyTransition::CurrentValuePortion() const
MOZ_ASSERT(!computedTiming.mProgress.IsNull(),
"Got a null progress for a fill mode of 'both'");
MOZ_ASSERT(mProperties.Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(mProperties[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
return ComputedTimingFunction::GetPortion(
mProperties[0].mSegments[0].mTimingFunction,
computedTiming.mProgress.Value(), computedTiming.mBeforeFlag);
MOZ_ASSERT(mFrames.Length() == 2,
"Should have two animation frames for a transition");
return ComputedTimingFunction::GetPortion(mFrames[0].mTimingFunction,
computedTiming.mProgress.Value(),
computedTiming.mBeforeFlag);
}
////////////////////////// CSSTransition ////////////////////////////
@@ -135,16 +133,6 @@ CSSTransition::QueueEvents()
mOwningElement.GetElement(owningElement, owningPseudoType);
MOZ_ASSERT(owningElement, "Owning element should be set");
// Do not queue any event for disabled properties. This could happen
// if the property has a default value which derives value from other
// property, e.g. color.
nsCSSProperty property = TransitionProperty();
if (!nsCSSProps::IsEnabled(property, nsCSSProps::eEnabledForAllContent) &&
(!nsContentUtils::IsSystemPrincipal(owningElement->NodePrincipal()) ||
!nsCSSProps::IsEnabled(property, nsCSSProps::eEnabledInChrome))) {
return;
}
nsPresContext* presContext = mOwningElement.GetRenderedPresContext();
if (!presContext) {
return;
@@ -152,7 +140,7 @@ CSSTransition::QueueEvents()
nsTransitionManager* manager = presContext->TransitionManager();
manager->QueueEvent(TransitionEventInfo(owningElement, owningPseudoType,
property,
TransitionProperty(),
mEffect->GetComputedTiming()
.mDuration,
AnimationTimeToTimeStamp(EffectEnd()),
@@ -178,6 +166,17 @@ CSSTransition::TransitionProperty() const
return effect->AsTransition()->TransitionProperty();
}
StyleAnimationValue
CSSTransition::ToValue() const
{
// FIXME: Once we support replacing/removing the effect (bug 1049975)
// the following assertion will no longer hold.
dom::KeyframeEffectReadOnly* effect = GetEffect();
MOZ_ASSERT(effect && effect->AsTransition(),
"Transition should have a transition effect");
return effect->AsTransition()->ToValue();
}
bool
CSSTransition::HasLowerCompositeOrderThan(const CSSTransition& aOther) const
{
@@ -335,131 +334,12 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
// Per http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html
// I'll consider only the transitions from the number of items in
// 'transition-property' on down, and later ones will override earlier
// ones (tracked using |whichStarted|).
bool startedAny = false;
nsCSSPropertySet whichStarted;
for (uint32_t i = disp->mTransitionPropertyCount; i-- != 0; ) {
const StyleTransition& t = disp->mTransitions[i];
// Check the combined duration (combination of delay and duration)
// first, since it defaults to zero, which means we can ignore the
// transition.
if (t.GetCombinedDuration() > 0.0f) {
// We might have something to transition. See if any of the
// properties in question changed and are animatable.
// FIXME: Would be good to find a way to share code between this
// interpretation of transition-property and the one below.
nsCSSProperty property = t.GetProperty();
if (property == eCSSPropertyExtra_no_properties ||
property == eCSSPropertyExtra_variable ||
property == eCSSProperty_UNKNOWN) {
// Nothing to do, but need to exclude this from cases below.
} else if (property == eCSSPropertyExtra_all_properties) {
for (nsCSSProperty p = nsCSSProperty(0);
p < eCSSProperty_COUNT_no_shorthands;
p = nsCSSProperty(p + 1)) {
ConsiderStartingTransition(p, t, aElement, collection,
aOldStyleContext, afterChangeStyle,
&startedAny, &whichStarted);
}
} else if (nsCSSProps::IsShorthand(property)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
subprop, property, nsCSSProps::eEnabledForAllContent) {
ConsiderStartingTransition(*subprop, t, aElement, collection,
aOldStyleContext, afterChangeStyle,
&startedAny, &whichStarted);
}
} else {
ConsiderStartingTransition(property, t, aElement, collection,
aOldStyleContext, afterChangeStyle,
&startedAny, &whichStarted);
}
}
}
// Stop any transitions for properties that are no longer in
// 'transition-property', including finished transitions.
// Also stop any transitions (and remove any finished transitions)
// for properties that just changed (and are still in the set of
// properties to transition), but for which we didn't just start the
// transition. This can happen delay and duration are both zero, or
// because the new value is not interpolable.
// Note that we also do the latter set of work in
// nsTransitionManager::PruneCompletedTransitions.
if (collection) {
bool checkProperties =
disp->mTransitions[0].GetProperty() != eCSSPropertyExtra_all_properties;
nsCSSPropertySet allTransitionProperties;
if (checkProperties) {
for (uint32_t i = disp->mTransitionPropertyCount; i-- != 0; ) {
const StyleTransition& t = disp->mTransitions[i];
// FIXME: Would be good to find a way to share code between this
// interpretation of transition-property and the one above.
nsCSSProperty property = t.GetProperty();
if (property == eCSSPropertyExtra_no_properties ||
property == eCSSPropertyExtra_variable ||
property == eCSSProperty_UNKNOWN) {
// Nothing to do, but need to exclude this from cases below.
} else if (property == eCSSPropertyExtra_all_properties) {
for (nsCSSProperty p = nsCSSProperty(0);
p < eCSSProperty_COUNT_no_shorthands;
p = nsCSSProperty(p + 1)) {
allTransitionProperties.AddProperty(p);
}
} else if (nsCSSProps::IsShorthand(property)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
subprop, property, nsCSSProps::eEnabledForAllContent) {
allTransitionProperties.AddProperty(*subprop);
}
} else {
allTransitionProperties.AddProperty(property);
}
}
}
OwningCSSTransitionPtrArray& animations = collection->mAnimations;
size_t i = animations.Length();
MOZ_ASSERT(i != 0, "empty transitions list?");
StyleAnimationValue currentValue;
do {
--i;
CSSTransition* anim = animations[i];
dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
MOZ_ASSERT(effect && effect->Properties().Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(effect && effect->Properties()[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
const AnimationProperty& prop = effect->Properties()[0];
const AnimationPropertySegment& segment = prop.mSegments[0];
// properties no longer in 'transition-property'
if ((checkProperties &&
!allTransitionProperties.HasProperty(prop.mProperty)) ||
// properties whose computed values changed but for which we
// did not start a new transition (because delay and
// duration are both zero, or because the new value is not
// interpolable); a new transition would have segment.mToValue
// matching currentValue
!ExtractComputedValueForTransition(prop.mProperty, afterChangeStyle,
currentValue) ||
currentValue != segment.mToValue) {
// stop the transition
if (anim->HasCurrentEffect()) {
EffectSet* effectSet = EffectSet::GetEffectSet(aElement, pseudoType);
if (effectSet) {
effectSet->UpdateAnimationGeneration(mPresContext);
}
}
anim->CancelFromStyle();
animations.RemoveElementAt(i);
}
} while (i != 0);
if (animations.IsEmpty()) {
collection->Destroy();
collection = nullptr;
}
DebugOnly<bool> startedAny = false;
// We don't have to update transitions if display:none, although we will
// cancel them after restyling.
if (!afterChangeStyle->IsInDisplayNoneSubtree()) {
startedAny = UpdateTransitions(disp, aElement, collection,
aOldStyleContext, afterChangeStyle);
}
MOZ_ASSERT(!startedAny || collection,
@@ -491,6 +371,145 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
}
}
bool
nsTransitionManager::UpdateTransitions(
const nsStyleDisplay* aDisp,
dom::Element* aElement,
CSSTransitionCollection*& aElementTransitions,
nsStyleContext* aOldStyleContext,
nsStyleContext* aNewStyleContext)
{
MOZ_ASSERT(aDisp, "Null nsStyleDisplay");
MOZ_ASSERT(!aElementTransitions ||
aElementTransitions->mElement == aElement, "Element mismatch");
// Per http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html
// I'll consider only the transitions from the number of items in
// 'transition-property' on down, and later ones will override earlier
// ones (tracked using |whichStarted|).
bool startedAny = false;
nsCSSPropertySet whichStarted;
for (uint32_t i = aDisp->mTransitionPropertyCount; i-- != 0; ) {
const StyleTransition& t = aDisp->mTransitions[i];
// Check the combined duration (combination of delay and duration)
// first, since it defaults to zero, which means we can ignore the
// transition.
if (t.GetCombinedDuration() > 0.0f) {
// We might have something to transition. See if any of the
// properties in question changed and are animatable.
// FIXME: Would be good to find a way to share code between this
// interpretation of transition-property and the one below.
nsCSSProperty property = t.GetProperty();
if (property == eCSSPropertyExtra_no_properties ||
property == eCSSPropertyExtra_variable ||
property == eCSSProperty_UNKNOWN) {
// Nothing to do, but need to exclude this from cases below.
} else if (property == eCSSPropertyExtra_all_properties) {
for (nsCSSProperty p = nsCSSProperty(0);
p < eCSSProperty_COUNT_no_shorthands;
p = nsCSSProperty(p + 1)) {
ConsiderStartingTransition(p, t, aElement, aElementTransitions,
aOldStyleContext, aNewStyleContext,
&startedAny, &whichStarted);
}
} else if (nsCSSProps::IsShorthand(property)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, property,
nsCSSProps::eEnabledForAllContent)
{
ConsiderStartingTransition(*subprop, t, aElement, aElementTransitions,
aOldStyleContext, aNewStyleContext,
&startedAny, &whichStarted);
}
} else {
ConsiderStartingTransition(property, t, aElement, aElementTransitions,
aOldStyleContext, aNewStyleContext,
&startedAny, &whichStarted);
}
}
}
// Stop any transitions for properties that are no longer in
// 'transition-property', including finished transitions.
// Also stop any transitions (and remove any finished transitions)
// for properties that just changed (and are still in the set of
// properties to transition), but for which we didn't just start the
// transition. This can happen delay and duration are both zero, or
// because the new value is not interpolable.
// Note that we also do the latter set of work in
// nsTransitionManager::PruneCompletedTransitions.
if (aElementTransitions) {
bool checkProperties =
aDisp->mTransitions[0].GetProperty() != eCSSPropertyExtra_all_properties;
nsCSSPropertySet allTransitionProperties;
if (checkProperties) {
for (uint32_t i = aDisp->mTransitionPropertyCount; i-- != 0; ) {
const StyleTransition& t = aDisp->mTransitions[i];
// FIXME: Would be good to find a way to share code between this
// interpretation of transition-property and the one above.
nsCSSProperty property = t.GetProperty();
if (property == eCSSPropertyExtra_no_properties ||
property == eCSSPropertyExtra_variable ||
property == eCSSProperty_UNKNOWN) {
// Nothing to do, but need to exclude this from cases below.
} else if (property == eCSSPropertyExtra_all_properties) {
for (nsCSSProperty p = nsCSSProperty(0);
p < eCSSProperty_COUNT_no_shorthands;
p = nsCSSProperty(p + 1)) {
allTransitionProperties.AddProperty(p);
}
} else if (nsCSSProps::IsShorthand(property)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
subprop, property, nsCSSProps::eEnabledForAllContent) {
allTransitionProperties.AddProperty(*subprop);
}
} else {
allTransitionProperties.AddProperty(property);
}
}
}
OwningCSSTransitionPtrArray& animations = aElementTransitions->mAnimations;
size_t i = animations.Length();
MOZ_ASSERT(i != 0, "empty transitions list?");
StyleAnimationValue currentValue;
do {
--i;
CSSTransition* anim = animations[i];
// properties no longer in 'transition-property'
if ((checkProperties &&
!allTransitionProperties.HasProperty(anim->TransitionProperty())) ||
// properties whose computed values changed but for which we
// did not start a new transition (because delay and
// duration are both zero, or because the new value is not
// interpolable); a new transition would have anim->ToValue()
// matching currentValue
!ExtractComputedValueForTransition(anim->TransitionProperty(),
aNewStyleContext,
currentValue) ||
currentValue != anim->ToValue()) {
// stop the transition
if (anim->HasCurrentEffect()) {
EffectSet* effectSet =
EffectSet::GetEffectSet(aElement,
aNewStyleContext->GetPseudoType());
if (effectSet) {
effectSet->UpdateAnimationGeneration(mPresContext);
}
}
anim->CancelFromStyle();
animations.RemoveElementAt(i);
}
} while (i != 0);
if (animations.IsEmpty()) {
aElementTransitions->Destroy();
aElementTransitions = nullptr;
}
}
return startedAny;
}
void
nsTransitionManager::ConsiderStartingTransition(
nsCSSProperty aProperty,
@@ -508,6 +527,13 @@ nsTransitionManager::ConsiderStartingTransition(
NS_ASSERTION(!aElementTransitions ||
aElementTransitions->mElement == aElement, "Element mismatch");
// Ignore disabled properties. We can arrive here if the transition-property
// is 'all' and the disabled property has a default value which derives value
// from another property, e.g. color.
if (!nsCSSProps::IsEnabled(aProperty, nsCSSProps::eEnabledForAllContent)) {
return;
}
if (aWhichStarted->HasProperty(aProperty)) {
// A later item in transition-property already started a
// transition for this property, so we ignore this one.
@@ -667,19 +693,9 @@ nsTransitionManager::ConsiderStartingTransition(
aNewStyleContext->GetPseudoType(), timing,
startForReversingTest, reversePortion);
AnimationProperty& prop = *pt->Properties().AppendElement();
prop.mProperty = aProperty;
AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
segment.mFromValue = startValue;
segment.mToValue = endValue;
segment.mFromKey = 0;
segment.mToKey = 1;
if (tf.mType != nsTimingFunction::Type::Linear) {
ComputedTimingFunction computedTimingFunction;
computedTimingFunction.Init(tf);
segment.mTimingFunction = Some(computedTimingFunction);
}
pt->SetFrames(GetTransitionKeyframes(aNewStyleContext, aProperty,
Move(startValue), Move(endValue), tf),
aNewStyleContext);
MOZ_ASSERT(mPresContext->RestyleManager()->IsGecko(),
"ServoRestyleManager should not use nsTransitionManager "
@@ -747,6 +763,43 @@ nsTransitionManager::ConsiderStartingTransition(
aWhichStarted->AddProperty(aProperty);
}
static Keyframe&
AppendKeyframe(double aOffset, nsCSSProperty aProperty,
StyleAnimationValue&& aValue, nsTArray<Keyframe>& aKeyframes)
{
Keyframe& frame = *aKeyframes.AppendElement();
frame.mOffset.emplace(aOffset);
PropertyValuePair& pv = *frame.mPropertyValues.AppendElement();
pv.mProperty = aProperty;
DebugOnly<bool> uncomputeResult =
StyleAnimationValue::UncomputeValue(aProperty, Move(aValue), pv.mValue);
MOZ_ASSERT(uncomputeResult,
"Unable to get specified value from computed value");
return frame;
}
nsTArray<Keyframe>
nsTransitionManager::GetTransitionKeyframes(
nsStyleContext* aStyleContext,
nsCSSProperty aProperty,
StyleAnimationValue&& aStartValue,
StyleAnimationValue&& aEndValue,
const nsTimingFunction& aTimingFunction)
{
nsTArray<Keyframe> keyframes(2);
Keyframe& fromFrame = AppendKeyframe(0.0, aProperty, Move(aStartValue),
keyframes);
if (aTimingFunction.mType != nsTimingFunction::Type::Linear) {
fromFrame.mTimingFunction.emplace();
fromFrame.mTimingFunction->Init(aTimingFunction);
}
AppendKeyframe(1.0, aProperty, Move(aEndValue), keyframes);
return keyframes;
}
void
nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
CSSPseudoElementType aPseudoType,
@@ -775,20 +828,13 @@ nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
continue;
}
dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
MOZ_ASSERT(effect->Properties().Length() == 1,
"Should have one animation property for a transition");
MOZ_ASSERT(effect->Properties()[0].mSegments.Length() == 1,
"Animation property should have one segment for a transition");
const AnimationProperty& prop = effect->Properties()[0];
const AnimationPropertySegment& segment = prop.mSegments[0];
// Since effect is a finished transition, we know it didn't
// influence style.
StyleAnimationValue currentValue;
if (!ExtractComputedValueForTransition(prop.mProperty, aNewStyleContext,
if (!ExtractComputedValueForTransition(anim->TransitionProperty(),
aNewStyleContext,
currentValue) ||
currentValue != segment.mToValue) {
currentValue != anim->ToValue()) {
anim->CancelFromStyle();
animations.RemoveElementAt(i);
}
+39 -10
View File
@@ -23,6 +23,7 @@ class nsCSSPropertySet;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
struct Keyframe;
struct StyleTransition;
} // namespace mozilla
@@ -52,19 +53,28 @@ struct ElementPropertyTransition : public dom::KeyframeEffectReadOnly
}
nsCSSProperty TransitionProperty() const {
MOZ_ASSERT(mProperties.Length() == 1,
"Transitions should have exactly one animation property. "
MOZ_ASSERT(mFrames.Length() == 2,
"Transitions should have exactly two animation frames. "
"Perhaps we are using an un-initialized transition?");
return mProperties[0].mProperty;
MOZ_ASSERT(mFrames[0].mPropertyValues.Length() == 1,
"Transitions should have exactly one property in their first "
"frame");
return mFrames[0].mPropertyValues[0].mProperty;
}
StyleAnimationValue ToValue() const {
MOZ_ASSERT(mProperties.Length() == 1,
"Transitions should have exactly one animation property");
MOZ_ASSERT(mProperties[0].mSegments.Length() == 1,
"Transitions should have one animation property segment ");
// If we failed to generate properties from the transition frames,
// return a null value but also show a warning since we should be
// detecting that kind of situation in advance and not generating a
// transition in the first place.
if (mProperties.Length() < 1 ||
mProperties[0].mSegments.Length() < 1) {
NS_WARNING("Failed to generate transition property values");
return StyleAnimationValue();
}
return mProperties[0].mSegments[0].mToValue;
}
// This is the start value to be used for a check for whether a
// transition is being reversed. Normally the same as
// mProperties[0].mSegments[0].mFromValue, except when this transition
@@ -147,6 +157,7 @@ public:
void Tick() override;
nsCSSProperty TransitionProperty() const;
StyleAnimationValue ToValue() const;
bool HasLowerCompositeOrderThan(const CSSTransition& aOther) const;
EffectCompositor::CascadeLevel CascadeLevel() const override
@@ -250,10 +261,10 @@ struct TransitionEventInfo {
, mTimeStamp(aTimeStamp)
{
// XXX Looks like nobody initialize WidgetEvent::time
mEvent.propertyName =
mEvent.mPropertyName =
NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aProperty));
mEvent.elapsedTime = aDuration.ToSeconds();
mEvent.pseudoElement =
mEvent.mElapsedTime = aDuration.ToSeconds();
mEvent.mPseudoElement =
AnimationCollection<dom::CSSTransition>::PseudoTypeAsString(aPseudoType);
}
@@ -351,6 +362,17 @@ protected:
typedef nsTArray<RefPtr<mozilla::dom::CSSTransition>>
OwningCSSTransitionPtrArray;
// Update the transitions. It'd start new, replace, or stop current
// transitions if need. aDisp and aElement shouldn't be nullptr.
// aElementTransitions is the collection of current transitions, and it
// could be a nullptr if we don't have any transitions.
bool
UpdateTransitions(const nsStyleDisplay* aDisp,
mozilla::dom::Element* aElement,
CSSTransitionCollection*& aElementTransitions,
nsStyleContext* aOldStyleContext,
nsStyleContext* aNewStyleContext);
void
ConsiderStartingTransition(nsCSSProperty aProperty,
const mozilla::StyleTransition& aTransition,
@@ -361,6 +383,13 @@ protected:
bool* aStartedAny,
nsCSSPropertySet* aWhichStarted);
nsTArray<mozilla::Keyframe> GetTransitionKeyframes(
nsStyleContext* aStyleContext,
nsCSSProperty aProperty,
mozilla::StyleAnimationValue&& aStartValue,
mozilla::StyleAnimationValue&& aEndValue,
const nsTimingFunction& aTimingFunction);
bool mInAnimationOnlyStyleUpdate;
mozilla::DelayedEventDispatcher<mozilla::TransitionEventInfo>
+2 -1
View File
@@ -264,6 +264,8 @@ skip-if = (android_version == '18' && debug) # bug 1159532
[test_transitions_per_property.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227 # b2g(times out, needs more time + various failures) b2g-debug(times out, needs more time + various failures) b2g-desktop(times out, needs more time + various failures)
[test_transitions_step_functions.html]
[test_transitions_with_displaynone.html]
[test_transitions_with_disabled_properties.html]
[test_unclosed_parentheses.html]
[test_unicode_range_loading.html]
support-files = ../../reftests/fonts/markA.woff ../../reftests/fonts/markB.woff ../../reftests/fonts/markC.woff ../../reftests/fonts/markD.woff
@@ -298,6 +300,5 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262,
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262, :visited support) b2g-debug(bug 870262, :visited support) b2g-desktop(bug 870262, :visited support)
[test_visited_reftests.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262, :visited support) b2g-debug(bug 870262, :visited support) b2g-desktop(bug 870262, :visited support)
[test_webkit_box_orient.html]
[test_webkit_device_pixel_ratio.html]
[test_asyncopen2.html]
+20 -58
View File
@@ -665,7 +665,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, rgb(1,2,3)))",
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, #00ff00))",
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, #00f))",
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, hsla(240, 30%, 50%, 0.9)))",
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, hsla(240, 30%, 50%, 0.8)))",
"-webkit-gradient(linear, 1 2, 3 4, color-stop(0, rgba(255, 230, 10, 0.5)))",
// linear w/ multiple color stops:
@@ -4331,7 +4331,7 @@ var gCSSProperties = {
initial_values: [ "auto", "normal" ],
other_values: [ "start", "end", "flex-start", "flex-end", "self-start",
"self-end", "center", "left", "right", "baseline",
"last-baseline", "stretch", "left true", "true right",
"last-baseline", "stretch", "left unsafe", "unsafe right",
"safe right", "center safe" ],
invalid_values: [ "space-between", "abc", "30px", "none",
"legacy left", "right legacy" ]
@@ -4875,25 +4875,6 @@ function logical_box_prop_get_computed(cs, property)
return cs.getPropertyValue(property);
}
// Helper to get computed style of "-webkit-box-orient" from "flex-direction"
// and the "writing-mode".
function webkit_orient_get_computed(cs, property)
{
var writingMode = cs.getPropertyValue("writing-mode") || "horizontal-tb";
var mapping; // map from flex-direction values to -webkit-box-orient values.
if (writingMode == "horizontal-tb") {
// Horizontal writing-mode
mapping = { "row" : "horizontal", "column" : "vertical"};
} else {
// Vertical writing-mode
mapping = { "row" : "vertical", "column" : "horizontal"};
}
var flexDirection = cs.getPropertyValue("flex-direction");
return mapping[flexDirection];
}
// Get the computed value for a property. For shorthands, return the
// computed values of all the subproperties, delimited by " ; ".
function get_computed_value(cs, property)
@@ -6590,17 +6571,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.background-blend-mode.enabled")) {
};
}
if (SpecialPowers.getBoolPref("layout.css.will-change.enabled")) {
gCSSProperties["will-change"] = {
domProp: "willChange",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "auto" ],
other_values: [ "scroll-position", "contents", "transform", "opacity", "scroll-position, transform", "transform, opacity", "contents, transform", "property-that-doesnt-exist-yet" ],
invalid_values: [ "none", "all", "default", "auto, scroll-position", "scroll-position, auto", "transform scroll-position", ",", "trailing,", "will-change", "transform, will-change" ]
};
}
if (IsCSSPropertyPrefEnabled("layout.css.object-fit-and-position.enabled")) {
gCSSProperties["object-fit"] = {
domProp: "objectFit",
@@ -7216,13 +7186,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
alias_for: "border-bottom-right-radius",
subproperties: [ "border-bottom-right-radius" ],
};
gCSSProperties["-webkit-appearance"] = {
domProp: "webkitAppearance",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "-moz-appearance",
subproperties: [ "-moz-appearance" ],
};
gCSSProperties["-webkit-background-clip"] = {
domProp: "webkitBackgroundClip",
inherited: false,
@@ -7269,44 +7232,43 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) {
domProp: "webkitBoxFlex",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "flex-grow",
subproperties: [ "flex-grow" ],
alias_for: "-moz-box-flex",
subproperties: [ "-moz-box-flex" ],
};
gCSSProperties["-webkit-box-ordinal-group"] = {
domProp: "webkitBoxOrdinalGroup",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "order",
subproperties: [ "order" ],
alias_for: "-moz-box-ordinal-group",
subproperties: [ "-moz-box-ordinal-group" ],
};
/* This one is not an alias - it's implemented as a logical property: */
gCSSProperties["-webkit-box-orient"] = {
domProp: "webkitBoxOrient",
inherited: false,
type: CSS_TYPE_LONGHAND,
logical: true,
get_computed: webkit_orient_get_computed,
initial_values: [ "horizontal" ],
other_values: [ "vertical" ],
invalid_values: [
"0", "0px", "auto",
/* Flex-direction values: */
"row", "column", "row-reverse", "column-reverse",
],
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "-moz-box-orient",
subproperties: [ "-moz-box-orient" ],
};
gCSSProperties["-webkit-box-direction"] = {
domProp: "webkitBoxDirection",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "-moz-box-direction",
subproperties: [ "-moz-box-direction" ],
};
gCSSProperties["-webkit-box-align"] = {
domProp: "webkitBoxAlign",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "align-items",
subproperties: [ "align-items" ],
alias_for: "-moz-box-align",
subproperties: [ "-moz-box-align" ],
};
gCSSProperties["-webkit-box-pack"] = {
domProp: "webkitBoxPack",
inherited: false,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "justify-content",
subproperties: [ "justify-content" ],
alias_for: "-moz-box-pack",
subproperties: [ "-moz-box-pack" ],
};
gCSSProperties["-webkit-user-select"] = {
domProp: "webkitUserSelect",
+6 -9
View File
@@ -738,18 +738,15 @@ add_future_call(8, check_number_tests);
function check_display_tests(time)
{
var tf = timingFunctions["ease-in-out"];
for (var i in display_tests) {
var p = display_tests[i];
check_transition_value(tf, 0, 8, 0, 100,
getComputedStyle(p, "").textIndent,
"display test for test with " +
p.childNodes[0].data,
// TODO: Making transitions work on 'display:none' elements is
// still not implemented.
function(range) { return p != to_none_test &&
range[1] < 100 });
// There is no transition if the old or new style is display:none, so
// the computed value is always the end value.
var computedValue = getComputedStyle(p, "").textIndent;
is(computedValue, "100px",
"display test for test with " + p.childNodes[0].data +
": computed value " + computedValue + " should be 100px.");
}
}
@@ -0,0 +1,56 @@
<!doctype html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1265611
-->
<head>
<meta charset=utf-8>
<title>Test for bug 1265611</title>
<script type="application/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
#display {
transition: all 0.01s;
}
</style>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265611">Mozilla Bug
1265611</a>
<div id="display"></div>
<pre id="test">
<script>
SimpleTest.waitForExplicitFinish();
/*
* This tests for transitions generated on the -webkit-text-fill-color property.
* This property has an initial value of 'currentcolor' so by triggering a
* transition on the 'color' property we also--at least at the point when
* this test was written--trigger a transition on the -webkit-text-fill-color
* property (that behavior may change in bug 1260543).
*
* However, before beginning the test we disable -webkit-text-fill-color by
* setting layout.css.prefixes.webkit to false. This code tests that we don't
* end up triggering a transition on the (disabled) property in that case.
*/
SpecialPowers.pushPrefEnv({'set': [['layout.css.prefixes.webkit', false],
['dom.animations-api.core.enabled', true]] },
() => {
var display = document.getElementById('display');
display.style.color = 'green';
var transitionedProperties =
display.getAnimations().map(transition => transition.transitionProperty);
ok(!transitionedProperties.includes('-webkit-text-fill-color'),
'We should not fire transitions for properties disabled by prefs');
SimpleTest.finish();
}
);
</script>
</pre>
</body>
</html>
@@ -0,0 +1,71 @@
<!doctype html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1182856
-->
<head>
<title>Test for Bug 1182856</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="animation_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
#display {
background: blue;
height: 10px;
width: 10px;
}
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1182856">Mozilla Bug 1182856</a>
<div id="display"></div>
<pre id="test"></pre>
<script type="application/javascript">
'use strict';
function TestDisplayNoneTurnOffTransitions(elem, cs, elemToDisplayNone, name) {
var ended = false;
var markEnded = function () {
ended = true;
};
elem.addEventListener('transitionend', markEnded, false);
cs.marginLeft; // flush
elem.style.marginLeft = "100px"; // start transition
is(cs.marginLeft, "0px", name + ": margin-left at 0s");
advance_clock(1000);
is(cs.marginLeft, "10px", name + ": margin-left at 1s");
elemToDisplayNone.style.display = "none";
is(cs.marginLeft, "100px", name + ": margin-left after display:none");
advance_clock(10000);
ok(!ended, name + ": Should not get transitionend");
}
advance_clock(0);
// Set display:none on the target.
var [div, cs] = new_div("margin-left: 0px; transition: margin-left 10s linear");
TestDisplayNoneTurnOffTransitions(div, cs, div, "Set display:none on target");
done_div();
// Set display:none on the ancestor of the target.
var [div, cs] = new_div("margin-left: 0px; transition: margin-left 10s linear");
var ancestor = document.createElement("div");
div.parentNode.insertBefore(ancestor, div);
ancestor.appendChild(div);
TestDisplayNoneTurnOffTransitions(div, cs, ancestor,
"Set display:none on ancestor");
ancestor.parentNode.insertBefore(div, ancestor);
ancestor.remove();
done_div();
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
</script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More