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/AXObjectCache.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
AXScrollView(ScrollView * view)37 AXScrollView::AXScrollView(ScrollView* view)
38 : m_scrollView(view)
39 , m_childrenDirty(false)
40 {
41 }
42
~AXScrollView()43 AXScrollView::~AXScrollView()
44 {
45 ASSERT(isDetached());
46 }
47
detach()48 void AXScrollView::detach()
49 {
50 AXObject::detach();
51 m_scrollView = 0;
52 }
53
create(ScrollView * view)54 PassRefPtr<AXScrollView> AXScrollView::create(ScrollView* view)
55 {
56 return adoptRef(new AXScrollView(view));
57 }
58
scrollBar(AccessibilityOrientation orientation)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 ScrollView object in WK1).
75 // In WebKit2, the ScrollView object will return the AX information (because there are no platform widgets).
isAttachment() const76 bool AXScrollView::isAttachment() const
77 {
78 return false;
79 }
80
widgetForAttachmentView() const81 Widget* AXScrollView::widgetForAttachmentView() const
82 {
83 return m_scrollView;
84 }
85
updateChildrenIfNecessary()86 void AXScrollView::updateChildrenIfNecessary()
87 {
88 if (m_childrenDirty)
89 clearChildren();
90
91 if (!m_haveChildren)
92 addChildren();
93
94 updateScrollbars();
95 }
96
updateScrollbars()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
removeChildScrollbar(AXObject * scrollbar)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
addChildScrollbar(Scrollbar * scrollbar)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
clearChildren()137 void AXScrollView::clearChildren()
138 {
139 AXObject::clearChildren();
140 m_verticalScrollbar = nullptr;
141 m_horizontalScrollbar = nullptr;
142 }
143
computeAccessibilityIsIgnored() const144 bool AXScrollView::computeAccessibilityIsIgnored() const
145 {
146 AXObject* webArea = webAreaObject();
147 if (!webArea)
148 return true;
149
150 return webArea->accessibilityIsIgnored();
151 }
152
addChildren()153 void AXScrollView::addChildren()
154 {
155 ASSERT(!m_haveChildren);
156 m_haveChildren = true;
157
158 AXObject* webArea = webAreaObject();
159 if (webArea && !webArea->accessibilityIsIgnored())
160 m_children.append(webArea);
161
162 updateScrollbars();
163 }
164
webAreaObject() const165 AXObject* AXScrollView::webAreaObject() const
166 {
167 if (!m_scrollView || !m_scrollView->isFrameView())
168 return 0;
169
170 Document* doc = toFrameView(m_scrollView)->frame().document();
171 if (!doc || !doc->renderView())
172 return 0;
173
174 return axObjectCache()->getOrCreate(doc);
175 }
176
accessibilityHitTest(const IntPoint & point) const177 AXObject* AXScrollView::accessibilityHitTest(const IntPoint& point) const
178 {
179 AXObject* webArea = webAreaObject();
180 if (!webArea)
181 return 0;
182
183 if (m_horizontalScrollbar && m_horizontalScrollbar->elementRect().contains(point))
184 return m_horizontalScrollbar.get();
185 if (m_verticalScrollbar && m_verticalScrollbar->elementRect().contains(point))
186 return m_verticalScrollbar.get();
187
188 return webArea->accessibilityHitTest(point);
189 }
190
elementRect() const191 LayoutRect AXScrollView::elementRect() const
192 {
193 if (!m_scrollView)
194 return LayoutRect();
195
196 return m_scrollView->frameRect();
197 }
198
documentFrameView() const199 FrameView* AXScrollView::documentFrameView() const
200 {
201 if (!m_scrollView || !m_scrollView->isFrameView())
202 return 0;
203
204 return toFrameView(m_scrollView);
205 }
206
parentObject() const207 AXObject* AXScrollView::parentObject() const
208 {
209 if (!m_scrollView || !m_scrollView->isFrameView())
210 return 0;
211
212 // FIXME: Broken for OOPI.
213 HTMLFrameOwnerElement* owner = toFrameView(m_scrollView)->frame().deprecatedLocalOwner();
214 if (owner && owner->renderer())
215 return axObjectCache()->getOrCreate(owner);
216
217 return axObjectCache()->getOrCreate(toFrameView(m_scrollView)->frame().pagePopupOwner());
218 }
219
parentObjectIfExists() const220 AXObject* AXScrollView::parentObjectIfExists() const
221 {
222 if (!m_scrollView || !m_scrollView->isFrameView())
223 return 0;
224
225 HTMLFrameOwnerElement* owner = toFrameView(m_scrollView)->frame().deprecatedLocalOwner();
226 if (owner && owner->renderer())
227 return axObjectCache()->get(owner);
228
229 return axObjectCache()->get(toFrameView(m_scrollView)->frame().pagePopupOwner());
230 }
231
getScrollableAreaIfScrollable() const232 ScrollableArea* AXScrollView::getScrollableAreaIfScrollable() const
233 {
234 return m_scrollView;
235 }
236
scrollTo(const IntPoint & point) const237 void AXScrollView::scrollTo(const IntPoint& point) const
238 {
239 if (m_scrollView)
240 m_scrollView->setScrollPosition(point);
241 }
242
243 } // namespace blink
244