accessible/src/xul/XULElementAccessibles.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:1b10d6e9e3a3
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 "XULElementAccessibles.h"
7
8 #include "Accessible-inl.h"
9 #include "BaseAccessibles.h"
10 #include "DocAccessible-inl.h"
11 #include "nsAccUtils.h"
12 #include "nsCoreUtils.h"
13 #include "nsTextEquivUtils.h"
14 #include "Relation.h"
15 #include "Role.h"
16 #include "States.h"
17 #include "TextUpdater.h"
18
19 #ifdef A11Y_LOG
20 #include "Logging.h"
21 #endif
22
23 #include "nsIAccessibleRelation.h"
24 #include "nsIDOMXULDescriptionElement.h"
25 #include "nsNameSpaceManager.h"
26 #include "nsNetUtil.h"
27 #include "nsString.h"
28 #include "nsTextBoxFrame.h"
29
30 using namespace mozilla::a11y;
31
32 ////////////////////////////////////////////////////////////////////////////////
33 // XULLabelAccessible
34 ////////////////////////////////////////////////////////////////////////////////
35
36 XULLabelAccessible::
37 XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) :
38 HyperTextAccessibleWrap(aContent, aDoc)
39 {
40 mType = eXULLabelType;
41
42 // If @value attribute is given then it's rendered instead text content. In
43 // this case we need to create a text leaf accessible to make @value attribute
44 // accessible.
45 // XXX: text interface doesn't let you get the text by words.
46 nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame());
47 if (textBoxFrame) {
48 mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc);
49 mDoc->BindToDocument(mValueTextLeaf, nullptr);
50
51 nsAutoString text;
52 textBoxFrame->GetCroppedTitle(text);
53 mValueTextLeaf->SetText(text);
54 }
55 }
56
57 void
58 XULLabelAccessible::Shutdown()
59 {
60 mValueTextLeaf = nullptr;
61 HyperTextAccessibleWrap::Shutdown();
62 }
63
64 ENameValueFlag
65 XULLabelAccessible::NativeName(nsString& aName)
66 {
67 // if the value attr doesn't exist, the screen reader must get the accessible text
68 // from the accessible text interface or from the children
69 if (mValueTextLeaf)
70 return mValueTextLeaf->Name(aName);
71
72 return eNameOK;
73 }
74
75 role
76 XULLabelAccessible::NativeRole()
77 {
78 return roles::LABEL;
79 }
80
81 uint64_t
82 XULLabelAccessible::NativeState()
83 {
84 // Labels and description have read only state
85 // They are not focusable or selectable
86 return HyperTextAccessibleWrap::NativeState() | states::READONLY;
87 }
88
89 Relation
90 XULLabelAccessible::RelationByType(RelationType aType)
91 {
92 Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
93 if (aType == RelationType::LABEL_FOR) {
94 // Caption is the label for groupbox
95 nsIContent* parent = mContent->GetFlattenedTreeParent();
96 if (parent && parent->Tag() == nsGkAtoms::caption) {
97 Accessible* parent = Parent();
98 if (parent && parent->Role() == roles::GROUPING)
99 rel.AppendTarget(parent);
100 }
101 }
102
103 return rel;
104 }
105
106 void
107 XULLabelAccessible::UpdateLabelValue(const nsString& aValue)
108 {
109 #ifdef A11Y_LOG
110 if (logging::IsEnabled(logging::eText)) {
111 logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)");
112 logging::Node("container", mContent);
113 logging::MsgEntry("old text '%s'",
114 NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get());
115 logging::MsgEntry("new text: '%s'",
116 NS_ConvertUTF16toUTF8(aValue).get());
117 logging::MsgEnd();
118 }
119 #endif
120
121 TextUpdater::Run(mDoc, mValueTextLeaf, aValue);
122 }
123
124 void
125 XULLabelAccessible::CacheChildren()
126 {
127 if (mValueTextLeaf) {
128 AppendChild(mValueTextLeaf);
129 return;
130 }
131
132 // Cache children from subtree.
133 AccessibleWrap::CacheChildren();
134 }
135
136
137 ////////////////////////////////////////////////////////////////////////////////
138 // XULLabelTextLeafAccessible
139 ////////////////////////////////////////////////////////////////////////////////
140
141 role
142 XULLabelTextLeafAccessible::NativeRole()
143 {
144 return roles::TEXT_LEAF;
145 }
146
147 uint64_t
148 XULLabelTextLeafAccessible::NativeState()
149 {
150 return TextLeafAccessibleWrap::NativeState() | states::READONLY;
151 }
152
153
154 ////////////////////////////////////////////////////////////////////////////////
155 // XULTooltipAccessible
156 ////////////////////////////////////////////////////////////////////////////////
157
158 XULTooltipAccessible::
159 XULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc) :
160 LeafAccessible(aContent, aDoc)
161 {
162 }
163
164 uint64_t
165 XULTooltipAccessible::NativeState()
166 {
167 return LeafAccessible::NativeState() | states::READONLY;
168 }
169
170 role
171 XULTooltipAccessible::NativeRole()
172 {
173 return roles::TOOLTIP;
174 }
175
176
177 ////////////////////////////////////////////////////////////////////////////////
178 // XULLinkAccessible
179 ////////////////////////////////////////////////////////////////////////////////
180
181 XULLinkAccessible::
182 XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) :
183 XULLabelAccessible(aContent, aDoc)
184 {
185 }
186
187 // Expose nsIAccessibleHyperLink unconditionally
188 NS_IMPL_ISUPPORTS_INHERITED(XULLinkAccessible, XULLabelAccessible,
189 nsIAccessibleHyperLink)
190
191 ////////////////////////////////////////////////////////////////////////////////
192 // XULLinkAccessible. nsIAccessible
193
194 void
195 XULLinkAccessible::Value(nsString& aValue)
196 {
197 aValue.Truncate();
198
199 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue);
200 }
201
202 ENameValueFlag
203 XULLinkAccessible::NativeName(nsString& aName)
204 {
205 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
206 if (!aName.IsEmpty())
207 return eNameOK;
208
209 nsTextEquivUtils::GetNameFromSubtree(this, aName);
210 return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
211 }
212
213 role
214 XULLinkAccessible::NativeRole()
215 {
216 return roles::LINK;
217 }
218
219
220 uint64_t
221 XULLinkAccessible::NativeLinkState() const
222 {
223 return states::LINKED;
224 }
225
226 uint8_t
227 XULLinkAccessible::ActionCount()
228 {
229 return 1;
230 }
231
232 NS_IMETHODIMP
233 XULLinkAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
234 {
235 aName.Truncate();
236
237 if (aIndex != eAction_Jump)
238 return NS_ERROR_INVALID_ARG;
239
240 aName.AssignLiteral("jump");
241 return NS_OK;
242 }
243
244 NS_IMETHODIMP
245 XULLinkAccessible::DoAction(uint8_t aIndex)
246 {
247 if (aIndex != eAction_Jump)
248 return NS_ERROR_INVALID_ARG;
249
250 if (IsDefunct())
251 return NS_ERROR_FAILURE;
252
253 DoCommand();
254 return NS_OK;
255 }
256
257 ////////////////////////////////////////////////////////////////////////////////
258 // XULLinkAccessible: HyperLinkAccessible
259
260 bool
261 XULLinkAccessible::IsLink()
262 {
263 // Expose HyperLinkAccessible unconditionally.
264 return true;
265 }
266
267 uint32_t
268 XULLinkAccessible::StartOffset()
269 {
270 // If XUL link accessible is not contained by hypertext accessible then
271 // start offset matches index in parent because the parent doesn't contains
272 // a text.
273 // XXX: accessible parent of XUL link accessible should be a hypertext
274 // accessible.
275 if (Accessible::IsLink())
276 return Accessible::StartOffset();
277 return IndexInParent();
278 }
279
280 uint32_t
281 XULLinkAccessible::EndOffset()
282 {
283 if (Accessible::IsLink())
284 return Accessible::EndOffset();
285 return IndexInParent() + 1;
286 }
287
288 already_AddRefed<nsIURI>
289 XULLinkAccessible::AnchorURIAt(uint32_t aAnchorIndex)
290 {
291 if (aAnchorIndex != 0)
292 return nullptr;
293
294 nsAutoString href;
295 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
296
297 nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
298 nsIDocument* document = mContent->OwnerDoc();
299
300 nsCOMPtr<nsIURI> anchorURI;
301 NS_NewURI(getter_AddRefs(anchorURI), href,
302 document->GetDocumentCharacterSet().get(),
303 baseURI);
304
305 return anchorURI.forget();
306 }

mercurial