|
1 /* -*- Mode: C++; tab-width: 4; 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 "XULListboxAccessible.h" |
|
7 |
|
8 #include "Accessible-inl.h" |
|
9 #include "nsAccessibilityService.h" |
|
10 #include "nsAccUtils.h" |
|
11 #include "DocAccessible.h" |
|
12 #include "Role.h" |
|
13 #include "States.h" |
|
14 |
|
15 #include "nsComponentManagerUtils.h" |
|
16 #include "nsIAutoCompleteInput.h" |
|
17 #include "nsIAutoCompletePopup.h" |
|
18 #include "nsIDOMXULMenuListElement.h" |
|
19 #include "nsIDOMXULMultSelectCntrlEl.h" |
|
20 #include "nsIDOMNodeList.h" |
|
21 #include "nsIDOMXULPopupElement.h" |
|
22 #include "nsIDOMXULSelectCntrlItemEl.h" |
|
23 #include "nsIMutableArray.h" |
|
24 #include "nsIPersistentProperties2.h" |
|
25 |
|
26 using namespace mozilla::a11y; |
|
27 |
|
28 //////////////////////////////////////////////////////////////////////////////// |
|
29 // XULColumAccessible |
|
30 //////////////////////////////////////////////////////////////////////////////// |
|
31 |
|
32 XULColumAccessible:: |
|
33 XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
34 AccessibleWrap(aContent, aDoc) |
|
35 { |
|
36 } |
|
37 |
|
38 role |
|
39 XULColumAccessible::NativeRole() |
|
40 { |
|
41 return roles::LIST; |
|
42 } |
|
43 |
|
44 uint64_t |
|
45 XULColumAccessible::NativeState() |
|
46 { |
|
47 return states::READONLY; |
|
48 } |
|
49 |
|
50 |
|
51 //////////////////////////////////////////////////////////////////////////////// |
|
52 // XULColumnItemAccessible |
|
53 //////////////////////////////////////////////////////////////////////////////// |
|
54 |
|
55 XULColumnItemAccessible:: |
|
56 XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
57 LeafAccessible(aContent, aDoc) |
|
58 { |
|
59 } |
|
60 |
|
61 role |
|
62 XULColumnItemAccessible::NativeRole() |
|
63 { |
|
64 return roles::COLUMNHEADER; |
|
65 } |
|
66 |
|
67 uint64_t |
|
68 XULColumnItemAccessible::NativeState() |
|
69 { |
|
70 return states::READONLY; |
|
71 } |
|
72 |
|
73 uint8_t |
|
74 XULColumnItemAccessible::ActionCount() |
|
75 { |
|
76 return 1; |
|
77 } |
|
78 |
|
79 NS_IMETHODIMP |
|
80 XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) |
|
81 { |
|
82 if (aIndex != eAction_Click) |
|
83 return NS_ERROR_INVALID_ARG; |
|
84 |
|
85 aName.AssignLiteral("click"); |
|
86 return NS_OK; |
|
87 } |
|
88 |
|
89 NS_IMETHODIMP |
|
90 XULColumnItemAccessible::DoAction(uint8_t aIndex) |
|
91 { |
|
92 if (aIndex != eAction_Click) |
|
93 return NS_ERROR_INVALID_ARG; |
|
94 |
|
95 DoCommand(); |
|
96 return NS_OK; |
|
97 } |
|
98 |
|
99 //////////////////////////////////////////////////////////////////////////////// |
|
100 // XULListboxAccessible |
|
101 //////////////////////////////////////////////////////////////////////////////// |
|
102 |
|
103 XULListboxAccessible:: |
|
104 XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
105 XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) |
|
106 { |
|
107 nsIContent* parentContent = mContent->GetFlattenedTreeParent(); |
|
108 if (parentContent) { |
|
109 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
110 do_QueryInterface(parentContent); |
|
111 if (autoCompletePopupElm) |
|
112 mGenericTypes |= eAutoCompletePopup; |
|
113 } |
|
114 } |
|
115 |
|
116 NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible) |
|
117 NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible) |
|
118 |
|
119 nsresult |
|
120 XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) |
|
121 { |
|
122 nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr); |
|
123 if (*aInstancePtr) |
|
124 return rv; |
|
125 |
|
126 if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) { |
|
127 *aInstancePtr = static_cast<nsIAccessibleTable*>(this); |
|
128 NS_ADDREF_THIS(); |
|
129 return NS_OK; |
|
130 } |
|
131 |
|
132 return NS_ERROR_NO_INTERFACE; |
|
133 } |
|
134 |
|
135 //////////////////////////////////////////////////////////////////////////////// |
|
136 // Accessible |
|
137 |
|
138 void |
|
139 XULListboxAccessible::Shutdown() |
|
140 { |
|
141 mTable = nullptr; |
|
142 XULSelectControlAccessible::Shutdown(); |
|
143 } |
|
144 |
|
145 bool |
|
146 XULListboxAccessible::IsMulticolumn() |
|
147 { |
|
148 int32_t numColumns = 0; |
|
149 nsresult rv = GetColumnCount(&numColumns); |
|
150 if (NS_FAILED(rv)) |
|
151 return false; |
|
152 |
|
153 return numColumns > 1; |
|
154 } |
|
155 |
|
156 //////////////////////////////////////////////////////////////////////////////// |
|
157 // XULListboxAccessible. nsIAccessible |
|
158 |
|
159 uint64_t |
|
160 XULListboxAccessible::NativeState() |
|
161 { |
|
162 // As a XULListboxAccessible we can have the following states: |
|
163 // FOCUSED, READONLY, FOCUSABLE |
|
164 |
|
165 // Get focus status from base class |
|
166 uint64_t states = Accessible::NativeState(); |
|
167 |
|
168 // see if we are multiple select if so set ourselves as such |
|
169 |
|
170 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype, |
|
171 nsGkAtoms::multiple, eCaseMatters)) { |
|
172 states |= states::MULTISELECTABLE | states::EXTSELECTABLE; |
|
173 } |
|
174 |
|
175 return states; |
|
176 } |
|
177 |
|
178 /** |
|
179 * Our value is the label of our ( first ) selected child. |
|
180 */ |
|
181 void |
|
182 XULListboxAccessible::Value(nsString& aValue) |
|
183 { |
|
184 aValue.Truncate(); |
|
185 |
|
186 nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent)); |
|
187 if (select) { |
|
188 nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem; |
|
189 select->GetSelectedItem(getter_AddRefs(selectedItem)); |
|
190 if (selectedItem) |
|
191 selectedItem->GetLabel(aValue); |
|
192 } |
|
193 } |
|
194 |
|
195 role |
|
196 XULListboxAccessible::NativeRole() |
|
197 { |
|
198 // A richlistbox is used with the new autocomplete URL bar, and has a parent |
|
199 // popup <panel>. |
|
200 nsCOMPtr<nsIDOMXULPopupElement> xulPopup = |
|
201 do_QueryInterface(mContent->GetParent()); |
|
202 if (xulPopup) |
|
203 return roles::COMBOBOX_LIST; |
|
204 |
|
205 return IsMulticolumn() ? roles::TABLE : roles::LISTBOX; |
|
206 } |
|
207 |
|
208 //////////////////////////////////////////////////////////////////////////////// |
|
209 // XULListboxAccessible. nsIAccessibleTable |
|
210 |
|
211 uint32_t |
|
212 XULListboxAccessible::ColCount() |
|
213 { |
|
214 nsIContent* headContent = nullptr; |
|
215 for (nsIContent* childContent = mContent->GetFirstChild(); childContent; |
|
216 childContent = childContent->GetNextSibling()) { |
|
217 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols, |
|
218 kNameSpaceID_XUL)) { |
|
219 headContent = childContent; |
|
220 } |
|
221 } |
|
222 if (!headContent) |
|
223 return 0; |
|
224 |
|
225 uint32_t columnCount = 0; |
|
226 for (nsIContent* childContent = headContent->GetFirstChild(); childContent; |
|
227 childContent = childContent->GetNextSibling()) { |
|
228 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol, |
|
229 kNameSpaceID_XUL)) { |
|
230 columnCount++; |
|
231 } |
|
232 } |
|
233 |
|
234 return columnCount; |
|
235 } |
|
236 |
|
237 uint32_t |
|
238 XULListboxAccessible::RowCount() |
|
239 { |
|
240 nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent)); |
|
241 |
|
242 uint32_t itemCount = 0; |
|
243 if(element) |
|
244 element->GetItemCount(&itemCount); |
|
245 |
|
246 return itemCount; |
|
247 } |
|
248 |
|
249 Accessible* |
|
250 XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex) |
|
251 { |
|
252 nsCOMPtr<nsIDOMXULSelectControlElement> control = |
|
253 do_QueryInterface(mContent); |
|
254 NS_ENSURE_TRUE(control, nullptr); |
|
255 |
|
256 nsCOMPtr<nsIDOMXULSelectControlItemElement> item; |
|
257 control->GetItemAtIndex(aRowIndex, getter_AddRefs(item)); |
|
258 if (!item) |
|
259 return nullptr; |
|
260 |
|
261 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item)); |
|
262 if (!itemContent) |
|
263 return nullptr; |
|
264 |
|
265 Accessible* row = mDoc->GetAccessible(itemContent); |
|
266 NS_ENSURE_TRUE(row, nullptr); |
|
267 |
|
268 return row->GetChildAt(aColumnIndex); |
|
269 } |
|
270 |
|
271 bool |
|
272 XULListboxAccessible::IsColSelected(uint32_t aColIdx) |
|
273 { |
|
274 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
275 do_QueryInterface(mContent); |
|
276 NS_ASSERTION(control, |
|
277 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
278 |
|
279 int32_t selectedrowCount = 0; |
|
280 nsresult rv = control->GetSelectedCount(&selectedrowCount); |
|
281 NS_ENSURE_SUCCESS(rv, false); |
|
282 |
|
283 return selectedrowCount == RowCount(); |
|
284 } |
|
285 |
|
286 bool |
|
287 XULListboxAccessible::IsRowSelected(uint32_t aRowIdx) |
|
288 { |
|
289 nsCOMPtr<nsIDOMXULSelectControlElement> control = |
|
290 do_QueryInterface(mContent); |
|
291 NS_ASSERTION(control, |
|
292 "Doesn't implement nsIDOMXULSelectControlElement."); |
|
293 |
|
294 nsCOMPtr<nsIDOMXULSelectControlItemElement> item; |
|
295 nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); |
|
296 NS_ENSURE_SUCCESS(rv, false); |
|
297 |
|
298 bool isSelected = false; |
|
299 item->GetSelected(&isSelected); |
|
300 return isSelected; |
|
301 } |
|
302 |
|
303 bool |
|
304 XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) |
|
305 { |
|
306 return IsRowSelected(aRowIdx); |
|
307 } |
|
308 |
|
309 uint32_t |
|
310 XULListboxAccessible::SelectedCellCount() |
|
311 { |
|
312 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
313 do_QueryInterface(mContent); |
|
314 NS_ASSERTION(control, |
|
315 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
316 |
|
317 nsCOMPtr<nsIDOMNodeList> selectedItems; |
|
318 control->GetSelectedItems(getter_AddRefs(selectedItems)); |
|
319 if (!selectedItems) |
|
320 return 0; |
|
321 |
|
322 uint32_t selectedItemsCount = 0; |
|
323 nsresult rv = selectedItems->GetLength(&selectedItemsCount); |
|
324 NS_ENSURE_SUCCESS(rv, 0); |
|
325 |
|
326 return selectedItemsCount * ColCount(); |
|
327 } |
|
328 |
|
329 uint32_t |
|
330 XULListboxAccessible::SelectedColCount() |
|
331 { |
|
332 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
333 do_QueryInterface(mContent); |
|
334 NS_ASSERTION(control, |
|
335 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
336 |
|
337 int32_t selectedRowCount = 0; |
|
338 nsresult rv = control->GetSelectedCount(&selectedRowCount); |
|
339 NS_ENSURE_SUCCESS(rv, 0); |
|
340 |
|
341 return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0; |
|
342 } |
|
343 |
|
344 uint32_t |
|
345 XULListboxAccessible::SelectedRowCount() |
|
346 { |
|
347 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
348 do_QueryInterface(mContent); |
|
349 NS_ASSERTION(control, |
|
350 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
351 |
|
352 int32_t selectedRowCount = 0; |
|
353 nsresult rv = control->GetSelectedCount(&selectedRowCount); |
|
354 NS_ENSURE_SUCCESS(rv, 0); |
|
355 |
|
356 return selectedRowCount >= 0 ? selectedRowCount : 0; |
|
357 } |
|
358 |
|
359 void |
|
360 XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells) |
|
361 { |
|
362 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
363 do_QueryInterface(mContent); |
|
364 NS_ASSERTION(control, |
|
365 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
366 |
|
367 nsCOMPtr<nsIDOMNodeList> selectedItems; |
|
368 control->GetSelectedItems(getter_AddRefs(selectedItems)); |
|
369 if (!selectedItems) |
|
370 return; |
|
371 |
|
372 uint32_t selectedItemsCount = 0; |
|
373 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount); |
|
374 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); |
|
375 |
|
376 for (uint32_t index = 0; index < selectedItemsCount; index++) { |
|
377 nsCOMPtr<nsIDOMNode> itemNode; |
|
378 selectedItems->Item(index, getter_AddRefs(itemNode)); |
|
379 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode)); |
|
380 Accessible* item = mDoc->GetAccessible(itemContent); |
|
381 |
|
382 if (item) { |
|
383 uint32_t cellCount = item->ChildCount(); |
|
384 for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) { |
|
385 Accessible* cell = mChildren[cellIdx]; |
|
386 if (cell->Role() == roles::CELL) |
|
387 aCells->AppendElement(cell); |
|
388 } |
|
389 } |
|
390 } |
|
391 } |
|
392 |
|
393 void |
|
394 XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) |
|
395 { |
|
396 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
397 do_QueryInterface(mContent); |
|
398 NS_ASSERTION(control, |
|
399 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
400 |
|
401 nsCOMPtr<nsIDOMNodeList> selectedItems; |
|
402 control->GetSelectedItems(getter_AddRefs(selectedItems)); |
|
403 if (!selectedItems) |
|
404 return; |
|
405 |
|
406 uint32_t selectedItemsCount = 0; |
|
407 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount); |
|
408 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); |
|
409 |
|
410 uint32_t colCount = ColCount(); |
|
411 aCells->SetCapacity(selectedItemsCount * colCount); |
|
412 aCells->AppendElements(selectedItemsCount * colCount); |
|
413 |
|
414 for (uint32_t selItemsIdx = 0, cellsIdx = 0; |
|
415 selItemsIdx < selectedItemsCount; selItemsIdx++) { |
|
416 |
|
417 nsCOMPtr<nsIDOMNode> itemNode; |
|
418 selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode)); |
|
419 nsCOMPtr<nsIDOMXULSelectControlItemElement> item = |
|
420 do_QueryInterface(itemNode); |
|
421 |
|
422 if (item) { |
|
423 int32_t itemIdx = -1; |
|
424 control->GetIndexOfItem(item, &itemIdx); |
|
425 if (itemIdx >= 0) |
|
426 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++) |
|
427 aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx; |
|
428 } |
|
429 } |
|
430 } |
|
431 |
|
432 void |
|
433 XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) |
|
434 { |
|
435 uint32_t selColCount = SelectedColCount(); |
|
436 aCols->SetCapacity(selColCount); |
|
437 |
|
438 for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++) |
|
439 aCols->AppendElement(colIdx); |
|
440 } |
|
441 |
|
442 void |
|
443 XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) |
|
444 { |
|
445 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
446 do_QueryInterface(mContent); |
|
447 NS_ASSERTION(control, |
|
448 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
449 |
|
450 nsCOMPtr<nsIDOMNodeList> selectedItems; |
|
451 control->GetSelectedItems(getter_AddRefs(selectedItems)); |
|
452 if (!selectedItems) |
|
453 return; |
|
454 |
|
455 uint32_t rowCount = 0; |
|
456 DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount); |
|
457 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); |
|
458 |
|
459 if (!rowCount) |
|
460 return; |
|
461 |
|
462 aRows->SetCapacity(rowCount); |
|
463 aRows->AppendElements(rowCount); |
|
464 |
|
465 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { |
|
466 nsCOMPtr<nsIDOMNode> itemNode; |
|
467 selectedItems->Item(rowIdx, getter_AddRefs(itemNode)); |
|
468 nsCOMPtr<nsIDOMXULSelectControlItemElement> item = |
|
469 do_QueryInterface(itemNode); |
|
470 |
|
471 if (item) { |
|
472 int32_t itemIdx = -1; |
|
473 control->GetIndexOfItem(item, &itemIdx); |
|
474 if (itemIdx >= 0) |
|
475 aRows->ElementAt(rowIdx) = itemIdx; |
|
476 } |
|
477 } |
|
478 } |
|
479 |
|
480 void |
|
481 XULListboxAccessible::SelectRow(uint32_t aRowIdx) |
|
482 { |
|
483 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
484 do_QueryInterface(mContent); |
|
485 NS_ASSERTION(control, |
|
486 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
487 |
|
488 nsCOMPtr<nsIDOMXULSelectControlItemElement> item; |
|
489 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); |
|
490 control->SelectItem(item); |
|
491 } |
|
492 |
|
493 void |
|
494 XULListboxAccessible::UnselectRow(uint32_t aRowIdx) |
|
495 { |
|
496 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = |
|
497 do_QueryInterface(mContent); |
|
498 NS_ASSERTION(control, |
|
499 "Doesn't implement nsIDOMXULMultiSelectControlElement."); |
|
500 |
|
501 nsCOMPtr<nsIDOMXULSelectControlItemElement> item; |
|
502 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); |
|
503 control->RemoveItemFromSelection(item); |
|
504 } |
|
505 |
|
506 //////////////////////////////////////////////////////////////////////////////// |
|
507 // XULListboxAccessible: Widgets |
|
508 |
|
509 bool |
|
510 XULListboxAccessible::IsWidget() const |
|
511 { |
|
512 return true; |
|
513 } |
|
514 |
|
515 bool |
|
516 XULListboxAccessible::IsActiveWidget() const |
|
517 { |
|
518 if (IsAutoCompletePopup()) { |
|
519 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
520 do_QueryInterface(mContent->GetParent()); |
|
521 |
|
522 if (autoCompletePopupElm) { |
|
523 bool isOpen = false; |
|
524 autoCompletePopupElm->GetPopupOpen(&isOpen); |
|
525 return isOpen; |
|
526 } |
|
527 } |
|
528 return FocusMgr()->HasDOMFocus(mContent); |
|
529 } |
|
530 |
|
531 bool |
|
532 XULListboxAccessible::AreItemsOperable() const |
|
533 { |
|
534 if (IsAutoCompletePopup()) { |
|
535 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
536 do_QueryInterface(mContent->GetParent()); |
|
537 |
|
538 if (autoCompletePopupElm) { |
|
539 bool isOpen = false; |
|
540 autoCompletePopupElm->GetPopupOpen(&isOpen); |
|
541 return isOpen; |
|
542 } |
|
543 } |
|
544 return true; |
|
545 } |
|
546 |
|
547 Accessible* |
|
548 XULListboxAccessible::ContainerWidget() const |
|
549 { |
|
550 if (IsAutoCompletePopup()) { |
|
551 // This works for XUL autocompletes. It doesn't work for HTML forms |
|
552 // autocomplete because of potential crossprocess calls (when autocomplete |
|
553 // lives in content process while popup lives in chrome process). If that's |
|
554 // a problem then rethink Widgets interface. |
|
555 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = |
|
556 do_QueryInterface(mContent->GetParent()); |
|
557 if (menuListElm) { |
|
558 nsCOMPtr<nsIDOMNode> inputElm; |
|
559 menuListElm->GetInputField(getter_AddRefs(inputElm)); |
|
560 if (inputElm) { |
|
561 nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm); |
|
562 if (inputNode) { |
|
563 Accessible* input = |
|
564 mDoc->GetAccessible(inputNode); |
|
565 return input ? input->ContainerWidget() : nullptr; |
|
566 } |
|
567 } |
|
568 } |
|
569 } |
|
570 return nullptr; |
|
571 } |
|
572 |
|
573 //////////////////////////////////////////////////////////////////////////////// |
|
574 // XULListitemAccessible |
|
575 //////////////////////////////////////////////////////////////////////////////// |
|
576 |
|
577 XULListitemAccessible:: |
|
578 XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
579 XULMenuitemAccessible(aContent, aDoc) |
|
580 { |
|
581 mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None, |
|
582 nsGkAtoms::type, |
|
583 nsGkAtoms::checkbox, |
|
584 eCaseMatters); |
|
585 mType = eXULListItemType; |
|
586 } |
|
587 |
|
588 NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible) |
|
589 |
|
590 Accessible* |
|
591 XULListitemAccessible::GetListAccessible() |
|
592 { |
|
593 if (IsDefunct()) |
|
594 return nullptr; |
|
595 |
|
596 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem = |
|
597 do_QueryInterface(mContent); |
|
598 if (!listItem) |
|
599 return nullptr; |
|
600 |
|
601 nsCOMPtr<nsIDOMXULSelectControlElement> list; |
|
602 listItem->GetControl(getter_AddRefs(list)); |
|
603 |
|
604 nsCOMPtr<nsIContent> listContent(do_QueryInterface(list)); |
|
605 if (!listContent) |
|
606 return nullptr; |
|
607 |
|
608 return mDoc->GetAccessible(listContent); |
|
609 } |
|
610 |
|
611 //////////////////////////////////////////////////////////////////////////////// |
|
612 // XULListitemAccessible Accessible |
|
613 |
|
614 void |
|
615 XULListitemAccessible::Description(nsString& aDesc) |
|
616 { |
|
617 AccessibleWrap::Description(aDesc); |
|
618 } |
|
619 |
|
620 //////////////////////////////////////////////////////////////////////////////// |
|
621 // XULListitemAccessible. nsIAccessible |
|
622 |
|
623 /** |
|
624 * If there is a Listcell as a child ( not anonymous ) use it, otherwise |
|
625 * default to getting the name from GetXULName |
|
626 */ |
|
627 ENameValueFlag |
|
628 XULListitemAccessible::NativeName(nsString& aName) |
|
629 { |
|
630 nsIContent* childContent = mContent->GetFirstChild(); |
|
631 if (childContent) { |
|
632 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell, |
|
633 kNameSpaceID_XUL)) { |
|
634 childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName); |
|
635 return eNameOK; |
|
636 } |
|
637 } |
|
638 |
|
639 return Accessible::NativeName(aName); |
|
640 } |
|
641 |
|
642 role |
|
643 XULListitemAccessible::NativeRole() |
|
644 { |
|
645 Accessible* list = GetListAccessible(); |
|
646 if (!list) { |
|
647 NS_ERROR("No list accessible for listitem accessible!"); |
|
648 return roles::NOTHING; |
|
649 } |
|
650 |
|
651 if (list->Role() == roles::TABLE) |
|
652 return roles::ROW; |
|
653 |
|
654 if (mIsCheckbox) |
|
655 return roles::CHECK_RICH_OPTION; |
|
656 |
|
657 if (mParent && mParent->Role() == roles::COMBOBOX_LIST) |
|
658 return roles::COMBOBOX_OPTION; |
|
659 |
|
660 return roles::RICH_OPTION; |
|
661 } |
|
662 |
|
663 uint64_t |
|
664 XULListitemAccessible::NativeState() |
|
665 { |
|
666 if (mIsCheckbox) |
|
667 return XULMenuitemAccessible::NativeState(); |
|
668 |
|
669 uint64_t states = NativeInteractiveState(); |
|
670 |
|
671 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem = |
|
672 do_QueryInterface(mContent); |
|
673 |
|
674 if (listItem) { |
|
675 bool isSelected; |
|
676 listItem->GetSelected(&isSelected); |
|
677 if (isSelected) |
|
678 states |= states::SELECTED; |
|
679 |
|
680 if (FocusMgr()->IsFocused(this)) |
|
681 states |= states::FOCUSED; |
|
682 } |
|
683 |
|
684 return states; |
|
685 } |
|
686 |
|
687 uint64_t |
|
688 XULListitemAccessible::NativeInteractiveState() const |
|
689 { |
|
690 return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ? |
|
691 states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE; |
|
692 } |
|
693 |
|
694 NS_IMETHODIMP |
|
695 XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) |
|
696 { |
|
697 if (aIndex == eAction_Click && mIsCheckbox) { |
|
698 // check or uncheck |
|
699 uint64_t states = NativeState(); |
|
700 |
|
701 if (states & states::CHECKED) |
|
702 aName.AssignLiteral("uncheck"); |
|
703 else |
|
704 aName.AssignLiteral("check"); |
|
705 |
|
706 return NS_OK; |
|
707 } |
|
708 return NS_ERROR_INVALID_ARG; |
|
709 } |
|
710 |
|
711 bool |
|
712 XULListitemAccessible::CanHaveAnonChildren() |
|
713 { |
|
714 // That indicates we should walk anonymous children for listitems |
|
715 return true; |
|
716 } |
|
717 |
|
718 //////////////////////////////////////////////////////////////////////////////// |
|
719 // XULListitemAccessible: Widgets |
|
720 |
|
721 Accessible* |
|
722 XULListitemAccessible::ContainerWidget() const |
|
723 { |
|
724 return Parent(); |
|
725 } |
|
726 |
|
727 |
|
728 //////////////////////////////////////////////////////////////////////////////// |
|
729 // XULListCellAccessible |
|
730 //////////////////////////////////////////////////////////////////////////////// |
|
731 |
|
732 XULListCellAccessible:: |
|
733 XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
734 HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this) |
|
735 { |
|
736 mGenericTypes |= eTableCell; |
|
737 } |
|
738 |
|
739 //////////////////////////////////////////////////////////////////////////////// |
|
740 // nsISupports |
|
741 |
|
742 NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible, |
|
743 HyperTextAccessible, |
|
744 nsIAccessibleTableCell) |
|
745 |
|
746 //////////////////////////////////////////////////////////////////////////////// |
|
747 // XULListCellAccessible: nsIAccessibleTableCell implementation |
|
748 |
|
749 TableAccessible* |
|
750 XULListCellAccessible::Table() const |
|
751 { |
|
752 Accessible* thisRow = Parent(); |
|
753 if (!thisRow || thisRow->Role() != roles::ROW) |
|
754 return nullptr; |
|
755 |
|
756 Accessible* table = thisRow->Parent(); |
|
757 if (!table || table->Role() != roles::TABLE) |
|
758 return nullptr; |
|
759 |
|
760 return table->AsTable(); |
|
761 } |
|
762 |
|
763 uint32_t |
|
764 XULListCellAccessible::ColIdx() const |
|
765 { |
|
766 Accessible* row = Parent(); |
|
767 if (!row) |
|
768 return 0; |
|
769 |
|
770 int32_t indexInRow = IndexInParent(); |
|
771 uint32_t colIdx = 0; |
|
772 for (int32_t idx = 0; idx < indexInRow; idx++) { |
|
773 Accessible* cell = row->GetChildAt(idx); |
|
774 roles::Role role = cell->Role(); |
|
775 if (role == roles::CELL || role == roles::GRID_CELL || |
|
776 role == roles::ROWHEADER || role == roles::COLUMNHEADER) |
|
777 colIdx++; |
|
778 } |
|
779 |
|
780 return colIdx; |
|
781 } |
|
782 |
|
783 uint32_t |
|
784 XULListCellAccessible::RowIdx() const |
|
785 { |
|
786 Accessible* row = Parent(); |
|
787 if (!row) |
|
788 return 0; |
|
789 |
|
790 Accessible* table = row->Parent(); |
|
791 if (!table) |
|
792 return 0; |
|
793 |
|
794 int32_t indexInTable = row->IndexInParent(); |
|
795 uint32_t rowIdx = 0; |
|
796 for (int32_t idx = 0; idx < indexInTable; idx++) { |
|
797 row = table->GetChildAt(idx); |
|
798 if (row->Role() == roles::ROW) |
|
799 rowIdx++; |
|
800 } |
|
801 |
|
802 return rowIdx; |
|
803 } |
|
804 |
|
805 void |
|
806 XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells) |
|
807 { |
|
808 TableAccessible* table = Table(); |
|
809 NS_ASSERTION(table, "cell not in a table!"); |
|
810 if (!table) |
|
811 return; |
|
812 |
|
813 // Get column header cell from XUL listhead. |
|
814 Accessible* list = nullptr; |
|
815 |
|
816 Accessible* tableAcc = table->AsAccessible(); |
|
817 uint32_t tableChildCount = tableAcc->ChildCount(); |
|
818 for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) { |
|
819 Accessible* child = tableAcc->GetChildAt(childIdx); |
|
820 if (child->Role() == roles::LIST) { |
|
821 list = child; |
|
822 break; |
|
823 } |
|
824 } |
|
825 |
|
826 if (list) { |
|
827 Accessible* headerCell = list->GetChildAt(ColIdx()); |
|
828 if (headerCell) { |
|
829 aCells->AppendElement(headerCell); |
|
830 return; |
|
831 } |
|
832 } |
|
833 |
|
834 // No column header cell from XUL markup, try to get it from ARIA markup. |
|
835 TableCellAccessible::ColHeaderCells(aCells); |
|
836 } |
|
837 |
|
838 bool |
|
839 XULListCellAccessible::Selected() |
|
840 { |
|
841 TableAccessible* table = Table(); |
|
842 NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table) |
|
843 |
|
844 return table->IsRowSelected(RowIdx()); |
|
845 } |
|
846 |
|
847 //////////////////////////////////////////////////////////////////////////////// |
|
848 // XULListCellAccessible. Accessible implementation |
|
849 |
|
850 void |
|
851 XULListCellAccessible::Shutdown() |
|
852 { |
|
853 mTableCell = nullptr; |
|
854 HyperTextAccessibleWrap::Shutdown(); |
|
855 } |
|
856 |
|
857 role |
|
858 XULListCellAccessible::NativeRole() |
|
859 { |
|
860 return roles::CELL; |
|
861 } |
|
862 |
|
863 already_AddRefed<nsIPersistentProperties> |
|
864 XULListCellAccessible::NativeAttributes() |
|
865 { |
|
866 nsCOMPtr<nsIPersistentProperties> attributes = |
|
867 HyperTextAccessibleWrap::NativeAttributes(); |
|
868 |
|
869 // "table-cell-index" attribute |
|
870 TableAccessible* table = Table(); |
|
871 if (!table) // we expect to be in a listbox (table) |
|
872 return attributes.forget(); |
|
873 |
|
874 nsAutoString stringIdx; |
|
875 stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx())); |
|
876 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx); |
|
877 |
|
878 return attributes.forget(); |
|
879 } |