Bug 1166138 - Make img srcset react to resize/viewport changes, r=jdm
This commit is contained in:
@@ -80,8 +80,9 @@ namespace dom {
|
||||
class ImageLoadTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit ImageLoadTask(HTMLImageElement *aElement) :
|
||||
mElement(aElement)
|
||||
ImageLoadTask(HTMLImageElement *aElement, bool aAlwaysLoad)
|
||||
: mElement(aElement)
|
||||
, mAlwaysLoad(aAlwaysLoad)
|
||||
{
|
||||
mDocument = aElement->OwnerDoc();
|
||||
mDocument->BlockOnload();
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
{
|
||||
if (mElement->mPendingImageLoadTask == this) {
|
||||
mElement->mPendingImageLoadTask = nullptr;
|
||||
mElement->LoadSelectedImage(true, true);
|
||||
mElement->LoadSelectedImage(true, true, mAlwaysLoad);
|
||||
}
|
||||
mDocument->UnblockOnload(false);
|
||||
return NS_OK;
|
||||
@@ -101,11 +102,13 @@ private:
|
||||
~ImageLoadTask() {}
|
||||
RefPtr<HTMLImageElement> mElement;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
bool mAlwaysLoad;
|
||||
};
|
||||
|
||||
HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
, mForm(nullptr)
|
||||
, mInDocResponsiveContent(false)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
@@ -427,7 +430,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
mResponsiveSelector->Content() == this) {
|
||||
mResponsiveSelector->SetDefaultSource(NullString());
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else {
|
||||
// Bug 1076583 - We still behave synchronously in the non-responsive case
|
||||
CancelImageRequests(aNotify);
|
||||
@@ -447,7 +450,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
if (InResponsiveMode()) {
|
||||
// per spec, full selection runs when this changes, even though
|
||||
// it doesn't directly affect the source selection
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else {
|
||||
// Bug 1076583 - We still use the older synchronous algorithm in
|
||||
// non-responsive mode. Force a new load of the image with the
|
||||
@@ -543,7 +546,7 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
mResponsiveSelector->Content() == this) {
|
||||
mResponsiveSelector->SetDefaultSource(aValue);
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else if (aNotify) {
|
||||
// If aNotify is false, we are coming from the parser or some such place;
|
||||
// we'll get bound after all the attributes have been set, so we'll do the
|
||||
@@ -586,13 +589,15 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
UpdateFormOwner();
|
||||
}
|
||||
|
||||
bool addedToPicture = aParent && aParent->IsHTMLElement(nsGkAtoms::picture) &&
|
||||
HTMLPictureElement::IsPictureEnabled();
|
||||
if (addedToPicture) {
|
||||
if (aDocument) {
|
||||
if (HaveSrcsetOrInPicture()) {
|
||||
if (aDocument && !mInDocResponsiveContent) {
|
||||
aDocument->AddResponsiveContent(this);
|
||||
mInDocResponsiveContent = true;
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
|
||||
bool forceLoadEvent = HTMLPictureElement::IsPictureEnabled() &&
|
||||
aParent && aParent->IsHTMLElement(nsGkAtoms::picture);
|
||||
QueueImageLoadTask(forceLoadEvent);
|
||||
} else if (!InResponsiveMode() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||
// We skip loading when our attributes were set from parser land,
|
||||
@@ -633,17 +638,22 @@ HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
}
|
||||
}
|
||||
|
||||
if (mInDocResponsiveContent) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
if (doc) {
|
||||
doc->RemoveResponsiveContent(this);
|
||||
mInDocResponsiveContent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetParent() &&
|
||||
GetParent()->IsHTMLElement(nsGkAtoms::picture) &&
|
||||
HTMLPictureElement::IsPictureEnabled()) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
if (doc) {
|
||||
doc->RemoveResponsiveContent(this);
|
||||
}
|
||||
// Being removed from picture re-triggers selection, even if we
|
||||
// weren't using a <source> peer
|
||||
if (aNullParent) {
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,7 +697,7 @@ HTMLImageElement::MaybeLoadImage()
|
||||
|
||||
// Note, check LoadingEnabled() after LoadImage call.
|
||||
|
||||
LoadSelectedImage(false, true);
|
||||
LoadSelectedImage(false, true, false);
|
||||
|
||||
if (!LoadingEnabled()) {
|
||||
CancelImageRequests(true);
|
||||
@@ -887,7 +897,7 @@ HTMLImageElement::ClearForm(bool aRemoveFromForm)
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::QueueImageLoadTask()
|
||||
HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad)
|
||||
{
|
||||
// If loading is temporarily disabled, we don't want to queue tasks
|
||||
// that may then run when loading is re-enabled.
|
||||
@@ -895,7 +905,7 @@ HTMLImageElement::QueueImageLoadTask()
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this);
|
||||
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this, aAlwaysLoad);
|
||||
// The task checks this to determine if it was the last
|
||||
// queued event, and so earlier tasks are implicitly canceled.
|
||||
mPendingImageLoadTask = task;
|
||||
@@ -929,7 +939,7 @@ HTMLImageElement::InResponsiveMode()
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
|
||||
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
@@ -937,7 +947,9 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
|
||||
// In responsive mode we generally want to re-run the full
|
||||
// selection algorithm whenever starting a new load, per
|
||||
// spec. This also causes us to re-resolve the URI as appropriate.
|
||||
UpdateResponsiveSource();
|
||||
if (!UpdateResponsiveSource() && !aAlwaysLoad) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (mResponsiveSelector) {
|
||||
@@ -990,9 +1002,17 @@ HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
|
||||
mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
|
||||
}
|
||||
|
||||
if (!mInDocResponsiveContent) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
if (doc) {
|
||||
doc->AddResponsiveContent(this);
|
||||
mInDocResponsiveContent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not using this source.
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1019,7 +1039,7 @@ HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not using this source.
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1035,7 +1055,7 @@ HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not switching to/from this source
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1045,7 +1065,7 @@ HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
|
||||
return;
|
||||
}
|
||||
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1055,15 +1075,17 @@ HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
|
||||
return;
|
||||
}
|
||||
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
HTMLImageElement::UpdateResponsiveSource()
|
||||
{
|
||||
bool hadSelector = !!mResponsiveSelector;
|
||||
|
||||
if (!IsSrcsetEnabled()) {
|
||||
mResponsiveSelector = nullptr;
|
||||
return;
|
||||
return hadSelector;
|
||||
}
|
||||
|
||||
nsIContent *currentSource =
|
||||
@@ -1083,7 +1105,7 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
if (candidateSource == currentSource) {
|
||||
// found no better source before current, re-run selection on
|
||||
// that and keep it if it's still usable.
|
||||
mResponsiveSelector->SelectImage(true);
|
||||
bool changed = mResponsiveSelector->SelectImage(true);
|
||||
if (mResponsiveSelector->NumCandidates()) {
|
||||
bool isUsableCandidate = true;
|
||||
|
||||
@@ -1095,7 +1117,7 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
}
|
||||
|
||||
if (isUsableCandidate) {
|
||||
break;
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,6 +1146,8 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
// Ran out of siblings without finding ourself, e.g. XBL magic.
|
||||
mResponsiveSelector = nullptr;
|
||||
}
|
||||
|
||||
return !hadSelector || mResponsiveSelector;
|
||||
}
|
||||
|
||||
/*static */ bool
|
||||
@@ -1296,7 +1320,7 @@ HTMLImageElement::DestroyContent()
|
||||
void
|
||||
HTMLImageElement::MediaFeatureValuesChanged()
|
||||
{
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user