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