no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / accessible / html / HTMLImageMapAccessible.cpp
blob14dd48587523a49f727e83c4e2126599149b7207
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 "EventTree.h"
10 #include "mozilla/a11y/Role.h"
12 #include "nsCoreUtils.h"
13 #include "nsIFrame.h"
14 #include "nsImageFrame.h"
15 #include "nsImageMap.h"
16 #include "nsLayoutUtils.h"
17 #include "mozilla/dom/HTMLAreaElement.h"
19 using namespace mozilla::a11y;
21 ////////////////////////////////////////////////////////////////////////////////
22 // HTMLImageMapAccessible
23 ////////////////////////////////////////////////////////////////////////////////
25 HTMLImageMapAccessible::HTMLImageMapAccessible(nsIContent* aContent,
26 DocAccessible* aDoc)
27 : ImageAccessible(aContent, aDoc) {
28 mType = eImageMapType;
30 UpdateChildAreas(false);
33 ////////////////////////////////////////////////////////////////////////////////
34 // HTMLImageMapAccessible: LocalAccessible public
36 role HTMLImageMapAccessible::NativeRole() const { return roles::IMAGE_MAP; }
38 ////////////////////////////////////////////////////////////////////////////////
39 // HTMLImageMapAccessible: public
41 void HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents) {
42 if (!mContent || !mContent->GetPrimaryFrame()) {
43 return;
45 nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
47 // If image map is not initialized yet then we trigger one time more later.
48 nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
49 if (!imageMapObj) return;
51 TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents);
53 // Remove areas that are not a valid part of the image map anymore.
54 for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
55 LocalAccessible* area = mChildren.ElementAt(childIdx);
56 if (area->GetContent()->GetPrimaryFrame()) continue;
58 mt.BeforeRemoval(area);
59 RemoveChild(area);
62 // Insert new areas into the tree.
63 uint32_t areaElmCount = imageMapObj->AreaCount();
64 for (uint32_t idx = 0; idx < areaElmCount; idx++) {
65 nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
66 LocalAccessible* area = mChildren.SafeElementAt(idx);
67 if (!area || area->GetContent() != areaContent) {
68 RefPtr<LocalAccessible> area = new HTMLAreaAccessible(areaContent, mDoc);
69 mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement()));
71 if (!InsertChildAt(idx, area)) {
72 mDoc->UnbindFromDocument(area);
73 break;
76 mt.AfterInsertion(area);
80 mt.Done();
83 LocalAccessible* HTMLImageMapAccessible::GetChildAccessibleFor(
84 const nsINode* aNode) const {
85 uint32_t length = mChildren.Length();
86 for (uint32_t i = 0; i < length; i++) {
87 LocalAccessible* area = mChildren[i];
88 if (area->GetContent() == aNode) return area;
91 return nullptr;
94 ////////////////////////////////////////////////////////////////////////////////
95 // HTMLAreaAccessible
96 ////////////////////////////////////////////////////////////////////////////////
98 HTMLAreaAccessible::HTMLAreaAccessible(nsIContent* aContent,
99 DocAccessible* aDoc)
100 : HTMLLinkAccessible(aContent, aDoc) {
101 // Make HTML area DOM element not accessible. HTML image map accessible
102 // manages its tree itself.
103 mStateFlags |= eNotNodeMapEntry;
106 ////////////////////////////////////////////////////////////////////////////////
107 // HTMLAreaAccessible: LocalAccessible
109 role HTMLAreaAccessible::NativeRole() const {
110 // A link element without an href attribute and without a click listener
111 // should be reported as a generic.
112 if (mContent->IsElement()) {
113 dom::Element* element = mContent->AsElement();
114 if (!element->HasAttr(nsGkAtoms::href) &&
115 !nsCoreUtils::HasClickListener(element)) {
116 return roles::TEXT;
119 return HTMLLinkAccessible::NativeRole();
122 ENameValueFlag HTMLAreaAccessible::NativeName(nsString& aName) const {
123 ENameValueFlag nameFlag = LocalAccessible::NativeName(aName);
124 if (!aName.IsEmpty()) return nameFlag;
126 if (!mContent->AsElement()->GetAttr(nsGkAtoms::alt, aName)) {
127 Value(aName);
130 return eNameOK;
133 void HTMLAreaAccessible::Description(nsString& aDescription) const {
134 aDescription.Truncate();
136 // Still to do - follow IE's standard here
137 RefPtr<dom::HTMLAreaElement> area =
138 dom::HTMLAreaElement::FromNodeOrNull(mContent);
139 if (area) area->GetShape(aDescription);
142 ////////////////////////////////////////////////////////////////////////////////
143 // HTMLAreaAccessible: LocalAccessible public
145 LocalAccessible* HTMLAreaAccessible::LocalChildAtPoint(
146 int32_t aX, int32_t aY, EWhichChildAtPoint aWhichChild) {
147 // Don't walk into area accessibles.
148 return this;
151 ////////////////////////////////////////////////////////////////////////////////
152 // HTMLImageMapAccessible: HyperLinkAccessible
154 uint32_t HTMLAreaAccessible::StartOffset() {
155 // Image map accessible is not hypertext accessible therefore
156 // StartOffset/EndOffset implementations of LocalAccessible doesn't work here.
157 // We return index in parent because image map contains area links only which
158 // are embedded objects.
159 // XXX: image map should be a hypertext accessible.
160 return IndexInParent();
163 uint32_t HTMLAreaAccessible::EndOffset() { return IndexInParent() + 1; }
165 nsRect HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const {
166 nsIFrame* frame = GetFrame();
167 if (!frame) return nsRect();
169 nsImageFrame* imageFrame = do_QueryFrame(frame);
170 nsImageMap* map = imageFrame->GetImageMap();
172 nsRect bounds;
173 nsresult rv = map->GetBoundsForAreaContent(mContent, bounds);
175 if (NS_FAILED(rv)) return nsRect();
177 // XXX Areas are screwy; they return their rects as a pair of points, one pair
178 // stored into the width and height.
179 *aBoundingFrame = frame;
180 bounds.SizeTo(bounds.Width() - bounds.X(), bounds.Height() - bounds.Y());
181 return bounds;
184 nsRect HTMLAreaAccessible::ParentRelativeBounds() {
185 nsIFrame* boundingFrame = nullptr;
186 nsRect relativeBoundsRect = RelativeBounds(&boundingFrame);
187 if (MOZ_UNLIKELY(!boundingFrame)) {
188 // Area is not attached to an image map?
189 return nsRect();
192 // The relative bounds returned above are relative to this area's
193 // image map, which is technically already "parent relative".
194 // Because area elements are `display:none` to layout, they can't
195 // have transforms or other styling applied directly, and so we
196 // don't apply any additional transforms here. Any transform
197 // at the image map layer will be taken care of when computing bounds
198 // in the parent process.
199 return relativeBoundsRect;