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 37 AXScrollView::AXScrollView(ScrollView* 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(ScrollView* 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 ScrollView object in WK1). 75 // In WebKit2, the ScrollView 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 AXObject* webArea = webAreaObject(); 147 if (!webArea) 148 return true; 149 150 return webArea->accessibilityIsIgnored(); 151 } 152 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 165 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 177 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 191 LayoutRect AXScrollView::elementRect() const 192 { 193 if (!m_scrollView) 194 return LayoutRect(); 195 196 return m_scrollView->frameRect(); 197 } 198 199 FrameView* AXScrollView::documentFrameView() const 200 { 201 if (!m_scrollView || !m_scrollView->isFrameView()) 202 return 0; 203 204 return toFrameView(m_scrollView); 205 } 206 207 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 220 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 232 ScrollableArea* AXScrollView::getScrollableAreaIfScrollable() const 233 { 234 return m_scrollView; 235 } 236 237 void AXScrollView::scrollTo(const IntPoint& point) const 238 { 239 if (m_scrollView) 240 m_scrollView->setScrollPosition(point); 241 } 242 243 } // namespace blink 244