XULListboxAccessible.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "XULListboxAccessible.h"
  6. #include "Accessible-inl.h"
  7. #include "nsAccessibilityService.h"
  8. #include "nsAccUtils.h"
  9. #include "DocAccessible.h"
  10. #include "Role.h"
  11. #include "States.h"
  12. #include "nsComponentManagerUtils.h"
  13. #include "nsIAutoCompleteInput.h"
  14. #include "nsIAutoCompletePopup.h"
  15. #include "nsIDOMXULMenuListElement.h"
  16. #include "nsIDOMXULMultSelectCntrlEl.h"
  17. #include "nsIDOMNodeList.h"
  18. #include "nsIDOMXULPopupElement.h"
  19. #include "nsIDOMXULSelectCntrlItemEl.h"
  20. #include "nsIMutableArray.h"
  21. #include "nsIPersistentProperties2.h"
  22. using namespace mozilla::a11y;
  23. ////////////////////////////////////////////////////////////////////////////////
  24. // XULColumAccessible
  25. ////////////////////////////////////////////////////////////////////////////////
  26. XULColumAccessible::
  27. XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  28. AccessibleWrap(aContent, aDoc)
  29. {
  30. }
  31. role
  32. XULColumAccessible::NativeRole()
  33. {
  34. return roles::LIST;
  35. }
  36. uint64_t
  37. XULColumAccessible::NativeState()
  38. {
  39. return states::READONLY;
  40. }
  41. ////////////////////////////////////////////////////////////////////////////////
  42. // XULColumnItemAccessible
  43. ////////////////////////////////////////////////////////////////////////////////
  44. XULColumnItemAccessible::
  45. XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  46. LeafAccessible(aContent, aDoc)
  47. {
  48. }
  49. role
  50. XULColumnItemAccessible::NativeRole()
  51. {
  52. return roles::COLUMNHEADER;
  53. }
  54. uint64_t
  55. XULColumnItemAccessible::NativeState()
  56. {
  57. return states::READONLY;
  58. }
  59. uint8_t
  60. XULColumnItemAccessible::ActionCount()
  61. {
  62. return 1;
  63. }
  64. void
  65. XULColumnItemAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
  66. {
  67. if (aIndex == eAction_Click)
  68. aName.AssignLiteral("click");
  69. }
  70. bool
  71. XULColumnItemAccessible::DoAction(uint8_t aIndex)
  72. {
  73. if (aIndex != eAction_Click)
  74. return false;
  75. DoCommand();
  76. return true;
  77. }
  78. ////////////////////////////////////////////////////////////////////////////////
  79. // XULListboxAccessible
  80. ////////////////////////////////////////////////////////////////////////////////
  81. XULListboxAccessible::
  82. XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  83. XULSelectControlAccessible(aContent, aDoc)
  84. {
  85. nsIContent* parentContent = mContent->GetFlattenedTreeParent();
  86. if (parentContent) {
  87. nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
  88. do_QueryInterface(parentContent);
  89. if (autoCompletePopupElm)
  90. mGenericTypes |= eAutoCompletePopup;
  91. }
  92. if (IsMulticolumn())
  93. mGenericTypes |= eTable;
  94. }
  95. ////////////////////////////////////////////////////////////////////////////////
  96. // XULListboxAccessible: Accessible
  97. uint64_t
  98. XULListboxAccessible::NativeState()
  99. {
  100. // As a XULListboxAccessible we can have the following states:
  101. // FOCUSED, READONLY, FOCUSABLE
  102. // Get focus status from base class
  103. uint64_t states = Accessible::NativeState();
  104. // see if we are multiple select if so set ourselves as such
  105. if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
  106. nsGkAtoms::multiple, eCaseMatters)) {
  107. states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
  108. }
  109. return states;
  110. }
  111. /**
  112. * Our value is the label of our ( first ) selected child.
  113. */
  114. void
  115. XULListboxAccessible::Value(nsString& aValue)
  116. {
  117. aValue.Truncate();
  118. nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
  119. if (select) {
  120. nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
  121. select->GetSelectedItem(getter_AddRefs(selectedItem));
  122. if (selectedItem)
  123. selectedItem->GetLabel(aValue);
  124. }
  125. }
  126. role
  127. XULListboxAccessible::NativeRole()
  128. {
  129. // A richlistbox is used with the new autocomplete URL bar, and has a parent
  130. // popup <panel>.
  131. nsCOMPtr<nsIDOMXULPopupElement> xulPopup =
  132. do_QueryInterface(mContent->GetParent());
  133. if (xulPopup)
  134. return roles::COMBOBOX_LIST;
  135. return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
  136. }
  137. ////////////////////////////////////////////////////////////////////////////////
  138. // XULListboxAccessible: Table
  139. uint32_t
  140. XULListboxAccessible::ColCount()
  141. {
  142. nsIContent* headContent = nullptr;
  143. for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
  144. childContent = childContent->GetNextSibling()) {
  145. if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols,
  146. kNameSpaceID_XUL)) {
  147. headContent = childContent;
  148. }
  149. }
  150. if (!headContent)
  151. return 0;
  152. uint32_t columnCount = 0;
  153. for (nsIContent* childContent = headContent->GetFirstChild(); childContent;
  154. childContent = childContent->GetNextSibling()) {
  155. if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol,
  156. kNameSpaceID_XUL)) {
  157. columnCount++;
  158. }
  159. }
  160. return columnCount;
  161. }
  162. uint32_t
  163. XULListboxAccessible::RowCount()
  164. {
  165. nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
  166. uint32_t itemCount = 0;
  167. if(element)
  168. element->GetItemCount(&itemCount);
  169. return itemCount;
  170. }
  171. Accessible*
  172. XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
  173. {
  174. nsCOMPtr<nsIDOMXULSelectControlElement> control =
  175. do_QueryInterface(mContent);
  176. NS_ENSURE_TRUE(control, nullptr);
  177. nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
  178. control->GetItemAtIndex(aRowIndex, getter_AddRefs(item));
  179. if (!item)
  180. return nullptr;
  181. nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item));
  182. if (!itemContent)
  183. return nullptr;
  184. Accessible* row = mDoc->GetAccessible(itemContent);
  185. NS_ENSURE_TRUE(row, nullptr);
  186. return row->GetChildAt(aColumnIndex);
  187. }
  188. bool
  189. XULListboxAccessible::IsColSelected(uint32_t aColIdx)
  190. {
  191. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  192. do_QueryInterface(mContent);
  193. NS_ASSERTION(control,
  194. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  195. int32_t selectedrowCount = 0;
  196. nsresult rv = control->GetSelectedCount(&selectedrowCount);
  197. NS_ENSURE_SUCCESS(rv, false);
  198. return selectedrowCount == static_cast<int32_t>(RowCount());
  199. }
  200. bool
  201. XULListboxAccessible::IsRowSelected(uint32_t aRowIdx)
  202. {
  203. nsCOMPtr<nsIDOMXULSelectControlElement> control =
  204. do_QueryInterface(mContent);
  205. NS_ASSERTION(control,
  206. "Doesn't implement nsIDOMXULSelectControlElement.");
  207. nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
  208. nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
  209. NS_ENSURE_SUCCESS(rv, false);
  210. bool isSelected = false;
  211. item->GetSelected(&isSelected);
  212. return isSelected;
  213. }
  214. bool
  215. XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
  216. {
  217. return IsRowSelected(aRowIdx);
  218. }
  219. uint32_t
  220. XULListboxAccessible::SelectedCellCount()
  221. {
  222. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  223. do_QueryInterface(mContent);
  224. NS_ASSERTION(control,
  225. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  226. nsCOMPtr<nsIDOMNodeList> selectedItems;
  227. control->GetSelectedItems(getter_AddRefs(selectedItems));
  228. if (!selectedItems)
  229. return 0;
  230. uint32_t selectedItemsCount = 0;
  231. nsresult rv = selectedItems->GetLength(&selectedItemsCount);
  232. NS_ENSURE_SUCCESS(rv, 0);
  233. return selectedItemsCount * ColCount();
  234. }
  235. uint32_t
  236. XULListboxAccessible::SelectedColCount()
  237. {
  238. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  239. do_QueryInterface(mContent);
  240. NS_ASSERTION(control,
  241. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  242. int32_t selectedRowCount = 0;
  243. nsresult rv = control->GetSelectedCount(&selectedRowCount);
  244. NS_ENSURE_SUCCESS(rv, 0);
  245. return selectedRowCount > 0 &&
  246. selectedRowCount == static_cast<int32_t>(RowCount()) ? ColCount() : 0;
  247. }
  248. uint32_t
  249. XULListboxAccessible::SelectedRowCount()
  250. {
  251. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  252. do_QueryInterface(mContent);
  253. NS_ASSERTION(control,
  254. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  255. int32_t selectedRowCount = 0;
  256. nsresult rv = control->GetSelectedCount(&selectedRowCount);
  257. NS_ENSURE_SUCCESS(rv, 0);
  258. return selectedRowCount >= 0 ? selectedRowCount : 0;
  259. }
  260. void
  261. XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
  262. {
  263. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  264. do_QueryInterface(mContent);
  265. NS_ASSERTION(control,
  266. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  267. nsCOMPtr<nsIDOMNodeList> selectedItems;
  268. control->GetSelectedItems(getter_AddRefs(selectedItems));
  269. if (!selectedItems)
  270. return;
  271. uint32_t selectedItemsCount = 0;
  272. DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
  273. NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
  274. for (uint32_t index = 0; index < selectedItemsCount; index++) {
  275. nsCOMPtr<nsIDOMNode> itemNode;
  276. selectedItems->Item(index, getter_AddRefs(itemNode));
  277. nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
  278. Accessible* item = mDoc->GetAccessible(itemContent);
  279. if (item) {
  280. uint32_t cellCount = item->ChildCount();
  281. for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) {
  282. Accessible* cell = mChildren[cellIdx];
  283. if (cell->Role() == roles::CELL)
  284. aCells->AppendElement(cell);
  285. }
  286. }
  287. }
  288. }
  289. void
  290. XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
  291. {
  292. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  293. do_QueryInterface(mContent);
  294. NS_ASSERTION(control,
  295. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  296. nsCOMPtr<nsIDOMNodeList> selectedItems;
  297. control->GetSelectedItems(getter_AddRefs(selectedItems));
  298. if (!selectedItems)
  299. return;
  300. uint32_t selectedItemsCount = 0;
  301. DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
  302. NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
  303. uint32_t colCount = ColCount();
  304. aCells->SetCapacity(selectedItemsCount * colCount);
  305. aCells->AppendElements(selectedItemsCount * colCount);
  306. for (uint32_t selItemsIdx = 0, cellsIdx = 0;
  307. selItemsIdx < selectedItemsCount; selItemsIdx++) {
  308. nsCOMPtr<nsIDOMNode> itemNode;
  309. selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode));
  310. nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
  311. do_QueryInterface(itemNode);
  312. if (item) {
  313. int32_t itemIdx = -1;
  314. control->GetIndexOfItem(item, &itemIdx);
  315. if (itemIdx >= 0)
  316. for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
  317. aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
  318. }
  319. }
  320. }
  321. void
  322. XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
  323. {
  324. uint32_t selColCount = SelectedColCount();
  325. aCols->SetCapacity(selColCount);
  326. for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
  327. aCols->AppendElement(colIdx);
  328. }
  329. void
  330. XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
  331. {
  332. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  333. do_QueryInterface(mContent);
  334. NS_ASSERTION(control,
  335. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  336. nsCOMPtr<nsIDOMNodeList> selectedItems;
  337. control->GetSelectedItems(getter_AddRefs(selectedItems));
  338. if (!selectedItems)
  339. return;
  340. uint32_t rowCount = 0;
  341. DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount);
  342. NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
  343. if (!rowCount)
  344. return;
  345. aRows->SetCapacity(rowCount);
  346. aRows->AppendElements(rowCount);
  347. for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
  348. nsCOMPtr<nsIDOMNode> itemNode;
  349. selectedItems->Item(rowIdx, getter_AddRefs(itemNode));
  350. nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
  351. do_QueryInterface(itemNode);
  352. if (item) {
  353. int32_t itemIdx = -1;
  354. control->GetIndexOfItem(item, &itemIdx);
  355. if (itemIdx >= 0)
  356. aRows->ElementAt(rowIdx) = itemIdx;
  357. }
  358. }
  359. }
  360. void
  361. XULListboxAccessible::SelectRow(uint32_t aRowIdx)
  362. {
  363. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  364. do_QueryInterface(mContent);
  365. NS_ASSERTION(control,
  366. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  367. nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
  368. control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
  369. control->SelectItem(item);
  370. }
  371. void
  372. XULListboxAccessible::UnselectRow(uint32_t aRowIdx)
  373. {
  374. nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
  375. do_QueryInterface(mContent);
  376. NS_ASSERTION(control,
  377. "Doesn't implement nsIDOMXULMultiSelectControlElement.");
  378. nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
  379. control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
  380. control->RemoveItemFromSelection(item);
  381. }
  382. ////////////////////////////////////////////////////////////////////////////////
  383. // XULListboxAccessible: Widgets
  384. bool
  385. XULListboxAccessible::IsWidget() const
  386. {
  387. return true;
  388. }
  389. bool
  390. XULListboxAccessible::IsActiveWidget() const
  391. {
  392. if (IsAutoCompletePopup()) {
  393. nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
  394. do_QueryInterface(mContent->GetParent());
  395. if (autoCompletePopupElm) {
  396. bool isOpen = false;
  397. autoCompletePopupElm->GetPopupOpen(&isOpen);
  398. return isOpen;
  399. }
  400. }
  401. return FocusMgr()->HasDOMFocus(mContent);
  402. }
  403. bool
  404. XULListboxAccessible::AreItemsOperable() const
  405. {
  406. if (IsAutoCompletePopup()) {
  407. nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
  408. do_QueryInterface(mContent->GetParent());
  409. if (autoCompletePopupElm) {
  410. bool isOpen = false;
  411. autoCompletePopupElm->GetPopupOpen(&isOpen);
  412. return isOpen;
  413. }
  414. }
  415. return true;
  416. }
  417. Accessible*
  418. XULListboxAccessible::ContainerWidget() const
  419. {
  420. if (IsAutoCompletePopup()) {
  421. // This works for XUL autocompletes. It doesn't work for HTML forms
  422. // autocomplete because of potential crossprocess calls (when autocomplete
  423. // lives in content process while popup lives in chrome process). If that's
  424. // a problem then rethink Widgets interface.
  425. nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
  426. do_QueryInterface(mContent->GetParent());
  427. if (menuListElm) {
  428. nsCOMPtr<nsIDOMNode> inputElm;
  429. menuListElm->GetInputField(getter_AddRefs(inputElm));
  430. if (inputElm) {
  431. nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
  432. if (inputNode) {
  433. Accessible* input =
  434. mDoc->GetAccessible(inputNode);
  435. return input ? input->ContainerWidget() : nullptr;
  436. }
  437. }
  438. }
  439. }
  440. return nullptr;
  441. }
  442. ////////////////////////////////////////////////////////////////////////////////
  443. // XULListitemAccessible
  444. ////////////////////////////////////////////////////////////////////////////////
  445. XULListitemAccessible::
  446. XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  447. XULMenuitemAccessible(aContent, aDoc)
  448. {
  449. mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
  450. nsGkAtoms::type,
  451. nsGkAtoms::checkbox,
  452. eCaseMatters);
  453. mType = eXULListItemType;
  454. // Walk XBL anonymous children for list items. Overrides the flag value from
  455. // base XULMenuitemAccessible class.
  456. mStateFlags &= ~eNoXBLKids;
  457. }
  458. XULListitemAccessible::~XULListitemAccessible()
  459. {
  460. }
  461. NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)
  462. Accessible*
  463. XULListitemAccessible::GetListAccessible() const
  464. {
  465. if (IsDefunct())
  466. return nullptr;
  467. nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
  468. do_QueryInterface(mContent);
  469. if (!listItem)
  470. return nullptr;
  471. nsCOMPtr<nsIDOMXULSelectControlElement> list;
  472. listItem->GetControl(getter_AddRefs(list));
  473. nsCOMPtr<nsIContent> listContent(do_QueryInterface(list));
  474. if (!listContent)
  475. return nullptr;
  476. return mDoc->GetAccessible(listContent);
  477. }
  478. ////////////////////////////////////////////////////////////////////////////////
  479. // XULListitemAccessible Accessible
  480. void
  481. XULListitemAccessible::Description(nsString& aDesc)
  482. {
  483. AccessibleWrap::Description(aDesc);
  484. }
  485. ////////////////////////////////////////////////////////////////////////////////
  486. // XULListitemAccessible: Accessible
  487. /**
  488. * If there is a Listcell as a child ( not anonymous ) use it, otherwise
  489. * default to getting the name from GetXULName
  490. */
  491. ENameValueFlag
  492. XULListitemAccessible::NativeName(nsString& aName)
  493. {
  494. nsIContent* childContent = mContent->GetFirstChild();
  495. if (childContent) {
  496. if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
  497. kNameSpaceID_XUL)) {
  498. childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
  499. return eNameOK;
  500. }
  501. }
  502. return Accessible::NativeName(aName);
  503. }
  504. role
  505. XULListitemAccessible::NativeRole()
  506. {
  507. Accessible* list = GetListAccessible();
  508. if (!list) {
  509. NS_ERROR("No list accessible for listitem accessible!");
  510. return roles::NOTHING;
  511. }
  512. if (list->Role() == roles::TABLE)
  513. return roles::ROW;
  514. if (mIsCheckbox)
  515. return roles::CHECK_RICH_OPTION;
  516. if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
  517. return roles::COMBOBOX_OPTION;
  518. return roles::RICH_OPTION;
  519. }
  520. uint64_t
  521. XULListitemAccessible::NativeState()
  522. {
  523. if (mIsCheckbox)
  524. return XULMenuitemAccessible::NativeState();
  525. uint64_t states = NativeInteractiveState();
  526. nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
  527. do_QueryInterface(mContent);
  528. if (listItem) {
  529. bool isSelected;
  530. listItem->GetSelected(&isSelected);
  531. if (isSelected)
  532. states |= states::SELECTED;
  533. if (FocusMgr()->IsFocused(this))
  534. states |= states::FOCUSED;
  535. }
  536. return states;
  537. }
  538. uint64_t
  539. XULListitemAccessible::NativeInteractiveState() const
  540. {
  541. return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
  542. states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
  543. }
  544. void
  545. XULListitemAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
  546. {
  547. if (aIndex == eAction_Click && mIsCheckbox) {
  548. uint64_t states = NativeState();
  549. if (states & states::CHECKED)
  550. aName.AssignLiteral("uncheck");
  551. else
  552. aName.AssignLiteral("check");
  553. }
  554. }
  555. ////////////////////////////////////////////////////////////////////////////////
  556. // XULListitemAccessible: Widgets
  557. Accessible*
  558. XULListitemAccessible::ContainerWidget() const
  559. {
  560. return Parent();
  561. }
  562. ////////////////////////////////////////////////////////////////////////////////
  563. // XULListCellAccessible
  564. ////////////////////////////////////////////////////////////////////////////////
  565. XULListCellAccessible::
  566. XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  567. HyperTextAccessibleWrap(aContent, aDoc)
  568. {
  569. mGenericTypes |= eTableCell;
  570. }
  571. ////////////////////////////////////////////////////////////////////////////////
  572. // nsISupports
  573. NS_IMPL_ISUPPORTS_INHERITED0(XULListCellAccessible,
  574. HyperTextAccessible)
  575. ////////////////////////////////////////////////////////////////////////////////
  576. // XULListCellAccessible: TableCell
  577. TableAccessible*
  578. XULListCellAccessible::Table() const
  579. {
  580. Accessible* thisRow = Parent();
  581. if (!thisRow || thisRow->Role() != roles::ROW)
  582. return nullptr;
  583. Accessible* table = thisRow->Parent();
  584. if (!table || table->Role() != roles::TABLE)
  585. return nullptr;
  586. return table->AsTable();
  587. }
  588. uint32_t
  589. XULListCellAccessible::ColIdx() const
  590. {
  591. Accessible* row = Parent();
  592. if (!row)
  593. return 0;
  594. int32_t indexInRow = IndexInParent();
  595. uint32_t colIdx = 0;
  596. for (int32_t idx = 0; idx < indexInRow; idx++) {
  597. Accessible* cell = row->GetChildAt(idx);
  598. roles::Role role = cell->Role();
  599. if (role == roles::CELL || role == roles::GRID_CELL ||
  600. role == roles::ROWHEADER || role == roles::COLUMNHEADER)
  601. colIdx++;
  602. }
  603. return colIdx;
  604. }
  605. uint32_t
  606. XULListCellAccessible::RowIdx() const
  607. {
  608. Accessible* row = Parent();
  609. if (!row)
  610. return 0;
  611. Accessible* table = row->Parent();
  612. if (!table)
  613. return 0;
  614. int32_t indexInTable = row->IndexInParent();
  615. uint32_t rowIdx = 0;
  616. for (int32_t idx = 0; idx < indexInTable; idx++) {
  617. row = table->GetChildAt(idx);
  618. if (row->Role() == roles::ROW)
  619. rowIdx++;
  620. }
  621. return rowIdx;
  622. }
  623. void
  624. XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells)
  625. {
  626. TableAccessible* table = Table();
  627. NS_ASSERTION(table, "cell not in a table!");
  628. if (!table)
  629. return;
  630. // Get column header cell from XUL listhead.
  631. Accessible* list = nullptr;
  632. Accessible* tableAcc = table->AsAccessible();
  633. uint32_t tableChildCount = tableAcc->ChildCount();
  634. for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) {
  635. Accessible* child = tableAcc->GetChildAt(childIdx);
  636. if (child->Role() == roles::LIST) {
  637. list = child;
  638. break;
  639. }
  640. }
  641. if (list) {
  642. Accessible* headerCell = list->GetChildAt(ColIdx());
  643. if (headerCell) {
  644. aCells->AppendElement(headerCell);
  645. return;
  646. }
  647. }
  648. // No column header cell from XUL markup, try to get it from ARIA markup.
  649. TableCellAccessible::ColHeaderCells(aCells);
  650. }
  651. bool
  652. XULListCellAccessible::Selected()
  653. {
  654. TableAccessible* table = Table();
  655. NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table)
  656. return table->IsRowSelected(RowIdx());
  657. }
  658. ////////////////////////////////////////////////////////////////////////////////
  659. // XULListCellAccessible. Accessible implementation
  660. role
  661. XULListCellAccessible::NativeRole()
  662. {
  663. return roles::CELL;
  664. }
  665. already_AddRefed<nsIPersistentProperties>
  666. XULListCellAccessible::NativeAttributes()
  667. {
  668. nsCOMPtr<nsIPersistentProperties> attributes =
  669. HyperTextAccessibleWrap::NativeAttributes();
  670. // "table-cell-index" attribute
  671. TableAccessible* table = Table();
  672. if (!table) // we expect to be in a listbox (table)
  673. return attributes.forget();
  674. nsAutoString stringIdx;
  675. stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
  676. nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
  677. return attributes.forget();
  678. }