accessible/src/xul/XULComboboxAccessible.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "XULComboboxAccessible.h"
michael@0 7
michael@0 8 #include "Accessible-inl.h"
michael@0 9 #include "nsAccessibilityService.h"
michael@0 10 #include "DocAccessible.h"
michael@0 11 #include "nsCoreUtils.h"
michael@0 12 #include "Role.h"
michael@0 13 #include "States.h"
michael@0 14
michael@0 15 #include "nsIAutoCompleteInput.h"
michael@0 16 #include "nsIDOMXULMenuListElement.h"
michael@0 17 #include "nsIDOMXULSelectCntrlItemEl.h"
michael@0 18
michael@0 19 using namespace mozilla::a11y;
michael@0 20
michael@0 21 ////////////////////////////////////////////////////////////////////////////////
michael@0 22 // XULComboboxAccessible
michael@0 23 ////////////////////////////////////////////////////////////////////////////////
michael@0 24
michael@0 25 XULComboboxAccessible::
michael@0 26 XULComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 27 AccessibleWrap(aContent, aDoc)
michael@0 28 {
michael@0 29 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
michael@0 30 nsGkAtoms::autocomplete, eIgnoreCase))
michael@0 31 mGenericTypes |= eAutoComplete;
michael@0 32 else
michael@0 33 mGenericTypes |= eCombobox;
michael@0 34 }
michael@0 35
michael@0 36 role
michael@0 37 XULComboboxAccessible::NativeRole()
michael@0 38 {
michael@0 39 return IsAutoComplete() ? roles::AUTOCOMPLETE : roles::COMBOBOX;
michael@0 40 }
michael@0 41
michael@0 42 uint64_t
michael@0 43 XULComboboxAccessible::NativeState()
michael@0 44 {
michael@0 45 // As a nsComboboxAccessible we can have the following states:
michael@0 46 // STATE_FOCUSED
michael@0 47 // STATE_FOCUSABLE
michael@0 48 // STATE_HASPOPUP
michael@0 49 // STATE_EXPANDED
michael@0 50 // STATE_COLLAPSED
michael@0 51
michael@0 52 // Get focus status from base class
michael@0 53 uint64_t state = Accessible::NativeState();
michael@0 54
michael@0 55 nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
michael@0 56 if (menuList) {
michael@0 57 bool isOpen = false;
michael@0 58 menuList->GetOpen(&isOpen);
michael@0 59 if (isOpen)
michael@0 60 state |= states::EXPANDED;
michael@0 61 else
michael@0 62 state |= states::COLLAPSED;
michael@0 63 }
michael@0 64
michael@0 65 return state | states::HASPOPUP;
michael@0 66 }
michael@0 67
michael@0 68 void
michael@0 69 XULComboboxAccessible::Description(nsString& aDescription)
michael@0 70 {
michael@0 71 aDescription.Truncate();
michael@0 72 // Use description of currently focused option
michael@0 73 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm(do_QueryInterface(mContent));
michael@0 74 if (!menuListElm)
michael@0 75 return;
michael@0 76
michael@0 77 nsCOMPtr<nsIDOMXULSelectControlItemElement> focusedOptionItem;
michael@0 78 menuListElm->GetSelectedItem(getter_AddRefs(focusedOptionItem));
michael@0 79 nsCOMPtr<nsIContent> focusedOptionContent =
michael@0 80 do_QueryInterface(focusedOptionItem);
michael@0 81 if (focusedOptionContent && mDoc) {
michael@0 82 Accessible* focusedOptionAcc = mDoc->GetAccessible(focusedOptionContent);
michael@0 83 if (focusedOptionAcc)
michael@0 84 focusedOptionAcc->Description(aDescription);
michael@0 85 }
michael@0 86 }
michael@0 87
michael@0 88 void
michael@0 89 XULComboboxAccessible::Value(nsString& aValue)
michael@0 90 {
michael@0 91 aValue.Truncate();
michael@0 92
michael@0 93 // The value is the option or text shown entered in the combobox.
michael@0 94 nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
michael@0 95 if (menuList)
michael@0 96 menuList->GetLabel(aValue);
michael@0 97 }
michael@0 98
michael@0 99 bool
michael@0 100 XULComboboxAccessible::CanHaveAnonChildren()
michael@0 101 {
michael@0 102 if (mContent->NodeInfo()->Equals(nsGkAtoms::textbox, kNameSpaceID_XUL) ||
michael@0 103 mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
michael@0 104 nsGkAtoms::_true, eIgnoreCase)) {
michael@0 105 // Both the XUL <textbox type="autocomplete"> and <menulist editable="true"> widgets
michael@0 106 // use XULComboboxAccessible. We need to walk the anonymous children for these
michael@0 107 // so that the entry field is a child
michael@0 108 return true;
michael@0 109 }
michael@0 110
michael@0 111 // Argument of false indicates we don't walk anonymous children for
michael@0 112 // menuitems
michael@0 113 return false;
michael@0 114 }
michael@0 115
michael@0 116 uint8_t
michael@0 117 XULComboboxAccessible::ActionCount()
michael@0 118 {
michael@0 119 // Just one action (click).
michael@0 120 return 1;
michael@0 121 }
michael@0 122
michael@0 123 NS_IMETHODIMP
michael@0 124 XULComboboxAccessible::DoAction(uint8_t aIndex)
michael@0 125 {
michael@0 126 if (aIndex != XULComboboxAccessible::eAction_Click) {
michael@0 127 return NS_ERROR_INVALID_ARG;
michael@0 128 }
michael@0 129
michael@0 130 if (IsDefunct())
michael@0 131 return NS_ERROR_FAILURE;
michael@0 132
michael@0 133 // Programmaticaly toggle the combo box.
michael@0 134 nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
michael@0 135 if (!menuList) {
michael@0 136 return NS_ERROR_FAILURE;
michael@0 137 }
michael@0 138 bool isDroppedDown;
michael@0 139 menuList->GetOpen(&isDroppedDown);
michael@0 140 return menuList->SetOpen(!isDroppedDown);
michael@0 141 }
michael@0 142
michael@0 143 NS_IMETHODIMP
michael@0 144 XULComboboxAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 145 {
michael@0 146 if (aIndex != XULComboboxAccessible::eAction_Click) {
michael@0 147 return NS_ERROR_INVALID_ARG;
michael@0 148 }
michael@0 149
michael@0 150 if (IsDefunct())
michael@0 151 return NS_ERROR_FAILURE;
michael@0 152
michael@0 153 // Our action name is the reverse of our state:
michael@0 154 // if we are close -> open is our name.
michael@0 155 // if we are open -> close is our name.
michael@0 156 // Uses the frame to get the state, updated on every click.
michael@0 157
michael@0 158 nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
michael@0 159 if (!menuList) {
michael@0 160 return NS_ERROR_FAILURE;
michael@0 161 }
michael@0 162 bool isDroppedDown;
michael@0 163 menuList->GetOpen(&isDroppedDown);
michael@0 164 if (isDroppedDown)
michael@0 165 aName.AssignLiteral("close");
michael@0 166 else
michael@0 167 aName.AssignLiteral("open");
michael@0 168
michael@0 169 return NS_OK;
michael@0 170 }
michael@0 171
michael@0 172 ////////////////////////////////////////////////////////////////////////////////
michael@0 173 // Widgets
michael@0 174
michael@0 175 bool
michael@0 176 XULComboboxAccessible::IsActiveWidget() const
michael@0 177 {
michael@0 178 if (IsAutoComplete() ||
michael@0 179 mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::editable,
michael@0 180 nsGkAtoms::_true, eIgnoreCase)) {
michael@0 181 int32_t childCount = mChildren.Length();
michael@0 182 for (int32_t idx = 0; idx < childCount; idx++) {
michael@0 183 Accessible* child = mChildren[idx];
michael@0 184 if (child->Role() == roles::ENTRY)
michael@0 185 return FocusMgr()->HasDOMFocus(child->GetContent());
michael@0 186 }
michael@0 187 return false;
michael@0 188 }
michael@0 189
michael@0 190 return FocusMgr()->HasDOMFocus(mContent);
michael@0 191 }
michael@0 192
michael@0 193 bool
michael@0 194 XULComboboxAccessible::AreItemsOperable() const
michael@0 195 {
michael@0 196 if (IsAutoComplete()) {
michael@0 197 nsCOMPtr<nsIAutoCompleteInput> autoCompleteInputElm =
michael@0 198 do_QueryInterface(mContent);
michael@0 199 if (autoCompleteInputElm) {
michael@0 200 bool isOpen = false;
michael@0 201 autoCompleteInputElm->GetPopupOpen(&isOpen);
michael@0 202 return isOpen;
michael@0 203 }
michael@0 204 return false;
michael@0 205 }
michael@0 206
michael@0 207 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = do_QueryInterface(mContent);
michael@0 208 if (menuListElm) {
michael@0 209 bool isOpen = false;
michael@0 210 menuListElm->GetOpen(&isOpen);
michael@0 211 return isOpen;
michael@0 212 }
michael@0 213
michael@0 214 return false;
michael@0 215 }

mercurial