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 "XULComboboxAccessible.h"
8 #include "Accessible-inl.h"
9 #include "nsAccessibilityService.h"
10 #include "DocAccessible.h"
11 #include "nsCoreUtils.h"
15 #include "nsIAutoCompleteInput.h"
16 #include "nsIDOMXULMenuListElement.h"
17 #include "nsIDOMXULSelectCntrlItemEl.h"
19 using namespace mozilla::a11y
;
21 ////////////////////////////////////////////////////////////////////////////////
22 // XULComboboxAccessible
23 ////////////////////////////////////////////////////////////////////////////////
25 XULComboboxAccessible::
26 XULComboboxAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
) :
27 AccessibleWrap(aContent
, aDoc
)
29 if (mContent
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::type
,
30 nsGkAtoms::autocomplete
, eIgnoreCase
))
31 mGenericTypes
|= eAutoComplete
;
33 mGenericTypes
|= eCombobox
;
37 XULComboboxAccessible::NativeRole()
39 return IsAutoComplete() ? roles::AUTOCOMPLETE
: roles::COMBOBOX
;
43 XULComboboxAccessible::NativeState()
45 // As a nsComboboxAccessible we can have the following states:
52 // Get focus status from base class
53 uint64_t state
= Accessible::NativeState();
55 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList(do_QueryInterface(mContent
));
58 menuList
->GetOpen(&isOpen
);
60 state
|= states::EXPANDED
;
62 state
|= states::COLLAPSED
;
65 return state
| states::HASPOPUP
;
69 XULComboboxAccessible::Description(nsString
& aDescription
)
71 aDescription
.Truncate();
72 // Use description of currently focused option
73 nsCOMPtr
<nsIDOMXULMenuListElement
> menuListElm(do_QueryInterface(mContent
));
77 nsCOMPtr
<nsIDOMXULSelectControlItemElement
> focusedOptionItem
;
78 menuListElm
->GetSelectedItem(getter_AddRefs(focusedOptionItem
));
79 nsCOMPtr
<nsIContent
> focusedOptionContent
=
80 do_QueryInterface(focusedOptionItem
);
81 if (focusedOptionContent
&& mDoc
) {
82 Accessible
* focusedOptionAcc
= mDoc
->GetAccessible(focusedOptionContent
);
84 focusedOptionAcc
->Description(aDescription
);
89 XULComboboxAccessible::Value(nsString
& aValue
)
93 // The value is the option or text shown entered in the combobox.
94 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList(do_QueryInterface(mContent
));
96 menuList
->GetLabel(aValue
);
100 XULComboboxAccessible::CanHaveAnonChildren()
102 if (mContent
->NodeInfo()->Equals(nsGkAtoms::textbox
, kNameSpaceID_XUL
) ||
103 mContent
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::editable
,
104 nsGkAtoms::_true
, eIgnoreCase
)) {
105 // Both the XUL <textbox type="autocomplete"> and <menulist editable="true"> widgets
106 // use XULComboboxAccessible. We need to walk the anonymous children for these
107 // so that the entry field is a child
111 // Argument of false indicates we don't walk anonymous children for
117 XULComboboxAccessible::ActionCount()
119 // Just one action (click).
124 XULComboboxAccessible::DoAction(uint8_t aIndex
)
126 if (aIndex
!= XULComboboxAccessible::eAction_Click
) {
127 return NS_ERROR_INVALID_ARG
;
131 return NS_ERROR_FAILURE
;
133 // Programmaticaly toggle the combo box.
134 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList(do_QueryInterface(mContent
));
136 return NS_ERROR_FAILURE
;
139 menuList
->GetOpen(&isDroppedDown
);
140 return menuList
->SetOpen(!isDroppedDown
);
144 XULComboboxAccessible::GetActionName(uint8_t aIndex
, nsAString
& aName
)
146 if (aIndex
!= XULComboboxAccessible::eAction_Click
) {
147 return NS_ERROR_INVALID_ARG
;
151 return NS_ERROR_FAILURE
;
153 // Our action name is the reverse of our state:
154 // if we are close -> open is our name.
155 // if we are open -> close is our name.
156 // Uses the frame to get the state, updated on every click.
158 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList(do_QueryInterface(mContent
));
160 return NS_ERROR_FAILURE
;
163 menuList
->GetOpen(&isDroppedDown
);
165 aName
.AssignLiteral("close");
167 aName
.AssignLiteral("open");
172 ////////////////////////////////////////////////////////////////////////////////
176 XULComboboxAccessible::IsActiveWidget() const
178 if (IsAutoComplete() ||
179 mContent
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::editable
,
180 nsGkAtoms::_true
, eIgnoreCase
)) {
181 int32_t childCount
= mChildren
.Length();
182 for (int32_t idx
= 0; idx
< childCount
; idx
++) {
183 Accessible
* child
= mChildren
[idx
];
184 if (child
->Role() == roles::ENTRY
)
185 return FocusMgr()->HasDOMFocus(child
->GetContent());
190 return FocusMgr()->HasDOMFocus(mContent
);
194 XULComboboxAccessible::AreItemsOperable() const
196 if (IsAutoComplete()) {
197 nsCOMPtr
<nsIAutoCompleteInput
> autoCompleteInputElm
=
198 do_QueryInterface(mContent
);
199 if (autoCompleteInputElm
) {
201 autoCompleteInputElm
->GetPopupOpen(&isOpen
);
207 nsCOMPtr
<nsIDOMXULMenuListElement
> menuListElm
= do_QueryInterface(mContent
);
210 menuListElm
->GetOpen(&isOpen
);