Home | History | Annotate | Download | only in accessibility
      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