1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/xul/XULListboxAccessible.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,879 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "XULListboxAccessible.h" 1.10 + 1.11 +#include "Accessible-inl.h" 1.12 +#include "nsAccessibilityService.h" 1.13 +#include "nsAccUtils.h" 1.14 +#include "DocAccessible.h" 1.15 +#include "Role.h" 1.16 +#include "States.h" 1.17 + 1.18 +#include "nsComponentManagerUtils.h" 1.19 +#include "nsIAutoCompleteInput.h" 1.20 +#include "nsIAutoCompletePopup.h" 1.21 +#include "nsIDOMXULMenuListElement.h" 1.22 +#include "nsIDOMXULMultSelectCntrlEl.h" 1.23 +#include "nsIDOMNodeList.h" 1.24 +#include "nsIDOMXULPopupElement.h" 1.25 +#include "nsIDOMXULSelectCntrlItemEl.h" 1.26 +#include "nsIMutableArray.h" 1.27 +#include "nsIPersistentProperties2.h" 1.28 + 1.29 +using namespace mozilla::a11y; 1.30 + 1.31 +//////////////////////////////////////////////////////////////////////////////// 1.32 +// XULColumAccessible 1.33 +//////////////////////////////////////////////////////////////////////////////// 1.34 + 1.35 +XULColumAccessible:: 1.36 + XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.37 + AccessibleWrap(aContent, aDoc) 1.38 +{ 1.39 +} 1.40 + 1.41 +role 1.42 +XULColumAccessible::NativeRole() 1.43 +{ 1.44 + return roles::LIST; 1.45 +} 1.46 + 1.47 +uint64_t 1.48 +XULColumAccessible::NativeState() 1.49 +{ 1.50 + return states::READONLY; 1.51 +} 1.52 + 1.53 + 1.54 +//////////////////////////////////////////////////////////////////////////////// 1.55 +// XULColumnItemAccessible 1.56 +//////////////////////////////////////////////////////////////////////////////// 1.57 + 1.58 +XULColumnItemAccessible:: 1.59 + XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.60 + LeafAccessible(aContent, aDoc) 1.61 +{ 1.62 +} 1.63 + 1.64 +role 1.65 +XULColumnItemAccessible::NativeRole() 1.66 +{ 1.67 + return roles::COLUMNHEADER; 1.68 +} 1.69 + 1.70 +uint64_t 1.71 +XULColumnItemAccessible::NativeState() 1.72 +{ 1.73 + return states::READONLY; 1.74 +} 1.75 + 1.76 +uint8_t 1.77 +XULColumnItemAccessible::ActionCount() 1.78 +{ 1.79 + return 1; 1.80 +} 1.81 + 1.82 +NS_IMETHODIMP 1.83 +XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) 1.84 +{ 1.85 + if (aIndex != eAction_Click) 1.86 + return NS_ERROR_INVALID_ARG; 1.87 + 1.88 + aName.AssignLiteral("click"); 1.89 + return NS_OK; 1.90 +} 1.91 + 1.92 +NS_IMETHODIMP 1.93 +XULColumnItemAccessible::DoAction(uint8_t aIndex) 1.94 +{ 1.95 + if (aIndex != eAction_Click) 1.96 + return NS_ERROR_INVALID_ARG; 1.97 + 1.98 + DoCommand(); 1.99 + return NS_OK; 1.100 +} 1.101 + 1.102 +//////////////////////////////////////////////////////////////////////////////// 1.103 +// XULListboxAccessible 1.104 +//////////////////////////////////////////////////////////////////////////////// 1.105 + 1.106 +XULListboxAccessible:: 1.107 + XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.108 + XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this) 1.109 +{ 1.110 + nsIContent* parentContent = mContent->GetFlattenedTreeParent(); 1.111 + if (parentContent) { 1.112 + nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = 1.113 + do_QueryInterface(parentContent); 1.114 + if (autoCompletePopupElm) 1.115 + mGenericTypes |= eAutoCompletePopup; 1.116 + } 1.117 +} 1.118 + 1.119 +NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible) 1.120 +NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible) 1.121 + 1.122 +nsresult 1.123 +XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr) 1.124 +{ 1.125 + nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr); 1.126 + if (*aInstancePtr) 1.127 + return rv; 1.128 + 1.129 + if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) { 1.130 + *aInstancePtr = static_cast<nsIAccessibleTable*>(this); 1.131 + NS_ADDREF_THIS(); 1.132 + return NS_OK; 1.133 + } 1.134 + 1.135 + return NS_ERROR_NO_INTERFACE; 1.136 +} 1.137 + 1.138 +//////////////////////////////////////////////////////////////////////////////// 1.139 +// Accessible 1.140 + 1.141 +void 1.142 +XULListboxAccessible::Shutdown() 1.143 +{ 1.144 + mTable = nullptr; 1.145 + XULSelectControlAccessible::Shutdown(); 1.146 +} 1.147 + 1.148 +bool 1.149 +XULListboxAccessible::IsMulticolumn() 1.150 +{ 1.151 + int32_t numColumns = 0; 1.152 + nsresult rv = GetColumnCount(&numColumns); 1.153 + if (NS_FAILED(rv)) 1.154 + return false; 1.155 + 1.156 + return numColumns > 1; 1.157 +} 1.158 + 1.159 +//////////////////////////////////////////////////////////////////////////////// 1.160 +// XULListboxAccessible. nsIAccessible 1.161 + 1.162 +uint64_t 1.163 +XULListboxAccessible::NativeState() 1.164 +{ 1.165 + // As a XULListboxAccessible we can have the following states: 1.166 + // FOCUSED, READONLY, FOCUSABLE 1.167 + 1.168 + // Get focus status from base class 1.169 + uint64_t states = Accessible::NativeState(); 1.170 + 1.171 + // see if we are multiple select if so set ourselves as such 1.172 + 1.173 + if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype, 1.174 + nsGkAtoms::multiple, eCaseMatters)) { 1.175 + states |= states::MULTISELECTABLE | states::EXTSELECTABLE; 1.176 + } 1.177 + 1.178 + return states; 1.179 +} 1.180 + 1.181 +/** 1.182 + * Our value is the label of our ( first ) selected child. 1.183 + */ 1.184 +void 1.185 +XULListboxAccessible::Value(nsString& aValue) 1.186 +{ 1.187 + aValue.Truncate(); 1.188 + 1.189 + nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent)); 1.190 + if (select) { 1.191 + nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem; 1.192 + select->GetSelectedItem(getter_AddRefs(selectedItem)); 1.193 + if (selectedItem) 1.194 + selectedItem->GetLabel(aValue); 1.195 + } 1.196 +} 1.197 + 1.198 +role 1.199 +XULListboxAccessible::NativeRole() 1.200 +{ 1.201 + // A richlistbox is used with the new autocomplete URL bar, and has a parent 1.202 + // popup <panel>. 1.203 + nsCOMPtr<nsIDOMXULPopupElement> xulPopup = 1.204 + do_QueryInterface(mContent->GetParent()); 1.205 + if (xulPopup) 1.206 + return roles::COMBOBOX_LIST; 1.207 + 1.208 + return IsMulticolumn() ? roles::TABLE : roles::LISTBOX; 1.209 +} 1.210 + 1.211 +//////////////////////////////////////////////////////////////////////////////// 1.212 +// XULListboxAccessible. nsIAccessibleTable 1.213 + 1.214 +uint32_t 1.215 +XULListboxAccessible::ColCount() 1.216 +{ 1.217 + nsIContent* headContent = nullptr; 1.218 + for (nsIContent* childContent = mContent->GetFirstChild(); childContent; 1.219 + childContent = childContent->GetNextSibling()) { 1.220 + if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols, 1.221 + kNameSpaceID_XUL)) { 1.222 + headContent = childContent; 1.223 + } 1.224 + } 1.225 + if (!headContent) 1.226 + return 0; 1.227 + 1.228 + uint32_t columnCount = 0; 1.229 + for (nsIContent* childContent = headContent->GetFirstChild(); childContent; 1.230 + childContent = childContent->GetNextSibling()) { 1.231 + if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol, 1.232 + kNameSpaceID_XUL)) { 1.233 + columnCount++; 1.234 + } 1.235 + } 1.236 + 1.237 + return columnCount; 1.238 +} 1.239 + 1.240 +uint32_t 1.241 +XULListboxAccessible::RowCount() 1.242 +{ 1.243 + nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent)); 1.244 + 1.245 + uint32_t itemCount = 0; 1.246 + if(element) 1.247 + element->GetItemCount(&itemCount); 1.248 + 1.249 + return itemCount; 1.250 +} 1.251 + 1.252 +Accessible* 1.253 +XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex) 1.254 +{ 1.255 + nsCOMPtr<nsIDOMXULSelectControlElement> control = 1.256 + do_QueryInterface(mContent); 1.257 + NS_ENSURE_TRUE(control, nullptr); 1.258 + 1.259 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item; 1.260 + control->GetItemAtIndex(aRowIndex, getter_AddRefs(item)); 1.261 + if (!item) 1.262 + return nullptr; 1.263 + 1.264 + nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item)); 1.265 + if (!itemContent) 1.266 + return nullptr; 1.267 + 1.268 + Accessible* row = mDoc->GetAccessible(itemContent); 1.269 + NS_ENSURE_TRUE(row, nullptr); 1.270 + 1.271 + return row->GetChildAt(aColumnIndex); 1.272 +} 1.273 + 1.274 +bool 1.275 +XULListboxAccessible::IsColSelected(uint32_t aColIdx) 1.276 +{ 1.277 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.278 + do_QueryInterface(mContent); 1.279 + NS_ASSERTION(control, 1.280 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.281 + 1.282 + int32_t selectedrowCount = 0; 1.283 + nsresult rv = control->GetSelectedCount(&selectedrowCount); 1.284 + NS_ENSURE_SUCCESS(rv, false); 1.285 + 1.286 + return selectedrowCount == RowCount(); 1.287 +} 1.288 + 1.289 +bool 1.290 +XULListboxAccessible::IsRowSelected(uint32_t aRowIdx) 1.291 +{ 1.292 + nsCOMPtr<nsIDOMXULSelectControlElement> control = 1.293 + do_QueryInterface(mContent); 1.294 + NS_ASSERTION(control, 1.295 + "Doesn't implement nsIDOMXULSelectControlElement."); 1.296 + 1.297 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item; 1.298 + nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); 1.299 + NS_ENSURE_SUCCESS(rv, false); 1.300 + 1.301 + bool isSelected = false; 1.302 + item->GetSelected(&isSelected); 1.303 + return isSelected; 1.304 +} 1.305 + 1.306 +bool 1.307 +XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) 1.308 +{ 1.309 + return IsRowSelected(aRowIdx); 1.310 +} 1.311 + 1.312 +uint32_t 1.313 +XULListboxAccessible::SelectedCellCount() 1.314 +{ 1.315 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.316 + do_QueryInterface(mContent); 1.317 + NS_ASSERTION(control, 1.318 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.319 + 1.320 + nsCOMPtr<nsIDOMNodeList> selectedItems; 1.321 + control->GetSelectedItems(getter_AddRefs(selectedItems)); 1.322 + if (!selectedItems) 1.323 + return 0; 1.324 + 1.325 + uint32_t selectedItemsCount = 0; 1.326 + nsresult rv = selectedItems->GetLength(&selectedItemsCount); 1.327 + NS_ENSURE_SUCCESS(rv, 0); 1.328 + 1.329 + return selectedItemsCount * ColCount(); 1.330 +} 1.331 + 1.332 +uint32_t 1.333 +XULListboxAccessible::SelectedColCount() 1.334 +{ 1.335 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.336 + do_QueryInterface(mContent); 1.337 + NS_ASSERTION(control, 1.338 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.339 + 1.340 + int32_t selectedRowCount = 0; 1.341 + nsresult rv = control->GetSelectedCount(&selectedRowCount); 1.342 + NS_ENSURE_SUCCESS(rv, 0); 1.343 + 1.344 + return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0; 1.345 +} 1.346 + 1.347 +uint32_t 1.348 +XULListboxAccessible::SelectedRowCount() 1.349 +{ 1.350 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.351 + do_QueryInterface(mContent); 1.352 + NS_ASSERTION(control, 1.353 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.354 + 1.355 + int32_t selectedRowCount = 0; 1.356 + nsresult rv = control->GetSelectedCount(&selectedRowCount); 1.357 + NS_ENSURE_SUCCESS(rv, 0); 1.358 + 1.359 + return selectedRowCount >= 0 ? selectedRowCount : 0; 1.360 +} 1.361 + 1.362 +void 1.363 +XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells) 1.364 +{ 1.365 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.366 + do_QueryInterface(mContent); 1.367 + NS_ASSERTION(control, 1.368 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.369 + 1.370 + nsCOMPtr<nsIDOMNodeList> selectedItems; 1.371 + control->GetSelectedItems(getter_AddRefs(selectedItems)); 1.372 + if (!selectedItems) 1.373 + return; 1.374 + 1.375 + uint32_t selectedItemsCount = 0; 1.376 + DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount); 1.377 + NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); 1.378 + 1.379 + for (uint32_t index = 0; index < selectedItemsCount; index++) { 1.380 + nsCOMPtr<nsIDOMNode> itemNode; 1.381 + selectedItems->Item(index, getter_AddRefs(itemNode)); 1.382 + nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode)); 1.383 + Accessible* item = mDoc->GetAccessible(itemContent); 1.384 + 1.385 + if (item) { 1.386 + uint32_t cellCount = item->ChildCount(); 1.387 + for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) { 1.388 + Accessible* cell = mChildren[cellIdx]; 1.389 + if (cell->Role() == roles::CELL) 1.390 + aCells->AppendElement(cell); 1.391 + } 1.392 + } 1.393 + } 1.394 +} 1.395 + 1.396 +void 1.397 +XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) 1.398 +{ 1.399 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.400 + do_QueryInterface(mContent); 1.401 + NS_ASSERTION(control, 1.402 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.403 + 1.404 + nsCOMPtr<nsIDOMNodeList> selectedItems; 1.405 + control->GetSelectedItems(getter_AddRefs(selectedItems)); 1.406 + if (!selectedItems) 1.407 + return; 1.408 + 1.409 + uint32_t selectedItemsCount = 0; 1.410 + DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount); 1.411 + NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); 1.412 + 1.413 + uint32_t colCount = ColCount(); 1.414 + aCells->SetCapacity(selectedItemsCount * colCount); 1.415 + aCells->AppendElements(selectedItemsCount * colCount); 1.416 + 1.417 + for (uint32_t selItemsIdx = 0, cellsIdx = 0; 1.418 + selItemsIdx < selectedItemsCount; selItemsIdx++) { 1.419 + 1.420 + nsCOMPtr<nsIDOMNode> itemNode; 1.421 + selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode)); 1.422 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item = 1.423 + do_QueryInterface(itemNode); 1.424 + 1.425 + if (item) { 1.426 + int32_t itemIdx = -1; 1.427 + control->GetIndexOfItem(item, &itemIdx); 1.428 + if (itemIdx >= 0) 1.429 + for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++) 1.430 + aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx; 1.431 + } 1.432 + } 1.433 +} 1.434 + 1.435 +void 1.436 +XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) 1.437 +{ 1.438 + uint32_t selColCount = SelectedColCount(); 1.439 + aCols->SetCapacity(selColCount); 1.440 + 1.441 + for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++) 1.442 + aCols->AppendElement(colIdx); 1.443 +} 1.444 + 1.445 +void 1.446 +XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) 1.447 +{ 1.448 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.449 + do_QueryInterface(mContent); 1.450 + NS_ASSERTION(control, 1.451 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.452 + 1.453 + nsCOMPtr<nsIDOMNodeList> selectedItems; 1.454 + control->GetSelectedItems(getter_AddRefs(selectedItems)); 1.455 + if (!selectedItems) 1.456 + return; 1.457 + 1.458 + uint32_t rowCount = 0; 1.459 + DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount); 1.460 + NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!"); 1.461 + 1.462 + if (!rowCount) 1.463 + return; 1.464 + 1.465 + aRows->SetCapacity(rowCount); 1.466 + aRows->AppendElements(rowCount); 1.467 + 1.468 + for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) { 1.469 + nsCOMPtr<nsIDOMNode> itemNode; 1.470 + selectedItems->Item(rowIdx, getter_AddRefs(itemNode)); 1.471 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item = 1.472 + do_QueryInterface(itemNode); 1.473 + 1.474 + if (item) { 1.475 + int32_t itemIdx = -1; 1.476 + control->GetIndexOfItem(item, &itemIdx); 1.477 + if (itemIdx >= 0) 1.478 + aRows->ElementAt(rowIdx) = itemIdx; 1.479 + } 1.480 + } 1.481 +} 1.482 + 1.483 +void 1.484 +XULListboxAccessible::SelectRow(uint32_t aRowIdx) 1.485 +{ 1.486 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.487 + do_QueryInterface(mContent); 1.488 + NS_ASSERTION(control, 1.489 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.490 + 1.491 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item; 1.492 + control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); 1.493 + control->SelectItem(item); 1.494 +} 1.495 + 1.496 +void 1.497 +XULListboxAccessible::UnselectRow(uint32_t aRowIdx) 1.498 +{ 1.499 + nsCOMPtr<nsIDOMXULMultiSelectControlElement> control = 1.500 + do_QueryInterface(mContent); 1.501 + NS_ASSERTION(control, 1.502 + "Doesn't implement nsIDOMXULMultiSelectControlElement."); 1.503 + 1.504 + nsCOMPtr<nsIDOMXULSelectControlItemElement> item; 1.505 + control->GetItemAtIndex(aRowIdx, getter_AddRefs(item)); 1.506 + control->RemoveItemFromSelection(item); 1.507 +} 1.508 + 1.509 +//////////////////////////////////////////////////////////////////////////////// 1.510 +// XULListboxAccessible: Widgets 1.511 + 1.512 +bool 1.513 +XULListboxAccessible::IsWidget() const 1.514 +{ 1.515 + return true; 1.516 +} 1.517 + 1.518 +bool 1.519 +XULListboxAccessible::IsActiveWidget() const 1.520 +{ 1.521 + if (IsAutoCompletePopup()) { 1.522 + nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = 1.523 + do_QueryInterface(mContent->GetParent()); 1.524 + 1.525 + if (autoCompletePopupElm) { 1.526 + bool isOpen = false; 1.527 + autoCompletePopupElm->GetPopupOpen(&isOpen); 1.528 + return isOpen; 1.529 + } 1.530 + } 1.531 + return FocusMgr()->HasDOMFocus(mContent); 1.532 +} 1.533 + 1.534 +bool 1.535 +XULListboxAccessible::AreItemsOperable() const 1.536 +{ 1.537 + if (IsAutoCompletePopup()) { 1.538 + nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = 1.539 + do_QueryInterface(mContent->GetParent()); 1.540 + 1.541 + if (autoCompletePopupElm) { 1.542 + bool isOpen = false; 1.543 + autoCompletePopupElm->GetPopupOpen(&isOpen); 1.544 + return isOpen; 1.545 + } 1.546 + } 1.547 + return true; 1.548 +} 1.549 + 1.550 +Accessible* 1.551 +XULListboxAccessible::ContainerWidget() const 1.552 +{ 1.553 + if (IsAutoCompletePopup()) { 1.554 + // This works for XUL autocompletes. It doesn't work for HTML forms 1.555 + // autocomplete because of potential crossprocess calls (when autocomplete 1.556 + // lives in content process while popup lives in chrome process). If that's 1.557 + // a problem then rethink Widgets interface. 1.558 + nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = 1.559 + do_QueryInterface(mContent->GetParent()); 1.560 + if (menuListElm) { 1.561 + nsCOMPtr<nsIDOMNode> inputElm; 1.562 + menuListElm->GetInputField(getter_AddRefs(inputElm)); 1.563 + if (inputElm) { 1.564 + nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm); 1.565 + if (inputNode) { 1.566 + Accessible* input = 1.567 + mDoc->GetAccessible(inputNode); 1.568 + return input ? input->ContainerWidget() : nullptr; 1.569 + } 1.570 + } 1.571 + } 1.572 + } 1.573 + return nullptr; 1.574 +} 1.575 + 1.576 +//////////////////////////////////////////////////////////////////////////////// 1.577 +// XULListitemAccessible 1.578 +//////////////////////////////////////////////////////////////////////////////// 1.579 + 1.580 +XULListitemAccessible:: 1.581 + XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.582 + XULMenuitemAccessible(aContent, aDoc) 1.583 +{ 1.584 + mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None, 1.585 + nsGkAtoms::type, 1.586 + nsGkAtoms::checkbox, 1.587 + eCaseMatters); 1.588 + mType = eXULListItemType; 1.589 +} 1.590 + 1.591 +NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible) 1.592 + 1.593 +Accessible* 1.594 +XULListitemAccessible::GetListAccessible() 1.595 +{ 1.596 + if (IsDefunct()) 1.597 + return nullptr; 1.598 + 1.599 + nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem = 1.600 + do_QueryInterface(mContent); 1.601 + if (!listItem) 1.602 + return nullptr; 1.603 + 1.604 + nsCOMPtr<nsIDOMXULSelectControlElement> list; 1.605 + listItem->GetControl(getter_AddRefs(list)); 1.606 + 1.607 + nsCOMPtr<nsIContent> listContent(do_QueryInterface(list)); 1.608 + if (!listContent) 1.609 + return nullptr; 1.610 + 1.611 + return mDoc->GetAccessible(listContent); 1.612 +} 1.613 + 1.614 +//////////////////////////////////////////////////////////////////////////////// 1.615 +// XULListitemAccessible Accessible 1.616 + 1.617 +void 1.618 +XULListitemAccessible::Description(nsString& aDesc) 1.619 +{ 1.620 + AccessibleWrap::Description(aDesc); 1.621 +} 1.622 + 1.623 +//////////////////////////////////////////////////////////////////////////////// 1.624 +// XULListitemAccessible. nsIAccessible 1.625 + 1.626 +/** 1.627 + * If there is a Listcell as a child ( not anonymous ) use it, otherwise 1.628 + * default to getting the name from GetXULName 1.629 + */ 1.630 +ENameValueFlag 1.631 +XULListitemAccessible::NativeName(nsString& aName) 1.632 +{ 1.633 + nsIContent* childContent = mContent->GetFirstChild(); 1.634 + if (childContent) { 1.635 + if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell, 1.636 + kNameSpaceID_XUL)) { 1.637 + childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName); 1.638 + return eNameOK; 1.639 + } 1.640 + } 1.641 + 1.642 + return Accessible::NativeName(aName); 1.643 +} 1.644 + 1.645 +role 1.646 +XULListitemAccessible::NativeRole() 1.647 +{ 1.648 + Accessible* list = GetListAccessible(); 1.649 + if (!list) { 1.650 + NS_ERROR("No list accessible for listitem accessible!"); 1.651 + return roles::NOTHING; 1.652 + } 1.653 + 1.654 + if (list->Role() == roles::TABLE) 1.655 + return roles::ROW; 1.656 + 1.657 + if (mIsCheckbox) 1.658 + return roles::CHECK_RICH_OPTION; 1.659 + 1.660 + if (mParent && mParent->Role() == roles::COMBOBOX_LIST) 1.661 + return roles::COMBOBOX_OPTION; 1.662 + 1.663 + return roles::RICH_OPTION; 1.664 +} 1.665 + 1.666 +uint64_t 1.667 +XULListitemAccessible::NativeState() 1.668 +{ 1.669 + if (mIsCheckbox) 1.670 + return XULMenuitemAccessible::NativeState(); 1.671 + 1.672 + uint64_t states = NativeInteractiveState(); 1.673 + 1.674 + nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem = 1.675 + do_QueryInterface(mContent); 1.676 + 1.677 + if (listItem) { 1.678 + bool isSelected; 1.679 + listItem->GetSelected(&isSelected); 1.680 + if (isSelected) 1.681 + states |= states::SELECTED; 1.682 + 1.683 + if (FocusMgr()->IsFocused(this)) 1.684 + states |= states::FOCUSED; 1.685 + } 1.686 + 1.687 + return states; 1.688 +} 1.689 + 1.690 +uint64_t 1.691 +XULListitemAccessible::NativeInteractiveState() const 1.692 +{ 1.693 + return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ? 1.694 + states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE; 1.695 +} 1.696 + 1.697 +NS_IMETHODIMP 1.698 +XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName) 1.699 +{ 1.700 + if (aIndex == eAction_Click && mIsCheckbox) { 1.701 + // check or uncheck 1.702 + uint64_t states = NativeState(); 1.703 + 1.704 + if (states & states::CHECKED) 1.705 + aName.AssignLiteral("uncheck"); 1.706 + else 1.707 + aName.AssignLiteral("check"); 1.708 + 1.709 + return NS_OK; 1.710 + } 1.711 + return NS_ERROR_INVALID_ARG; 1.712 +} 1.713 + 1.714 +bool 1.715 +XULListitemAccessible::CanHaveAnonChildren() 1.716 +{ 1.717 + // That indicates we should walk anonymous children for listitems 1.718 + return true; 1.719 +} 1.720 + 1.721 +//////////////////////////////////////////////////////////////////////////////// 1.722 +// XULListitemAccessible: Widgets 1.723 + 1.724 +Accessible* 1.725 +XULListitemAccessible::ContainerWidget() const 1.726 +{ 1.727 + return Parent(); 1.728 +} 1.729 + 1.730 + 1.731 +//////////////////////////////////////////////////////////////////////////////// 1.732 +// XULListCellAccessible 1.733 +//////////////////////////////////////////////////////////////////////////////// 1.734 + 1.735 +XULListCellAccessible:: 1.736 + XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.737 + HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this) 1.738 +{ 1.739 + mGenericTypes |= eTableCell; 1.740 +} 1.741 + 1.742 +//////////////////////////////////////////////////////////////////////////////// 1.743 +// nsISupports 1.744 + 1.745 +NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible, 1.746 + HyperTextAccessible, 1.747 + nsIAccessibleTableCell) 1.748 + 1.749 +//////////////////////////////////////////////////////////////////////////////// 1.750 +// XULListCellAccessible: nsIAccessibleTableCell implementation 1.751 + 1.752 +TableAccessible* 1.753 +XULListCellAccessible::Table() const 1.754 +{ 1.755 + Accessible* thisRow = Parent(); 1.756 + if (!thisRow || thisRow->Role() != roles::ROW) 1.757 + return nullptr; 1.758 + 1.759 + Accessible* table = thisRow->Parent(); 1.760 + if (!table || table->Role() != roles::TABLE) 1.761 + return nullptr; 1.762 + 1.763 + return table->AsTable(); 1.764 +} 1.765 + 1.766 +uint32_t 1.767 +XULListCellAccessible::ColIdx() const 1.768 +{ 1.769 + Accessible* row = Parent(); 1.770 + if (!row) 1.771 + return 0; 1.772 + 1.773 + int32_t indexInRow = IndexInParent(); 1.774 + uint32_t colIdx = 0; 1.775 + for (int32_t idx = 0; idx < indexInRow; idx++) { 1.776 + Accessible* cell = row->GetChildAt(idx); 1.777 + roles::Role role = cell->Role(); 1.778 + if (role == roles::CELL || role == roles::GRID_CELL || 1.779 + role == roles::ROWHEADER || role == roles::COLUMNHEADER) 1.780 + colIdx++; 1.781 + } 1.782 + 1.783 + return colIdx; 1.784 +} 1.785 + 1.786 +uint32_t 1.787 +XULListCellAccessible::RowIdx() const 1.788 +{ 1.789 + Accessible* row = Parent(); 1.790 + if (!row) 1.791 + return 0; 1.792 + 1.793 + Accessible* table = row->Parent(); 1.794 + if (!table) 1.795 + return 0; 1.796 + 1.797 + int32_t indexInTable = row->IndexInParent(); 1.798 + uint32_t rowIdx = 0; 1.799 + for (int32_t idx = 0; idx < indexInTable; idx++) { 1.800 + row = table->GetChildAt(idx); 1.801 + if (row->Role() == roles::ROW) 1.802 + rowIdx++; 1.803 + } 1.804 + 1.805 + return rowIdx; 1.806 +} 1.807 + 1.808 +void 1.809 +XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells) 1.810 +{ 1.811 + TableAccessible* table = Table(); 1.812 + NS_ASSERTION(table, "cell not in a table!"); 1.813 + if (!table) 1.814 + return; 1.815 + 1.816 + // Get column header cell from XUL listhead. 1.817 + Accessible* list = nullptr; 1.818 + 1.819 + Accessible* tableAcc = table->AsAccessible(); 1.820 + uint32_t tableChildCount = tableAcc->ChildCount(); 1.821 + for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) { 1.822 + Accessible* child = tableAcc->GetChildAt(childIdx); 1.823 + if (child->Role() == roles::LIST) { 1.824 + list = child; 1.825 + break; 1.826 + } 1.827 + } 1.828 + 1.829 + if (list) { 1.830 + Accessible* headerCell = list->GetChildAt(ColIdx()); 1.831 + if (headerCell) { 1.832 + aCells->AppendElement(headerCell); 1.833 + return; 1.834 + } 1.835 + } 1.836 + 1.837 + // No column header cell from XUL markup, try to get it from ARIA markup. 1.838 + TableCellAccessible::ColHeaderCells(aCells); 1.839 +} 1.840 + 1.841 +bool 1.842 +XULListCellAccessible::Selected() 1.843 +{ 1.844 + TableAccessible* table = Table(); 1.845 + NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table) 1.846 + 1.847 + return table->IsRowSelected(RowIdx()); 1.848 +} 1.849 + 1.850 +//////////////////////////////////////////////////////////////////////////////// 1.851 +// XULListCellAccessible. Accessible implementation 1.852 + 1.853 +void 1.854 +XULListCellAccessible::Shutdown() 1.855 +{ 1.856 + mTableCell = nullptr; 1.857 + HyperTextAccessibleWrap::Shutdown(); 1.858 +} 1.859 + 1.860 +role 1.861 +XULListCellAccessible::NativeRole() 1.862 +{ 1.863 + return roles::CELL; 1.864 +} 1.865 + 1.866 +already_AddRefed<nsIPersistentProperties> 1.867 +XULListCellAccessible::NativeAttributes() 1.868 +{ 1.869 + nsCOMPtr<nsIPersistentProperties> attributes = 1.870 + HyperTextAccessibleWrap::NativeAttributes(); 1.871 + 1.872 + // "table-cell-index" attribute 1.873 + TableAccessible* table = Table(); 1.874 + if (!table) // we expect to be in a listbox (table) 1.875 + return attributes.forget(); 1.876 + 1.877 + nsAutoString stringIdx; 1.878 + stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx())); 1.879 + nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx); 1.880 + 1.881 + return attributes.forget(); 1.882 +}