OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 { | 64 { |
65 return accessibilityIsIgnoredByDefault(); | 65 return accessibilityIsIgnoredByDefault(); |
66 } | 66 } |
67 | 67 |
68 AXMenuListOption* AXMenuListPopup::menuListOptionAXObject(HTMLElement* element)
const | 68 AXMenuListOption* AXMenuListPopup::menuListOptionAXObject(HTMLElement* element)
const |
69 { | 69 { |
70 ASSERT(element); | 70 ASSERT(element); |
71 if (!isHTMLOptionElement(*element)) | 71 if (!isHTMLOptionElement(*element)) |
72 return 0; | 72 return 0; |
73 | 73 |
74 AXObject* object = axObjectCache()->getOrCreate(element); | 74 AXObject* object = axObjectCache()->getOrCreate(MenuListOptionRole); |
75 if (!object) | 75 ASSERT_WITH_SECURITY_IMPLICATION(object->isMenuListOption()); |
76 return 0; | |
77 | 76 |
78 ASSERT_WITH_SECURITY_IMPLICATION(object->isMenuListOption()); | 77 AXMenuListOption* option = toAXMenuListOption(object); |
79 return toAXMenuListOption(object); | 78 option->setElement(element); |
| 79 |
| 80 return option; |
80 } | 81 } |
81 | 82 |
82 int AXMenuListPopup::getSelectedIndex() const | 83 int AXMenuListPopup::getSelectedIndex() const |
83 { | 84 { |
84 if (!m_parent) | |
85 return -1; | |
86 | |
87 Node* selectNode = m_parent->node(); | 85 Node* selectNode = m_parent->node(); |
88 if (!selectNode) | 86 if (!selectNode) |
89 return -1; | 87 return -1; |
90 | 88 |
91 HTMLSelectElement* htmlSelectElement = toHTMLSelectElement(selectNode); | 89 HTMLSelectElement* htmlSelectElement = toHTMLSelectElement(selectNode); |
92 return htmlSelectElement->selectedIndex(); | 90 return htmlSelectElement->selectedIndex(); |
93 } | 91 } |
94 | 92 |
95 bool AXMenuListPopup::press() const | 93 bool AXMenuListPopup::press() const |
96 { | 94 { |
97 if (!m_parent) | 95 if (!m_parent) |
98 return false; | 96 return false; |
99 | 97 |
100 m_parent->press(); | 98 m_parent->press(); |
101 return true; | 99 return true; |
102 } | 100 } |
103 | 101 |
104 void AXMenuListPopup::addChildren() | 102 void AXMenuListPopup::addChildren() |
105 { | 103 { |
106 if (!m_parent) | 104 if (!m_parent) |
107 return; | 105 return; |
108 | 106 |
109 Node* selectNode = m_parent->node(); | 107 Node* selectNode = m_parent->node(); |
110 if (!selectNode) | 108 if (!selectNode) |
111 return; | 109 return; |
112 | 110 |
113 HTMLSelectElement* htmlSelectElement = toHTMLSelectElement(selectNode); | 111 HTMLSelectElement* htmlSelectElement = toHTMLSelectElement(selectNode); |
114 m_haveChildren = true; | 112 m_haveChildren = true; |
115 | 113 |
116 if (m_activeIndex == -1) | 114 m_activeIndex = getSelectedIndex(); |
117 m_activeIndex = getSelectedIndex(); | |
118 | |
119 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = htmlSel
ectElement->listItems(); | 115 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = htmlSel
ectElement->listItems(); |
120 unsigned length = listItems.size(); | 116 unsigned length = listItems.size(); |
121 for (unsigned i = 0; i < length; i++) { | 117 for (unsigned i = 0; i < length; i++) { |
122 AXMenuListOption* option = menuListOptionAXObject(listItems[i]); | 118 AXMenuListOption* option = menuListOptionAXObject(listItems[i]); |
123 if (option) { | 119 if (option) { |
124 option->setParent(this); | 120 option->setParent(this); |
125 m_children.append(option); | 121 m_children.append(option); |
126 } | 122 } |
127 } | 123 } |
128 } | 124 } |
129 | 125 |
130 void AXMenuListPopup::updateChildrenIfNecessary() | 126 void AXMenuListPopup::childrenChanged() |
131 { | 127 { |
132 if (m_haveChildren && m_parent && m_parent->needsToUpdateChildren()) | 128 AXObjectCacheImpl* cache = axObjectCache(); |
133 clearChildren(); | 129 if (!cache) |
| 130 return; |
| 131 for (size_t i = m_children.size(); i > 0 ; --i) { |
| 132 AXObject* child = m_children[i - 1].get(); |
| 133 // FIXME: How could children end up in here that have no actionElement()
, the check |
| 134 // in menuListOptionAXObject would seem to prevent that. |
| 135 if (child->actionElement()) { |
| 136 child->detachFromParent(); |
| 137 cache->remove(child->axObjectID()); |
| 138 } |
| 139 } |
134 | 140 |
135 if (!m_haveChildren) | 141 m_children.clear(); |
136 addChildren(); | 142 m_haveChildren = false; |
137 } | 143 } |
138 | 144 |
139 void AXMenuListPopup::didUpdateActiveOption(int optionIndex) | 145 void AXMenuListPopup::didUpdateActiveOption(int optionIndex) |
140 { | 146 { |
141 updateChildrenIfNecessary(); | 147 // We defer creation of the children until updating the active option so tha
t we don't |
| 148 // create AXObjects for <option> elements while they're in the middle of rem
oval. |
| 149 if (!m_haveChildren) |
| 150 addChildren(); |
| 151 |
| 152 ASSERT_ARG(optionIndex, optionIndex >= 0); |
| 153 ASSERT_ARG(optionIndex, optionIndex < static_cast<int>(m_children.size())); |
142 | 154 |
143 AXObjectCacheImpl* cache = axObjectCache(); | 155 AXObjectCacheImpl* cache = axObjectCache(); |
144 if (m_activeIndex != optionIndex && m_activeIndex >= 0 && m_activeIndex < st
atic_cast<int>(m_children.size())) { | 156 if (m_activeIndex != optionIndex && m_activeIndex >= 0 && m_activeIndex < st
atic_cast<int>(m_children.size())) { |
145 RefPtr<AXObject> previousChild = m_children[m_activeIndex].get(); | 157 RefPtr<AXObject> previousChild = m_children[m_activeIndex].get(); |
146 cache->postNotification(previousChild.get(), AXObjectCacheImpl::AXMenuLi
stItemUnselected); | 158 cache->postNotification(previousChild.get(), AXObjectCacheImpl::AXMenuLi
stItemUnselected); |
147 } | 159 } |
148 | 160 |
149 if (optionIndex >= 0 && optionIndex < static_cast<int>(m_children.size())) { | 161 RefPtr<AXObject> child = m_children[optionIndex].get(); |
150 RefPtr<AXObject> child = m_children[optionIndex].get(); | 162 cache->postNotification(child.get(), AXObjectCacheImpl::AXFocusedUIElementCh
anged); |
151 cache->postNotification(child.get(), AXObjectCacheImpl::AXFocusedUIEleme
ntChanged); | 163 cache->postNotification(child.get(), AXObjectCacheImpl::AXMenuListItemSelect
ed); |
152 cache->postNotification(child.get(), AXObjectCacheImpl::AXMenuListItemSe
lected); | |
153 } | |
154 | |
155 m_activeIndex = optionIndex; | 164 m_activeIndex = optionIndex; |
156 } | 165 } |
157 | 166 |
158 void AXMenuListPopup::didHide() | 167 void AXMenuListPopup::didHide() |
159 { | 168 { |
160 AXObjectCacheImpl* cache = axObjectCache(); | 169 AXObjectCacheImpl* cache = axObjectCache(); |
161 cache->postNotification(this, AXObjectCacheImpl::AXHide); | 170 cache->postNotification(this, AXObjectCacheImpl::AXHide); |
162 if (activeChild()) | 171 if (activeChild()) |
163 cache->postNotification(activeChild(), AXObjectCacheImpl::AXMenuListItem
Unselected); | 172 cache->postNotification(activeChild(), AXObjectCacheImpl::AXMenuListItem
Unselected); |
164 } | 173 } |
(...skipping 14 matching lines...) Expand all Loading... |
179 | 188 |
180 AXObject* AXMenuListPopup::activeChild() | 189 AXObject* AXMenuListPopup::activeChild() |
181 { | 190 { |
182 if (m_activeIndex < 0 || m_activeIndex >= static_cast<int>(children().size()
)) | 191 if (m_activeIndex < 0 || m_activeIndex >= static_cast<int>(children().size()
)) |
183 return nullptr; | 192 return nullptr; |
184 | 193 |
185 return m_children[m_activeIndex].get(); | 194 return m_children[m_activeIndex].get(); |
186 } | 195 } |
187 | 196 |
188 } // namespace blink | 197 } // namespace blink |
OLD | NEW |