зеркало из https://github.com/mozilla/gecko-dev.git
Bug 870022 - Part 7 - HTMLImageElement - Make <picture> aware, react to <source> tag and sizes attr changes. r=jst
This commit is contained in:
Родитель
82db106ffb
Коммит
8efbaf6fec
|
@ -151,6 +151,21 @@ ResponsiveImageSelector::SetDefaultSource(const nsAString & aSpec)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ResponsiveImageSelector::NumCandidates(bool aIncludeDefault)
|
||||||
|
{
|
||||||
|
uint32_t candidates = mCandidates.Length();
|
||||||
|
|
||||||
|
// If present, the default candidate is the last item
|
||||||
|
if (!aIncludeDefault && candidates &&
|
||||||
|
(mCandidates[candidates - 1].Type() ==
|
||||||
|
ResponsiveImageCandidate::eCandidateType_Default)) {
|
||||||
|
candidates--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResponsiveImageSelector::SetDefaultSource(nsIURI *aURL)
|
ResponsiveImageSelector::SetDefaultSource(nsIURI *aURL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,10 @@ public:
|
||||||
nsresult SetDefaultSource(const nsAString & aSpec);
|
nsresult SetDefaultSource(const nsAString & aSpec);
|
||||||
void SetDefaultSource(nsIURI *aURL);
|
void SetDefaultSource(nsIURI *aURL);
|
||||||
|
|
||||||
|
uint32_t NumCandidates(bool aIncludeDefault = true);
|
||||||
|
|
||||||
|
nsIContent *Content() { return mContent; }
|
||||||
|
|
||||||
// Get the URL for the selected best candidate
|
// Get the URL for the selected best candidate
|
||||||
already_AddRefed<nsIURI> GetSelectedImageURL();
|
already_AddRefed<nsIURI> GetSelectedImageURL();
|
||||||
double GetSelectedImageDensity();
|
double GetSelectedImageDensity();
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
#include "nsFocusManager.h"
|
#include "nsFocusManager.h"
|
||||||
#include "mozilla/dom/HTMLFormElement.h"
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
|
|
||||||
|
// Responsive images!
|
||||||
|
#include "mozilla/dom/HTMLSourceElement.h"
|
||||||
|
#include "mozilla/dom/ResponsiveImageSelector.h"
|
||||||
|
|
||||||
#include "imgIContainer.h"
|
#include "imgIContainer.h"
|
||||||
#include "imgILoader.h"
|
#include "imgILoader.h"
|
||||||
#include "imgINotificationObserver.h"
|
#include "imgINotificationObserver.h"
|
||||||
|
@ -46,6 +50,21 @@ static const char *kPrefSrcsetEnabled = "dom.image.srcset.enabled";
|
||||||
|
|
||||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
|
NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
|
||||||
|
|
||||||
|
// Is aSubject a previous sibling of aNode.
|
||||||
|
static bool IsPreviousSibling(nsINode *aSubject, nsINode *aNode)
|
||||||
|
{
|
||||||
|
if (aSubject == aNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsINode *parent = aSubject->GetParentNode();
|
||||||
|
if (parent && parent == aNode->GetParentNode()) {
|
||||||
|
return parent->IndexOf(aSubject) < parent->IndexOf(aNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
@ -351,6 +370,8 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
// Handle src/srcset/crossorigin updates. If aNotify is false, we are coming
|
// Handle src/srcset/crossorigin updates. If aNotify is false, we are coming
|
||||||
// from the parser or some such place; we'll get bound after all the
|
// from the parser or some such place; we'll get bound after all the
|
||||||
// attributes have been set, so we'll do the image load from BindToTree.
|
// attributes have been set, so we'll do the image load from BindToTree.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> thisContent = AsContent();
|
||||||
if (aName == nsGkAtoms::src &&
|
if (aName == nsGkAtoms::src &&
|
||||||
aNameSpaceID == kNameSpaceID_None) {
|
aNameSpaceID == kNameSpaceID_None) {
|
||||||
// SetAttr handles setting src in the non-responsive case, so only handle it
|
// SetAttr handles setting src in the non-responsive case, so only handle it
|
||||||
|
@ -368,8 +389,14 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
AsContent()->IsInDoc() &&
|
AsContent()->IsInDoc() &&
|
||||||
IsSrcsetEnabled()) {
|
IsSrcsetEnabled()) {
|
||||||
// We currently don't handle responsive mode until BindToTree
|
// We currently don't handle responsive mode until BindToTree
|
||||||
UpdateSourceSet(aValue->GetStringValue());
|
PictureSourceSrcsetChanged(thisContent,
|
||||||
LoadSelectedImage(false, aNotify);
|
aValue ? aValue->GetStringValue() : EmptyString(),
|
||||||
|
aNotify);
|
||||||
|
} else if (aName == nsGkAtoms::sizes &&
|
||||||
|
aNameSpaceID == kNameSpaceID_None &&
|
||||||
|
thisContent->IsInDoc() &&
|
||||||
|
HTMLPictureElement::IsPictureEnabled()) {
|
||||||
|
PictureSourceSizesChanged(thisContent, aValue->GetStringValue(), aNotify);
|
||||||
} else if (aName == nsGkAtoms::crossorigin &&
|
} else if (aName == nsGkAtoms::crossorigin &&
|
||||||
aNameSpaceID == kNameSpaceID_None &&
|
aNameSpaceID == kNameSpaceID_None &&
|
||||||
aNotify) {
|
aNotify) {
|
||||||
|
@ -502,9 +529,12 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
UpdateFormOwner();
|
UpdateFormOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool addedToPicture = aParent && aParent->Tag() == nsGkAtoms::picture &&
|
||||||
|
HTMLPictureElement::IsPictureEnabled();
|
||||||
bool haveSrcset = IsSrcsetEnabled() &&
|
bool haveSrcset = IsSrcsetEnabled() &&
|
||||||
HasAttr(kNameSpaceID_None, nsGkAtoms::srcset);
|
HasAttr(kNameSpaceID_None, nsGkAtoms::srcset);
|
||||||
if (haveSrcset || HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
if (addedToPicture || haveSrcset ||
|
||||||
|
HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||||
// FIXME: Bug 660963 it would be nice if we could just have
|
// FIXME: Bug 660963 it would be nice if we could just have
|
||||||
// ClearBrokenState update our state and do it fast...
|
// ClearBrokenState update our state and do it fast...
|
||||||
ClearBrokenState();
|
ClearBrokenState();
|
||||||
|
@ -512,15 +542,8 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
|
|
||||||
// We don't handle responsive changes when not bound to a tree, update them
|
// We don't handle responsive changes when not bound to a tree, update them
|
||||||
// now if necessary
|
// now if necessary
|
||||||
if (haveSrcset) {
|
if (addedToPicture || haveSrcset) {
|
||||||
nsAutoString srcset;
|
MaybeUpdateResponsiveSelector();
|
||||||
GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset);
|
|
||||||
UpdateSourceSet(srcset);
|
|
||||||
if (mResponsiveSelector) {
|
|
||||||
nsAutoString src;
|
|
||||||
GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
|
|
||||||
mResponsiveSelector->SetDefaultSource(src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If loading is temporarily disabled, don't even launch MaybeLoadImage.
|
// If loading is temporarily disabled, don't even launch MaybeLoadImage.
|
||||||
|
@ -796,37 +819,224 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
|
||||||
|
const nsAString& aNewValue,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
if (aSourceNode != AsContent() && !HTMLPictureElement::IsPictureEnabled()) {
|
||||||
|
// Don't consider <source> nodes if picture is pref'd off
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent *currentSrc = mResponsiveSelector ? mResponsiveSelector->Content()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (aSourceNode == currentSrc) {
|
||||||
|
// We're currently using this node as our responsive selector source.
|
||||||
|
mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
|
||||||
|
// Search for a new source if we are no longer valid.
|
||||||
|
MaybeUpdateResponsiveSelector(currentSrc);
|
||||||
|
|
||||||
|
LoadSelectedImage(false, aNotify);
|
||||||
|
} else if (currentSrc && IsPreviousSibling(currentSrc, aSourceNode)) {
|
||||||
|
// If we have a source and it is previous to the one being updated, ignore
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// This is previous to our current source or we don't have a current source,
|
||||||
|
// use it if valid.
|
||||||
|
if (TryCreateResponsiveSelector(aSourceNode, &aNewValue, nullptr)) {
|
||||||
|
LoadSelectedImage(false, aNotify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
|
||||||
|
const nsAString& aNewValue,
|
||||||
|
bool aNotify)
|
||||||
|
{
|
||||||
|
if (!HTMLPictureElement::IsPictureEnabled()) {
|
||||||
|
// Don't consider sizes at all if picture support is disabled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent *currentSrc = mResponsiveSelector ? mResponsiveSelector->Content()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (aSourceNode == currentSrc) {
|
||||||
|
// We're currently using this node as our responsive selector source.
|
||||||
|
mResponsiveSelector->SetSizesFromDescriptor(aNewValue);
|
||||||
|
LoadSelectedImage(false, aNotify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
|
||||||
|
{
|
||||||
|
// If the source node is previous to our current one, or ourselves if we have
|
||||||
|
// no responsive source, try to use it as a responsive source.
|
||||||
|
nsIContent *currentSrc = mResponsiveSelector ? mResponsiveSelector->Content()
|
||||||
|
: AsContent();
|
||||||
|
|
||||||
|
if (HTMLPictureElement::IsPictureEnabled() &&
|
||||||
|
IsPreviousSibling(aSourceNode, currentSrc) &&
|
||||||
|
TryCreateResponsiveSelector(aSourceNode, nullptr, nullptr)) {
|
||||||
|
LoadSelectedImage(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
|
||||||
|
{
|
||||||
|
// If this is our current source, we'll need to find another one or leave
|
||||||
|
// responsive mode.
|
||||||
|
if (mResponsiveSelector && mResponsiveSelector->Content() == aSourceNode) {
|
||||||
|
MaybeUpdateResponsiveSelector(aSourceNode, true);
|
||||||
|
LoadSelectedImage(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HTMLImageElement::MaybeUpdateResponsiveSelector(nsIContent *aCurrentSource,
|
||||||
|
bool aSourceRemoved)
|
||||||
|
{
|
||||||
|
nsIContent *thisContent = AsContent();
|
||||||
|
|
||||||
|
if (!aCurrentSource && mResponsiveSelector) {
|
||||||
|
aCurrentSource = mResponsiveSelector->Content();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a source with candidates, no update is needed unless it is being
|
||||||
|
// removed
|
||||||
|
if (aCurrentSource && !aSourceRemoved &&
|
||||||
|
mResponsiveSelector->NumCandidates()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, invalidate
|
||||||
|
bool hadSelector = !!mResponsiveSelector;
|
||||||
|
mResponsiveSelector = nullptr;
|
||||||
|
|
||||||
|
if (!IsSrcsetEnabled()) {
|
||||||
|
return hadSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if there's another source node we could use.
|
||||||
|
bool pictureEnabled = HTMLPictureElement::IsPictureEnabled();
|
||||||
|
nsIContent *nextSource = nullptr;
|
||||||
|
if (pictureEnabled && aCurrentSource && aCurrentSource != thisContent) {
|
||||||
|
// If current source is the <img> tag, there is no next candidate. Otherwise,
|
||||||
|
// it's the next sibling of the current source.
|
||||||
|
MOZ_ASSERT(IsPreviousSibling(aCurrentSource, thisContent) &&
|
||||||
|
thisContent->GetParentNode()->Tag() == nsGkAtoms::picture);
|
||||||
|
nextSource = aCurrentSource->GetNextSibling();
|
||||||
|
} else if (!aCurrentSource) {
|
||||||
|
// If no current source at all, start from the first possible source, which
|
||||||
|
// is the first node of the <picture> element or ourselves if we're not a
|
||||||
|
// picture
|
||||||
|
nsINode *parent = pictureEnabled ? thisContent->GetParentNode() : nullptr;
|
||||||
|
if (parent && parent->Tag() == nsGkAtoms::picture) {
|
||||||
|
nextSource = parent->GetFirstChild();
|
||||||
|
} else {
|
||||||
|
nextSource = thisContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (nextSource) {
|
||||||
|
if (nextSource == thisContent) {
|
||||||
|
// We are the last possible source, so stop searching if we match or
|
||||||
|
// not
|
||||||
|
TryCreateResponsiveSelector(nextSource);
|
||||||
|
break;
|
||||||
|
} else if (nextSource->Tag() == nsGkAtoms::source &&
|
||||||
|
TryCreateResponsiveSelector(nextSource)) {
|
||||||
|
// If this led to a valid source, stop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextSource = nextSource->GetNextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
// State changed unless we didn't make a selector and didn't start with one
|
||||||
|
return mResponsiveSelector || hadSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode,
|
||||||
|
const nsAString *aSrcset,
|
||||||
|
const nsAString *aSizes)
|
||||||
|
{
|
||||||
|
if (!IsSrcsetEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pictureEnabled = HTMLPictureElement::IsPictureEnabled();
|
||||||
|
// Skip if this is not a <source> with matching media query
|
||||||
|
bool isSourceTag = aSourceNode->Tag() == nsGkAtoms::source;
|
||||||
|
if (isSourceTag) {
|
||||||
|
DebugOnly<nsINode *> parent(nsINode::GetParentNode());
|
||||||
|
MOZ_ASSERT(parent && parent->Tag() == nsGkAtoms::picture);
|
||||||
|
MOZ_ASSERT(IsPreviousSibling(aSourceNode, AsContent()));
|
||||||
|
MOZ_ASSERT(pictureEnabled);
|
||||||
|
|
||||||
|
HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode);
|
||||||
|
if (!src->MatchesCurrentMedia()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (aSourceNode->Tag() == nsGkAtoms::img) {
|
||||||
|
// Otherwise this is the <img> tag itself
|
||||||
|
MOZ_ASSERT(aSourceNode == AsContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if has no srcset or an empty srcset
|
||||||
|
nsString srcset;
|
||||||
|
if (aSrcset) {
|
||||||
|
srcset = *aSrcset;
|
||||||
|
} else if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset,
|
||||||
|
srcset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcset.IsEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Try to parse
|
||||||
|
nsRefPtr<ResponsiveImageSelector> sel = new ResponsiveImageSelector(this);
|
||||||
|
if (!sel->SetCandidatesFromSourceSet(srcset)) {
|
||||||
|
// No possible candidates, don't need to bother parsing sizes
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pictureEnabled && aSizes) {
|
||||||
|
sel->SetSizesFromDescriptor(*aSizes);
|
||||||
|
} else if (pictureEnabled) {
|
||||||
|
nsAutoString sizes;
|
||||||
|
aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
|
||||||
|
sel->SetSizesFromDescriptor(sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the <img> tag, also pull in src as the default source
|
||||||
|
if (!isSourceTag) {
|
||||||
|
MOZ_ASSERT(aSourceNode == AsContent());
|
||||||
|
nsAutoString src;
|
||||||
|
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && !src.IsEmpty()) {
|
||||||
|
sel->SetDefaultSource(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mResponsiveSelector = sel;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLImageElement::DestroyContent()
|
HTMLImageElement::DestroyContent()
|
||||||
{
|
{
|
||||||
mResponsiveSelector = nullptr;
|
mResponsiveSelector = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
HTMLImageElement::UpdateSourceSet(const nsAString & aSrcset)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(IsSrcsetEnabled());
|
|
||||||
|
|
||||||
bool haveSrcset = !aSrcset.IsEmpty();
|
|
||||||
|
|
||||||
if (haveSrcset && !mResponsiveSelector) {
|
|
||||||
mResponsiveSelector = new ResponsiveImageSelector(this);
|
|
||||||
mResponsiveSelector->SetCandidatesFromSourceSet(aSrcset);
|
|
||||||
|
|
||||||
// src may have been set before we decided we were responsive
|
|
||||||
nsAutoString src;
|
|
||||||
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && src.Length()) {
|
|
||||||
mResponsiveSelector->SetDefaultSource(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (haveSrcset) {
|
|
||||||
mResponsiveSelector->SetCandidatesFromSourceSet(aSrcset);
|
|
||||||
} else if (mResponsiveSelector) {
|
|
||||||
// Clearing srcset, don't need responsive selector anymore
|
|
||||||
mResponsiveSelector = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,20 @@
|
||||||
#include "nsIDOMHTMLImageElement.h"
|
#include "nsIDOMHTMLImageElement.h"
|
||||||
#include "imgRequestProxy.h"
|
#include "imgRequestProxy.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
#include "mozilla/dom/ResponsiveImageSelector.h"
|
|
||||||
|
// Only needed for IsPictureEnabled()
|
||||||
|
#include "mozilla/dom/HTMLPictureElement.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class EventChainPreVisitor;
|
class EventChainPreVisitor;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
class ResponsiveImageSelector;
|
||||||
class HTMLImageElement MOZ_FINAL : public nsGenericHTMLElement,
|
class HTMLImageElement MOZ_FINAL : public nsGenericHTMLElement,
|
||||||
public nsImageLoadingContent,
|
public nsImageLoadingContent,
|
||||||
public nsIDOMHTMLImageElement
|
public nsIDOMHTMLImageElement
|
||||||
{
|
{
|
||||||
|
friend class HTMLSourceElement;
|
||||||
public:
|
public:
|
||||||
explicit HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
explicit HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||||
virtual ~HTMLImageElement();
|
virtual ~HTMLImageElement();
|
||||||
|
@ -190,7 +194,27 @@ protected:
|
||||||
nsresult LoadSelectedImage(bool aForce, bool aNotify);
|
nsresult LoadSelectedImage(bool aForce, bool aNotify);
|
||||||
|
|
||||||
// Update/create/destroy mResponsiveSelector
|
// Update/create/destroy mResponsiveSelector
|
||||||
void UpdateSourceSet(const nsAString & aSrcset);
|
void PictureSourceSrcsetChanged(nsIContent *aSourceNode,
|
||||||
|
const nsAString& aNewValue, bool aNotify);
|
||||||
|
void PictureSourceSizesChanged(nsIContent *aSourceNode,
|
||||||
|
const nsAString& aNewValue, bool aNotify);
|
||||||
|
|
||||||
|
void PictureSourceAdded(nsIContent *aSourceNode);
|
||||||
|
// This should be called prior to the unbind, such that nextsibling works
|
||||||
|
void PictureSourceRemoved(nsIContent *aSourceNode);
|
||||||
|
|
||||||
|
bool MaybeUpdateResponsiveSelector(nsIContent *aCurrentSource = nullptr,
|
||||||
|
bool aSourceRemoved = false);
|
||||||
|
|
||||||
|
// Given a <source> node that is a previous sibling *or* ourselves, try to
|
||||||
|
// create a ResponsiveSelector.
|
||||||
|
|
||||||
|
// If the node's srcset/sizes make for an invalid selector, returns
|
||||||
|
// false. This does not guarantee the resulting selector matches an image,
|
||||||
|
// only that it is valid.
|
||||||
|
bool TryCreateResponsiveSelector(nsIContent *aSourceNode,
|
||||||
|
const nsAString *aSrcset = nullptr,
|
||||||
|
const nsAString *aSizes = nullptr);
|
||||||
|
|
||||||
CSSIntPoint GetXY();
|
CSSIntPoint GetXY();
|
||||||
virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
|
virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
|
||||||
|
|
|
@ -7,9 +7,16 @@
|
||||||
#include "mozilla/dom/HTMLSourceElement.h"
|
#include "mozilla/dom/HTMLSourceElement.h"
|
||||||
#include "mozilla/dom/HTMLSourceElementBinding.h"
|
#include "mozilla/dom/HTMLSourceElementBinding.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/HTMLImageElement.h"
|
||||||
|
#include "mozilla/dom/ResponsiveImageSelector.h"
|
||||||
|
|
||||||
|
#include "nsGkAtoms.h"
|
||||||
|
|
||||||
#include "nsIMediaList.h"
|
#include "nsIMediaList.h"
|
||||||
#include "nsCSSParser.h"
|
#include "nsCSSParser.h"
|
||||||
|
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
|
||||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
|
NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -52,7 +59,28 @@ nsresult
|
||||||
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAttrValue* aValue, bool aNotify)
|
const nsAttrValue* aValue, bool aNotify)
|
||||||
{
|
{
|
||||||
if (aName == nsGkAtoms::media) {
|
// If we are associated with a <picture> with a valid <img>, notify it of
|
||||||
|
// responsive parameter changes
|
||||||
|
nsINode *parent = nsINode::GetParentNode();
|
||||||
|
if (aNameSpaceID == kNameSpaceID_None &&
|
||||||
|
(aName == nsGkAtoms::srcset || aName == nsGkAtoms::sizes) &&
|
||||||
|
parent && parent->Tag() == nsGkAtoms::picture && MatchesCurrentMedia()) {
|
||||||
|
|
||||||
|
nsString strVal = aValue ? aValue->GetStringValue() : EmptyString();
|
||||||
|
// Find all img siblings after this <source> and notify them of the change
|
||||||
|
nsCOMPtr<nsINode> sibling = AsContent();
|
||||||
|
while ( (sibling = sibling->GetNextSibling()) ) {
|
||||||
|
if (sibling->Tag() == nsGkAtoms::img) {
|
||||||
|
HTMLImageElement *img = static_cast<HTMLImageElement*>(sibling.get());
|
||||||
|
if (aName == nsGkAtoms::srcset) {
|
||||||
|
img->PictureSourceSrcsetChanged(AsContent(), strVal, aNotify);
|
||||||
|
} else if (aName == nsGkAtoms::sizes) {
|
||||||
|
img->PictureSourceSizesChanged(AsContent(), strVal, aNotify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::media) {
|
||||||
mMediaList = nullptr;
|
mMediaList = nullptr;
|
||||||
if (aValue) {
|
if (aValue) {
|
||||||
nsString mediaStr = aValue->GetStringValue();
|
nsString mediaStr = aValue->GetStringValue();
|
||||||
|
@ -92,15 +120,41 @@ HTMLSourceElement::BindToTree(nsIDocument *aDocument,
|
||||||
aCompileEventHandlers);
|
aCompileEventHandlers);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!aParent || !aParent->IsNodeOfType(nsINode::eMEDIA))
|
if (aParent && aParent->IsNodeOfType(nsINode::eMEDIA)) {
|
||||||
return NS_OK;
|
HTMLMediaElement* media = static_cast<HTMLMediaElement*>(aParent);
|
||||||
|
media->NotifyAddedSource();
|
||||||
HTMLMediaElement* media = static_cast<HTMLMediaElement*>(aParent);
|
} else if (aParent && aParent->Tag() == nsGkAtoms::picture) {
|
||||||
media->NotifyAddedSource();
|
// Find any img siblings after this <source> and notify them
|
||||||
|
nsCOMPtr<nsINode> sibling = AsContent();
|
||||||
|
while ( (sibling = sibling->GetNextSibling()) ) {
|
||||||
|
if (sibling->Tag() == nsGkAtoms::img) {
|
||||||
|
HTMLImageElement *img = static_cast<HTMLImageElement*>(sibling.get());
|
||||||
|
img->PictureSourceAdded(AsContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLSourceElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||||
|
{
|
||||||
|
nsINode *parent = nsINode::GetParentNode();
|
||||||
|
if (parent && parent->Tag() == nsGkAtoms::picture) {
|
||||||
|
// Find all img siblings after this <source> and notify them of our demise
|
||||||
|
nsCOMPtr<nsINode> sibling = AsContent();
|
||||||
|
while ( (sibling = sibling->GetNextSibling()) ) {
|
||||||
|
if (sibling->Tag() == nsGkAtoms::img) {
|
||||||
|
HTMLImageElement *img = static_cast<HTMLImageElement*>(sibling.get());
|
||||||
|
img->PictureSourceRemoved(AsContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||||
|
}
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
HTMLSourceElement::WrapNode(JSContext* aCx)
|
HTMLSourceElement::WrapNode(JSContext* aCx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@ class nsMediaList;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
class ResponsiveImageSelector;
|
||||||
class HTMLSourceElement MOZ_FINAL : public nsGenericHTMLElement,
|
class HTMLSourceElement MOZ_FINAL : public nsGenericHTMLElement,
|
||||||
public nsIDOMHTMLSourceElement
|
public nsIDOMHTMLSourceElement
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,7 @@ public:
|
||||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
nsIContent* aBindingParent,
|
nsIContent* aBindingParent,
|
||||||
bool aCompileEventHandlers) MOZ_OVERRIDE;
|
bool aCompileEventHandlers) MOZ_OVERRIDE;
|
||||||
|
virtual void UnbindFromTree(bool aDeep, bool aNullParent) MOZ_OVERRIDE;
|
||||||
|
|
||||||
// If this element's media attr matches for its owner document. Returns true
|
// If this element's media attr matches for its owner document. Returns true
|
||||||
// if no media attr was set.
|
// if no media attr was set.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче