Bug 1753131 - Dispatch devicechange events even without an actively capturing MediaSt...
[gecko.git] / accessible / html / HTMLImageMapAccessible.cpp
blob025f9342b0d54fc99e49ea24578834b5b4a1c818
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "HTMLImageMapAccessible.h"
8 #include "ARIAMap.h"
9 #include "nsAccUtils.h"
10 #include "DocAccessible-inl.h"
11 #include "Role.h"
13 #include "nsIFrame.h"
14 #include "nsImageFrame.h"
15 #include "nsImageMap.h"
16 #include "nsIURI.h"
17 #include "nsLayoutUtils.h"
18 #include "mozilla/dom/HTMLAreaElement.h"
20 using namespace mozilla::a11y;
22 ////////////////////////////////////////////////////////////////////////////////
23 // HTMLImageMapAccessible
24 ////////////////////////////////////////////////////////////////////////////////
26 HTMLImageMapAccessible::HTMLImageMapAccessible(nsIContent* aContent,
27 DocAccessible* aDoc)
28 : ImageAccessibleWrap(aContent, aDoc) {
29 mType = eImageMapType;
31 UpdateChildAreas(false);
34 ////////////////////////////////////////////////////////////////////////////////
35 // HTMLImageMapAccessible: LocalAccessible public
37 role HTMLImageMapAccessible::NativeRole() const { return roles::IMAGE_MAP; }
39 ////////////////////////////////////////////////////////////////////////////////
40 // HTMLImageMapAccessible: HyperLinkAccessible
42 uint32_t HTMLImageMapAccessible::AnchorCount() { return ChildCount(); }
44 LocalAccessible* HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex) {
45 return LocalChildAt(aAnchorIndex);
48 already_AddRefed<nsIURI> HTMLImageMapAccessible::AnchorURIAt(
49 uint32_t aAnchorIndex) const {
50 LocalAccessible* area = LocalChildAt(aAnchorIndex);
51 if (!area) return nullptr;
53 nsIContent* linkContent = area->GetContent();
54 return linkContent ? linkContent->GetHrefURI() : nullptr;
57 ////////////////////////////////////////////////////////////////////////////////
58 // HTMLImageMapAccessible: public
60 void HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents) {
61 nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
63 // If image map is not initialized yet then we trigger one time more later.
64 nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
65 if (!imageMapObj) return;
67 TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents);
69 // Remove areas that are not a valid part of the image map anymore.
70 for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
71 LocalAccessible* area = mChildren.ElementAt(childIdx);
72 if (area->GetContent()->GetPrimaryFrame()) continue;
74 mt.BeforeRemoval(area);
75 RemoveChild(area);
78 // Insert new areas into the tree.
79 uint32_t areaElmCount = imageMapObj->AreaCount();
80 for (uint32_t idx = 0; idx < areaElmCount; idx++) {
81 nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
82 LocalAccessible* area = mChildren.SafeElementAt(idx);
83 if (!area || area->GetContent() != areaContent) {
84 RefPtr<LocalAccessible> area = new HTMLAreaAccessible(areaContent, mDoc);
85 mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement()));
87 if (!InsertChildAt(idx, area)) {
88 mDoc->UnbindFromDocument(area);
89 break;
92 mt.AfterInsertion(area);
96 mt.Done();
99 LocalAccessible* HTMLImageMapAccessible::GetChildAccessibleFor(
100 const nsINode* aNode) const {
101 uint32_t length = mChildren.Length();
102 for (uint32_t i = 0; i < length; i++) {
103 LocalAccessible* area = mChildren[i];
104 if (area->GetContent() == aNode) return area;
107 return nullptr;
110 ////////////////////////////////////////////////////////////////////////////////
111 // HTMLAreaAccessible
112 ////////////////////////////////////////////////////////////////////////////////
114 HTMLAreaAccessible::HTMLAreaAccessible(nsIContent* aContent,
115 DocAccessible* aDoc)
116 : HTMLLinkAccessible(aContent, aDoc) {
117 // Make HTML area DOM element not accessible. HTML image map accessible
118 // manages its tree itself.
119 mStateFlags |= eNotNodeMapEntry;
122 ////////////////////////////////////////////////////////////////////////////////
123 // HTMLAreaAccessible: LocalAccessible
125 ENameValueFlag HTMLAreaAccessible::NativeName(nsString& aName) const {
126 ENameValueFlag nameFlag = LocalAccessible::NativeName(aName);
127 if (!aName.IsEmpty()) return nameFlag;
129 if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt,
130 aName)) {
131 Value(aName);
134 return eNameOK;
137 void HTMLAreaAccessible::Description(nsString& aDescription) const {
138 aDescription.Truncate();
140 // Still to do - follow IE's standard here
141 RefPtr<dom::HTMLAreaElement> area =
142 dom::HTMLAreaElement::FromNodeOrNull(mContent);
143 if (area) area->GetShape(aDescription);
146 ////////////////////////////////////////////////////////////////////////////////
147 // HTMLAreaAccessible: LocalAccessible public
149 LocalAccessible* HTMLAreaAccessible::LocalChildAtPoint(
150 int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild) {
151 // Don't walk into area accessibles.
152 return this;
155 ////////////////////////////////////////////////////////////////////////////////
156 // HTMLImageMapAccessible: HyperLinkAccessible
158 uint32_t HTMLAreaAccessible::StartOffset() {
159 // Image map accessible is not hypertext accessible therefore
160 // StartOffset/EndOffset implementations of LocalAccessible doesn't work here.
161 // We return index in parent because image map contains area links only which
162 // are embedded objects.
163 // XXX: image map should be a hypertext accessible.
164 return IndexInParent();
167 uint32_t HTMLAreaAccessible::EndOffset() { return IndexInParent() + 1; }
169 nsRect HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const {
170 nsIFrame* frame = GetFrame();
171 if (!frame) return nsRect();
173 nsImageFrame* imageFrame = do_QueryFrame(frame);
174 nsImageMap* map = imageFrame->GetImageMap();
176 nsRect bounds;
177 nsresult rv = map->GetBoundsForAreaContent(mContent, bounds);
179 if (NS_FAILED(rv)) return nsRect();
181 // XXX Areas are screwy; they return their rects as a pair of points, one pair
182 // stored into the width and height.
183 *aBoundingFrame = frame;
184 bounds.SizeTo(bounds.Width() - bounds.X(), bounds.Height() - bounds.Y());
185 return bounds;
188 nsRect HTMLAreaAccessible::ParentRelativeBounds() {
189 nsIFrame* boundingFrame = nullptr;
190 nsRect relativeBoundsRect = RelativeBounds(&boundingFrame);
192 nsIFrame* parentBoundingFrame = nullptr;
193 if (mParent) {
194 parentBoundingFrame = mParent->GetFrame();
197 if (!parentBoundingFrame) {
198 // if we can't get the bounding frame, use the pres shell root for the
199 // bounding frame RelativeBounds returned
200 parentBoundingFrame =
201 nsLayoutUtils::GetContainingBlockForClientRect(boundingFrame);
204 nsLayoutUtils::TransformRect(boundingFrame, parentBoundingFrame,
205 relativeBoundsRect);
207 return relativeBoundsRect;