AX: move isIgnored caching to AXObject
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityScrollView.cpp
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 "AccessibilityScrollView.h"
28
29 #include "AXObjectCache.h"
30 #include "AccessibilityScrollbar.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "HTMLFrameOwnerElement.h"
34 #include "RenderPart.h"
35 #include "ScrollView.h"
36 #include "Widget.h"
37
38 namespace WebCore {
39     
40 AccessibilityScrollView::AccessibilityScrollView(ScrollView* view)
41     : m_scrollView(view)
42     , m_childrenDirty(false)
43 {
44 }
45
46 AccessibilityScrollView::~AccessibilityScrollView()
47 {
48     ASSERT(isDetached());
49 }
50
51 void AccessibilityScrollView::detach()
52 {
53     AccessibilityObject::detach();
54     m_scrollView = 0;
55 }
56
57 PassRefPtr<AccessibilityScrollView> AccessibilityScrollView::create(ScrollView* view)
58 {
59     return adoptRef(new AccessibilityScrollView(view));
60 }
61     
62 AccessibilityObject* AccessibilityScrollView::scrollBar(AccessibilityOrientation orientation)
63 {
64     updateScrollbars();
65     
66     switch (orientation) {
67     case AccessibilityOrientationVertical:
68         return m_verticalScrollbar ? m_verticalScrollbar.get() : 0;
69     case AccessibilityOrientationHorizontal:
70         return m_horizontalScrollbar ? m_horizontalScrollbar.get() : 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 ScrollView object in WK1).
78 // In WebKit2, the ScrollView object will return the AX information (because there are no platform widgets).
79 bool AccessibilityScrollView::isAttachment() const
80 {
81     return m_scrollView && m_scrollView->platformWidget();
82 }
83
84 Widget* AccessibilityScrollView::widgetForAttachmentView() const
85 {
86     return m_scrollView;
87 }
88     
89 void AccessibilityScrollView::updateChildrenIfNecessary()
90 {
91     if (m_childrenDirty)
92         clearChildren();
93
94     if (!m_haveChildren)
95         addChildren();
96     
97     updateScrollbars();
98 }
99
100 void AccessibilityScrollView::updateScrollbars()
101 {
102     if (!m_scrollView)
103         return;
104
105     if (m_scrollView->horizontalScrollbar() && !m_horizontalScrollbar)
106         m_horizontalScrollbar = addChildScrollbar(m_scrollView->horizontalScrollbar());
107     else if (!m_scrollView->horizontalScrollbar() && m_horizontalScrollbar) {
108         removeChildScrollbar(m_horizontalScrollbar.get());
109         m_horizontalScrollbar = 0;
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 = 0;
117     }
118 }
119     
120 void AccessibilityScrollView::removeChildScrollbar(AccessibilityObject* scrollbar)
121 {
122     size_t pos = m_children.find(scrollbar);
123     if (pos != WTF::notFound) {
124         m_children[pos]->detachFromParent();
125         m_children.remove(pos);
126     }
127 }
128     
129 AccessibilityScrollbar* AccessibilityScrollView::addChildScrollbar(Scrollbar* scrollbar)
130 {
131     if (!scrollbar)
132         return 0;
133     
134     AccessibilityScrollbar* scrollBarObject = static_cast<AccessibilityScrollbar*>(axObjectCache()->getOrCreate(scrollbar));
135     scrollBarObject->setParent(this);
136     m_children.append(scrollBarObject);
137     return scrollBarObject;
138 }
139         
140 void AccessibilityScrollView::clearChildren()
141 {
142     AccessibilityObject::clearChildren();
143     m_verticalScrollbar = 0;
144     m_horizontalScrollbar = 0;
145 }
146
147 bool AccessibilityScrollView::computeAccessibilityIsIgnored() const
148 {
149     AccessibilityObject* webArea = webAreaObject();
150     if (!webArea)
151         return true;
152     
153     return webArea->accessibilityIsIgnored();
154 }
155
156 void AccessibilityScrollView::addChildren()
157 {
158     ASSERT(!m_haveChildren);
159     m_haveChildren = true;
160     
161     AccessibilityObject* webArea = webAreaObject();
162     if (webArea && !webArea->accessibilityIsIgnored())
163         m_children.append(webArea);
164     
165     updateScrollbars();
166 }
167
168 AccessibilityObject* AccessibilityScrollView::webAreaObject() const
169 {
170     if (!m_scrollView || !m_scrollView->isFrameView())
171         return 0;
172     
173     Document* doc = static_cast<FrameView*>(m_scrollView)->frame()->document();
174     if (!doc || !doc->renderer())
175         return 0;
176
177     return axObjectCache()->getOrCreate(doc);
178 }
179
180 AccessibilityObject* AccessibilityScrollView::accessibilityHitTest(const IntPoint& point) const
181 {
182     AccessibilityObject* webArea = webAreaObject();
183     if (!webArea)
184         return 0;
185     
186     if (m_horizontalScrollbar && m_horizontalScrollbar->elementRect().contains(point))
187         return m_horizontalScrollbar.get();
188     if (m_verticalScrollbar && m_verticalScrollbar->elementRect().contains(point))
189         return m_verticalScrollbar.get();
190     
191     return webArea->accessibilityHitTest(point);
192 }
193
194 LayoutRect AccessibilityScrollView::elementRect() const
195 {
196     if (!m_scrollView)
197         return LayoutRect();
198
199     return m_scrollView->frameRect();
200 }
201
202 FrameView* AccessibilityScrollView::documentFrameView() const
203 {
204     if (!m_scrollView || !m_scrollView->isFrameView())
205         return 0;
206     
207     return static_cast<FrameView*>(m_scrollView);
208 }    
209
210 AccessibilityObject* AccessibilityScrollView::parentObject() const
211 {
212     if (!m_scrollView || !m_scrollView->isFrameView())
213         return 0;
214     
215     HTMLFrameOwnerElement* owner = static_cast<FrameView*>(m_scrollView)->frame()->ownerElement();
216     if (owner && owner->renderer())
217         return axObjectCache()->getOrCreate(owner);
218
219     return 0;
220 }
221     
222 AccessibilityObject* AccessibilityScrollView::parentObjectIfExists() const
223 {
224     if (!m_scrollView || !m_scrollView->isFrameView())
225         return 0;
226     
227     HTMLFrameOwnerElement* owner = static_cast<FrameView*>(m_scrollView)->frame()->ownerElement();
228     if (owner && owner->renderer())
229         return axObjectCache()->get(owner);
230     
231     return 0;
232 }
233
234 ScrollableArea* AccessibilityScrollView::getScrollableAreaIfScrollable() const
235 {
236     return m_scrollView;
237 }
238
239 void AccessibilityScrollView::scrollTo(const IntPoint& point) const
240 {
241     if (m_scrollView)
242         m_scrollView->setScrollPosition(point);
243 }
244
245 } // namespace WebCore