зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1733238 - P2: Make ImageAccessible an imgINotificationObserver. r=Jamie
Use imgINotificationObserver to get notified of size availability. Layout uses an observer to wait for this too. Our observer is notified after layout so we should have bounds by then. We need to store the request status because we get a lot of "replayed" status changes that would cause chatty and wrong state change events when the accessible is first created and bound to parent. We can use that status for both INVISIBLE and ANIMATED states in NativeState. Differential Revision: https://phabricator.services.mozilla.com/D127719
This commit is contained in:
Родитель
4df7a921a8
Коммит
306495fc6c
|
@ -365,25 +365,6 @@ void nsAccessibilityService::FireAccessibleEvent(uint32_t aEvent,
|
|||
nsEventShell::FireEvent(aEvent, aTarget);
|
||||
}
|
||||
|
||||
void nsAccessibilityService::NotifyOfImageSizeAvailable(
|
||||
mozilla::PresShell* aPresShell, nsIContent* aContent) {
|
||||
// If the size of an image is initially unknown, it will have the invisible
|
||||
// state (and a 0 width and height), causing it to be ignored by some screen
|
||||
// readers. Fire a state change event to update any client caches.
|
||||
DocAccessible* document = GetDocAccessible(aPresShell);
|
||||
if (document) {
|
||||
LocalAccessible* accessible = document->GetAccessible(aContent);
|
||||
// The accessible may not be an ImageAccessible if this was previously a
|
||||
// broken image with an alt attribute. In that case, do nothing; the
|
||||
// accessible will be recreated if this becomes a valid image.
|
||||
if (accessible && accessible->IsImage()) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(accessible, states::INVISIBLE, false);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsAccessibilityService::NotifyOfPossibleBoundsChange(
|
||||
mozilla::PresShell* aPresShell, nsIContent* aContent) {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
|
|
|
@ -221,15 +221,6 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
|
||||
void FireAccessibleEvent(uint32_t aEvent, LocalAccessible* aTarget);
|
||||
|
||||
/**
|
||||
* Notify accessibility that the size has become available for an image.
|
||||
* This occurs when the size of an image is initially not known, but we've
|
||||
* now loaded enough data to know the size.
|
||||
* Called by layout.
|
||||
*/
|
||||
void NotifyOfImageSizeAvailable(mozilla::PresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
void NotifyOfPossibleBoundsChange(mozilla::PresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
|
|
|
@ -23,13 +23,27 @@
|
|||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(ImageAccessible, LinkableAccessible,
|
||||
imgINotificationObserver)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ImageAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ImageAccessible::ImageAccessible(nsIContent* aContent, DocAccessible* aDoc)
|
||||
: LinkableAccessible(aContent, aDoc) {
|
||||
: LinkableAccessible(aContent, aDoc),
|
||||
mImageRequestStatus(imgIRequest::STATUS_NONE) {
|
||||
mType = eImageType;
|
||||
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent));
|
||||
if (content) {
|
||||
content->AddNativeObserver(this);
|
||||
nsCOMPtr<imgIRequest> imageRequest;
|
||||
content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imageRequest));
|
||||
if (imageRequest) {
|
||||
imageRequest->GetImageStatus(&mImageRequestStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImageAccessible::~ImageAccessible() {}
|
||||
|
@ -37,43 +51,34 @@ ImageAccessible::~ImageAccessible() {}
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LocalAccessible public
|
||||
|
||||
void ImageAccessible::Shutdown() {
|
||||
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent));
|
||||
if (content) {
|
||||
content->RemoveNativeObserver(this);
|
||||
}
|
||||
|
||||
LinkableAccessible::Shutdown();
|
||||
}
|
||||
|
||||
uint64_t ImageAccessible::NativeState() const {
|
||||
// The state is a bitfield, get our inherited state, then logically OR it with
|
||||
// states::ANIMATED if this is an animated image.
|
||||
|
||||
uint64_t state = LinkableAccessible::NativeState();
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent));
|
||||
nsCOMPtr<imgIRequest> imageRequest;
|
||||
|
||||
if (content) {
|
||||
content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imageRequest));
|
||||
if (mImageRequestStatus & imgIRequest::STATUS_IS_ANIMATED) {
|
||||
state |= states::ANIMATED;
|
||||
}
|
||||
|
||||
if (imageRequest) {
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
imageRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
if (imgContainer) {
|
||||
bool animated = false;
|
||||
imgContainer->GetAnimated(&animated);
|
||||
if (animated) {
|
||||
state |= states::ANIMATED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mImageRequestStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
nsIFrame* frame = GetFrame();
|
||||
MOZ_ASSERT(!frame || frame->AccessibleType() == eImageType ||
|
||||
frame->AccessibleType() == a11y::eHTMLImageMapType);
|
||||
if (frame && !(frame->GetStateBits() & IMAGE_SIZECONSTRAINED)) {
|
||||
uint32_t status = imgIRequest::STATUS_NONE;
|
||||
imageRequest->GetImageStatus(&status);
|
||||
if (!(status & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
// The size of this image hasn't been constrained and we haven't loaded
|
||||
// enough of the image to know its size yet. This means it currently
|
||||
// has 0 width and height.
|
||||
state |= states::INVISIBLE;
|
||||
}
|
||||
// The size of this image hasn't been constrained and we haven't loaded
|
||||
// enough of the image to know its size yet. This means it currently
|
||||
// has 0 width and height.
|
||||
state |= states::INVISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,3 +205,36 @@ already_AddRefed<nsIURI> ImageAccessible::GetLongDescURI() const {
|
|||
bool ImageAccessible::IsLongDescIndex(uint8_t aIndex) const {
|
||||
return aIndex == LinkableAccessible::ActionCount();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// imgINotificationObserver
|
||||
|
||||
void ImageAccessible::Notify(imgIRequest* aRequest, int32_t aType,
|
||||
const nsIntRect* aData) {
|
||||
if (aType != imgINotificationObserver::FRAME_COMPLETE &&
|
||||
aType != imgINotificationObserver::LOAD_COMPLETE &&
|
||||
aType != imgINotificationObserver::DECODE_COMPLETE) {
|
||||
// We should update our state if the whole image was decoded,
|
||||
// or the first frame in the case of a gif.
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDefunct() || !mParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t status = imgIRequest::STATUS_NONE;
|
||||
aRequest->GetImageStatus(&status);
|
||||
|
||||
if ((status ^ mImageRequestStatus) & imgIRequest::STATUS_SIZE_AVAILABLE) {
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame && !(frame->GetStateBits() & IMAGE_SIZECONSTRAINED)) {
|
||||
RefPtr<AccEvent> event = new AccStateChangeEvent(
|
||||
this, states::INVISIBLE,
|
||||
!(status & imgIRequest::STATUS_SIZE_AVAILABLE));
|
||||
mDoc->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
mImageRequestStatus = status;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define mozilla_a11y_ImageAccessible_h__
|
||||
|
||||
#include "BaseAccessibles.h"
|
||||
#include "imgINotificationObserver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
@ -16,11 +17,16 @@ namespace a11y {
|
|||
* - gets name, role
|
||||
* - support basic state
|
||||
*/
|
||||
class ImageAccessible : public LinkableAccessible {
|
||||
class ImageAccessible : public LinkableAccessible,
|
||||
public imgINotificationObserver {
|
||||
public:
|
||||
ImageAccessible(nsIContent* aContent, DocAccessible* aDoc);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||
|
||||
// LocalAccessible
|
||||
virtual void Shutdown() override;
|
||||
virtual a11y::role NativeRole() const override;
|
||||
virtual uint64_t NativeState() const override;
|
||||
virtual already_AddRefed<AccAttributes> NativeAttributes() override;
|
||||
|
@ -66,6 +72,8 @@ class ImageAccessible : public LinkableAccessible {
|
|||
* @returns true if index is valid for longdesc action.
|
||||
*/
|
||||
inline bool IsLongDescIndex(uint8_t aIndex) const;
|
||||
|
||||
uint32_t mImageRequestStatus;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -949,13 +949,6 @@ void nsImageFrame::UpdateImage(imgIRequest* aRequest, imgIContainer* aImage) {
|
|||
// Now we need to reflow if we have an unconstrained size and have
|
||||
// already gotten the initial reflow.
|
||||
if (!(mState & IMAGE_SIZECONSTRAINED)) {
|
||||
#ifdef ACCESSIBILITY
|
||||
if (mKind != Kind::ListStyleImage) {
|
||||
if (nsAccessibilityService* accService = GetAccService()) {
|
||||
accService->NotifyOfImageSizeAvailable(PresShell(), mContent);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
PresShell()->FrameNeedsReflow(this, IntrinsicDirty::StyleChange,
|
||||
NS_FRAME_IS_DIRTY);
|
||||
} else if (PresShell()->IsActive()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче