XULComboboxAccessible.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 "XULComboboxAccessible.h"
  6. #include "Accessible-inl.h"
  7. #include "nsAccessibilityService.h"
  8. #include "DocAccessible.h"
  9. #include "nsCoreUtils.h"
  10. #include "Role.h"
  11. #include "States.h"
  12. #include "nsIAutoCompleteInput.h"
  13. #include "nsIDOMXULMenuListElement.h"
  14. #include "nsIDOMXULSelectCntrlItemEl.h"
  15. using namespace mozilla::a11y;
  16. ////////////////////////////////////////////////////////////////////////////////
  17. // XULComboboxAccessible
  18. ////////////////////////////////////////////////////////////////////////////////
  19. XULComboboxAccessible::
  20. XULComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  21. AccessibleWrap(aContent, aDoc)
  22. {
  23. if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
  24. nsGkAtoms::autocomplete, eIgnoreCase))
  25. mGenericTypes |= eAutoComplete;
  26. else
  27. mGenericTypes |= eCombobox;
  28. // Both the XUL <textbox type="autocomplete"> and <menulist editable="true">
  29. // widgets use XULComboboxAccessible. We need to walk the anonymous children
  30. // for these so that the entry field is a child. Otherwise no XBL children.
  31. if (!mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL) &&
  32. !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
  33. nsGkAtoms::_true, eIgnoreCase)) {
  34. mStateFlags |= eNoXBLKids;
  35. }
  36. }
  37. role
  38. XULComboboxAccessible::NativeRole()
  39. {
  40. return IsAutoComplete() ? roles::AUTOCOMPLETE : roles::COMBOBOX;
  41. }
  42. uint64_t
  43. XULComboboxAccessible::NativeState()
  44. {
  45. // As a nsComboboxAccessible we can have the following states:
  46. // STATE_FOCUSED
  47. // STATE_FOCUSABLE
  48. // STATE_HASPOPUP
  49. // STATE_EXPANDED
  50. // STATE_COLLAPSED
  51. // Get focus status from base class
  52. uint64_t state = Accessible::NativeState();
  53. nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
  54. if (menuList) {
  55. bool isOpen = false;
  56. menuList->GetOpen(&isOpen);
  57. if (isOpen)
  58. state |= states::EXPANDED;
  59. else
  60. state |= states::COLLAPSED;
  61. }
  62. return state | states::HASPOPUP;
  63. }
  64. void
  65. XULComboboxAccessible::Description(nsString& aDescription)
  66. {
  67. aDescription.Truncate();
  68. // Use description of currently focused option
  69. nsCOMPtr<nsIDOMXULMenuListElement> menuListElm(do_QueryInterface(mContent));
  70. if (!menuListElm)
  71. return;
  72. nsCOMPtr<nsIDOMXULSelectControlItemElement> focusedOptionItem;
  73. menuListElm->GetSelectedItem(getter_AddRefs(focusedOptionItem));
  74. nsCOMPtr<nsIContent> focusedOptionContent =
  75. do_QueryInterface(focusedOptionItem);
  76. if (focusedOptionContent && mDoc) {
  77. Accessible* focusedOptionAcc = mDoc->GetAccessible(focusedOptionContent);
  78. if (focusedOptionAcc)
  79. focusedOptionAcc->Description(aDescription);
  80. }
  81. }
  82. void
  83. XULComboboxAccessible::Value(nsString& aValue)
  84. {
  85. aValue.Truncate();
  86. // The value is the option or text shown entered in the combobox.
  87. nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
  88. if (menuList)
  89. menuList->GetLabel(aValue);
  90. }
  91. uint8_t
  92. XULComboboxAccessible::ActionCount()
  93. {
  94. // Just one action (click).
  95. return 1;
  96. }
  97. bool
  98. XULComboboxAccessible::DoAction(uint8_t aIndex)
  99. {
  100. if (aIndex != XULComboboxAccessible::eAction_Click)
  101. return false;
  102. // Programmaticaly toggle the combo box.
  103. nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
  104. if (!menuList)
  105. return false;
  106. bool isDroppedDown = false;
  107. menuList->GetOpen(&isDroppedDown);
  108. menuList->SetOpen(!isDroppedDown);
  109. return true;
  110. }
  111. void
  112. XULComboboxAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
  113. {
  114. aName.Truncate();
  115. if (aIndex != XULComboboxAccessible::eAction_Click)
  116. return;
  117. nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
  118. if (!menuList)
  119. return;
  120. bool isDroppedDown = false;
  121. menuList->GetOpen(&isDroppedDown);
  122. if (isDroppedDown)
  123. aName.AssignLiteral("close");
  124. else
  125. aName.AssignLiteral("open");
  126. }
  127. ////////////////////////////////////////////////////////////////////////////////
  128. // Widgets
  129. bool
  130. XULComboboxAccessible::IsActiveWidget() const
  131. {
  132. if (IsAutoComplete() ||
  133. mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
  134. nsGkAtoms::_true, eIgnoreCase)) {
  135. int32_t childCount = mChildren.Length();
  136. for (int32_t idx = 0; idx < childCount; idx++) {
  137. Accessible* child = mChildren[idx];
  138. if (child->Role() == roles::ENTRY)
  139. return FocusMgr()->HasDOMFocus(child->GetContent());
  140. }
  141. return false;
  142. }
  143. return FocusMgr()->HasDOMFocus(mContent);
  144. }
  145. bool
  146. XULComboboxAccessible::AreItemsOperable() const
  147. {
  148. if (IsAutoComplete()) {
  149. nsCOMPtr<nsIAutoCompleteInput> autoCompleteInputElm =
  150. do_QueryInterface(mContent);
  151. if (autoCompleteInputElm) {
  152. bool isOpen = false;
  153. autoCompleteInputElm->GetPopupOpen(&isOpen);
  154. return isOpen;
  155. }
  156. return false;
  157. }
  158. nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = do_QueryInterface(mContent);
  159. if (menuListElm) {
  160. bool isOpen = false;
  161. menuListElm->GetOpen(&isOpen);
  162. return isOpen;
  163. }
  164. return false;
  165. }