diff --git a/mozilla/content/base/src/nsImageLoadingContent.cpp b/mozilla/content/base/src/nsImageLoadingContent.cpp index faa116772c0..91d2ff29d1a 100644 --- a/mozilla/content/base/src/nsImageLoadingContent.cpp +++ b/mozilla/content/base/src/nsImageLoadingContent.cpp @@ -98,6 +98,7 @@ nsImageLoadingContent::nsImageLoadingContent() mImageBlockingStatus(nsIContentPolicy::ACCEPT), mLoadingEnabled(PR_TRUE), mStartingLoad(PR_FALSE), + mLoading(PR_FALSE), // mBroken starts out true, since an image without a URI is broken.... mBroken(PR_TRUE), mUserDisabled(PR_FALSE), @@ -162,6 +163,10 @@ nsImageLoadingContent::OnStartContainer(imgIRequest* aRequest, imgIContainer* aContainer) { LOOP_OVER_OBSERVERS(OnStartContainer(aRequest, aContainer)); + + // Have to check for state changes here, since we might have been in + // the LOADING state before. + UpdateImageState(PR_TRUE); return NS_OK; } @@ -540,7 +545,8 @@ nsImageLoadingContent::ImageState() const return (mBroken * NS_EVENT_STATE_BROKEN) | (mUserDisabled * NS_EVENT_STATE_USERDISABLED) | - (mSuppressed * NS_EVENT_STATE_SUPPRESSED); + (mSuppressed * NS_EVENT_STATE_SUPPRESSED) | + (mLoading * NS_EVENT_STATE_LOADING); } void @@ -562,7 +568,7 @@ nsImageLoadingContent::UpdateImageState(PRBool aNotify) PRInt32 oldState = ImageState(); - mBroken = mUserDisabled = mSuppressed = PR_FALSE; + mLoading = mBroken = mUserDisabled = mSuppressed = PR_FALSE; // If we were blocked by server-based content policy, we claim to be // suppressed. If we were blocked by type-based content policy, we claim to @@ -579,6 +585,8 @@ nsImageLoadingContent::UpdateImageState(PRBool aNotify) nsresult rv = mCurrentRequest->GetImageStatus(¤tLoadStatus); if (NS_FAILED(rv) || (currentLoadStatus & imgIRequest::STATUS_ERROR)) { mBroken = PR_TRUE; + } else if (!(currentLoadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) { + mLoading = PR_TRUE; } } diff --git a/mozilla/content/base/src/nsImageLoadingContent.h b/mozilla/content/base/src/nsImageLoadingContent.h index 63b20d85644..fe113c974d9 100644 --- a/mozilla/content/base/src/nsImageLoadingContent.h +++ b/mozilla/content/base/src/nsImageLoadingContent.h @@ -250,6 +250,7 @@ private: * The state we had the last time we checked whether we needed to notify the * document of a state change. These are maintained by UpdateImageState. */ + PRPackedBool mLoading : 1; PRPackedBool mBroken : 1; PRPackedBool mUserDisabled : 1; PRPackedBool mSuppressed : 1; diff --git a/mozilla/content/events/public/nsIEventStateManager.h b/mozilla/content/events/public/nsIEventStateManager.h index eaa78757c72..123c27a6ff8 100644 --- a/mozilla/content/events/public/nsIEventStateManager.h +++ b/mozilla/content/events/public/nsIEventStateManager.h @@ -177,5 +177,8 @@ public: #define NS_EVENT_STATE_USERDISABLED 0x00010000 // Content suppressed by the user (ad blocking, etc) #define NS_EVENT_STATE_SUPPRESSED 0x00020000 +// Content is still loading such that there is nothing to show the +// user (eg an image which hasn't started coming in yet) +#define NS_EVENT_STATE_LOADING 0x00040000 #endif // nsIEventStateManager_h__ diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 6cd59779429..e487683429b 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -10436,7 +10436,7 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent, nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent); if (primaryFrame) { if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | - NS_EVENT_STATE_SUPPRESSED)) { + NS_EVENT_STATE_SUPPRESSED | NS_EVENT_STATE_LOADING)) { hint = nsChangeHint_ReconstructFrame; } else { PRUint8 app = primaryFrame->GetStyleDisplay()->mAppearance; diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index 66a95b7702a..ce15424ce5d 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -438,14 +438,15 @@ nsImageFrame::SourceRectToDest(const nsRect& aRect) } static PRBool -ImageOK(nsIContent* aContent) +ImageOK(PRInt32 aContentState) { // Note that we treat NS_EVENT_STATE_SUPPRESSED images as "OK". This means // that we'll construct image frames for them as needed if their display is // toggled from "none" (though we won't paint them, unless their visibility // is changed too). - return !(aContent->IntrinsicState() & - (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED)); + return !(aContentState & + (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | + NS_EVENT_STATE_LOADING)); } /* static */ @@ -453,10 +454,16 @@ PRBool nsImageFrame::ShouldCreateImageFrameFor(nsIContent* aContent, nsStyleContext* aStyleContext) { - if (ImageOK(aContent)) { + PRInt32 state = aContent->IntrinsicState(); + if (ImageOK(state)) { // Image is fine; do the image frame thing return PR_TRUE; } + + if ((state & NS_EVENT_STATE_LOADING) && + HaveFixedSize(aStyleContext->GetStylePosition())) { + return PR_TRUE; + } // Check if we want to use a placeholder box with an icon or just // let the the presShell make us into inline text. Decide as follows: @@ -1273,7 +1280,7 @@ nsImageFrame::Paint(nsPresContext* aPresContext, getter_AddRefs(currentRequest)); } - PRBool imageOK = ImageOK(mContent); + PRBool imageOK = ImageOK(mContent->IntrinsicState()); nsCOMPtr imgCon; if (currentRequest) { diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css index 847f413bce5..1e7a6f6b44f 100644 --- a/mozilla/layout/style/html.css +++ b/mozilla/layout/style/html.css @@ -394,6 +394,7 @@ hr[size="1"] { img:-moz-broken::before, input:-moz-broken::before, img:-moz-user-disabled::before, input:-moz-user-disabled::before, +img:-moz-loading::before, input:-moz-loading::before, /* Nonempty applets should just show their kids. XXXbz do we need a selector that will ignore elements? */ applet:empty:-moz-broken::before, diff --git a/mozilla/layout/style/nsCSSPseudoClassList.h b/mozilla/layout/style/nsCSSPseudoClassList.h index 0230cba1061..54067b169b2 100644 --- a/mozilla/layout/style/nsCSSPseudoClassList.h +++ b/mozilla/layout/style/nsCSSPseudoClassList.h @@ -80,6 +80,7 @@ CSS_PSEUDO_CLASS(onlyChild, ":only-child") CSS_PSEUDO_CLASS(mozBroken, ":-moz-broken") CSS_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled") CSS_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed") +CSS_PSEUDO_CLASS(mozLoading, ":-moz-loading") // CSS 3 UI // http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index a7a81fa845a..55bd352fd49 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -3145,6 +3145,9 @@ static PRBool SelectorMatches(RuleProcessorData &data, else if (nsCSSPseudoClasses::mozSuppressed == pseudoClass->mAtom) { result = STATE_CHECK(NS_EVENT_STATE_SUPPRESSED); } + else if (nsCSSPseudoClasses::mozLoading == pseudoClass->mAtom) { + result = STATE_CHECK(NS_EVENT_STATE_LOADING); + } else if (nsCSSPseudoClasses::required == pseudoClass->mAtom) { result = STATE_CHECK(NS_EVENT_STATE_REQUIRED); } @@ -3689,6 +3692,7 @@ PRBool IsStateSelector(nsCSSSelector& aSelector) (pseudoClass->mAtom == nsCSSPseudoClasses::mozBroken) || (pseudoClass->mAtom == nsCSSPseudoClasses::mozUserDisabled) || (pseudoClass->mAtom == nsCSSPseudoClasses::mozSuppressed) || + (pseudoClass->mAtom == nsCSSPseudoClasses::mozLoading) || (pseudoClass->mAtom == nsCSSPseudoClasses::required) || (pseudoClass->mAtom == nsCSSPseudoClasses::optional) || (pseudoClass->mAtom == nsCSSPseudoClasses::valid) ||