accessible/src/xul/XULListboxAccessible.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "XULListboxAccessible.h"
     8 #include "Accessible-inl.h"
     9 #include "nsAccessibilityService.h"
    10 #include "nsAccUtils.h"
    11 #include "DocAccessible.h"
    12 #include "Role.h"
    13 #include "States.h"
    15 #include "nsComponentManagerUtils.h"
    16 #include "nsIAutoCompleteInput.h"
    17 #include "nsIAutoCompletePopup.h"
    18 #include "nsIDOMXULMenuListElement.h"
    19 #include "nsIDOMXULMultSelectCntrlEl.h"
    20 #include "nsIDOMNodeList.h"
    21 #include "nsIDOMXULPopupElement.h"
    22 #include "nsIDOMXULSelectCntrlItemEl.h"
    23 #include "nsIMutableArray.h"
    24 #include "nsIPersistentProperties2.h"
    26 using namespace mozilla::a11y;
    28 ////////////////////////////////////////////////////////////////////////////////
    29 // XULColumAccessible
    30 ////////////////////////////////////////////////////////////////////////////////
    32 XULColumAccessible::
    33   XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
    34   AccessibleWrap(aContent, aDoc)
    35 {
    36 }
    38 role
    39 XULColumAccessible::NativeRole()
    40 {
    41   return roles::LIST;
    42 }
    44 uint64_t
    45 XULColumAccessible::NativeState()
    46 {
    47   return states::READONLY;
    48 }
    51 ////////////////////////////////////////////////////////////////////////////////
    52 // XULColumnItemAccessible
    53 ////////////////////////////////////////////////////////////////////////////////
    55 XULColumnItemAccessible::
    56   XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
    57   LeafAccessible(aContent, aDoc)
    58 {
    59 }
    61 role
    62 XULColumnItemAccessible::NativeRole()
    63 {
    64   return roles::COLUMNHEADER;
    65 }
    67 uint64_t
    68 XULColumnItemAccessible::NativeState()
    69 {
    70   return states::READONLY;
    71 }
    73 uint8_t
    74 XULColumnItemAccessible::ActionCount()
    75 {
    76   return 1;
    77 }
    79 NS_IMETHODIMP
    80 XULColumnItemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
    81 {
    82   if (aIndex != eAction_Click)
    83     return NS_ERROR_INVALID_ARG;
    85   aName.AssignLiteral("click");
    86   return NS_OK;
    87 }
    89 NS_IMETHODIMP
    90 XULColumnItemAccessible::DoAction(uint8_t aIndex)
    91 {
    92   if (aIndex != eAction_Click)
    93     return NS_ERROR_INVALID_ARG;
    95   DoCommand();
    96   return NS_OK;
    97 }
    99 ////////////////////////////////////////////////////////////////////////////////
   100 // XULListboxAccessible
   101 ////////////////////////////////////////////////////////////////////////////////
   103 XULListboxAccessible::
   104   XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   105   XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
   106 {
   107   nsIContent* parentContent = mContent->GetFlattenedTreeParent();
   108   if (parentContent) {
   109     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
   110       do_QueryInterface(parentContent);
   111     if (autoCompletePopupElm)
   112       mGenericTypes |= eAutoCompletePopup;
   113   }
   114 }
   116 NS_IMPL_ADDREF_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
   117 NS_IMPL_RELEASE_INHERITED(XULListboxAccessible, XULSelectControlAccessible)
   119 nsresult
   120 XULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
   121 {
   122   nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr);
   123   if (*aInstancePtr)
   124     return rv;
   126   if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) {
   127     *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
   128     NS_ADDREF_THIS();
   129     return NS_OK;
   130   }
   132   return NS_ERROR_NO_INTERFACE;
   133 }
   135 ////////////////////////////////////////////////////////////////////////////////
   136 // Accessible
   138 void
   139 XULListboxAccessible::Shutdown()
   140 {
   141   mTable = nullptr;
   142   XULSelectControlAccessible::Shutdown();
   143 }
   145 bool
   146 XULListboxAccessible::IsMulticolumn()
   147 {
   148   int32_t numColumns = 0;
   149   nsresult rv = GetColumnCount(&numColumns);
   150   if (NS_FAILED(rv))
   151     return false;
   153   return numColumns > 1;
   154 }
   156 ////////////////////////////////////////////////////////////////////////////////
   157 // XULListboxAccessible. nsIAccessible
   159 uint64_t
   160 XULListboxAccessible::NativeState()
   161 {
   162   // As a XULListboxAccessible we can have the following states:
   163   //   FOCUSED, READONLY, FOCUSABLE
   165   // Get focus status from base class
   166   uint64_t states = Accessible::NativeState();
   168   // see if we are multiple select if so set ourselves as such
   170   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
   171                             nsGkAtoms::multiple, eCaseMatters)) {
   172       states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
   173   }
   175   return states;
   176 }
   178 /**
   179   * Our value is the label of our ( first ) selected child.
   180   */
   181 void
   182 XULListboxAccessible::Value(nsString& aValue)
   183 {
   184   aValue.Truncate();
   186   nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
   187   if (select) {
   188     nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
   189     select->GetSelectedItem(getter_AddRefs(selectedItem));
   190     if (selectedItem)
   191       selectedItem->GetLabel(aValue);
   192   }
   193 }
   195 role
   196 XULListboxAccessible::NativeRole()
   197 {
   198   // A richlistbox is used with the new autocomplete URL bar, and has a parent
   199   // popup <panel>.
   200   nsCOMPtr<nsIDOMXULPopupElement> xulPopup =
   201     do_QueryInterface(mContent->GetParent());
   202   if (xulPopup)
   203     return roles::COMBOBOX_LIST;
   205   return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
   206 }
   208 ////////////////////////////////////////////////////////////////////////////////
   209 // XULListboxAccessible. nsIAccessibleTable
   211 uint32_t
   212 XULListboxAccessible::ColCount()
   213 {
   214   nsIContent* headContent = nullptr;
   215   for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
   216        childContent = childContent->GetNextSibling()) {
   217     if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols,
   218                                          kNameSpaceID_XUL)) {
   219       headContent = childContent;
   220     }
   221   }
   222   if (!headContent)
   223     return 0;
   225   uint32_t columnCount = 0;
   226   for (nsIContent* childContent = headContent->GetFirstChild(); childContent;
   227        childContent = childContent->GetNextSibling()) {
   228     if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol,
   229                                          kNameSpaceID_XUL)) {
   230       columnCount++;
   231     }
   232   }
   234   return columnCount;
   235 }
   237 uint32_t
   238 XULListboxAccessible::RowCount()
   239 {
   240   nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
   242   uint32_t itemCount = 0;
   243   if(element)
   244     element->GetItemCount(&itemCount);
   246   return itemCount;
   247 }
   249 Accessible*
   250 XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
   251 { 
   252   nsCOMPtr<nsIDOMXULSelectControlElement> control =
   253     do_QueryInterface(mContent);
   254   NS_ENSURE_TRUE(control, nullptr);
   256   nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
   257   control->GetItemAtIndex(aRowIndex, getter_AddRefs(item));
   258   if (!item)
   259     return nullptr;
   261   nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item));
   262   if (!itemContent)
   263     return nullptr;
   265   Accessible* row = mDoc->GetAccessible(itemContent);
   266   NS_ENSURE_TRUE(row, nullptr);
   268   return row->GetChildAt(aColumnIndex);
   269 }
   271 bool
   272 XULListboxAccessible::IsColSelected(uint32_t aColIdx)
   273 {
   274   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   275     do_QueryInterface(mContent);
   276   NS_ASSERTION(control,
   277                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   279   int32_t selectedrowCount = 0;
   280   nsresult rv = control->GetSelectedCount(&selectedrowCount);
   281   NS_ENSURE_SUCCESS(rv, false);
   283   return selectedrowCount == RowCount();
   284 }
   286 bool
   287 XULListboxAccessible::IsRowSelected(uint32_t aRowIdx)
   288 {
   289   nsCOMPtr<nsIDOMXULSelectControlElement> control =
   290     do_QueryInterface(mContent);
   291   NS_ASSERTION(control,
   292                "Doesn't implement nsIDOMXULSelectControlElement.");
   294   nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
   295   nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
   296   NS_ENSURE_SUCCESS(rv, false);
   298   bool isSelected = false;
   299   item->GetSelected(&isSelected);
   300   return isSelected;
   301 }
   303 bool
   304 XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
   305 {
   306   return IsRowSelected(aRowIdx);
   307 }
   309 uint32_t
   310 XULListboxAccessible::SelectedCellCount()
   311 {
   312   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   313     do_QueryInterface(mContent);
   314   NS_ASSERTION(control,
   315                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   317   nsCOMPtr<nsIDOMNodeList> selectedItems;
   318   control->GetSelectedItems(getter_AddRefs(selectedItems));
   319   if (!selectedItems)
   320     return 0;
   322   uint32_t selectedItemsCount = 0;
   323   nsresult rv = selectedItems->GetLength(&selectedItemsCount);
   324   NS_ENSURE_SUCCESS(rv, 0);
   326   return selectedItemsCount * ColCount();
   327 }
   329 uint32_t
   330 XULListboxAccessible::SelectedColCount()
   331 {
   332   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   333     do_QueryInterface(mContent);
   334   NS_ASSERTION(control,
   335                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   337   int32_t selectedRowCount = 0;
   338   nsresult rv = control->GetSelectedCount(&selectedRowCount);
   339   NS_ENSURE_SUCCESS(rv, 0);
   341   return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0;
   342 }
   344 uint32_t
   345 XULListboxAccessible::SelectedRowCount()
   346 {
   347   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   348     do_QueryInterface(mContent);
   349   NS_ASSERTION(control,
   350                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   352   int32_t selectedRowCount = 0;
   353   nsresult rv = control->GetSelectedCount(&selectedRowCount);
   354   NS_ENSURE_SUCCESS(rv, 0);
   356   return selectedRowCount >= 0 ? selectedRowCount : 0;
   357 }
   359 void
   360 XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
   361 {
   362   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   363     do_QueryInterface(mContent);
   364   NS_ASSERTION(control,
   365                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   367   nsCOMPtr<nsIDOMNodeList> selectedItems;
   368   control->GetSelectedItems(getter_AddRefs(selectedItems));
   369   if (!selectedItems)
   370     return;
   372   uint32_t selectedItemsCount = 0;
   373   DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
   374   NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
   376   for (uint32_t index = 0; index < selectedItemsCount; index++) {
   377     nsCOMPtr<nsIDOMNode> itemNode;
   378     selectedItems->Item(index, getter_AddRefs(itemNode));
   379     nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
   380     Accessible* item = mDoc->GetAccessible(itemContent);
   382     if (item) {
   383       uint32_t cellCount = item->ChildCount();
   384       for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) {
   385         Accessible* cell = mChildren[cellIdx];
   386         if (cell->Role() == roles::CELL)
   387           aCells->AppendElement(cell);
   388       }
   389     }
   390   }
   391 }
   393 void
   394 XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
   395 {
   396   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   397     do_QueryInterface(mContent);
   398   NS_ASSERTION(control,
   399                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   401   nsCOMPtr<nsIDOMNodeList> selectedItems;
   402   control->GetSelectedItems(getter_AddRefs(selectedItems));
   403   if (!selectedItems)
   404     return;
   406   uint32_t selectedItemsCount = 0;
   407   DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
   408   NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
   410   uint32_t colCount = ColCount();
   411   aCells->SetCapacity(selectedItemsCount * colCount);
   412   aCells->AppendElements(selectedItemsCount * colCount);
   414   for (uint32_t selItemsIdx = 0, cellsIdx = 0;
   415        selItemsIdx < selectedItemsCount; selItemsIdx++) {
   417     nsCOMPtr<nsIDOMNode> itemNode;
   418     selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode));
   419     nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
   420       do_QueryInterface(itemNode);
   422     if (item) {
   423       int32_t itemIdx = -1;
   424       control->GetIndexOfItem(item, &itemIdx);
   425       if (itemIdx >= 0)
   426         for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
   427           aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
   428     }
   429   }
   430 }
   432 void
   433 XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
   434 {
   435   uint32_t selColCount = SelectedColCount();
   436   aCols->SetCapacity(selColCount);
   438   for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
   439     aCols->AppendElement(colIdx);
   440 }
   442 void
   443 XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
   444 {
   445   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   446     do_QueryInterface(mContent);
   447   NS_ASSERTION(control,
   448                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   450   nsCOMPtr<nsIDOMNodeList> selectedItems;
   451   control->GetSelectedItems(getter_AddRefs(selectedItems));
   452   if (!selectedItems)
   453     return;
   455   uint32_t rowCount = 0;
   456   DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount);
   457   NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
   459   if (!rowCount)
   460     return;
   462   aRows->SetCapacity(rowCount);
   463   aRows->AppendElements(rowCount);
   465   for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
   466     nsCOMPtr<nsIDOMNode> itemNode;
   467     selectedItems->Item(rowIdx, getter_AddRefs(itemNode));
   468     nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
   469       do_QueryInterface(itemNode);
   471     if (item) {
   472       int32_t itemIdx = -1;
   473       control->GetIndexOfItem(item, &itemIdx);
   474       if (itemIdx >= 0)
   475         aRows->ElementAt(rowIdx) = itemIdx;
   476     }
   477   }
   478 }
   480 void
   481 XULListboxAccessible::SelectRow(uint32_t aRowIdx)
   482 {
   483   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   484     do_QueryInterface(mContent);
   485   NS_ASSERTION(control,
   486                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   488   nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
   489   control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
   490   control->SelectItem(item);
   491 }
   493 void
   494 XULListboxAccessible::UnselectRow(uint32_t aRowIdx)
   495 {
   496   nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
   497     do_QueryInterface(mContent);
   498   NS_ASSERTION(control,
   499                "Doesn't implement nsIDOMXULMultiSelectControlElement.");
   501   nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
   502   control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
   503   control->RemoveItemFromSelection(item);
   504 }
   506 ////////////////////////////////////////////////////////////////////////////////
   507 // XULListboxAccessible: Widgets
   509 bool
   510 XULListboxAccessible::IsWidget() const
   511 {
   512   return true;
   513 }
   515 bool
   516 XULListboxAccessible::IsActiveWidget() const
   517 {
   518   if (IsAutoCompletePopup()) {
   519     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
   520       do_QueryInterface(mContent->GetParent());
   522     if (autoCompletePopupElm) {
   523       bool isOpen = false;
   524       autoCompletePopupElm->GetPopupOpen(&isOpen);
   525       return isOpen;
   526     }
   527   }
   528   return FocusMgr()->HasDOMFocus(mContent);
   529 }
   531 bool
   532 XULListboxAccessible::AreItemsOperable() const
   533 {
   534   if (IsAutoCompletePopup()) {
   535     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
   536       do_QueryInterface(mContent->GetParent());
   538     if (autoCompletePopupElm) {
   539       bool isOpen = false;
   540       autoCompletePopupElm->GetPopupOpen(&isOpen);
   541       return isOpen;
   542     }
   543   }
   544   return true;
   545 }
   547 Accessible*
   548 XULListboxAccessible::ContainerWidget() const
   549 {
   550   if (IsAutoCompletePopup()) {
   551     // This works for XUL autocompletes. It doesn't work for HTML forms
   552     // autocomplete because of potential crossprocess calls (when autocomplete
   553     // lives in content process while popup lives in chrome process). If that's
   554     // a problem then rethink Widgets interface.
   555     nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
   556       do_QueryInterface(mContent->GetParent());
   557     if (menuListElm) {
   558       nsCOMPtr<nsIDOMNode> inputElm;
   559       menuListElm->GetInputField(getter_AddRefs(inputElm));
   560       if (inputElm) {
   561         nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
   562         if (inputNode) {
   563           Accessible* input = 
   564             mDoc->GetAccessible(inputNode);
   565           return input ? input->ContainerWidget() : nullptr;
   566         }
   567       }
   568     }
   569   }
   570   return nullptr;
   571 }
   573 ////////////////////////////////////////////////////////////////////////////////
   574 // XULListitemAccessible
   575 ////////////////////////////////////////////////////////////////////////////////
   577 XULListitemAccessible::
   578   XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   579   XULMenuitemAccessible(aContent, aDoc)
   580 {
   581   mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
   582                                       nsGkAtoms::type,
   583                                       nsGkAtoms::checkbox,
   584                                       eCaseMatters);
   585   mType = eXULListItemType;
   586 }
   588 NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)
   590 Accessible* 
   591 XULListitemAccessible::GetListAccessible()
   592 {
   593   if (IsDefunct())
   594     return nullptr;
   596   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
   597     do_QueryInterface(mContent);
   598   if (!listItem)
   599     return nullptr;
   601   nsCOMPtr<nsIDOMXULSelectControlElement> list;
   602   listItem->GetControl(getter_AddRefs(list));
   604   nsCOMPtr<nsIContent> listContent(do_QueryInterface(list));
   605   if (!listContent)
   606     return nullptr;
   608   return mDoc->GetAccessible(listContent);
   609 }
   611 ////////////////////////////////////////////////////////////////////////////////
   612 // XULListitemAccessible Accessible
   614 void
   615 XULListitemAccessible::Description(nsString& aDesc)
   616 {
   617   AccessibleWrap::Description(aDesc);
   618 }
   620 ////////////////////////////////////////////////////////////////////////////////
   621 // XULListitemAccessible. nsIAccessible
   623 /**
   624   * If there is a Listcell as a child ( not anonymous ) use it, otherwise
   625   *   default to getting the name from GetXULName
   626   */
   627 ENameValueFlag
   628 XULListitemAccessible::NativeName(nsString& aName)
   629 {
   630   nsIContent* childContent = mContent->GetFirstChild();
   631   if (childContent) {
   632     if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
   633                                          kNameSpaceID_XUL)) {
   634       childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
   635       return eNameOK;
   636     }
   637   }
   639   return Accessible::NativeName(aName);
   640 }
   642 role
   643 XULListitemAccessible::NativeRole()
   644 {
   645   Accessible* list = GetListAccessible();
   646   if (!list) {
   647     NS_ERROR("No list accessible for listitem accessible!");
   648     return roles::NOTHING;
   649   }
   651   if (list->Role() == roles::TABLE)
   652     return roles::ROW;
   654   if (mIsCheckbox)
   655     return roles::CHECK_RICH_OPTION;
   657   if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
   658     return roles::COMBOBOX_OPTION;
   660   return roles::RICH_OPTION;
   661 }
   663 uint64_t
   664 XULListitemAccessible::NativeState()
   665 {
   666   if (mIsCheckbox)
   667     return XULMenuitemAccessible::NativeState();
   669   uint64_t states = NativeInteractiveState();
   671   nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
   672     do_QueryInterface(mContent);
   674   if (listItem) {
   675     bool isSelected;
   676     listItem->GetSelected(&isSelected);
   677     if (isSelected)
   678       states |= states::SELECTED;
   680     if (FocusMgr()->IsFocused(this))
   681       states |= states::FOCUSED;
   682   }
   684   return states;
   685 }
   687 uint64_t
   688 XULListitemAccessible::NativeInteractiveState() const
   689 {
   690   return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
   691     states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
   692 }
   694 NS_IMETHODIMP
   695 XULListitemAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
   696 {
   697   if (aIndex == eAction_Click && mIsCheckbox) {
   698     // check or uncheck
   699     uint64_t states = NativeState();
   701     if (states & states::CHECKED)
   702       aName.AssignLiteral("uncheck");
   703     else
   704       aName.AssignLiteral("check");
   706     return NS_OK;
   707   }
   708   return NS_ERROR_INVALID_ARG;
   709 }
   711 bool
   712 XULListitemAccessible::CanHaveAnonChildren()
   713 {
   714   // That indicates we should walk anonymous children for listitems
   715   return true;
   716 }
   718 ////////////////////////////////////////////////////////////////////////////////
   719 // XULListitemAccessible: Widgets
   721 Accessible*
   722 XULListitemAccessible::ContainerWidget() const
   723 {
   724   return Parent();
   725 }
   728 ////////////////////////////////////////////////////////////////////////////////
   729 // XULListCellAccessible
   730 ////////////////////////////////////////////////////////////////////////////////
   732 XULListCellAccessible::
   733   XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   734   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
   735 {
   736   mGenericTypes |= eTableCell;
   737 }
   739 ////////////////////////////////////////////////////////////////////////////////
   740 // nsISupports
   742 NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible,
   743                             HyperTextAccessible,
   744                             nsIAccessibleTableCell)
   746 ////////////////////////////////////////////////////////////////////////////////
   747 // XULListCellAccessible: nsIAccessibleTableCell implementation
   749 TableAccessible*
   750 XULListCellAccessible::Table() const
   751 {
   752   Accessible* thisRow = Parent();
   753   if (!thisRow || thisRow->Role() != roles::ROW)
   754     return nullptr;
   756   Accessible* table = thisRow->Parent();
   757   if (!table || table->Role() != roles::TABLE)
   758     return nullptr;
   760   return table->AsTable();
   761 }
   763 uint32_t
   764 XULListCellAccessible::ColIdx() const
   765 {
   766   Accessible* row = Parent();
   767   if (!row)
   768     return 0;
   770   int32_t indexInRow = IndexInParent();
   771   uint32_t colIdx = 0;
   772   for (int32_t idx = 0; idx < indexInRow; idx++) {
   773     Accessible* cell = row->GetChildAt(idx);
   774     roles::Role role = cell->Role();
   775     if (role == roles::CELL || role == roles::GRID_CELL ||
   776         role == roles::ROWHEADER || role == roles::COLUMNHEADER)
   777       colIdx++;
   778   }
   780   return colIdx;
   781 }
   783 uint32_t
   784 XULListCellAccessible::RowIdx() const
   785 {
   786   Accessible* row = Parent();
   787   if (!row)
   788     return 0;
   790   Accessible* table = row->Parent();
   791   if (!table)
   792     return 0;
   794   int32_t indexInTable = row->IndexInParent();
   795   uint32_t rowIdx = 0;
   796   for (int32_t idx = 0; idx < indexInTable; idx++) {
   797     row = table->GetChildAt(idx);
   798     if (row->Role() == roles::ROW)
   799       rowIdx++;
   800   }
   802   return rowIdx;
   803 }
   805 void
   806 XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells)
   807 {
   808   TableAccessible* table = Table();
   809   NS_ASSERTION(table, "cell not in a table!");
   810   if (!table)
   811     return;
   813   // Get column header cell from XUL listhead.
   814   Accessible* list = nullptr;
   816   Accessible* tableAcc = table->AsAccessible();
   817   uint32_t tableChildCount = tableAcc->ChildCount();
   818   for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) {
   819     Accessible* child = tableAcc->GetChildAt(childIdx);
   820     if (child->Role() == roles::LIST) {
   821       list = child;
   822       break;
   823     }
   824   }
   826   if (list) {
   827     Accessible* headerCell = list->GetChildAt(ColIdx());
   828     if (headerCell) {
   829       aCells->AppendElement(headerCell);
   830       return;
   831     }
   832   }
   834   // No column header cell from XUL markup, try to get it from ARIA markup.
   835   TableCellAccessible::ColHeaderCells(aCells);
   836 }
   838 bool
   839 XULListCellAccessible::Selected()
   840 {
   841   TableAccessible* table = Table();
   842   NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table)
   844   return table->IsRowSelected(RowIdx());
   845 }
   847 ////////////////////////////////////////////////////////////////////////////////
   848 // XULListCellAccessible. Accessible implementation
   850 void
   851 XULListCellAccessible::Shutdown()
   852 {
   853   mTableCell = nullptr;
   854   HyperTextAccessibleWrap::Shutdown();
   855 }
   857 role
   858 XULListCellAccessible::NativeRole()
   859 {
   860   return roles::CELL;
   861 }
   863 already_AddRefed<nsIPersistentProperties>
   864 XULListCellAccessible::NativeAttributes()
   865 {
   866   nsCOMPtr<nsIPersistentProperties> attributes =
   867     HyperTextAccessibleWrap::NativeAttributes();
   869   // "table-cell-index" attribute
   870   TableAccessible* table = Table();
   871   if (!table) // we expect to be in a listbox (table)
   872     return attributes.forget();
   874   nsAutoString stringIdx;
   875   stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
   876   nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
   878   return attributes.forget();
   879 }

mercurial