OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 #include "modules/accessibility/AXScrollView.h" | |
28 | |
29 #include "core/frame/FrameView.h" | |
30 #include "core/frame/LocalFrame.h" | |
31 #include "core/html/HTMLFrameOwnerElement.h" | |
32 #include "modules/accessibility/AXObjectCacheImpl.h" | |
33 #include "modules/accessibility/AXScrollbar.h" | |
34 | |
35 namespace blink { | |
36 | |
37 AXScrollView::AXScrollView(FrameView* view, AXObjectCacheImpl& axObjectCache) | |
38 : AXObject(axObjectCache) | |
39 , m_scrollView(view) | |
40 , m_childrenDirty(false) | |
41 { | |
42 } | |
43 | |
44 AXScrollView::~AXScrollView() | |
45 { | |
46 ASSERT(!m_scrollView); | |
47 } | |
48 | |
49 void AXScrollView::detach() | |
50 { | |
51 AXObject::detach(); | |
52 m_scrollView = nullptr; | |
53 } | |
54 | |
55 AXScrollView* AXScrollView::create(FrameView* view, AXObjectCacheImpl& axObjectC
ache) | |
56 { | |
57 return new AXScrollView(view, axObjectCache); | |
58 } | |
59 | |
60 AXObject* AXScrollView::scrollBar(AccessibilityOrientation orientation) | |
61 { | |
62 updateScrollbars(); | |
63 | |
64 switch (orientation) { | |
65 case AccessibilityOrientationVertical: | |
66 return m_verticalScrollbar ? m_verticalScrollbar.get() : 0; | |
67 case AccessibilityOrientationHorizontal: | |
68 return m_horizontalScrollbar ? m_horizontalScrollbar.get() : 0; | |
69 case AccessibilityOrientationUndefined: | |
70 return 0; | |
71 } | |
72 | |
73 return 0; | |
74 } | |
75 | |
76 // If this is WebKit1 then the native scroll view needs to return the | |
77 // AX information (because there are no scroll bar children in the FrameView obj
ect in WK1). | |
78 // In WebKit2, the FrameView object will return the AX information (because ther
e are no platform widgets). | |
79 bool AXScrollView::isAttachment() const | |
80 { | |
81 return false; | |
82 } | |
83 | |
84 Widget* AXScrollView::widgetForAttachmentView() const | |
85 { | |
86 return m_scrollView; | |
87 } | |
88 | |
89 void AXScrollView::updateChildrenIfNecessary() | |
90 { | |
91 if (m_childrenDirty) | |
92 clearChildren(); | |
93 | |
94 if (!m_haveChildren) | |
95 addChildren(); | |
96 | |
97 updateScrollbars(); | |
98 } | |
99 | |
100 void AXScrollView::updateScrollbars() | |
101 { | |
102 if (!m_scrollView) | |
103 return; | |
104 | |
105 if (m_scrollView->horizontalScrollbar() && !m_horizontalScrollbar) { | |
106 m_horizontalScrollbar = addChildScrollbar(m_scrollView->horizontalScroll
bar()); | |
107 } else if (!m_scrollView->horizontalScrollbar() && m_horizontalScrollbar) { | |
108 removeChildScrollbar(m_horizontalScrollbar.get()); | |
109 m_horizontalScrollbar = nullptr; | |
110 } | |
111 | |
112 if (m_scrollView->verticalScrollbar() && !m_verticalScrollbar) { | |
113 m_verticalScrollbar = addChildScrollbar(m_scrollView->verticalScrollbar(
)); | |
114 } else if (!m_scrollView->verticalScrollbar() && m_verticalScrollbar) { | |
115 removeChildScrollbar(m_verticalScrollbar.get()); | |
116 m_verticalScrollbar = nullptr; | |
117 } | |
118 } | |
119 | |
120 void AXScrollView::removeChildScrollbar(AXObject* scrollbar) | |
121 { | |
122 size_t pos = m_children.find(scrollbar); | |
123 if (pos != kNotFound) { | |
124 m_children[pos]->detachFromParent(); | |
125 m_children.remove(pos); | |
126 } | |
127 } | |
128 | |
129 AXScrollbar* AXScrollView::addChildScrollbar(Scrollbar* scrollbar) | |
130 { | |
131 if (!scrollbar) | |
132 return 0; | |
133 | |
134 AXScrollbar* scrollBarObject = toAXScrollbar(axObjectCache().getOrCreate(scr
ollbar)); | |
135 scrollBarObject->setParent(this); | |
136 m_children.append(scrollBarObject); | |
137 return scrollBarObject; | |
138 } | |
139 | |
140 void AXScrollView::clearChildren() | |
141 { | |
142 AXObject::clearChildren(); | |
143 m_verticalScrollbar = nullptr; | |
144 m_horizontalScrollbar = nullptr; | |
145 } | |
146 | |
147 bool AXScrollView::computeAccessibilityIsIgnored(IgnoredReasons* ignoredReasons)
const | |
148 { | |
149 // We just want to match whatever's returned by our web area, which is a chi
ld of this | |
150 // object. Normally cached attribute values may only search up the tree. We
can't just | |
151 // call accessibilityIsIgnored on the web area, because the web area may sea
rch up its | |
152 // ancestors and call this function recursively, and we'd loop until a stack
overflow. | |
153 | |
154 // Instead, we first update the cached accessibilityIsIgnored value for this
node to | |
155 // false, call accessibilityIsIgnored on the web area, then return the mathc
ing value. | |
156 m_cachedIsIgnored = false; | |
157 m_lastModificationCount = axObjectCache().modificationCount(); | |
158 | |
159 AXObject* webArea = webAreaObject(); | |
160 if (!webArea) | |
161 return true; | |
162 | |
163 if (!webArea->accessibilityIsIgnored()) | |
164 return false; | |
165 | |
166 if (ignoredReasons) | |
167 return webArea->computeAccessibilityIsIgnored(ignoredReasons); | |
168 | |
169 return true; | |
170 } | |
171 | |
172 void AXScrollView::addChildren() | |
173 { | |
174 ASSERT(!m_haveChildren); | |
175 m_haveChildren = true; | |
176 | |
177 AXObject* webArea = webAreaObject(); | |
178 if (webArea && !webArea->accessibilityIsIgnored()) | |
179 m_children.append(webArea); | |
180 | |
181 updateScrollbars(); | |
182 } | |
183 | |
184 AXObject* AXScrollView::webAreaObject() const | |
185 { | |
186 if (!m_scrollView || !m_scrollView->isFrameView()) | |
187 return 0; | |
188 | |
189 Document* doc = m_scrollView->frame().document(); | |
190 if (!doc || !doc->layoutView()) | |
191 return 0; | |
192 | |
193 return axObjectCache().getOrCreate(doc); | |
194 } | |
195 | |
196 AXObject* AXScrollView::accessibilityHitTest(const IntPoint& point) const | |
197 { | |
198 AXObject* webArea = webAreaObject(); | |
199 if (!webArea) | |
200 return 0; | |
201 | |
202 if (m_horizontalScrollbar && m_horizontalScrollbar->elementRect().contains(p
oint)) | |
203 return m_horizontalScrollbar.get(); | |
204 if (m_verticalScrollbar && m_verticalScrollbar->elementRect().contains(point
)) | |
205 return m_verticalScrollbar.get(); | |
206 | |
207 return webArea->accessibilityHitTest(point); | |
208 } | |
209 | |
210 LayoutRect AXScrollView::elementRect() const | |
211 { | |
212 if (!m_scrollView) | |
213 return LayoutRect(); | |
214 | |
215 return LayoutRect(m_scrollView->frameRect()); | |
216 } | |
217 | |
218 FrameView* AXScrollView::documentFrameView() const | |
219 { | |
220 if (!m_scrollView || !m_scrollView->isFrameView()) | |
221 return 0; | |
222 | |
223 return m_scrollView; | |
224 } | |
225 | |
226 AXObject* AXScrollView::computeParent() const | |
227 { | |
228 if (!m_scrollView || !m_scrollView->isFrameView()) | |
229 return 0; | |
230 | |
231 // FIXME: Broken for OOPI. | |
232 HTMLFrameOwnerElement* owner = m_scrollView->frame().deprecatedLocalOwner(); | |
233 if (owner && owner->layoutObject()) | |
234 return axObjectCache().getOrCreate(owner); | |
235 | |
236 return axObjectCache().getOrCreate(m_scrollView->frame().pagePopupOwner()); | |
237 } | |
238 | |
239 AXObject* AXScrollView::computeParentIfExists() const | |
240 { | |
241 if (!m_scrollView || !m_scrollView->isFrameView()) | |
242 return 0; | |
243 | |
244 HTMLFrameOwnerElement* owner = m_scrollView->frame().deprecatedLocalOwner(); | |
245 if (owner && owner->layoutObject()) | |
246 return axObjectCache().get(owner); | |
247 | |
248 return axObjectCache().get(m_scrollView->frame().pagePopupOwner()); | |
249 } | |
250 | |
251 ScrollableArea* AXScrollView::getScrollableAreaIfScrollable() const | |
252 { | |
253 return m_scrollView; | |
254 } | |
255 | |
256 DEFINE_TRACE(AXScrollView) | |
257 { | |
258 visitor->trace(m_scrollView); | |
259 visitor->trace(m_horizontalScrollbar); | |
260 visitor->trace(m_verticalScrollbar); | |
261 AXObject::trace(visitor); | |
262 } | |
263 | |
264 } // namespace blink | |
OLD | NEW |