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 "RenderElement.h" 35#include "ScrollView.h" 36#include "Widget.h" 37 38namespace WebCore { 39 40AccessibilityScrollView::AccessibilityScrollView(ScrollView* view) 41 : m_scrollView(view) 42 , m_childrenDirty(false) 43{ 44} 45 46AccessibilityScrollView::~AccessibilityScrollView() 47{ 48 ASSERT(isDetached()); 49} 50 51void AccessibilityScrollView::detach(AccessibilityDetachmentType detachmentType, AXObjectCache* cache) 52{ 53 AccessibilityObject::detach(detachmentType, cache); 54 m_scrollView = 0; 55} 56 57PassRefPtr<AccessibilityScrollView> AccessibilityScrollView::create(ScrollView* view) 58{ 59 return adoptRef(new AccessibilityScrollView(view)); 60} 61 62AccessibilityObject* 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). 79bool AccessibilityScrollView::isAttachment() const 80{ 81 return m_scrollView && m_scrollView->platformWidget(); 82} 83 84Widget* AccessibilityScrollView::widgetForAttachmentView() const 85{ 86 return m_scrollView; 87} 88 89bool AccessibilityScrollView::canSetFocusAttribute() const 90{ 91 AccessibilityObject* webArea = webAreaObject(); 92 return webArea && webArea->canSetFocusAttribute(); 93} 94 95bool AccessibilityScrollView::isFocused() const 96{ 97 AccessibilityObject* webArea = webAreaObject(); 98 return webArea && webArea->isFocused(); 99} 100 101void AccessibilityScrollView::setFocused(bool focused) 102{ 103 if (AccessibilityObject* webArea = webAreaObject()) 104 webArea->setFocused(focused); 105} 106 107void AccessibilityScrollView::updateChildrenIfNecessary() 108{ 109 if (m_childrenDirty) 110 clearChildren(); 111 112 if (!m_haveChildren) 113 addChildren(); 114 115 updateScrollbars(); 116} 117 118void AccessibilityScrollView::updateScrollbars() 119{ 120 if (!m_scrollView) 121 return; 122 123 if (m_scrollView->horizontalScrollbar() && !m_horizontalScrollbar) 124 m_horizontalScrollbar = addChildScrollbar(m_scrollView->horizontalScrollbar()); 125 else if (!m_scrollView->horizontalScrollbar() && m_horizontalScrollbar) { 126 removeChildScrollbar(m_horizontalScrollbar.get()); 127 m_horizontalScrollbar = 0; 128 } 129 130 if (m_scrollView->verticalScrollbar() && !m_verticalScrollbar) 131 m_verticalScrollbar = addChildScrollbar(m_scrollView->verticalScrollbar()); 132 else if (!m_scrollView->verticalScrollbar() && m_verticalScrollbar) { 133 removeChildScrollbar(m_verticalScrollbar.get()); 134 m_verticalScrollbar = 0; 135 } 136} 137 138void AccessibilityScrollView::removeChildScrollbar(AccessibilityObject* scrollbar) 139{ 140 size_t pos = m_children.find(scrollbar); 141 if (pos != WTF::notFound) { 142 m_children[pos]->detachFromParent(); 143 m_children.remove(pos); 144 } 145} 146 147AccessibilityScrollbar* AccessibilityScrollView::addChildScrollbar(Scrollbar* scrollbar) 148{ 149 if (!scrollbar) 150 return 0; 151 152 AXObjectCache* cache = axObjectCache(); 153 if (!cache) 154 return nullptr; 155 156 AccessibilityScrollbar* scrollBarObject = toAccessibilityScrollbar(cache->getOrCreate(scrollbar)); 157 scrollBarObject->setParent(this); 158 m_children.append(scrollBarObject); 159 return scrollBarObject; 160} 161 162void AccessibilityScrollView::clearChildren() 163{ 164 AccessibilityObject::clearChildren(); 165 m_verticalScrollbar = 0; 166 m_horizontalScrollbar = 0; 167} 168 169bool AccessibilityScrollView::computeAccessibilityIsIgnored() const 170{ 171 AccessibilityObject* webArea = webAreaObject(); 172 if (!webArea) 173 return true; 174 175 return webArea->accessibilityIsIgnored(); 176} 177 178void AccessibilityScrollView::addChildren() 179{ 180 ASSERT(!m_haveChildren); 181 m_haveChildren = true; 182 183 AccessibilityObject* webArea = webAreaObject(); 184 if (webArea && !webArea->accessibilityIsIgnored()) 185 m_children.append(webArea); 186 187 updateScrollbars(); 188} 189 190AccessibilityObject* AccessibilityScrollView::webAreaObject() const 191{ 192 if (!m_scrollView || !m_scrollView->isFrameView()) 193 return 0; 194 195 Document* doc = toFrameView(m_scrollView)->frame().document(); 196 if (!doc || !doc->hasLivingRenderTree()) 197 return 0; 198 199 if (AXObjectCache* cache = axObjectCache()) 200 return cache->getOrCreate(doc); 201 202 return nullptr; 203} 204 205AccessibilityObject* AccessibilityScrollView::accessibilityHitTest(const IntPoint& point) const 206{ 207 AccessibilityObject* webArea = webAreaObject(); 208 if (!webArea) 209 return 0; 210 211 if (m_horizontalScrollbar && m_horizontalScrollbar->elementRect().contains(point)) 212 return m_horizontalScrollbar.get(); 213 if (m_verticalScrollbar && m_verticalScrollbar->elementRect().contains(point)) 214 return m_verticalScrollbar.get(); 215 216 return webArea->accessibilityHitTest(point); 217} 218 219LayoutRect AccessibilityScrollView::elementRect() const 220{ 221 if (!m_scrollView) 222 return LayoutRect(); 223 224 LayoutRect rect = m_scrollView->frameRect(); 225 rect.setY(rect.y() + m_scrollView->topContentInset()); 226 return rect; 227} 228 229FrameView* AccessibilityScrollView::documentFrameView() const 230{ 231 if (!m_scrollView || !m_scrollView->isFrameView()) 232 return 0; 233 234 return toFrameView(m_scrollView); 235} 236 237AccessibilityObject* AccessibilityScrollView::parentObject() const 238{ 239 if (!m_scrollView || !m_scrollView->isFrameView()) 240 return 0; 241 242 AXObjectCache* cache = axObjectCache(); 243 if (!cache) 244 return nullptr; 245 246 HTMLFrameOwnerElement* owner = toFrameView(m_scrollView)->frame().ownerElement(); 247 if (owner && owner->renderer()) 248 return cache->getOrCreate(owner); 249 250 return 0; 251} 252 253AccessibilityObject* AccessibilityScrollView::parentObjectIfExists() const 254{ 255 if (!m_scrollView || !m_scrollView->isFrameView()) 256 return 0; 257 258 AXObjectCache* cache = axObjectCache(); 259 if (!cache) 260 return nullptr; 261 262 HTMLFrameOwnerElement* owner = toFrameView(m_scrollView)->frame().ownerElement(); 263 if (owner && owner->renderer()) 264 return cache->get(owner); 265 266 return 0; 267} 268 269ScrollableArea* AccessibilityScrollView::getScrollableAreaIfScrollable() const 270{ 271 return m_scrollView; 272} 273 274void AccessibilityScrollView::scrollTo(const IntPoint& point) const 275{ 276 if (m_scrollView) 277 m_scrollView->setScrollPosition(point); 278} 279 280} // namespace WebCore 281