michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "XULListboxAccessible.h" michael@0: michael@0: #include "Accessible-inl.h" michael@0: #include "nsAccessibilityService.h" michael@0: #include "nsAccUtils.h" michael@0: #include "DocAccessible.h" michael@0: #include "Role.h" michael@0: #include "States.h" michael@0: michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsIAutoCompleteInput.h" michael@0: #include "nsIAutoCompletePopup.h" michael@0: #include "nsIDOMXULMenuListElement.h" michael@0: #include "nsIDOMXULMultSelectCntrlEl.h" michael@0: #include "nsIDOMNodeList.h" michael@0: #include "nsIDOMXULPopupElement.h" michael@0: #include "nsIDOMXULSelectCntrlItemEl.h" michael@0: #include "nsIMutableArray.h" michael@0: #include "nsIPersistentProperties2.h" michael@0: michael@0: using namespace mozilla::a11y; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULColumAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULColumAccessible:: michael@0: XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: AccessibleWrap(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: role michael@0: XULColumAccessible::NativeRole() michael@0: { michael@0: return roles::LIST; michael@0: } michael@0: michael@0: uint64_t michael@0: XULColumAccessible::NativeState() michael@0: { michael@0: return states::READONLY; michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULColumnItemAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULColumnItemAccessible:: michael@0: XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: LeafAccessible(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: role michael@0: XULColumnItemAccessible::NativeRole() michael@0: { michael@0: return roles::COLUMNHEADER; michael@0: } michael@0: michael@0: uint64_t michael@0: XULColumnItemAccessible::NativeState() michael@0: { michael@0: return states::READONLY; michael@0: } michael@0: michael@0: uint8_t michael@0: XULColumnItemAccessible::ActionCount() michael@0: { michael@0: return 1; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) michael@0: { michael@0: if (aIndex != eAction_Click) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: aName.AssignLiteral("click"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: XULColumnItemAccessible::DoAction(uint8_t aIndex) michael@0: { michael@0: if (aIndex != eAction_Click) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: DoCommand(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListboxAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULListboxAccessible:: michael@0: XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) michael@0: { michael@0: nsIContent* parentContent = mContent->GetFlattenedTreeParent(); michael@0: if (parentContent) { michael@0: nsCOMPtr autoCompletePopupElm = michael@0: do_QueryInterface(parentContent); michael@0: if (autoCompletePopupElm) michael@0: mGenericTypes |= eAutoCompletePopup; michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible) michael@0: NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible) michael@0: michael@0: nsresult michael@0: XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) michael@0: { michael@0: nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr); michael@0: if (*aInstancePtr) michael@0: return rv; michael@0: michael@0: if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) { michael@0: *aInstancePtr = static_cast(this); michael@0: NS_ADDREF_THIS(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_ERROR_NO_INTERFACE; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // Accessible michael@0: michael@0: void michael@0: XULListboxAccessible::Shutdown() michael@0: { michael@0: mTable = nullptr; michael@0: XULSelectControlAccessible::Shutdown(); michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::IsMulticolumn() michael@0: { michael@0: int32_t numColumns = 0; michael@0: nsresult rv = GetColumnCount(&numColumns); michael@0: if (NS_FAILED(rv)) michael@0: return false; michael@0: michael@0: return numColumns > 1; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListboxAccessible. nsIAccessible michael@0: michael@0: uint64_t michael@0: XULListboxAccessible::NativeState() michael@0: { michael@0: // As a XULListboxAccessible we can have the following states: michael@0: // FOCUSED, READONLY, FOCUSABLE michael@0: michael@0: // Get focus status from base class michael@0: uint64_t states = Accessible::NativeState(); michael@0: michael@0: // see if we are multiple select if so set ourselves as such michael@0: michael@0: if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype, michael@0: nsGkAtoms::multiple, eCaseMatters)) { michael@0: states |= states::MULTISELECTABLE | states::EXTSELECTABLE; michael@0: } michael@0: michael@0: return states; michael@0: } michael@0: michael@0: /** michael@0: * Our value is the label of our ( first ) selected child. michael@0: */ michael@0: void michael@0: XULListboxAccessible::Value(nsString& aValue) michael@0: { michael@0: aValue.Truncate(); michael@0: michael@0: nsCOMPtr select(do_QueryInterface(mContent)); michael@0: if (select) { michael@0: nsCOMPtr selectedItem; michael@0: select->GetSelectedItem(getter_AddRefs(selectedItem)); michael@0: if (selectedItem) michael@0: selectedItem->GetLabel(aValue); michael@0: } michael@0: } michael@0: michael@0: role michael@0: XULListboxAccessible::NativeRole() michael@0: { michael@0: // A richlistbox is used with the new autocomplete URL bar, and has a parent michael@0: // popup . michael@0: nsCOMPtr xulPopup = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: if (xulPopup) michael@0: return roles::COMBOBOX_LIST; michael@0: michael@0: return IsMulticolumn() ? roles::TABLE : roles::LISTBOX; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListboxAccessible. nsIAccessibleTable michael@0: michael@0: uint32_t michael@0: XULListboxAccessible::ColCount() michael@0: { michael@0: nsIContent* headContent = nullptr; michael@0: for (nsIContent* childContent = mContent->GetFirstChild(); childContent; michael@0: childContent = childContent->GetNextSibling()) { michael@0: if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols, michael@0: kNameSpaceID_XUL)) { michael@0: headContent = childContent; michael@0: } michael@0: } michael@0: if (!headContent) michael@0: return 0; michael@0: michael@0: uint32_t columnCount = 0; michael@0: for (nsIContent* childContent = headContent->GetFirstChild(); childContent; michael@0: childContent = childContent->GetNextSibling()) { michael@0: if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol, michael@0: kNameSpaceID_XUL)) { michael@0: columnCount++; michael@0: } michael@0: } michael@0: michael@0: return columnCount; michael@0: } michael@0: michael@0: uint32_t michael@0: XULListboxAccessible::RowCount() michael@0: { michael@0: nsCOMPtr element(do_QueryInterface(mContent)); michael@0: michael@0: uint32_t itemCount = 0; michael@0: if(element) michael@0: element->GetItemCount(&itemCount); michael@0: michael@0: return itemCount; michael@0: } michael@0: michael@0: Accessible* michael@0: XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ENSURE_TRUE(control, nullptr); michael@0: michael@0: nsCOMPtr item; michael@0: control->GetItemAtIndex(aRowIndex, getter_AddRefs(item)); michael@0: if (!item) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr itemContent(do_QueryInterface(item)); michael@0: if (!itemContent) michael@0: return nullptr; michael@0: michael@0: Accessible* row = mDoc->GetAccessible(itemContent); michael@0: NS_ENSURE_TRUE(row, nullptr); michael@0: michael@0: return row->GetChildAt(aColumnIndex); michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::IsColSelected(uint32_t aColIdx) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: int32_t selectedrowCount = 0; michael@0: nsresult rv = control->GetSelectedCount(&selectedrowCount); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: return selectedrowCount == RowCount(); michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::IsRowSelected(uint32_t aRowIdx) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULSelectControlElement."); michael@0: michael@0: nsCOMPtr item; michael@0: nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: bool isSelected = false; michael@0: item->GetSelected(&isSelected); michael@0: return isSelected; michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) michael@0: { michael@0: return IsRowSelected(aRowIdx); michael@0: } michael@0: michael@0: uint32_t michael@0: XULListboxAccessible::SelectedCellCount() michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr selectedItems; michael@0: control->GetSelectedItems(getter_AddRefs(selectedItems)); michael@0: if (!selectedItems) michael@0: return 0; michael@0: michael@0: uint32_t selectedItemsCount = 0; michael@0: nsresult rv = selectedItems->GetLength(&selectedItemsCount); michael@0: NS_ENSURE_SUCCESS(rv, 0); michael@0: michael@0: return selectedItemsCount * ColCount(); michael@0: } michael@0: michael@0: uint32_t michael@0: XULListboxAccessible::SelectedColCount() michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: int32_t selectedRowCount = 0; michael@0: nsresult rv = control->GetSelectedCount(&selectedRowCount); michael@0: NS_ENSURE_SUCCESS(rv, 0); michael@0: michael@0: return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0; michael@0: } michael@0: michael@0: uint32_t michael@0: XULListboxAccessible::SelectedRowCount() michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: int32_t selectedRowCount = 0; michael@0: nsresult rv = control->GetSelectedCount(&selectedRowCount); michael@0: NS_ENSURE_SUCCESS(rv, 0); michael@0: michael@0: return selectedRowCount >= 0 ? selectedRowCount : 0; michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::SelectedCells(nsTArray* aCells) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr selectedItems; michael@0: control->GetSelectedItems(getter_AddRefs(selectedItems)); michael@0: if (!selectedItems) michael@0: return; michael@0: michael@0: uint32_t selectedItemsCount = 0; michael@0: DebugOnly rv = selectedItems->GetLength(&selectedItemsCount); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); michael@0: michael@0: for (uint32_t index = 0; index < selectedItemsCount; index++) { michael@0: nsCOMPtr itemNode; michael@0: selectedItems->Item(index, getter_AddRefs(itemNode)); michael@0: nsCOMPtr itemContent(do_QueryInterface(itemNode)); michael@0: Accessible* item = mDoc->GetAccessible(itemContent); michael@0: michael@0: if (item) { michael@0: uint32_t cellCount = item->ChildCount(); michael@0: for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) { michael@0: Accessible* cell = mChildren[cellIdx]; michael@0: if (cell->Role() == roles::CELL) michael@0: aCells->AppendElement(cell); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::SelectedCellIndices(nsTArray* aCells) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr selectedItems; michael@0: control->GetSelectedItems(getter_AddRefs(selectedItems)); michael@0: if (!selectedItems) michael@0: return; michael@0: michael@0: uint32_t selectedItemsCount = 0; michael@0: DebugOnly rv = selectedItems->GetLength(&selectedItemsCount); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); michael@0: michael@0: uint32_t colCount = ColCount(); michael@0: aCells->SetCapacity(selectedItemsCount * colCount); michael@0: aCells->AppendElements(selectedItemsCount * colCount); michael@0: michael@0: for (uint32_t selItemsIdx = 0, cellsIdx = 0; michael@0: selItemsIdx < selectedItemsCount; selItemsIdx++) { michael@0: michael@0: nsCOMPtr itemNode; michael@0: selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode)); michael@0: nsCOMPtr item = michael@0: do_QueryInterface(itemNode); michael@0: michael@0: if (item) { michael@0: int32_t itemIdx = -1; michael@0: control->GetIndexOfItem(item, &itemIdx); michael@0: if (itemIdx >= 0) michael@0: for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++) michael@0: aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx; michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::SelectedColIndices(nsTArray* aCols) michael@0: { michael@0: uint32_t selColCount = SelectedColCount(); michael@0: aCols->SetCapacity(selColCount); michael@0: michael@0: for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++) michael@0: aCols->AppendElement(colIdx); michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::SelectedRowIndices(nsTArray* aRows) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr selectedItems; michael@0: control->GetSelectedItems(getter_AddRefs(selectedItems)); michael@0: if (!selectedItems) michael@0: return; michael@0: michael@0: uint32_t rowCount = 0; michael@0: DebugOnly rv = selectedItems->GetLength(&rowCount); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); michael@0: michael@0: if (!rowCount) michael@0: return; michael@0: michael@0: aRows->SetCapacity(rowCount); michael@0: aRows->AppendElements(rowCount); michael@0: michael@0: for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { michael@0: nsCOMPtr itemNode; michael@0: selectedItems->Item(rowIdx, getter_AddRefs(itemNode)); michael@0: nsCOMPtr item = michael@0: do_QueryInterface(itemNode); michael@0: michael@0: if (item) { michael@0: int32_t itemIdx = -1; michael@0: control->GetIndexOfItem(item, &itemIdx); michael@0: if (itemIdx >= 0) michael@0: aRows->ElementAt(rowIdx) = itemIdx; michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::SelectRow(uint32_t aRowIdx) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr item; michael@0: control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); michael@0: control->SelectItem(item); michael@0: } michael@0: michael@0: void michael@0: XULListboxAccessible::UnselectRow(uint32_t aRowIdx) michael@0: { michael@0: nsCOMPtr control = michael@0: do_QueryInterface(mContent); michael@0: NS_ASSERTION(control, michael@0: "Doesn't implement nsIDOMXULMultiSelectControlElement."); michael@0: michael@0: nsCOMPtr item; michael@0: control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); michael@0: control->RemoveItemFromSelection(item); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListboxAccessible: Widgets michael@0: michael@0: bool michael@0: XULListboxAccessible::IsWidget() const michael@0: { michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::IsActiveWidget() const michael@0: { michael@0: if (IsAutoCompletePopup()) { michael@0: nsCOMPtr autoCompletePopupElm = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: michael@0: if (autoCompletePopupElm) { michael@0: bool isOpen = false; michael@0: autoCompletePopupElm->GetPopupOpen(&isOpen); michael@0: return isOpen; michael@0: } michael@0: } michael@0: return FocusMgr()->HasDOMFocus(mContent); michael@0: } michael@0: michael@0: bool michael@0: XULListboxAccessible::AreItemsOperable() const michael@0: { michael@0: if (IsAutoCompletePopup()) { michael@0: nsCOMPtr autoCompletePopupElm = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: michael@0: if (autoCompletePopupElm) { michael@0: bool isOpen = false; michael@0: autoCompletePopupElm->GetPopupOpen(&isOpen); michael@0: return isOpen; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: Accessible* michael@0: XULListboxAccessible::ContainerWidget() const michael@0: { michael@0: if (IsAutoCompletePopup()) { michael@0: // This works for XUL autocompletes. It doesn't work for HTML forms michael@0: // autocomplete because of potential crossprocess calls (when autocomplete michael@0: // lives in content process while popup lives in chrome process). If that's michael@0: // a problem then rethink Widgets interface. michael@0: nsCOMPtr menuListElm = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: if (menuListElm) { michael@0: nsCOMPtr inputElm; michael@0: menuListElm->GetInputField(getter_AddRefs(inputElm)); michael@0: if (inputElm) { michael@0: nsCOMPtr inputNode = do_QueryInterface(inputElm); michael@0: if (inputNode) { michael@0: Accessible* input = michael@0: mDoc->GetAccessible(inputNode); michael@0: return input ? input->ContainerWidget() : nullptr; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListitemAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULListitemAccessible:: michael@0: XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: XULMenuitemAccessible(aContent, aDoc) michael@0: { michael@0: mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None, michael@0: nsGkAtoms::type, michael@0: nsGkAtoms::checkbox, michael@0: eCaseMatters); michael@0: mType = eXULListItemType; michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible) michael@0: michael@0: Accessible* michael@0: XULListitemAccessible::GetListAccessible() michael@0: { michael@0: if (IsDefunct()) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr listItem = michael@0: do_QueryInterface(mContent); michael@0: if (!listItem) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr list; michael@0: listItem->GetControl(getter_AddRefs(list)); michael@0: michael@0: nsCOMPtr listContent(do_QueryInterface(list)); michael@0: if (!listContent) michael@0: return nullptr; michael@0: michael@0: return mDoc->GetAccessible(listContent); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListitemAccessible Accessible michael@0: michael@0: void michael@0: XULListitemAccessible::Description(nsString& aDesc) michael@0: { michael@0: AccessibleWrap::Description(aDesc); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListitemAccessible. nsIAccessible michael@0: michael@0: /** michael@0: * If there is a Listcell as a child ( not anonymous ) use it, otherwise michael@0: * default to getting the name from GetXULName michael@0: */ michael@0: ENameValueFlag michael@0: XULListitemAccessible::NativeName(nsString& aName) michael@0: { michael@0: nsIContent* childContent = mContent->GetFirstChild(); michael@0: if (childContent) { michael@0: if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell, michael@0: kNameSpaceID_XUL)) { michael@0: childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName); michael@0: return eNameOK; michael@0: } michael@0: } michael@0: michael@0: return Accessible::NativeName(aName); michael@0: } michael@0: michael@0: role michael@0: XULListitemAccessible::NativeRole() michael@0: { michael@0: Accessible* list = GetListAccessible(); michael@0: if (!list) { michael@0: NS_ERROR("No list accessible for listitem accessible!"); michael@0: return roles::NOTHING; michael@0: } michael@0: michael@0: if (list->Role() == roles::TABLE) michael@0: return roles::ROW; michael@0: michael@0: if (mIsCheckbox) michael@0: return roles::CHECK_RICH_OPTION; michael@0: michael@0: if (mParent && mParent->Role() == roles::COMBOBOX_LIST) michael@0: return roles::COMBOBOX_OPTION; michael@0: michael@0: return roles::RICH_OPTION; michael@0: } michael@0: michael@0: uint64_t michael@0: XULListitemAccessible::NativeState() michael@0: { michael@0: if (mIsCheckbox) michael@0: return XULMenuitemAccessible::NativeState(); michael@0: michael@0: uint64_t states = NativeInteractiveState(); michael@0: michael@0: nsCOMPtr listItem = michael@0: do_QueryInterface(mContent); michael@0: michael@0: if (listItem) { michael@0: bool isSelected; michael@0: listItem->GetSelected(&isSelected); michael@0: if (isSelected) michael@0: states |= states::SELECTED; michael@0: michael@0: if (FocusMgr()->IsFocused(this)) michael@0: states |= states::FOCUSED; michael@0: } michael@0: michael@0: return states; michael@0: } michael@0: michael@0: uint64_t michael@0: XULListitemAccessible::NativeInteractiveState() const michael@0: { michael@0: return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ? michael@0: states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) michael@0: { michael@0: if (aIndex == eAction_Click && mIsCheckbox) { michael@0: // check or uncheck michael@0: uint64_t states = NativeState(); michael@0: michael@0: if (states & states::CHECKED) michael@0: aName.AssignLiteral("uncheck"); michael@0: else michael@0: aName.AssignLiteral("check"); michael@0: michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: bool michael@0: XULListitemAccessible::CanHaveAnonChildren() michael@0: { michael@0: // That indicates we should walk anonymous children for listitems michael@0: return true; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListitemAccessible: Widgets michael@0: michael@0: Accessible* michael@0: XULListitemAccessible::ContainerWidget() const michael@0: { michael@0: return Parent(); michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListCellAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULListCellAccessible:: michael@0: XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this) michael@0: { michael@0: mGenericTypes |= eTableCell; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // nsISupports michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible, michael@0: HyperTextAccessible, michael@0: nsIAccessibleTableCell) michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListCellAccessible: nsIAccessibleTableCell implementation michael@0: michael@0: TableAccessible* michael@0: XULListCellAccessible::Table() const michael@0: { michael@0: Accessible* thisRow = Parent(); michael@0: if (!thisRow || thisRow->Role() != roles::ROW) michael@0: return nullptr; michael@0: michael@0: Accessible* table = thisRow->Parent(); michael@0: if (!table || table->Role() != roles::TABLE) michael@0: return nullptr; michael@0: michael@0: return table->AsTable(); michael@0: } michael@0: michael@0: uint32_t michael@0: XULListCellAccessible::ColIdx() const michael@0: { michael@0: Accessible* row = Parent(); michael@0: if (!row) michael@0: return 0; michael@0: michael@0: int32_t indexInRow = IndexInParent(); michael@0: uint32_t colIdx = 0; michael@0: for (int32_t idx = 0; idx < indexInRow; idx++) { michael@0: Accessible* cell = row->GetChildAt(idx); michael@0: roles::Role role = cell->Role(); michael@0: if (role == roles::CELL || role == roles::GRID_CELL || michael@0: role == roles::ROWHEADER || role == roles::COLUMNHEADER) michael@0: colIdx++; michael@0: } michael@0: michael@0: return colIdx; michael@0: } michael@0: michael@0: uint32_t michael@0: XULListCellAccessible::RowIdx() const michael@0: { michael@0: Accessible* row = Parent(); michael@0: if (!row) michael@0: return 0; michael@0: michael@0: Accessible* table = row->Parent(); michael@0: if (!table) michael@0: return 0; michael@0: michael@0: int32_t indexInTable = row->IndexInParent(); michael@0: uint32_t rowIdx = 0; michael@0: for (int32_t idx = 0; idx < indexInTable; idx++) { michael@0: row = table->GetChildAt(idx); michael@0: if (row->Role() == roles::ROW) michael@0: rowIdx++; michael@0: } michael@0: michael@0: return rowIdx; michael@0: } michael@0: michael@0: void michael@0: XULListCellAccessible::ColHeaderCells(nsTArray* aCells) michael@0: { michael@0: TableAccessible* table = Table(); michael@0: NS_ASSERTION(table, "cell not in a table!"); michael@0: if (!table) michael@0: return; michael@0: michael@0: // Get column header cell from XUL listhead. michael@0: Accessible* list = nullptr; michael@0: michael@0: Accessible* tableAcc = table->AsAccessible(); michael@0: uint32_t tableChildCount = tableAcc->ChildCount(); michael@0: for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) { michael@0: Accessible* child = tableAcc->GetChildAt(childIdx); michael@0: if (child->Role() == roles::LIST) { michael@0: list = child; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: if (list) { michael@0: Accessible* headerCell = list->GetChildAt(ColIdx()); michael@0: if (headerCell) { michael@0: aCells->AppendElement(headerCell); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: // No column header cell from XUL markup, try to get it from ARIA markup. michael@0: TableCellAccessible::ColHeaderCells(aCells); michael@0: } michael@0: michael@0: bool michael@0: XULListCellAccessible::Selected() michael@0: { michael@0: TableAccessible* table = Table(); michael@0: NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table) michael@0: michael@0: return table->IsRowSelected(RowIdx()); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULListCellAccessible. Accessible implementation michael@0: michael@0: void michael@0: XULListCellAccessible::Shutdown() michael@0: { michael@0: mTableCell = nullptr; michael@0: HyperTextAccessibleWrap::Shutdown(); michael@0: } michael@0: michael@0: role michael@0: XULListCellAccessible::NativeRole() michael@0: { michael@0: return roles::CELL; michael@0: } michael@0: michael@0: already_AddRefed michael@0: XULListCellAccessible::NativeAttributes() michael@0: { michael@0: nsCOMPtr attributes = michael@0: HyperTextAccessibleWrap::NativeAttributes(); michael@0: michael@0: // "table-cell-index" attribute michael@0: TableAccessible* table = Table(); michael@0: if (!table) // we expect to be in a listbox (table) michael@0: return attributes.forget(); michael@0: michael@0: nsAutoString stringIdx; michael@0: stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx())); michael@0: nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx); michael@0: michael@0: return attributes.forget(); michael@0: }