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/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