/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Aaron Leventhal (original author) * Kyle Yuan * Alexander Surkov * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsXULListboxAccessible.h" #include "States.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" #include "nsIDOMXULPopupElement.h" #include "nsIDOMXULMultSelectCntrlEl.h" #include "nsIDOMXULSelectCntrlItemEl.h" using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // nsXULColumnsAccessible //////////////////////////////////////////////////////////////////////////////// nsXULColumnsAccessible:: nsXULColumnsAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsAccessibleWrap(aContent, aShell) { } PRUint32 nsXULColumnsAccessible::NativeRole() { return nsIAccessibleRole::ROLE_LIST; } PRUint64 nsXULColumnsAccessible::NativeState() { return states::READONLY; } //////////////////////////////////////////////////////////////////////////////// // nsXULColumnItemAccessible //////////////////////////////////////////////////////////////////////////////// nsXULColumnItemAccessible:: nsXULColumnItemAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsLeafAccessible(aContent, aShell) { } PRUint32 nsXULColumnItemAccessible::NativeRole() { return nsIAccessibleRole::ROLE_COLUMNHEADER; } PRUint64 nsXULColumnItemAccessible::NativeState() { return states::READONLY; } NS_IMETHODIMP nsXULColumnItemAccessible::GetNumActions(PRUint8 *aNumActions) { NS_ENSURE_ARG_POINTER(aNumActions); *aNumActions = 1; return NS_OK; } NS_IMETHODIMP nsXULColumnItemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) { if (aIndex != eAction_Click) return NS_ERROR_INVALID_ARG; aName.AssignLiteral("click"); return NS_OK; } NS_IMETHODIMP nsXULColumnItemAccessible::DoAction(PRUint8 aIndex) { if (aIndex != eAction_Click) return NS_ERROR_INVALID_ARG; DoCommand(); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible //////////////////////////////////////////////////////////////////////////////// nsXULListboxAccessible:: nsXULListboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsXULSelectableAccessible(aContent, aShell) { } NS_IMPL_ADDREF_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible) NS_IMPL_RELEASE_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible) nsresult nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) { nsresult rv = nsXULSelectableAccessible::QueryInterface(aIID, aInstancePtr); if (*aInstancePtr) return rv; if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) { *aInstancePtr = static_cast(this); NS_ADDREF_THIS(); return NS_OK; } return NS_ERROR_NO_INTERFACE; } PRBool nsXULListboxAccessible::IsMulticolumn() { PRInt32 numColumns = 0; nsresult rv = GetColumnCount(&numColumns); if (NS_FAILED(rv)) return PR_FALSE; return numColumns > 1; } //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible. nsIAccessible PRUint64 nsXULListboxAccessible::NativeState() { // As a nsXULListboxAccessible we can have the following states: // FOCUSED, READONLY, FOCUSABLE // Get focus status from base class PRUint64 states = nsAccessible::NativeState(); // see if we are multiple select if so set ourselves as such if (mContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::seltype, nsAccessibilityAtoms::multiple, eCaseMatters)) { states |= states::MULTISELECTABLE | states::EXTSELECTABLE; } return states; } /** * Our value is the label of our ( first ) selected child. */ NS_IMETHODIMP nsXULListboxAccessible::GetValue(nsAString& _retval) { _retval.Truncate(); nsCOMPtr select(do_QueryInterface(mContent)); if (select) { nsCOMPtr selectedItem; select->GetSelectedItem(getter_AddRefs(selectedItem)); if (selectedItem) return selectedItem->GetLabel(_retval); } return NS_ERROR_FAILURE; } PRUint32 nsXULListboxAccessible::NativeRole() { // A richlistbox is used with the new autocomplete URL bar, and has a parent // popup . nsCOMPtr xulPopup = do_QueryInterface(mContent->GetParent()); if (xulPopup) return nsIAccessibleRole::ROLE_COMBOBOX_LIST; if (IsMulticolumn()) return nsIAccessibleRole::ROLE_TABLE; return nsIAccessibleRole::ROLE_LISTBOX; } //////////////////////////////////////////////////////////////////////////////// // nsXULListboxAccessible. nsIAccessibleTable NS_IMETHODIMP nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption) { NS_ENSURE_ARG_POINTER(aCaption); *aCaption = nsnull; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSummary(nsAString &aSummary) { aSummary.Truncate(); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetColumnCount(PRInt32 *aColumnsCout) { NS_ENSURE_ARG_POINTER(aColumnsCout); *aColumnsCout = 0; if (IsDefunct()) return NS_ERROR_FAILURE; nsIContent* headContent = nsnull; PRUint32 count = mContent->GetChildCount(); for (PRUint32 index = 0; index < count; ++index) { nsIContent* childContent = mContent->GetChildAt(index); if (childContent->NodeInfo()->Equals(nsAccessibilityAtoms::listcols, kNameSpaceID_XUL)) { headContent = childContent; } } if (!headContent) return NS_OK; PRUint32 columnCount = 0; count = headContent->GetChildCount(); for (PRUint32 index = 0; index < count; ++index) { nsIContent* childContent = headContent->GetChildAt(index); if (childContent->NodeInfo()->Equals(nsAccessibilityAtoms::listcol, kNameSpaceID_XUL)) { columnCount++; } } *aColumnsCout = columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetRowCount(PRInt32 *aRowCount) { NS_ENSURE_ARG_POINTER(aRowCount); *aRowCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr element(do_QueryInterface(mContent)); NS_ENSURE_STATE(element); PRUint32 itemCount = 0; nsresult rv = element->GetItemCount(&itemCount); NS_ENSURE_SUCCESS(rv, rv); *aRowCount = itemCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetCellAt(PRInt32 aRow, PRInt32 aColumn, nsIAccessible **aAccessibleCell) { NS_ENSURE_ARG_POINTER(aAccessibleCell); *aAccessibleCell = nsnull; if (IsDefunct()) return NS_OK; nsCOMPtr control = do_QueryInterface(mContent); nsCOMPtr item; control->GetItemAtIndex(aRow, getter_AddRefs(item)); NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG); nsCOMPtr itemContent(do_QueryInterface(item)); nsAccessible *row = GetAccService()->GetAccessibleInWeakShell(itemContent, mWeakShell); NS_ENSURE_STATE(row); nsresult rv = row->GetChildAt(aColumn, aAccessibleCell); NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetCellIndexAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex) { NS_ENSURE_ARG_POINTER(aIndex); *aIndex = -1; PRInt32 rowCount = 0; nsresult rv = GetRowCount(&rowCount); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(0 <= aRow && aRow <= rowCount, NS_ERROR_INVALID_ARG); PRInt32 columnCount = 0; rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(0 <= aColumn && aColumn <= columnCount, NS_ERROR_INVALID_ARG); *aIndex = aRow * columnCount + aColumn; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetColumnIndexAt(PRInt32 aIndex, PRInt32 *aColumn) { NS_ENSURE_ARG_POINTER(aColumn); *aColumn = -1; PRInt32 columnCount = 0; nsresult rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); *aColumn = aIndex % columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow) { NS_ENSURE_ARG_POINTER(aRow); *aRow = -1; PRInt32 columnCount = 0; nsresult rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); *aRow = aIndex / columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex, PRInt32* aRowIndex, PRInt32* aColumnIndex) { NS_ENSURE_ARG_POINTER(aRowIndex); *aRowIndex = -1; NS_ENSURE_ARG_POINTER(aColumnIndex); *aColumnIndex = -1; if (IsDefunct()) return NS_ERROR_FAILURE; PRInt32 columnCount = 0; nsresult rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); *aColumnIndex = aCellIndex % columnCount; *aRowIndex = aCellIndex / columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aCellSpans) { NS_ENSURE_ARG_POINTER(aCellSpans); *aCellSpans = 1; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetRowExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aCellSpans) { NS_ENSURE_ARG_POINTER(aCellSpans); *aCellSpans = 1; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetColumnDescription(PRInt32 aColumn, nsAString& aDescription) { aDescription.Truncate(); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription) { aDescription.Truncate(); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *aIsSelected) { NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); PRInt32 selectedrowCount = 0; nsresult rv = control->GetSelectedCount(&selectedrowCount); NS_ENSURE_SUCCESS(rv, rv); PRInt32 rowCount = 0; rv = GetRowCount(&rowCount); NS_ENSURE_SUCCESS(rv, rv); *aIsSelected = (selectedrowCount == rowCount); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected) { NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULSelectControlElement."); nsCOMPtr item; control->GetItemAtIndex(aRow, getter_AddRefs(item)); NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG); return item->GetSelected(aIsSelected); } NS_IMETHODIMP nsXULListboxAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex, PRBool *aIsSelected) { return IsRowSelected(aRowIndex, aIsSelected); } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedCellCount(PRUint32* aCount) { NS_ENSURE_ARG_POINTER(aCount); *aCount = 0; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr selectedItems; control->GetSelectedItems(getter_AddRefs(selectedItems)); if (!selectedItems) return NS_OK; PRUint32 selectedItemsCount = 0; nsresult rv = selectedItems->GetLength(&selectedItemsCount); NS_ENSURE_SUCCESS(rv, rv); if (!selectedItemsCount) return NS_OK; PRInt32 columnCount = 0; rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); *aCount = selectedItemsCount * columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedColumnCount(PRUint32* aCount) { NS_ENSURE_ARG_POINTER(aCount); *aCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); PRInt32 selectedrowCount = 0; nsresult rv = control->GetSelectedCount(&selectedrowCount); NS_ENSURE_SUCCESS(rv, rv); PRInt32 rowCount = 0; rv = GetRowCount(&rowCount); NS_ENSURE_SUCCESS(rv, rv); if (selectedrowCount != rowCount) return NS_OK; PRInt32 columnCount = 0; rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); *aCount = columnCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedRowCount(PRUint32* aCount) { NS_ENSURE_ARG_POINTER(aCount); *aCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); PRInt32 selectedrowCount = 0; nsresult rv = control->GetSelectedCount(&selectedrowCount); NS_ENSURE_SUCCESS(rv, rv); *aCount = selectedrowCount; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedCells(nsIArray **aCells) { NS_ENSURE_ARG_POINTER(aCells); *aCells = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsCOMPtr selCells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr selectedItems; control->GetSelectedItems(getter_AddRefs(selectedItems)); if (!selectedItems) return NS_OK; PRUint32 selectedItemsCount = 0; rv = selectedItems->GetLength(&selectedItemsCount); NS_ENSURE_SUCCESS(rv, rv); PRUint32 index = 0; for (; index < selectedItemsCount; index++) { nsCOMPtr itemNode; selectedItems->Item(index, getter_AddRefs(itemNode)); nsCOMPtr itemContent(do_QueryInterface(itemNode)); nsAccessible *item = GetAccService()->GetAccessibleInWeakShell(itemContent, mWeakShell); if (item) { PRInt32 cellCount = item->GetChildCount(); for (PRInt32 cellIdx = 0; cellIdx < cellCount; cellIdx++) { nsAccessible *cell = mChildren[cellIdx]; if (cell->Role() == nsIAccessibleRole::ROLE_CELL) selCells->AppendElement(static_cast(cell), PR_FALSE); } } } NS_ADDREF(*aCells = selCells); return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedCellIndices(PRUint32 *aNumCells, PRInt32 **aCells) { NS_ENSURE_ARG_POINTER(aNumCells); *aNumCells = 0; NS_ENSURE_ARG_POINTER(aCells); *aCells = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr selectedItems; control->GetSelectedItems(getter_AddRefs(selectedItems)); if (!selectedItems) return NS_OK; PRUint32 selectedItemsCount = 0; nsresult rv = selectedItems->GetLength(&selectedItemsCount); NS_ENSURE_SUCCESS(rv, rv); PRInt32 columnCount = 0; rv = GetColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); PRUint32 cellsCount = selectedItemsCount * columnCount; PRInt32 *cellsIdxArray = static_cast(nsMemory::Alloc((cellsCount) * sizeof(PRInt32))); NS_ENSURE_TRUE(cellsIdxArray, NS_ERROR_OUT_OF_MEMORY); PRUint32 index = 0, cellsIdx = 0; for (; index < selectedItemsCount; index++) { nsCOMPtr itemNode; selectedItems->Item(index, getter_AddRefs(itemNode)); nsCOMPtr item = do_QueryInterface(itemNode); if (item) { PRInt32 itemIdx = -1; control->GetIndexOfItem(item, &itemIdx); if (itemIdx != -1) { PRInt32 colIdx = 0; for (; colIdx < columnCount; colIdx++) cellsIdxArray[cellsIdx++] = itemIdx * columnCount + colIdx; } } } *aNumCells = cellsCount; *aCells = cellsIdxArray; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedColumnIndices(PRUint32 *aNumColumns, PRInt32 **aColumns) { NS_ENSURE_ARG_POINTER(aNumColumns); *aNumColumns = 0; NS_ENSURE_ARG_POINTER(aColumns); *aColumns = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; PRUint32 columnCount = 0; nsresult rv = GetSelectedColumnCount(&columnCount); NS_ENSURE_SUCCESS(rv, rv); if (!columnCount) return NS_OK; PRInt32 *colsIdxArray = static_cast(nsMemory::Alloc((columnCount) * sizeof(PRInt32))); NS_ENSURE_TRUE(colsIdxArray, NS_ERROR_OUT_OF_MEMORY); PRUint32 colIdx = 0; for (; colIdx < columnCount; colIdx++) colsIdxArray[colIdx] = colIdx; *aNumColumns = columnCount; *aColumns = colsIdxArray; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::GetSelectedRowIndices(PRUint32 *aNumRows, PRInt32 **aRows) { NS_ENSURE_ARG_POINTER(aNumRows); *aNumRows = 0; NS_ENSURE_ARG_POINTER(aRows); *aRows = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr selectedItems; control->GetSelectedItems(getter_AddRefs(selectedItems)); if (!selectedItems) return NS_OK; PRUint32 selectedItemsCount = 0; nsresult rv = selectedItems->GetLength(&selectedItemsCount); NS_ENSURE_SUCCESS(rv, rv); if (!selectedItemsCount) return NS_OK; PRInt32 *rowsIdxArray = static_cast(nsMemory::Alloc((selectedItemsCount) * sizeof(PRInt32))); NS_ENSURE_TRUE(rowsIdxArray, NS_ERROR_OUT_OF_MEMORY); PRUint32 index = 0; for (; index < selectedItemsCount; index++) { nsCOMPtr itemNode; selectedItems->Item(index, getter_AddRefs(itemNode)); nsCOMPtr item = do_QueryInterface(itemNode); if (item) { PRInt32 itemIdx = -1; control->GetIndexOfItem(item, &itemIdx); if (itemIdx != -1) rowsIdxArray[index] = itemIdx; } } *aNumRows = selectedItemsCount; *aRows = rowsIdxArray; return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::SelectRow(PRInt32 aRow) { if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr item; control->GetItemAtIndex(aRow, getter_AddRefs(item)); NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG); return control->SelectItem(item); } NS_IMETHODIMP nsXULListboxAccessible::SelectColumn(PRInt32 aColumn) { // xul:listbox and xul:richlistbox support row selection only. return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::UnselectRow(PRInt32 aRow) { if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr control = do_QueryInterface(mContent); NS_ASSERTION(control, "Doesn't implement nsIDOMXULMultiSelectControlElement."); nsCOMPtr item; control->GetItemAtIndex(aRow, getter_AddRefs(item)); NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG); return control->RemoveItemFromSelection(item); } NS_IMETHODIMP nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn) { // xul:listbox and xul:richlistbox support row selection only. return NS_OK; } NS_IMETHODIMP nsXULListboxAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout) { NS_ENSURE_ARG_POINTER(aIsProbablyForLayout); *aIsProbablyForLayout = PR_FALSE; return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsXULListitemAccessible //////////////////////////////////////////////////////////////////////////////// nsXULListitemAccessible:: nsXULListitemAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsXULMenuitemAccessible(aContent, aShell) { mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type, nsAccessibilityAtoms::checkbox, eCaseMatters); } NS_IMPL_ISUPPORTS_INHERITED0(nsXULListitemAccessible, nsAccessible) nsAccessible * nsXULListitemAccessible::GetListAccessible() { if (IsDefunct()) return nsnull; nsCOMPtr listItem = do_QueryInterface(mContent); if (!listItem) return nsnull; nsCOMPtr list; listItem->GetControl(getter_AddRefs(list)); nsCOMPtr listContent(do_QueryInterface(list)); if (!listContent) return nsnull; return GetAccService()->GetAccessibleInWeakShell(listContent, mWeakShell); } //////////////////////////////////////////////////////////////////////////////// // nsXULListitemAccessible nsAccessible void nsXULListitemAccessible::Description(nsString& aDesc) { nsAccessibleWrap::Description(aDesc); } //////////////////////////////////////////////////////////////////////////////// // nsXULListitemAccessible. nsIAccessible /** * If there is a Listcell as a child ( not anonymous ) use it, otherwise * default to getting the name from GetXULName */ nsresult nsXULListitemAccessible::GetNameInternal(nsAString& aName) { nsIContent* child = mContent->GetChildAt(0); if (child) { if (child->NodeInfo()->Equals(nsAccessibilityAtoms::listcell, kNameSpaceID_XUL)) { child->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::label, aName); return NS_OK; } } return GetXULName(aName); } PRUint32 nsXULListitemAccessible::NativeRole() { nsAccessible *list = GetListAccessible(); if (!list) { NS_ERROR("No list accessible for listitem accessible!"); return nsIAccessibleRole::ROLE_NOTHING; } if (list->Role() == nsIAccessibleRole::ROLE_TABLE) return nsIAccessibleRole::ROLE_ROW; if (mIsCheckbox) return nsIAccessibleRole::ROLE_CHECKBUTTON; if (mParent && mParent->Role() == nsIAccessibleRole::ROLE_COMBOBOX_LIST) return nsIAccessibleRole::ROLE_COMBOBOX_OPTION; return nsIAccessibleRole::ROLE_RICH_OPTION; } PRUint64 nsXULListitemAccessible::NativeState() { if (mIsCheckbox) return nsXULMenuitemAccessible::NativeState(); PRUint64 states = states::FOCUSABLE | states::SELECTABLE; nsCOMPtr listItem = do_QueryInterface(mContent); if (listItem) { PRBool isSelected; listItem->GetSelected(&isSelected); if (isSelected) states |= states::SELECTED; if (gLastFocusedNode == mContent) states |= states::FOCUSED; } return states; } NS_IMETHODIMP nsXULListitemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) { if (aIndex == eAction_Click && mIsCheckbox) { // check or uncheck PRUint64 states = NativeState(); if (states & states::CHECKED) aName.AssignLiteral("uncheck"); else aName.AssignLiteral("check"); return NS_OK; } return NS_ERROR_INVALID_ARG; } PRBool nsXULListitemAccessible::GetAllowsAnonChildAccessibles() { // That indicates we should walk anonymous children for listitems return PR_TRUE; } void nsXULListitemAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet, PRInt32 *aSetSize) { nsAccUtils::GetPositionAndSizeForXULSelectControlItem(mContent, aPosInSet, aSetSize); } //////////////////////////////////////////////////////////////////////////////// // nsXULListCellAccessible //////////////////////////////////////////////////////////////////////////////// nsXULListCellAccessible:: nsXULListCellAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsHyperTextAccessibleWrap(aContent, aShell) { } //////////////////////////////////////////////////////////////////////////////// // nsISupports NS_IMPL_ISUPPORTS_INHERITED1(nsXULListCellAccessible, nsHyperTextAccessible, nsIAccessibleTableCell) //////////////////////////////////////////////////////////////////////////////// // nsXULListCellAccessible: nsIAccessibleTableCell implementation NS_IMETHODIMP nsXULListCellAccessible::GetTable(nsIAccessibleTable **aTable) { NS_ENSURE_ARG_POINTER(aTable); *aTable = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsAccessible* thisRow = Parent(); if (!thisRow || thisRow->Role() != nsIAccessibleRole::ROLE_ROW) return NS_OK; nsAccessible* table = thisRow->Parent(); if (!table || table->Role() != nsIAccessibleRole::ROLE_TABLE) return NS_OK; CallQueryInterface(table, aTable); return NS_OK; } NS_IMETHODIMP nsXULListCellAccessible::GetColumnIndex(PRInt32 *aColumnIndex) { NS_ENSURE_ARG_POINTER(aColumnIndex); *aColumnIndex = -1; if (IsDefunct()) return NS_ERROR_FAILURE; nsAccessible* row = Parent(); if (!row) return NS_OK; *aColumnIndex = 0; PRInt32 indexInRow = IndexInParent(); for (PRInt32 idx = 0; idx < indexInRow; idx++) { nsAccessible* cell = row->GetChildAt(idx); PRUint32 role = cell->Role(); if (role == nsIAccessibleRole::ROLE_CELL || role == nsIAccessibleRole::ROLE_GRID_CELL || role == nsIAccessibleRole::ROLE_ROWHEADER || role == nsIAccessibleRole::ROLE_COLUMNHEADER) (*aColumnIndex)++; } return NS_OK; } NS_IMETHODIMP nsXULListCellAccessible::GetRowIndex(PRInt32 *aRowIndex) { NS_ENSURE_ARG_POINTER(aRowIndex); *aRowIndex = -1; if (IsDefunct()) return NS_ERROR_FAILURE; nsAccessible* row = Parent(); if (!row) return NS_OK; nsAccessible* table = row->Parent(); if (!table) return NS_OK; *aRowIndex = 0; PRInt32 indexInTable = row->IndexInParent(); for (PRInt32 idx = 0; idx < indexInTable; idx++) { row = table->GetChildAt(idx); if (row->Role() == nsIAccessibleRole::ROLE_ROW) (*aRowIndex)++; } return NS_OK; } NS_IMETHODIMP nsXULListCellAccessible::GetColumnExtent(PRInt32 *aExtentCount) { NS_ENSURE_ARG_POINTER(aExtentCount); *aExtentCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; *aExtentCount = 1; return NS_OK; } NS_IMETHODIMP nsXULListCellAccessible::GetRowExtent(PRInt32 *aExtentCount) { NS_ENSURE_ARG_POINTER(aExtentCount); *aExtentCount = 0; if (IsDefunct()) return NS_ERROR_FAILURE; *aExtentCount = 1; return NS_OK; } NS_IMETHODIMP nsXULListCellAccessible::GetColumnHeaderCells(nsIArray **aHeaderCells) { NS_ENSURE_ARG_POINTER(aHeaderCells); *aHeaderCells = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr table; GetTable(getter_AddRefs(table)); NS_ENSURE_STATE(table); // we expect to be in a listbox (table) // Get column header cell from XUL listhead. nsAccessible *list = nsnull; nsRefPtr tableAcc(do_QueryObject(table)); PRInt32 tableChildCount = tableAcc->GetChildCount(); for (PRInt32 childIdx = 0; childIdx < tableChildCount; childIdx++) { nsAccessible *child = tableAcc->GetChildAt(childIdx); if (child->Role() == nsIAccessibleRole::ROLE_LIST) { list = child; break; } } if (list) { PRInt32 colIdx = -1; GetColumnIndex(&colIdx); nsIAccessible *headerCell = list->GetChildAt(colIdx); if (headerCell) { nsresult rv = NS_OK; nsCOMPtr headerCells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); headerCells->AppendElement(headerCell, PR_FALSE); NS_ADDREF(*aHeaderCells = headerCells); return NS_OK; } } // No column header cell from XUL markup, try to get it from ARIA markup. return nsAccUtils::GetHeaderCellsFor(table, this, nsAccUtils::eColumnHeaderCells, aHeaderCells); } NS_IMETHODIMP nsXULListCellAccessible::GetRowHeaderCells(nsIArray **aHeaderCells) { NS_ENSURE_ARG_POINTER(aHeaderCells); *aHeaderCells = nsnull; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr table; GetTable(getter_AddRefs(table)); NS_ENSURE_STATE(table); // we expect to be in a listbox (table) // Calculate row header cells from ARIA markup. return nsAccUtils::GetHeaderCellsFor(table, this, nsAccUtils::eRowHeaderCells, aHeaderCells); } NS_IMETHODIMP nsXULListCellAccessible::IsSelected(PRBool *aIsSelected) { NS_ENSURE_ARG_POINTER(aIsSelected); *aIsSelected = PR_FALSE; if (IsDefunct()) return NS_ERROR_FAILURE; nsCOMPtr table; GetTable(getter_AddRefs(table)); NS_ENSURE_STATE(table); // we expect to be in a listbox (table) PRInt32 rowIdx = -1; GetRowIndex(&rowIdx); return table->IsRowSelected(rowIdx, aIsSelected); } //////////////////////////////////////////////////////////////////////////////// // nsXULListCellAccessible. nsAccessible implementation PRUint32 nsXULListCellAccessible::NativeRole() { return nsIAccessibleRole::ROLE_CELL; } nsresult nsXULListCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes) { NS_ENSURE_ARG_POINTER(aAttributes); if (IsDefunct()) return NS_ERROR_FAILURE; // "table-cell-index" attribute nsCOMPtr table; GetTable(getter_AddRefs(table)); NS_ENSURE_STATE(table); // we expect to be in a listbox (table) PRInt32 rowIdx = -1; GetRowIndex(&rowIdx); PRInt32 colIdx = -1; GetColumnIndex(&colIdx); PRInt32 cellIdx = -1; table->GetCellIndexAt(rowIdx, colIdx, &cellIdx); nsAutoString stringIdx; stringIdx.AppendInt(cellIdx); nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::tableCellIndex, stringIdx); return NS_OK; }