diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /accessible/html/HTMLImageMapAccessible.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'accessible/html/HTMLImageMapAccessible.cpp')
-rw-r--r-- | accessible/html/HTMLImageMapAccessible.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/accessible/html/HTMLImageMapAccessible.cpp b/accessible/html/HTMLImageMapAccessible.cpp new file mode 100644 index 0000000000..dfcd003e6e --- /dev/null +++ b/accessible/html/HTMLImageMapAccessible.cpp @@ -0,0 +1,190 @@ +/* -*- 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/. */ + +#include "HTMLImageMapAccessible.h" + +#include "ARIAMap.h" +#include "nsAccUtils.h" +#include "DocAccessible-inl.h" +#include "EventTree.h" +#include "Role.h" + +#include "nsIFrame.h" +#include "nsImageFrame.h" +#include "nsImageMap.h" +#include "nsIURI.h" +#include "nsLayoutUtils.h" +#include "mozilla/dom/HTMLAreaElement.h" + +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// HTMLImageMapAccessible +//////////////////////////////////////////////////////////////////////////////// + +HTMLImageMapAccessible::HTMLImageMapAccessible(nsIContent* aContent, + DocAccessible* aDoc) + : ImageAccessible(aContent, aDoc) { + mType = eImageMapType; + + UpdateChildAreas(false); +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLImageMapAccessible: LocalAccessible public + +role HTMLImageMapAccessible::NativeRole() const { return roles::IMAGE_MAP; } + +//////////////////////////////////////////////////////////////////////////////// +// HTMLImageMapAccessible: public + +void HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents) { + if (!mContent || !mContent->GetPrimaryFrame()) { + return; + } + nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame()); + + // If image map is not initialized yet then we trigger one time more later. + nsImageMap* imageMapObj = imageFrame->GetExistingImageMap(); + if (!imageMapObj) return; + + TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents); + + // Remove areas that are not a valid part of the image map anymore. + for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) { + LocalAccessible* area = mChildren.ElementAt(childIdx); + if (area->GetContent()->GetPrimaryFrame()) continue; + + mt.BeforeRemoval(area); + RemoveChild(area); + } + + // Insert new areas into the tree. + uint32_t areaElmCount = imageMapObj->AreaCount(); + for (uint32_t idx = 0; idx < areaElmCount; idx++) { + nsIContent* areaContent = imageMapObj->GetAreaAt(idx); + LocalAccessible* area = mChildren.SafeElementAt(idx); + if (!area || area->GetContent() != areaContent) { + RefPtr<LocalAccessible> area = new HTMLAreaAccessible(areaContent, mDoc); + mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement())); + + if (!InsertChildAt(idx, area)) { + mDoc->UnbindFromDocument(area); + break; + } + + mt.AfterInsertion(area); + } + } + + mt.Done(); +} + +LocalAccessible* HTMLImageMapAccessible::GetChildAccessibleFor( + const nsINode* aNode) const { + uint32_t length = mChildren.Length(); + for (uint32_t i = 0; i < length; i++) { + LocalAccessible* area = mChildren[i]; + if (area->GetContent() == aNode) return area; + } + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLAreaAccessible +//////////////////////////////////////////////////////////////////////////////// + +HTMLAreaAccessible::HTMLAreaAccessible(nsIContent* aContent, + DocAccessible* aDoc) + : HTMLLinkAccessible(aContent, aDoc) { + // Make HTML area DOM element not accessible. HTML image map accessible + // manages its tree itself. + mStateFlags |= eNotNodeMapEntry; +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLAreaAccessible: LocalAccessible + +ENameValueFlag HTMLAreaAccessible::NativeName(nsString& aName) const { + ENameValueFlag nameFlag = LocalAccessible::NativeName(aName); + if (!aName.IsEmpty()) return nameFlag; + + if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, + aName)) { + Value(aName); + } + + return eNameOK; +} + +void HTMLAreaAccessible::Description(nsString& aDescription) const { + aDescription.Truncate(); + + // Still to do - follow IE's standard here + RefPtr<dom::HTMLAreaElement> area = + dom::HTMLAreaElement::FromNodeOrNull(mContent); + if (area) area->GetShape(aDescription); +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLAreaAccessible: LocalAccessible public + +LocalAccessible* HTMLAreaAccessible::LocalChildAtPoint( + int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild) { + // Don't walk into area accessibles. + return this; +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLImageMapAccessible: HyperLinkAccessible + +uint32_t HTMLAreaAccessible::StartOffset() { + // Image map accessible is not hypertext accessible therefore + // StartOffset/EndOffset implementations of LocalAccessible doesn't work here. + // We return index in parent because image map contains area links only which + // are embedded objects. + // XXX: image map should be a hypertext accessible. + return IndexInParent(); +} + +uint32_t HTMLAreaAccessible::EndOffset() { return IndexInParent() + 1; } + +nsRect HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const { + nsIFrame* frame = GetFrame(); + if (!frame) return nsRect(); + + nsImageFrame* imageFrame = do_QueryFrame(frame); + nsImageMap* map = imageFrame->GetImageMap(); + + nsRect bounds; + nsresult rv = map->GetBoundsForAreaContent(mContent, bounds); + + if (NS_FAILED(rv)) return nsRect(); + + // XXX Areas are screwy; they return their rects as a pair of points, one pair + // stored into the width and height. + *aBoundingFrame = frame; + bounds.SizeTo(bounds.Width() - bounds.X(), bounds.Height() - bounds.Y()); + return bounds; +} + +nsRect HTMLAreaAccessible::ParentRelativeBounds() { + nsIFrame* boundingFrame = nullptr; + nsRect relativeBoundsRect = RelativeBounds(&boundingFrame); + if (MOZ_UNLIKELY(!boundingFrame)) { + // Area is not attached to an image map? + return nsRect(); + } + + // The relative bounds returned above are relative to this area's + // image map, which is technically already "parent relative". + // Because area elements are `display:none` to layout, they can't + // have transforms or other styling applied directly, and so we + // don't apply any additional transforms here. Any transform + // at the image map layer will be taken care of when computing bounds + // in the parent process. + return relativeBoundsRect; +} |