accessible/src/xul/XULListboxAccessible.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:e27d88996630
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 }

mercurial