|
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/. */ |
|
5 |
|
6 #include "HTMLImageMapAccessible.h" |
|
7 |
|
8 #include "ARIAMap.h" |
|
9 #include "nsAccUtils.h" |
|
10 #include "DocAccessible-inl.h" |
|
11 #include "Role.h" |
|
12 |
|
13 #include "nsIDOMHTMLCollection.h" |
|
14 #include "nsIServiceManager.h" |
|
15 #include "nsIDOMElement.h" |
|
16 #include "nsIDOMHTMLAreaElement.h" |
|
17 #include "nsIFrame.h" |
|
18 #include "nsImageFrame.h" |
|
19 #include "nsImageMap.h" |
|
20 #include "nsIURI.h" |
|
21 |
|
22 using namespace mozilla::a11y; |
|
23 |
|
24 //////////////////////////////////////////////////////////////////////////////// |
|
25 // HTMLImageMapAccessible |
|
26 //////////////////////////////////////////////////////////////////////////////// |
|
27 |
|
28 HTMLImageMapAccessible:: |
|
29 HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
30 ImageAccessibleWrap(aContent, aDoc) |
|
31 { |
|
32 mType = eImageMapType; |
|
33 } |
|
34 |
|
35 //////////////////////////////////////////////////////////////////////////////// |
|
36 // HTMLImageMapAccessible: nsISupports |
|
37 |
|
38 NS_IMPL_ISUPPORTS_INHERITED0(HTMLImageMapAccessible, ImageAccessible) |
|
39 |
|
40 //////////////////////////////////////////////////////////////////////////////// |
|
41 // HTMLImageMapAccessible: Accessible public |
|
42 |
|
43 role |
|
44 HTMLImageMapAccessible::NativeRole() |
|
45 { |
|
46 return roles::IMAGE_MAP; |
|
47 } |
|
48 |
|
49 //////////////////////////////////////////////////////////////////////////////// |
|
50 // HTMLImageMapAccessible: HyperLinkAccessible |
|
51 |
|
52 uint32_t |
|
53 HTMLImageMapAccessible::AnchorCount() |
|
54 { |
|
55 return ChildCount(); |
|
56 } |
|
57 |
|
58 Accessible* |
|
59 HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex) |
|
60 { |
|
61 return GetChildAt(aAnchorIndex); |
|
62 } |
|
63 |
|
64 already_AddRefed<nsIURI> |
|
65 HTMLImageMapAccessible::AnchorURIAt(uint32_t aAnchorIndex) |
|
66 { |
|
67 Accessible* area = GetChildAt(aAnchorIndex); |
|
68 if (!area) |
|
69 return nullptr; |
|
70 |
|
71 nsIContent* linkContent = area->GetContent(); |
|
72 return linkContent ? linkContent->GetHrefURI() : nullptr; |
|
73 } |
|
74 |
|
75 //////////////////////////////////////////////////////////////////////////////// |
|
76 // HTMLImageMapAccessible: public |
|
77 |
|
78 void |
|
79 HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents) |
|
80 { |
|
81 nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame()); |
|
82 |
|
83 // If image map is not initialized yet then we trigger one time more later. |
|
84 nsImageMap* imageMapObj = imageFrame->GetExistingImageMap(); |
|
85 if (!imageMapObj) |
|
86 return; |
|
87 |
|
88 bool doReorderEvent = false; |
|
89 nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this); |
|
90 |
|
91 // Remove areas that are not a valid part of the image map anymore. |
|
92 for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) { |
|
93 Accessible* area = mChildren.ElementAt(childIdx); |
|
94 if (area->GetContent()->GetPrimaryFrame()) |
|
95 continue; |
|
96 |
|
97 if (aDoFireEvents) { |
|
98 nsRefPtr<AccHideEvent> event = new AccHideEvent(area, area->GetContent()); |
|
99 mDoc->FireDelayedEvent(event); |
|
100 reorderEvent->AddSubMutationEvent(event); |
|
101 doReorderEvent = true; |
|
102 } |
|
103 |
|
104 RemoveChild(area); |
|
105 } |
|
106 |
|
107 // Insert new areas into the tree. |
|
108 uint32_t areaElmCount = imageMapObj->AreaCount(); |
|
109 for (uint32_t idx = 0; idx < areaElmCount; idx++) { |
|
110 nsIContent* areaContent = imageMapObj->GetAreaAt(idx); |
|
111 |
|
112 Accessible* area = mChildren.SafeElementAt(idx); |
|
113 if (!area || area->GetContent() != areaContent) { |
|
114 nsRefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc); |
|
115 mDoc->BindToDocument(area, aria::GetRoleMap(areaContent)); |
|
116 |
|
117 if (!InsertChildAt(idx, area)) { |
|
118 mDoc->UnbindFromDocument(area); |
|
119 break; |
|
120 } |
|
121 |
|
122 if (aDoFireEvents) { |
|
123 nsRefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent); |
|
124 mDoc->FireDelayedEvent(event); |
|
125 reorderEvent->AddSubMutationEvent(event); |
|
126 doReorderEvent = true; |
|
127 } |
|
128 } |
|
129 } |
|
130 |
|
131 // Fire reorder event if needed. |
|
132 if (doReorderEvent) |
|
133 mDoc->FireDelayedEvent(reorderEvent); |
|
134 } |
|
135 |
|
136 Accessible* |
|
137 HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const |
|
138 { |
|
139 uint32_t length = mChildren.Length(); |
|
140 for (uint32_t i = 0; i < length; i++) { |
|
141 Accessible* area = mChildren[i]; |
|
142 if (area->GetContent() == aNode) |
|
143 return area; |
|
144 } |
|
145 |
|
146 return nullptr; |
|
147 } |
|
148 |
|
149 //////////////////////////////////////////////////////////////////////////////// |
|
150 // HTMLImageMapAccessible: Accessible protected |
|
151 |
|
152 void |
|
153 HTMLImageMapAccessible::CacheChildren() |
|
154 { |
|
155 UpdateChildAreas(false); |
|
156 } |
|
157 |
|
158 |
|
159 //////////////////////////////////////////////////////////////////////////////// |
|
160 // HTMLAreaAccessible |
|
161 //////////////////////////////////////////////////////////////////////////////// |
|
162 |
|
163 HTMLAreaAccessible:: |
|
164 HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
165 HTMLLinkAccessible(aContent, aDoc) |
|
166 { |
|
167 // Make HTML area DOM element not accessible. HTML image map accessible |
|
168 // manages its tree itself. |
|
169 mStateFlags |= eNotNodeMapEntry; |
|
170 } |
|
171 |
|
172 //////////////////////////////////////////////////////////////////////////////// |
|
173 // HTMLAreaAccessible: nsIAccessible |
|
174 |
|
175 ENameValueFlag |
|
176 HTMLAreaAccessible::NativeName(nsString& aName) |
|
177 { |
|
178 ENameValueFlag nameFlag = Accessible::NativeName(aName); |
|
179 if (!aName.IsEmpty()) |
|
180 return nameFlag; |
|
181 |
|
182 if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) |
|
183 GetValue(aName); |
|
184 |
|
185 return eNameOK; |
|
186 } |
|
187 |
|
188 void |
|
189 HTMLAreaAccessible::Description(nsString& aDescription) |
|
190 { |
|
191 aDescription.Truncate(); |
|
192 |
|
193 // Still to do - follow IE's standard here |
|
194 nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mContent)); |
|
195 if (area) |
|
196 area->GetShape(aDescription); |
|
197 } |
|
198 |
|
199 //////////////////////////////////////////////////////////////////////////////// |
|
200 // HTMLAreaAccessible: Accessible public |
|
201 |
|
202 Accessible* |
|
203 HTMLAreaAccessible::ChildAtPoint(int32_t aX, int32_t aY, |
|
204 EWhichChildAtPoint aWhichChild) |
|
205 { |
|
206 // Don't walk into area accessibles. |
|
207 return this; |
|
208 } |
|
209 |
|
210 //////////////////////////////////////////////////////////////////////////////// |
|
211 // HTMLImageMapAccessible: HyperLinkAccessible |
|
212 |
|
213 uint32_t |
|
214 HTMLAreaAccessible::StartOffset() |
|
215 { |
|
216 // Image map accessible is not hypertext accessible therefore |
|
217 // StartOffset/EndOffset implementations of Accessible doesn't work here. |
|
218 // We return index in parent because image map contains area links only which |
|
219 // are embedded objects. |
|
220 // XXX: image map should be a hypertext accessible. |
|
221 return IndexInParent(); |
|
222 } |
|
223 |
|
224 uint32_t |
|
225 HTMLAreaAccessible::EndOffset() |
|
226 { |
|
227 return IndexInParent() + 1; |
|
228 } |
|
229 |
|
230 //////////////////////////////////////////////////////////////////////////////// |
|
231 // HTMLAreaAccessible: Accessible protected |
|
232 |
|
233 void |
|
234 HTMLAreaAccessible::CacheChildren() |
|
235 { |
|
236 // No children for aria accessible. |
|
237 } |
|
238 |
|
239 void |
|
240 HTMLAreaAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame) |
|
241 { |
|
242 nsIFrame* frame = GetFrame(); |
|
243 if (!frame) |
|
244 return; |
|
245 |
|
246 nsImageFrame* imageFrame = do_QueryFrame(frame); |
|
247 nsImageMap* map = imageFrame->GetImageMap(); |
|
248 |
|
249 nsresult rv = map->GetBoundsForAreaContent(mContent, aBounds); |
|
250 if (NS_FAILED(rv)) |
|
251 return; |
|
252 |
|
253 // XXX Areas are screwy; they return their rects as a pair of points, one pair |
|
254 // stored into the width and height. |
|
255 aBounds.width -= aBounds.x; |
|
256 aBounds.height -= aBounds.y; |
|
257 |
|
258 *aBoundingFrame = frame; |
|
259 } |