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 "LocalAccessible-inl.h"
9 #include "nsAccessibilityService.h"
10 #include "DocAccessible.h"
11 #include "nsCoreUtils.h"
12 #include "mozilla/a11y/Role.h"
15 #include "mozilla/dom/Element.h"
16 #include "nsIDOMXULMenuListElement.h"
18 using namespace mozilla::a11y
;
20 ////////////////////////////////////////////////////////////////////////////////
21 // XULComboboxAccessible
22 ////////////////////////////////////////////////////////////////////////////////
24 XULComboboxAccessible::XULComboboxAccessible(nsIContent
* aContent
,
26 : AccessibleWrap(aContent
, aDoc
) {
27 mGenericTypes
|= eCombobox
;
30 role
XULComboboxAccessible::NativeRole() const { return roles::COMBOBOX
; }
32 uint64_t XULComboboxAccessible::NativeState() const {
33 // As a nsComboboxAccessible we can have the following states:
40 // Get focus status from base class
41 uint64_t state
= LocalAccessible::NativeState();
43 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList
= Elm()->AsXULMenuList();
46 menuList
->GetOpen(&isOpen
);
48 state
|= states::EXPANDED
;
50 state
|= states::COLLAPSED
;
54 return state
| states::HASPOPUP
;
57 bool XULComboboxAccessible::IsAcceptableChild(nsIContent
* aContent
) const {
58 return AccessibleWrap::IsAcceptableChild(aContent
) && !aContent
->IsText();
61 void XULComboboxAccessible::Description(nsString
& aDescription
) const {
62 aDescription
.Truncate();
63 // Use description of currently focused option
64 nsCOMPtr
<nsIDOMXULMenuListElement
> menuListElm
= Elm()->AsXULMenuList();
65 if (!menuListElm
) return;
67 nsCOMPtr
<dom::Element
> focusedOptionItem
;
68 menuListElm
->GetSelectedItem(getter_AddRefs(focusedOptionItem
));
69 if (focusedOptionItem
&& mDoc
) {
70 LocalAccessible
* focusedOptionAcc
= mDoc
->GetAccessible(focusedOptionItem
);
71 if (focusedOptionAcc
) focusedOptionAcc
->Description(aDescription
);
75 void XULComboboxAccessible::Value(nsString
& aValue
) const {
78 // The value is the option or text shown entered in the combobox.
79 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList
= Elm()->AsXULMenuList();
80 if (menuList
) menuList
->GetLabel(aValue
);
83 bool XULComboboxAccessible::HasPrimaryAction() const { return true; }
85 bool XULComboboxAccessible::DoAction(uint8_t aIndex
) const {
86 if (aIndex
!= XULComboboxAccessible::eAction_Click
) return false;
88 // Programmaticaly toggle the combo box.
89 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList
= Elm()->AsXULMenuList();
90 if (!menuList
) return false;
92 bool isDroppedDown
= false;
93 menuList
->GetOpen(&isDroppedDown
);
94 menuList
->SetOpen(!isDroppedDown
);
98 void XULComboboxAccessible::ActionNameAt(uint8_t aIndex
, nsAString
& aName
) {
100 if (aIndex
!= XULComboboxAccessible::eAction_Click
) return;
102 nsCOMPtr
<nsIDOMXULMenuListElement
> menuList
= Elm()->AsXULMenuList();
103 if (!menuList
) return;
105 bool isDroppedDown
= false;
106 menuList
->GetOpen(&isDroppedDown
);
108 aName
.AssignLiteral("close");
110 aName
.AssignLiteral("open");
114 ////////////////////////////////////////////////////////////////////////////////
117 bool XULComboboxAccessible::IsActiveWidget() const {
118 if (mContent
->AsElement()->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::editable
,
119 nsGkAtoms::_true
, eIgnoreCase
)) {
120 int32_t childCount
= mChildren
.Length();
121 for (int32_t idx
= 0; idx
< childCount
; idx
++) {
122 LocalAccessible
* child
= mChildren
[idx
];
123 if (child
->Role() == roles::ENTRY
) {
124 return FocusMgr()->HasDOMFocus(child
->GetContent());
130 return FocusMgr()->HasDOMFocus(mContent
);
133 bool XULComboboxAccessible::AreItemsOperable() const {
134 nsCOMPtr
<nsIDOMXULMenuListElement
> menuListElm
= Elm()->AsXULMenuList();
137 menuListElm
->GetOpen(&isOpen
);