9c4c4165e1bdedd4af05aff051f558ad243d5bd0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / accessibility / AXScrollView.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 "core/accessibility/AXScrollView.h"
28
29 #include "core/accessibility/AXObjectCacheImpl.h"
30 #include "core/accessibility/AXScrollbar.h"
31 #include "core/frame/FrameView.h"
32 #include "core/frame/LocalFrame.h"
33 #include "core/html/HTMLFrameOwnerElement.h"
34
35 namespace blink {
36
37 AXScrollView::AXScrollView(FrameView* view)
38     : m_scrollView(view)
39     , m_childrenDirty(false)
40 {
41 }
42
43 AXScrollView::~AXScrollView()
44 {
45     ASSERT(isDetached());
46 }
47
48 void AXScrollView::detach()
49 {
50     AXObject::detach();
51     m_scrollView = 0;
52 }
53
54 PassRefPtr<AXScrollView> AXScrollView::create(FrameView* view)
55 {
56     return adoptRef(new AXScrollView(view));
57 }
58
59 AXObject* AXScrollView::scrollBar(AccessibilityOrientation orientation)
60 {
61     updateScrollbars();
62
63     switch (orientation) {
64     case AccessibilityOrientationVertical:
65         return m_verticalScrollbar ? m_verticalScrollbar.get() : 0;
66     case AccessibilityOrientationHorizontal:
67         return m_horizontalScrollbar ? m_horizontalScrollbar.get() : 0;
68     }
69
70     return 0;
71 }
72
73 // If this is WebKit1 then the native scroll view needs to return the
74 // AX information (because there are no scroll bar children in the FrameView object in WK1).
75 // In WebKit2, the FrameView object will return the AX information (because there are no platform widgets).
76 bool AXScrollView::isAttachment() const
77 {
78     return false;
79 }
80
81 Widget* AXScrollView::widgetForAttachmentView() const
82 {
83     return m_scrollView;
84 }
85
86 void AXScrollView::updateChildrenIfNecessary()
87 {
88     if (m_childrenDirty)
89         clearChildren();
90
91     if (!m_haveChildren)
92         addChildren();
93
94     updateScrollbars();
95 }
96
97 void AXScrollView::updateScrollbars()
98 {
99     if (!m_scrollView)
100         return;
101
102     if (m_scrollView->horizontalScrollbar() && !m_horizontalScrollbar) {
103         m_horizontalScrollbar = addChildScrollbar(m_scrollView->horizontalScrollbar());
104     } else if (!m_scrollView->horizontalScrollbar() && m_horizontalScrollbar) {
105         removeChildScrollbar(m_horizontalScrollbar.get());
106         m_horizontalScrollbar = nullptr;
107     }
108
109     if (m_scrollView->verticalScrollbar() && !m_verticalScrollbar) {
110         m_verticalScrollbar = addChildScrollbar(m_scrollView->verticalScrollbar());
111     } else if (!m_scrollView->verticalScrollbar() && m_verticalScrollbar) {
112         removeChildScrollbar(m_verticalScrollbar.get());
113         m_verticalScrollbar = nullptr;
114     }
115 }
116
117 void AXScrollView::removeChildScrollbar(AXObject* scrollbar)
118 {
119     size_t pos = m_children.find(scrollbar);
120     if (pos != kNotFound) {
121         m_children[pos]->detachFromParent();
122         m_children.remove(pos);
123     }
124 }
125
126 AXScrollbar* AXScrollView::addChildScrollbar(Scrollbar* scrollbar)
127 {
128     if (!scrollbar)
129         return 0;
130
131     AXScrollbar* scrollBarObject = toAXScrollbar(axObjectCache()->getOrCreate(scrollbar));
132     scrollBarObject->setParent(this);
133     m_children.append(scrollBarObject);
134     return scrollBarObject;
135 }
136
137 void AXScrollView::clearChildren()
138 {
139     AXObject::clearChildren();
140     m_verticalScrollbar = nullptr;
141     m_horizontalScrollbar = nullptr;
142 }
143
144 bool AXScrollView::computeAccessibilityIsIgnored() const
145 {
146     // We just want to match whatever's returned by our web area, which is a child of this
147     // object. Normally cached attribute values may only search up the tree. We can't just
148     // call accessibilityIsIgnored on the web area, because the web area may search up its
149     // ancestors and call this function recursively, and we'd loop until a stack overflow.
150
151     // Instead, we first update the cached accessibilityIsIgnored value for this node to
152     // false, call accessibilityIsIgnored on the web area, then return the mathcing value.
153     m_cachedIsIgnored = false;
154     m_lastModificationCount = axObjectCache()->modificationCount();
155
156     AXObject* webArea = webAreaObject();
157     if (webArea)
158         return webArea->accessibilityIsIgnored();
159
160     return true;
161 }
162
163 void AXScrollView::addChildren()
164 {
165     ASSERT(!m_haveChildren);
166     m_haveChildren = true;
167
168     AXObject* webArea = webAreaObject();
169     if (webArea && !webArea->accessibilityIsIgnored())
170         m_children.append(webArea);
171
172     updateScrollbars();
173 }
174
175 AXObject* AXScrollView::webAreaObject() const
176 {
177     if (!m_scrollView || !m_scrollView->isFrameView())
178         return 0;
179
180     Document* doc = m_scrollView->frame().document();
181     if (!doc || !doc->renderView())
182         return 0;
183
184     return axObjectCache()->getOrCreate(doc);
185 }
186
187 AXObject* AXScrollView::accessibilityHitTest(const IntPoint& point) const
188 {
189     AXObject* webArea = webAreaObject();
190     if (!webArea)
191         return 0;
192
193     if (m_horizontalScrollbar && m_horizontalScrollbar->elementRect().contains(point))
194         return m_horizontalScrollbar.get();
195     if (m_verticalScrollbar && m_verticalScrollbar->elementRect().contains(point))
196         return m_verticalScrollbar.get();
197
198     return webArea->accessibilityHitTest(point);
199 }
200
201 LayoutRect AXScrollView::elementRect() const
202 {
203     if (!m_scrollView)
204         return LayoutRect();
205
206     return m_scrollView->frameRect();
207 }
208
209 FrameView* AXScrollView::documentFrameView() const
210 {
211     if (!m_scrollView || !m_scrollView->isFrameView())
212         return 0;
213
214     return m_scrollView;
215 }
216
217 AXObject* AXScrollView::computeParent() const
218 {
219     if (!m_scrollView || !m_scrollView->isFrameView())
220         return 0;
221
222     // FIXME: Broken for OOPI.
223     HTMLFrameOwnerElement* owner = m_scrollView->frame().deprecatedLocalOwner();
224     if (owner && owner->renderer())
225         return axObjectCache()->getOrCreate(owner);
226
227     return axObjectCache()->getOrCreate(m_scrollView->frame().pagePopupOwner());
228 }
229
230 AXObject* AXScrollView::computeParentIfExists() const
231 {
232     if (!m_scrollView || !m_scrollView->isFrameView())
233         return 0;
234
235     HTMLFrameOwnerElement* owner = m_scrollView->frame().deprecatedLocalOwner();
236     if (owner && owner->renderer())
237         return axObjectCache()->get(owner);
238
239     return axObjectCache()->get(m_scrollView->frame().pagePopupOwner());
240 }
241
242 ScrollableArea* AXScrollView::getScrollableAreaIfScrollable() const
243 {
244     return m_scrollView;
245 }
246
247 void AXScrollView::scrollTo(const IntPoint& point) const
248 {
249     if (m_scrollView)
250         m_scrollView->setScrollPosition(point);
251 }
252
253 } // namespace blink