Bumping manifests a=b2g-bump
[gecko.git] / accessible / xul / XULListboxAccessible.cpp
blobfcf359235e9a2a235d659a2990cba3c130c54b91
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/. */
6 #include "XULListboxAccessible.h"
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"
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"
26 using namespace mozilla::a11y;
28 ////////////////////////////////////////////////////////////////////////////////
29 // XULColumAccessible
30 ////////////////////////////////////////////////////////////////////////////////
32 XULColumAccessible::
33 XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
34 AccessibleWrap(aContent, aDoc)
38 role
39 XULColumAccessible::NativeRole()
41 return roles::LIST;
44 uint64_t
45 XULColumAccessible::NativeState()
47 return states::READONLY;
51 ////////////////////////////////////////////////////////////////////////////////
52 // XULColumnItemAccessible
53 ////////////////////////////////////////////////////////////////////////////////
55 XULColumnItemAccessible::
56 XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
57 LeafAccessible(aContent, aDoc)
61 role
62 XULColumnItemAccessible::NativeRole()
64 return roles::COLUMNHEADER;
67 uint64_t
68 XULColumnItemAccessible::NativeState()
70 return states::READONLY;
73 uint8_t
74 XULColumnItemAccessible::ActionCount()
76 return 1;
79 NS_IMETHODIMP
80 XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
82 if (aIndex != eAction_Click)
83 return NS_ERROR_INVALID_ARG;
85 aName.AssignLiteral("click");
86 return NS_OK;
89 NS_IMETHODIMP
90 XULColumnItemAccessible::DoAction(uint8_t aIndex)
92 if (aIndex != eAction_Click)
93 return NS_ERROR_INVALID_ARG;
95 DoCommand();
96 return NS_OK;
99 ////////////////////////////////////////////////////////////////////////////////
100 // XULListboxAccessible
101 ////////////////////////////////////////////////////////////////////////////////
103 XULListboxAccessible::
104 XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
105 XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
107 nsIContent* parentContent = mContent->GetFlattenedTreeParent();
108 if (parentContent) {
109 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
110 do_QueryInterface(parentContent);
111 if (autoCompletePopupElm)
112 mGenericTypes |= eAutoCompletePopup;
116 NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
117 NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
119 nsresult
120 XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
122 nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr);
123 if (*aInstancePtr)
124 return rv;
126 if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) {
127 *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
128 NS_ADDREF_THIS();
129 return NS_OK;
132 return NS_ERROR_NO_INTERFACE;
135 ////////////////////////////////////////////////////////////////////////////////
136 // Accessible
138 void
139 XULListboxAccessible::Shutdown()
141 mTable = nullptr;
142 XULSelectControlAccessible::Shutdown();
145 bool
146 XULListboxAccessible::IsMulticolumn()
148 int32_t numColumns = 0;
149 nsresult rv = GetColumnCount(&numColumns);
150 if (NS_FAILED(rv))
151 return false;
153 return numColumns > 1;
156 ////////////////////////////////////////////////////////////////////////////////
157 // XULListboxAccessible. nsIAccessible
159 uint64_t
160 XULListboxAccessible::NativeState()
162 // As a XULListboxAccessible we can have the following states:
163 // FOCUSED, READONLY, FOCUSABLE
165 // Get focus status from base class
166 uint64_t states = Accessible::NativeState();
168 // see if we are multiple select if so set ourselves as such
170 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
171 nsGkAtoms::multiple, eCaseMatters)) {
172 states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
175 return states;
179 * Our value is the label of our ( first ) selected child.
181 void
182 XULListboxAccessible::Value(nsString& aValue)
184 aValue.Truncate();
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);
195 role
196 XULListboxAccessible::NativeRole()
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;
205 return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
208 ////////////////////////////////////////////////////////////////////////////////
209 // XULListboxAccessible. nsIAccessibleTable
211 uint32_t
212 XULListboxAccessible::ColCount()
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;
222 if (!headContent)
223 return 0;
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++;
234 return columnCount;
237 uint32_t
238 XULListboxAccessible::RowCount()
240 nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
242 uint32_t itemCount = 0;
243 if(element)
244 element->GetItemCount(&itemCount);
246 return itemCount;
249 Accessible*
250 XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
252 nsCOMPtr<nsIDOMXULSelectControlElement> control =
253 do_QueryInterface(mContent);
254 NS_ENSURE_TRUE(control, nullptr);
256 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
257 control->GetItemAtIndex(aRowIndex, getter_AddRefs(item));
258 if (!item)
259 return nullptr;
261 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item));
262 if (!itemContent)
263 return nullptr;
265 Accessible* row = mDoc->GetAccessible(itemContent);
266 NS_ENSURE_TRUE(row, nullptr);
268 return row->GetChildAt(aColumnIndex);
271 bool
272 XULListboxAccessible::IsColSelected(uint32_t aColIdx)
274 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
275 do_QueryInterface(mContent);
276 NS_ASSERTION(control,
277 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
279 int32_t selectedrowCount = 0;
280 nsresult rv = control->GetSelectedCount(&selectedrowCount);
281 NS_ENSURE_SUCCESS(rv, false);
283 return selectedrowCount == static_cast<int32_t>(RowCount());
286 bool
287 XULListboxAccessible::IsRowSelected(uint32_t aRowIdx)
289 nsCOMPtr<nsIDOMXULSelectControlElement> control =
290 do_QueryInterface(mContent);
291 NS_ASSERTION(control,
292 "Doesn't implement nsIDOMXULSelectControlElement.");
294 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
295 nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
296 NS_ENSURE_SUCCESS(rv, false);
298 bool isSelected = false;
299 item->GetSelected(&isSelected);
300 return isSelected;
303 bool
304 XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
306 return IsRowSelected(aRowIdx);
309 uint32_t
310 XULListboxAccessible::SelectedCellCount()
312 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
313 do_QueryInterface(mContent);
314 NS_ASSERTION(control,
315 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
317 nsCOMPtr<nsIDOMNodeList> selectedItems;
318 control->GetSelectedItems(getter_AddRefs(selectedItems));
319 if (!selectedItems)
320 return 0;
322 uint32_t selectedItemsCount = 0;
323 nsresult rv = selectedItems->GetLength(&selectedItemsCount);
324 NS_ENSURE_SUCCESS(rv, 0);
326 return selectedItemsCount * ColCount();
329 uint32_t
330 XULListboxAccessible::SelectedColCount()
332 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
333 do_QueryInterface(mContent);
334 NS_ASSERTION(control,
335 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
337 int32_t selectedRowCount = 0;
338 nsresult rv = control->GetSelectedCount(&selectedRowCount);
339 NS_ENSURE_SUCCESS(rv, 0);
341 return selectedRowCount > 0 &&
342 selectedRowCount == static_cast<int32_t>(RowCount()) ? ColCount() : 0;
345 uint32_t
346 XULListboxAccessible::SelectedRowCount()
348 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
349 do_QueryInterface(mContent);
350 NS_ASSERTION(control,
351 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
353 int32_t selectedRowCount = 0;
354 nsresult rv = control->GetSelectedCount(&selectedRowCount);
355 NS_ENSURE_SUCCESS(rv, 0);
357 return selectedRowCount >= 0 ? selectedRowCount : 0;
360 void
361 XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
363 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
364 do_QueryInterface(mContent);
365 NS_ASSERTION(control,
366 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
368 nsCOMPtr<nsIDOMNodeList> selectedItems;
369 control->GetSelectedItems(getter_AddRefs(selectedItems));
370 if (!selectedItems)
371 return;
373 uint32_t selectedItemsCount = 0;
374 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
375 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
377 for (uint32_t index = 0; index < selectedItemsCount; index++) {
378 nsCOMPtr<nsIDOMNode> itemNode;
379 selectedItems->Item(index, getter_AddRefs(itemNode));
380 nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
381 Accessible* item = mDoc->GetAccessible(itemContent);
383 if (item) {
384 uint32_t cellCount = item->ChildCount();
385 for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) {
386 Accessible* cell = mChildren[cellIdx];
387 if (cell->Role() == roles::CELL)
388 aCells->AppendElement(cell);
394 void
395 XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
397 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
398 do_QueryInterface(mContent);
399 NS_ASSERTION(control,
400 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
402 nsCOMPtr<nsIDOMNodeList> selectedItems;
403 control->GetSelectedItems(getter_AddRefs(selectedItems));
404 if (!selectedItems)
405 return;
407 uint32_t selectedItemsCount = 0;
408 DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
409 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
411 uint32_t colCount = ColCount();
412 aCells->SetCapacity(selectedItemsCount * colCount);
413 aCells->AppendElements(selectedItemsCount * colCount);
415 for (uint32_t selItemsIdx = 0, cellsIdx = 0;
416 selItemsIdx < selectedItemsCount; selItemsIdx++) {
418 nsCOMPtr<nsIDOMNode> itemNode;
419 selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode));
420 nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
421 do_QueryInterface(itemNode);
423 if (item) {
424 int32_t itemIdx = -1;
425 control->GetIndexOfItem(item, &itemIdx);
426 if (itemIdx >= 0)
427 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
428 aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
433 void
434 XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
436 uint32_t selColCount = SelectedColCount();
437 aCols->SetCapacity(selColCount);
439 for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
440 aCols->AppendElement(colIdx);
443 void
444 XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
446 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
447 do_QueryInterface(mContent);
448 NS_ASSERTION(control,
449 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
451 nsCOMPtr<nsIDOMNodeList> selectedItems;
452 control->GetSelectedItems(getter_AddRefs(selectedItems));
453 if (!selectedItems)
454 return;
456 uint32_t rowCount = 0;
457 DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount);
458 NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
460 if (!rowCount)
461 return;
463 aRows->SetCapacity(rowCount);
464 aRows->AppendElements(rowCount);
466 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
467 nsCOMPtr<nsIDOMNode> itemNode;
468 selectedItems->Item(rowIdx, getter_AddRefs(itemNode));
469 nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
470 do_QueryInterface(itemNode);
472 if (item) {
473 int32_t itemIdx = -1;
474 control->GetIndexOfItem(item, &itemIdx);
475 if (itemIdx >= 0)
476 aRows->ElementAt(rowIdx) = itemIdx;
481 void
482 XULListboxAccessible::SelectRow(uint32_t aRowIdx)
484 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
485 do_QueryInterface(mContent);
486 NS_ASSERTION(control,
487 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
489 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
490 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
491 control->SelectItem(item);
494 void
495 XULListboxAccessible::UnselectRow(uint32_t aRowIdx)
497 nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
498 do_QueryInterface(mContent);
499 NS_ASSERTION(control,
500 "Doesn't implement nsIDOMXULMultiSelectControlElement.");
502 nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
503 control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
504 control->RemoveItemFromSelection(item);
507 ////////////////////////////////////////////////////////////////////////////////
508 // XULListboxAccessible: Widgets
510 bool
511 XULListboxAccessible::IsWidget() const
513 return true;
516 bool
517 XULListboxAccessible::IsActiveWidget() const
519 if (IsAutoCompletePopup()) {
520 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
521 do_QueryInterface(mContent->GetParent());
523 if (autoCompletePopupElm) {
524 bool isOpen = false;
525 autoCompletePopupElm->GetPopupOpen(&isOpen);
526 return isOpen;
529 return FocusMgr()->HasDOMFocus(mContent);
532 bool
533 XULListboxAccessible::AreItemsOperable() const
535 if (IsAutoCompletePopup()) {
536 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
537 do_QueryInterface(mContent->GetParent());
539 if (autoCompletePopupElm) {
540 bool isOpen = false;
541 autoCompletePopupElm->GetPopupOpen(&isOpen);
542 return isOpen;
545 return true;
548 Accessible*
549 XULListboxAccessible::ContainerWidget() const
551 if (IsAutoCompletePopup()) {
552 // This works for XUL autocompletes. It doesn't work for HTML forms
553 // autocomplete because of potential crossprocess calls (when autocomplete
554 // lives in content process while popup lives in chrome process). If that's
555 // a problem then rethink Widgets interface.
556 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
557 do_QueryInterface(mContent->GetParent());
558 if (menuListElm) {
559 nsCOMPtr<nsIDOMNode> inputElm;
560 menuListElm->GetInputField(getter_AddRefs(inputElm));
561 if (inputElm) {
562 nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
563 if (inputNode) {
564 Accessible* input =
565 mDoc->GetAccessible(inputNode);
566 return input ? input->ContainerWidget() : nullptr;
571 return nullptr;
574 ////////////////////////////////////////////////////////////////////////////////
575 // XULListitemAccessible
576 ////////////////////////////////////////////////////////////////////////////////
578 XULListitemAccessible::
579 XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
580 XULMenuitemAccessible(aContent, aDoc)
582 mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
583 nsGkAtoms::type,
584 nsGkAtoms::checkbox,
585 eCaseMatters);
586 mType = eXULListItemType;
589 XULListitemAccessible::~XULListitemAccessible()
593 NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)
595 Accessible*
596 XULListitemAccessible::GetListAccessible()
598 if (IsDefunct())
599 return nullptr;
601 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
602 do_QueryInterface(mContent);
603 if (!listItem)
604 return nullptr;
606 nsCOMPtr<nsIDOMXULSelectControlElement> list;
607 listItem->GetControl(getter_AddRefs(list));
609 nsCOMPtr<nsIContent> listContent(do_QueryInterface(list));
610 if (!listContent)
611 return nullptr;
613 return mDoc->GetAccessible(listContent);
616 ////////////////////////////////////////////////////////////////////////////////
617 // XULListitemAccessible Accessible
619 void
620 XULListitemAccessible::Description(nsString& aDesc)
622 AccessibleWrap::Description(aDesc);
625 ////////////////////////////////////////////////////////////////////////////////
626 // XULListitemAccessible. nsIAccessible
629 * If there is a Listcell as a child ( not anonymous ) use it, otherwise
630 * default to getting the name from GetXULName
632 ENameValueFlag
633 XULListitemAccessible::NativeName(nsString& aName)
635 nsIContent* childContent = mContent->GetFirstChild();
636 if (childContent) {
637 if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
638 kNameSpaceID_XUL)) {
639 childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
640 return eNameOK;
644 return Accessible::NativeName(aName);
647 role
648 XULListitemAccessible::NativeRole()
650 Accessible* list = GetListAccessible();
651 if (!list) {
652 NS_ERROR("No list accessible for listitem accessible!");
653 return roles::NOTHING;
656 if (list->Role() == roles::TABLE)
657 return roles::ROW;
659 if (mIsCheckbox)
660 return roles::CHECK_RICH_OPTION;
662 if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
663 return roles::COMBOBOX_OPTION;
665 return roles::RICH_OPTION;
668 uint64_t
669 XULListitemAccessible::NativeState()
671 if (mIsCheckbox)
672 return XULMenuitemAccessible::NativeState();
674 uint64_t states = NativeInteractiveState();
676 nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
677 do_QueryInterface(mContent);
679 if (listItem) {
680 bool isSelected;
681 listItem->GetSelected(&isSelected);
682 if (isSelected)
683 states |= states::SELECTED;
685 if (FocusMgr()->IsFocused(this))
686 states |= states::FOCUSED;
689 return states;
692 uint64_t
693 XULListitemAccessible::NativeInteractiveState() const
695 return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
696 states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
699 NS_IMETHODIMP
700 XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
702 if (aIndex == eAction_Click && mIsCheckbox) {
703 // check or uncheck
704 uint64_t states = NativeState();
706 if (states & states::CHECKED)
707 aName.AssignLiteral("uncheck");
708 else
709 aName.AssignLiteral("check");
711 return NS_OK;
713 return NS_ERROR_INVALID_ARG;
716 bool
717 XULListitemAccessible::CanHaveAnonChildren()
719 // That indicates we should walk anonymous children for listitems
720 return true;
723 ////////////////////////////////////////////////////////////////////////////////
724 // XULListitemAccessible: Widgets
726 Accessible*
727 XULListitemAccessible::ContainerWidget() const
729 return Parent();
733 ////////////////////////////////////////////////////////////////////////////////
734 // XULListCellAccessible
735 ////////////////////////////////////////////////////////////////////////////////
737 XULListCellAccessible::
738 XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
739 HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
741 mGenericTypes |= eTableCell;
744 ////////////////////////////////////////////////////////////////////////////////
745 // nsISupports
747 NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible,
748 HyperTextAccessible,
749 nsIAccessibleTableCell)
751 ////////////////////////////////////////////////////////////////////////////////
752 // XULListCellAccessible: nsIAccessibleTableCell implementation
754 TableAccessible*
755 XULListCellAccessible::Table() const
757 Accessible* thisRow = Parent();
758 if (!thisRow || thisRow->Role() != roles::ROW)
759 return nullptr;
761 Accessible* table = thisRow->Parent();
762 if (!table || table->Role() != roles::TABLE)
763 return nullptr;
765 return table->AsTable();
768 uint32_t
769 XULListCellAccessible::ColIdx() const
771 Accessible* row = Parent();
772 if (!row)
773 return 0;
775 int32_t indexInRow = IndexInParent();
776 uint32_t colIdx = 0;
777 for (int32_t idx = 0; idx < indexInRow; idx++) {
778 Accessible* cell = row->GetChildAt(idx);
779 roles::Role role = cell->Role();
780 if (role == roles::CELL || role == roles::GRID_CELL ||
781 role == roles::ROWHEADER || role == roles::COLUMNHEADER)
782 colIdx++;
785 return colIdx;
788 uint32_t
789 XULListCellAccessible::RowIdx() const
791 Accessible* row = Parent();
792 if (!row)
793 return 0;
795 Accessible* table = row->Parent();
796 if (!table)
797 return 0;
799 int32_t indexInTable = row->IndexInParent();
800 uint32_t rowIdx = 0;
801 for (int32_t idx = 0; idx < indexInTable; idx++) {
802 row = table->GetChildAt(idx);
803 if (row->Role() == roles::ROW)
804 rowIdx++;
807 return rowIdx;
810 void
811 XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells)
813 TableAccessible* table = Table();
814 NS_ASSERTION(table, "cell not in a table!");
815 if (!table)
816 return;
818 // Get column header cell from XUL listhead.
819 Accessible* list = nullptr;
821 Accessible* tableAcc = table->AsAccessible();
822 uint32_t tableChildCount = tableAcc->ChildCount();
823 for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) {
824 Accessible* child = tableAcc->GetChildAt(childIdx);
825 if (child->Role() == roles::LIST) {
826 list = child;
827 break;
831 if (list) {
832 Accessible* headerCell = list->GetChildAt(ColIdx());
833 if (headerCell) {
834 aCells->AppendElement(headerCell);
835 return;
839 // No column header cell from XUL markup, try to get it from ARIA markup.
840 TableCellAccessible::ColHeaderCells(aCells);
843 bool
844 XULListCellAccessible::Selected()
846 TableAccessible* table = Table();
847 NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table)
849 return table->IsRowSelected(RowIdx());
852 ////////////////////////////////////////////////////////////////////////////////
853 // XULListCellAccessible. Accessible implementation
855 void
856 XULListCellAccessible::Shutdown()
858 mTableCell = nullptr;
859 HyperTextAccessibleWrap::Shutdown();
862 role
863 XULListCellAccessible::NativeRole()
865 return roles::CELL;
868 already_AddRefed<nsIPersistentProperties>
869 XULListCellAccessible::NativeAttributes()
871 nsCOMPtr<nsIPersistentProperties> attributes =
872 HyperTextAccessibleWrap::NativeAttributes();
874 // "table-cell-index" attribute
875 TableAccessible* table = Table();
876 if (!table) // we expect to be in a listbox (table)
877 return attributes.forget();
879 nsAutoString stringIdx;
880 stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
881 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
883 return attributes.forget();