18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * its contributors may be used to endorse or promote products derived 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * from this software without specific prior written permission. 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityObject.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AXObjectCache.h" 33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "AccessibilityRenderObject.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatRect.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FocusController.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "LocalizedStrings.h" 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NodeList.h" 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h" 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h" 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderImage.h" 43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "RenderListItem.h" 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderListMarker.h" 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderMenuList.h" 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderTextControl.h" 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderTheme.h" 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderView.h" 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderWidget.h" 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SelectionController.h" 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextIterator.h" 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h" 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "visible_units.h" 54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h> 552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <wtf/text/StringBuilder.h> 562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <wtf/text/StringConcatenate.h> 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h> 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAccessibilityObject::AccessibilityObject() 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_id(0) 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_haveChildren(false) 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_role(UnknownRole) 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(GTK) 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_wrapper(0) 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAccessibilityObject::~AccessibilityObject() 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isDetached()); 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AccessibilityObject::detach() 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(ACCESSIBILITY) 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project setWrapper(0); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAccessibilityObject* AccessibilityObject::parentObjectUnignored() const 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project AccessibilityObject* parent; 90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject()) { 91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return parent; 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockAccessibilityObject* AccessibilityObject::firstAccessibleObjectFromNode(const Node* node) 97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(AXObjectCache::accessibilityEnabled()); 99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!node) 101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Document* document = node->document(); 104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!document) 105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block AXObjectCache* cache = document->axObjectCache(); 108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block AccessibilityObject* accessibleObject = cache->getOrCreate(node->renderer()); 110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block while (accessibleObject && accessibleObject->accessibilityIsIgnored()) { 111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block node = node->traverseNextNode(); 112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block while (node && !node->renderer()) 114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block node = node->traverseNextSibling(); 115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!node) 117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block accessibleObject = cache->getOrCreate(node->renderer()); 120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return accessibleObject; 123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AccessibilityObject::isARIAInput(AccessibilityRole ariaRole) 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole; 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AccessibilityObject::isARIAControl(AccessibilityRole ariaRole) 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return isARIAInput(ariaRole) || ariaRole == TextAreaRole || ariaRole == ButtonRole 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project || ariaRole == ComboBoxRole || ariaRole == SliderRole; 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntPoint AccessibilityObject::clickPoint() const 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project IntRect rect = elementRect(); 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return IntPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AccessibilityObject::press() const 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Element* actionElem = actionElement(); 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!actionElem) 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (Frame* f = actionElem->document()->frame()) 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project f->loader()->resetMultipleFormSubmissionProtection(); 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project actionElem->accessKeyAction(true); 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString AccessibilityObject::language() const 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 155967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch const AtomicString& lang = getAttribute(langAttr); 156967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!lang.isEmpty()) 157967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return lang; 158967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch AccessibilityObject* parent = parentObject(); 1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // as a last resort, fall back to the content language specified in the meta tag 1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!parent) { 1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Document* doc = document(); 1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (doc) 1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return doc->contentLanguage(); 166967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return nullAtom; 1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return parent->language(); 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositions(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2) const 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos1.isNull() || visiblePos2.isNull()) 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPos; 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPos; 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool alreadyInOrder; 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // upstream is ordered before downstream for the same position 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM) 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project alreadyInOrder = false; 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // use selection order to see if the positions are in order 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian alreadyInOrder = VisibleSelection(visiblePos1, visiblePos2).isBaseFirst(); 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alreadyInOrder) { 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPos = visiblePos1; 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPos = visiblePos2; 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPos = visiblePos2; 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPos = visiblePos1; 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPos, endPos); 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::positionOfLeftWord(const VisiblePosition& visiblePos) const 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary); 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfWord(startPosition); 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::positionOfRightWord(const VisiblePosition& visiblePos) const 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary); 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfWord(startPosition); 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition) 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line. 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // So let's update the position to include that. 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition tempPosition; 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = visiblePosition; 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Position p; 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* renderer; 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (true) { 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project tempPosition = startPosition.previous(); 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (tempPosition.isNull()) 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p = tempPosition.deepEquivalent(); 22781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!p.deprecatedNode()) 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 22981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch renderer = p.deprecatedNode()->renderer(); 2305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!renderer || (renderer->isRenderBlock() && !p.deprecatedEditingOffset())) 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project InlineBox* box; 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int ignoredCaretOffset; 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project p.getInlineBoxAndOffset(tempPosition.affinity(), box, ignoredCaretOffset); 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (box) 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = tempPosition; 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startPosition; 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::leftLineVisiblePositionRange(const VisiblePosition& visiblePos) const 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make a caret selection for the position before marker position (to make sure 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // we move off of a line start) 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prevVisiblePos = visiblePos.previous(); 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (prevVisiblePos.isNull()) 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfLine(prevVisiblePos); 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // keep searching for a valid line start position. Unless the VisiblePosition is at the very beginning, there should 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // always be a valid line range. However, startOfLine will return null for position next to a floating object, 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // since floating object doesn't really belong to any line. 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This check will reposition the marker before the floating object, to ensure we get a line start. 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startPosition.isNull()) { 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (startPosition.isNull() && prevVisiblePos.isNotNull()) { 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project prevVisiblePos = prevVisiblePos.previous(); 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = startOfLine(prevVisiblePos); 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = updateAXLineStartForVisiblePosition(startPosition); 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfLine(prevVisiblePos); 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::rightLineVisiblePositionRange(const VisiblePosition& visiblePos) const 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a line end 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition nextVisiblePos = visiblePos.next(); 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextVisiblePos.isNull()) 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfLine(nextVisiblePos); 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // fetch for a valid line start position 285643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (startPosition.isNull()) { 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = visiblePos; 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextVisiblePos = nextVisiblePos.next(); 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = updateAXLineStartForVisiblePosition(startPosition); 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfLine(nextVisiblePos); 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Unless the VisiblePosition is at the very end, there should always be a valid line range. However, endOfLine will 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // return null for position by a floating object, since floating object doesn't really belong to any line. 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This check will reposition the marker after the floating object, to ensure we get a line end. 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (endPosition.isNull() && nextVisiblePos.isNotNull()) { 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextVisiblePos = nextVisiblePos.next(); 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPosition = endOfLine(nextVisiblePos); 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::sentenceForPosition(const VisiblePosition& visiblePos) const 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Related? <rdar://problem/3927736> Text selection broken in 8A336 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfSentence(visiblePos); 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfSentence(startPosition); 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::paragraphForPosition(const VisiblePosition& visiblePos) const 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfParagraph(visiblePos); 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfParagraph(startPosition); 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic VisiblePosition startOfStyleRange(const VisiblePosition visiblePos) 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 32381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch RenderObject* renderer = visiblePos.deepEquivalent().deprecatedNode()->renderer(); 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* startRenderer = renderer; 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle* style = renderer->style(); 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // traverse backward by renderer to look for style change 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) { 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip non-leaf nodes 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->firstChild()) 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // stop at style change 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->style() != style) 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember match 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startRenderer = r; 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 34181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return firstPositionInOrBeforeNode(startRenderer->node()); 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic VisiblePosition endOfStyleRange(const VisiblePosition& visiblePos) 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 34681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch RenderObject* renderer = visiblePos.deepEquivalent().deprecatedNode()->renderer(); 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderObject* endRenderer = renderer; 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RenderStyle* style = renderer->style(); 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // traverse forward by renderer to look for style change 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) { 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // skip non-leaf nodes 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->firstChild()) 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project continue; 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // stop at style change 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (r->style() != style) 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // remember match 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endRenderer = r; 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 36481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return lastPositionInOrAfterNode(endRenderer->node()); 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePosition& visiblePos) const 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startOfStyleRange(visiblePos), endOfStyleRange(visiblePos)); 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// NOTE: Consider providing this utility method as AX API 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePositionRange AccessibilityObject::visiblePositionRangeForRange(const PlainTextRange& range) const 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 37868513a70bcd92384395513322f1b801e7bf9c729Steve Block unsigned textLength = getLengthForTextRange(); 379db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block if (range.start + range.length > textLength) 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(); 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = visiblePositionForIndex(range.start); 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition.setAffinity(DOWNSTREAM); 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = visiblePositionForIndex(range.start + range.length); 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePositionRange(startPosition, endPosition); 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool replacedNodeNeedsCharacter(Node* replacedNode) 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // we should always be given a rendered node and a replaced node, but be safe 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // replaced nodes are either attachments (widgets) or images 392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // create an AX object, but skip it if it is not supposed to be seen 3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer()); 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (object->accessibilityIsIgnored()) 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 403231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Finds a RenderListItem parent give a node. 404967717af5423377c967781471ee106e2bb4e11c8Ben Murdochstatic RenderListItem* renderListItemContainerForNode(Node* node) 405231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 4066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner for (; node; node = node->parentNode()) { 407dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch RenderBoxModelObject* renderer = node->renderBoxModelObject(); 408dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (renderer && renderer->isListItem()) 409dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return toRenderListItem(renderer); 410231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 411231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 412231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 413231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 414231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Returns the text associated with a list marker if this node is contained within a list item. 415231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockString AccessibilityObject::listMarkerTextForNodeAndPosition(Node* node, const VisiblePosition& visiblePositionStart) const 416231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 417231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // If the range does not contain the start of the line, the list marker text should not be included. 418231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!isStartOfLine(visiblePositionStart)) 419231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return String(); 420231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 421231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RenderListItem* listItem = renderListItemContainerForNode(node); 422231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!listItem) 423231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return String(); 424231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 425231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // If this is in a list item, we need to manually add the text for the list marker 426231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // because a RenderListMarker does not have a Node equivalent and thus does not appear 427231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // when iterating text. 428231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block const String& markerText = listItem->markerText(); 429231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (markerText.isEmpty()) 430231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return String(); 431231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 432231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Append text, plus the period that follows the text. 433231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // FIXME: Not all list marker styles are followed by a period, but this 434231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // sounds much better when there is a synthesized pause because of a period. 4352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return makeString(markerText, ". "); 436231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 437231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePositionRange.isNull()) 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch StringBuilder builder; 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end); 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) 447643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (it.length()) { 448231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Add a textual representation for list marker text 449231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block String listMarkerText = listMarkerTextForNodeAndPosition(it.node(), visiblePositionRange.start); 450231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!listMarkerText.isEmpty()) 4512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch builder.append(listMarkerText); 4522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 4532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch builder.append(it.characters(), it.length()); 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // locate the node and starting offset for this replaced range 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* node = it.range()->startContainer(exception); 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(node == it.range()->endContainer(exception)); 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = it.range()->startOffset(exception); 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 461643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (replacedNodeNeedsCharacter(node->childNode(offset))) 4622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch builder.append(objectReplacementCharacter); 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return builder.toString(); 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint AccessibilityObject::lengthForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Multi-byte support 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePositionRange.isNull()) 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return -1; 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int length = 0; 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end); 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) 479643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (it.length()) 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length += it.length(); 481643ca7872b450ea4efacab6188849e5aac2ba161Steve Block else { 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // locate the node and starting offset for this replaced range 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int exception = 0; 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Node* node = it.range()->startContainer(exception); 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(node == it.range()->endContainer(exception)); 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int offset = it.range()->startOffset(exception); 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (replacedNodeNeedsCharacter(node->childNode(offset))) 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project length++; 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return length; 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::nextWordEnd(const VisiblePosition& visiblePos) const 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a word end 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition nextVisiblePos = visiblePos.next(); 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextVisiblePos.isNull()) 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return endOfWord(nextVisiblePos, LeftWordIfOnBoundary); 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::previousWordStart(const VisiblePosition& visiblePos) const 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a word start 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prevVisiblePos = visiblePos.previous(); 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (prevVisiblePos.isNull()) 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startOfWord(prevVisiblePos, RightWordIfOnBoundary); 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::nextLineEndPosition(const VisiblePosition& visiblePos) const 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // to make sure we move off of a line end 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition nextVisiblePos = visiblePos.next(); 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextVisiblePos.isNull()) 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition = endOfLine(nextVisiblePos); 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There are cases like when the position is next to a floating object that'll return null for end of line. This code will avoid returning null. 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (endPosition.isNull() && nextVisiblePos.isNotNull()) { 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextVisiblePos = nextVisiblePos.next(); 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPosition = endOfLine(nextVisiblePos); 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return endPosition; 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::previousLineStartPosition(const VisiblePosition& visiblePos) const 5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a line start 5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prevVisiblePos = visiblePos.previous(); 5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (prevVisiblePos.isNull()) 5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition = startOfLine(prevVisiblePos); 5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // as long as the position hasn't reached the beginning of the doc, keep searching for a valid line start position 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // There are cases like when the position is next to a floating object that'll return null for start of line. This code will avoid returning null. 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (startPosition.isNull()) { 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (startPosition.isNull() && prevVisiblePos.isNotNull()) { 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project prevVisiblePos = prevVisiblePos.previous(); 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = startOfLine(prevVisiblePos); 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = updateAXLineStartForVisiblePosition(startPosition); 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startPosition; 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::nextSentenceEndPosition(const VisiblePosition& visiblePos) const 5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) 5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Related? <rdar://problem/3927736> Text selection broken in 8A336 5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a sentence end 5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition nextVisiblePos = visiblePos.next(); 5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextVisiblePos.isNull()) 5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // an empty line is considered a sentence. If it's skipped, then the sentence parser will not 5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // see this empty line. Instead, return the end position of the empty line. 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition endPosition; 584635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 585635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project String lineString = plainText(makeRange(startOfLine(nextVisiblePos), endOfLine(nextVisiblePos)).get()); 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (lineString.isEmpty()) 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPosition = nextVisiblePos; 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project endPosition = endOfSentence(nextVisiblePos); 5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return endPosition; 5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::previousSentenceStartPosition(const VisiblePosition& visiblePos) const 5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) 5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Related? <rdar://problem/3927736> Text selection broken in 8A336 5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a sentence start 6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition previousVisiblePos = visiblePos.previous(); 6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (previousVisiblePos.isNull()) 6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // treat empty line as a separate sentence. 6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition startPosition; 608635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get()); 6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (lineString.isEmpty()) 6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = previousVisiblePos; 6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project startPosition = startOfSentence(previousVisiblePos); 6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startPosition; 6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::nextParagraphEndPosition(const VisiblePosition& visiblePos) const 6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a paragraph end 6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition nextPos = visiblePos.next(); 6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextPos.isNull()) 6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return endOfParagraph(nextPos); 6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectVisiblePosition AccessibilityObject::previousParagraphStartPosition(const VisiblePosition& visiblePos) const 6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // make sure we move off of a paragraph start 6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition previousPos = visiblePos.previous(); 6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (previousPos.isNull()) 6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return VisiblePosition(); 6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return startOfParagraph(previousPos); 6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAccessibilityObject* AccessibilityObject::accessibilityObjectForPosition(const VisiblePosition& visiblePos) const 6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 64981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch RenderObject* obj = visiblePos.deepEquivalent().deprecatedNode()->renderer(); 6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!obj) 6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian return obj->document()->axObjectCache()->getOrCreate(obj); 6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint AccessibilityObject::lineForPosition(const VisiblePosition& visiblePos) const 6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (visiblePos.isNull()) 6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned lineCount = 0; 6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition currentVisiblePos = visiblePos; 6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition savedVisiblePos; 6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // move up until we get to the top 6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This only takes us to the top of the rootEditableElement, not the top of the 6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // top document. 6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos))) { 6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ++lineCount; 6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project savedVisiblePos = currentVisiblePos; 6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0); 6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project currentVisiblePos = prevVisiblePos; 6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return lineCount - 1; 6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// NOTE: Consider providing this utility method as AX API 6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPlainTextRange AccessibilityObject::plainTextRangeForVisiblePositionRange(const VisiblePositionRange& positionRange) const 6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int index1 = index(positionRange.start); 6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int index2 = index(positionRange.end); 6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (index1 < 0 || index2 < 0 || index1 > index2) 6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return PlainTextRange(); 6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return PlainTextRange(index1, index2 - index1); 6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// The composed character range in the text associated with this accessibility object that 6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// is specified by the given screen coordinates. This parameterized attribute returns the 6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// complete range of characters (including surrogate pairs of multi-byte glyphs) at the given 6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// screen coordinates. 6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// NOTE: This varies from AppKit when the point is below the last line. AppKit returns an 6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// an error in that case. We return textControl->text().length(), 1. Does this matter? 6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPlainTextRange AccessibilityObject::doAXRangeForPosition(const IntPoint& point) const 6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int i = index(visiblePositionForPoint(point)); 6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (i < 0) 6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return PlainTextRange(); 7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return PlainTextRange(i, 1); 7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Given a character index, the range of text associated with this accessibility object 7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// over which the style in effect at that character index applies. 7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPlainTextRange AccessibilityObject::doAXStyleRangeForIndex(unsigned index) const 7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VisiblePositionRange range = styleRangeForPosition(visiblePositionForIndex(index, false)); 7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return plainTextRangeForVisiblePositionRange(range); 7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Given an indexed character, the line number of the text associated with this accessibility 7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// object that contains the character. 7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned AccessibilityObject::doAXLineForIndex(unsigned index) 7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return lineForPosition(visiblePositionForIndex(index, false)); 7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7192fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockDocument* AccessibilityObject::document() const 7202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 7212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FrameView* frameView = documentFrameView(); 7222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!frameView) 7232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return 0; 7242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 7252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return frameView->frame()->document(); 7262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectFrameView* AccessibilityObject::documentFrameView() const 7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const AccessibilityObject* object = this; 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (object && !object->isAccessibilityRenderObject()) 7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project object = object->parentObject(); 7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!object) 7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return object->documentFrameView(); 7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 739cad810f21b803229eb11403f9209855525a25d57Steve Block 740cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid AccessibilityObject::updateChildrenIfNecessary() 741cad810f21b803229eb11403f9209855525a25d57Steve Block{ 742cad810f21b803229eb11403f9209855525a25d57Steve Block if (!hasChildren()) 743cad810f21b803229eb11403f9209855525a25d57Steve Block addChildren(); 744cad810f21b803229eb11403f9209855525a25d57Steve Block} 7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AccessibilityObject::clearChildren() 7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_children.clear(); 749dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_haveChildren = false; 7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochAccessibilityObject* AccessibilityObject::anchorElementForNode(Node* node) 7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 7540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* obj = node->renderer(); 7550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!obj) 7560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RefPtr<AccessibilityObject> axObj = obj->document()->axObjectCache()->getOrCreate(obj); 7590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Element* anchor = axObj->anchorElement(); 7600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!anchor) 7610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 7620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RenderObject* anchorRenderer = anchor->renderer(); 7640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!anchorRenderer) 7650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 0; 7660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return anchorRenderer->document()->axObjectCache()->getOrCreate(anchorRenderer); 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 770643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid AccessibilityObject::ariaTreeRows(AccessibilityChildrenVector& result) 771643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 772643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityChildrenVector axChildren = children(); 773643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned count = axChildren.size(); 774643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned k = 0; k < count; ++k) { 775643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityObject* obj = axChildren[k].get(); 776643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 777643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Add tree items as the rows. 778643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (obj->roleValue() == TreeItemRole) 779643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.append(obj); 780643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 781643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Now see if this item also has rows hiding inside of it. 782643ca7872b450ea4efacab6188849e5aac2ba161Steve Block obj->ariaTreeRows(result); 783643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 785643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 786643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid AccessibilityObject::ariaTreeItemContent(AccessibilityChildrenVector& result) 787643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 788643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // The ARIA tree item content are the item that are not other tree items or their containing groups. 789643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityChildrenVector axChildren = children(); 790643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned count = axChildren.size(); 791643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned k = 0; k < count; ++k) { 792643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityObject* obj = axChildren[k].get(); 793643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityRole role = obj->roleValue(); 794643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (role == TreeItemRole || role == GroupRole) 795643ca7872b450ea4efacab6188849e5aac2ba161Steve Block continue; 796643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 797643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.append(obj); 798643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 799643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 801643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid AccessibilityObject::ariaTreeItemDisclosedRows(AccessibilityChildrenVector& result) 802643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityChildrenVector axChildren = children(); 804643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned count = axChildren.size(); 805643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned k = 0; k < count; ++k) { 806643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityObject* obj = axChildren[k].get(); 807643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 808643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Add tree items as the rows. 809643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (obj->roleValue() == TreeItemRole) 810643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.append(obj); 811643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // If it's not a tree item, then descend into the group to find more tree items. 812643ca7872b450ea4efacab6188849e5aac2ba161Steve Block else 813643ca7872b450ea4efacab6188849e5aac2ba161Steve Block obj->ariaTreeRows(result); 814643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 815643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 816643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst String& AccessibilityObject::actionVerb() const 8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Need to add verbs for select elements. 820635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, buttonAction, (AXButtonActionVerb())); 821635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, textFieldAction, (AXTextFieldActionVerb())); 822635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, radioButtonAction, (AXRadioButtonActionVerb())); 823635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, checkedCheckBoxAction, (AXCheckedCheckBoxActionVerb())); 824635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, uncheckedCheckBoxAction, (AXUncheckedCheckBoxActionVerb())); 825635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, linkAction, (AXLinkActionVerb())); 826d0825bca7fe65beaee391d30da42e937db621564Steve Block DEFINE_STATIC_LOCAL(const String, menuListAction, (AXMenuListActionVerb())); 827d0825bca7fe65beaee391d30da42e937db621564Steve Block DEFINE_STATIC_LOCAL(const String, menuListPopupAction, (AXMenuListPopupActionVerb())); 828635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const String, noAction, ()); 8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project switch (roleValue()) { 831643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case ButtonRole: 832643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return buttonAction; 833643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case TextFieldRole: 834643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case TextAreaRole: 835643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return textFieldAction; 836643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case RadioButtonRole: 837643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return radioButtonAction; 838643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case CheckBoxRole: 839643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction; 840643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case LinkRole: 841643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case WebCoreLinkRole: 842643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return linkAction; 843d0825bca7fe65beaee391d30da42e937db621564Steve Block case PopUpButtonRole: 844d0825bca7fe65beaee391d30da42e937db621564Steve Block return menuListAction; 845d0825bca7fe65beaee391d30da42e937db621564Steve Block case MenuListPopupRole: 846d0825bca7fe65beaee391d30da42e937db621564Steve Block return menuListPopupAction; 847643ca7872b450ea4efacab6188849e5aac2ba161Steve Block default: 848643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return noAction; 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 851f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 852f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool AccessibilityObject::ariaIsMultiline() const 853f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 854f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return equalIgnoringCase(getAttribute(aria_multilineAttr), "true"); 855f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 856f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 857f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochconst AtomicString& AccessibilityObject::invalidStatus() const 858f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 859f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch DEFINE_STATIC_LOCAL(const AtomicString, invalidStatusFalse, ("false")); 860f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 861f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // aria-invalid can return false (default), grammer, spelling, or true. 862f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const AtomicString& ariaInvalid = getAttribute(aria_invalidAttr); 863f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 864f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // If empty or not present, it should return false. 865f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (ariaInvalid.isEmpty()) 866f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return invalidStatusFalse; 867f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 868f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return ariaInvalid; 869f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 8700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 871967717af5423377c967781471ee106e2bb4e11c8Ben Murdochconst AtomicString& AccessibilityObject::getAttribute(const QualifiedName& attribute) const 872dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 873967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch Node* elementNode = node(); 874967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!elementNode) 875dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return nullAtom; 876dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 877967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (!elementNode->isElementNode()) 878dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return nullAtom; 879dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 880967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch Element* element = static_cast<Element*>(elementNode); 881f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return element->fastGetAttribute(attribute); 882dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 883dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 8840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Lacking concrete evidence of orientation, horizontal means width > height. vertical is height > width; 8850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochAccessibilityOrientation AccessibilityObject::orientation() const 886635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 8870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch IntRect bounds = elementRect(); 8880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (bounds.size().width() > bounds.size().height()) 8890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return AccessibilityOrientationHorizontal; 8900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (bounds.size().height() > bounds.size().width()) 8910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return AccessibilityOrientationVertical; 8920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // A tie goes to horizontal. 8940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return AccessibilityOrientationHorizontal; 895643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 896643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 897643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocktypedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; 898643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 899643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstruct RoleEntry { 900643ca7872b450ea4efacab6188849e5aac2ba161Steve Block String ariaRole; 901643ca7872b450ea4efacab6188849e5aac2ba161Steve Block AccessibilityRole webcoreRole; 902643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}; 903643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 904643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic ARIARoleMap* createARIARoleMap() 905643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 906643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const RoleEntry roles[] = { 907643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "alert", ApplicationAlertRole }, 908643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "alertdialog", ApplicationAlertDialogRole }, 909643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "application", LandmarkApplicationRole }, 910643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "article", DocumentArticleRole }, 911643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "banner", LandmarkBannerRole }, 912643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "button", ButtonRole }, 913643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "checkbox", CheckBoxRole }, 914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "complementary", LandmarkComplementaryRole }, 915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "contentinfo", LandmarkContentInfoRole }, 916643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "dialog", ApplicationDialogRole }, 917643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "directory", DirectoryRole }, 918643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "grid", TableRole }, 919643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "gridcell", CellRole }, 920643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "columnheader", ColumnHeaderRole }, 921643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "combobox", ComboBoxRole }, 922643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "definition", DefinitionListDefinitionRole }, 923643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "document", DocumentRole }, 924643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "rowheader", RowHeaderRole }, 925643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "group", GroupRole }, 926643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "heading", HeadingRole }, 927643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "img", ImageRole }, 928643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "link", WebCoreLinkRole }, 929643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "list", ListRole }, 93006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen { "listitem", ListItemRole }, 931643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "listbox", ListBoxRole }, 932643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "log", ApplicationLogRole }, 933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "option" isn't here because it may map to different roles depending on the parent element's role 934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "main", LandmarkMainRole }, 935643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "marquee", ApplicationMarqueeRole }, 936643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "math", DocumentMathRole }, 937643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "menu", MenuRole }, 938f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch { "menubar", MenuBarRole }, 939643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "menuitem" isn't here because it may map to different roles depending on the parent element's role 940643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "menuitemcheckbox", MenuItemRole }, 941643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "menuitemradio", MenuItemRole }, 942643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "note", DocumentNoteRole }, 943643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "navigation", LandmarkNavigationRole }, 944643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "option", ListBoxOptionRole }, 94506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen { "presentation", PresentationalRole }, 946643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "progressbar", ProgressIndicatorRole }, 947643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "radio", RadioButtonRole }, 948643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "radiogroup", RadioGroupRole }, 949643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "region", DocumentRegionRole }, 950643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "row", RowRole }, 951643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "range", SliderRole }, 952643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "scrollbar", ScrollBarRole }, 953643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "search", LandmarkSearchRole }, 954643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "separator", SplitterRole }, 955643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "slider", SliderRole }, 956643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "spinbutton", ProgressIndicatorRole }, 957643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "status", ApplicationStatusRole }, 958643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "tab", TabRole }, 959643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "tablist", TabListRole }, 960643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "tabpanel", TabPanelRole }, 961643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "text", StaticTextRole }, 962643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "textbox", TextAreaRole }, 963643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "timer", ApplicationTimerRole }, 964643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "toolbar", ToolbarRole }, 965643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "tooltip", UserInterfaceTooltipRole }, 966643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "tree", TreeRole }, 967d0825bca7fe65beaee391d30da42e937db621564Steve Block { "treegrid", TreeGridRole }, 968643ca7872b450ea4efacab6188849e5aac2ba161Steve Block { "treeitem", TreeItemRole } 969643ca7872b450ea4efacab6188849e5aac2ba161Steve Block }; 970643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ARIARoleMap* roleMap = new ARIARoleMap; 9714576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 9724576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i) 973643ca7872b450ea4efacab6188849e5aac2ba161Steve Block roleMap->set(roles[i].ariaRole, roles[i].webcoreRole); 974643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return roleMap; 975643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 976643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 977643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockAccessibilityRole AccessibilityObject::ariaRoleToWebCoreRole(const String& value) 978643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 979643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(!value.isEmpty()); 980643ca7872b450ea4efacab6188849e5aac2ba161Steve Block static const ARIARoleMap* roleMap = createARIARoleMap(); 981643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return roleMap->get(value); 982635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 983d0825bca7fe65beaee391d30da42e937db621564Steve Block 984dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst AtomicString& AccessibilityObject::placeholderValue() const 985dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{ 986dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch const AtomicString& placeholder = getAttribute(placeholderAttr); 987dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch if (!placeholder.isEmpty()) 988dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return placeholder; 989dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 990dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch return nullAtom; 991dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch} 992dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 993d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool AccessibilityObject::isInsideARIALiveRegion() const 994d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 995d0825bca7fe65beaee391d30da42e937db621564Steve Block if (supportsARIALiveRegion()) 996d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 997d0825bca7fe65beaee391d30da42e937db621564Steve Block 998d0825bca7fe65beaee391d30da42e937db621564Steve Block for (AccessibilityObject* axParent = parentObject(); axParent; axParent = axParent->parentObject()) { 999d0825bca7fe65beaee391d30da42e937db621564Steve Block if (axParent->supportsARIALiveRegion()) 1000d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 1001d0825bca7fe65beaee391d30da42e937db621564Steve Block } 1002d0825bca7fe65beaee391d30da42e937db621564Steve Block 1003d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 1004d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1005d0825bca7fe65beaee391d30da42e937db621564Steve Block 1006dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool AccessibilityObject::supportsARIAAttributes() const 1007dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 1008dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return supportsARIALiveRegion() || supportsARIADragging() || supportsARIADropping() || supportsARIAFlowTo() || supportsARIAOwns(); 1009dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 1010dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 1011d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool AccessibilityObject::supportsARIALiveRegion() const 1012d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 1013d0825bca7fe65beaee391d30da42e937db621564Steve Block const AtomicString& liveRegion = ariaLiveRegionStatus(); 1014d0825bca7fe65beaee391d30da42e937db621564Steve Block return equalIgnoringCase(liveRegion, "polite") || equalIgnoringCase(liveRegion, "assertive"); 1015d0825bca7fe65beaee391d30da42e937db621564Steve Block} 1016cad810f21b803229eb11403f9209855525a25d57Steve Block 1017cad810f21b803229eb11403f9209855525a25d57Steve BlockAccessibilityObject* AccessibilityObject::elementAccessibilityHitTest(const IntPoint& point) const 1018cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1019cad810f21b803229eb11403f9209855525a25d57Steve Block // Send the hit test back into the sub-frame if necessary. 1020cad810f21b803229eb11403f9209855525a25d57Steve Block if (isAttachment()) { 1021cad810f21b803229eb11403f9209855525a25d57Steve Block Widget* widget = widgetForAttachmentView(); 1022ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch // Normalize the point for the widget's bounds. 1023cad810f21b803229eb11403f9209855525a25d57Steve Block if (widget && widget->isFrameView()) 1024ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch return axObjectCache()->getOrCreate(widget)->accessibilityHitTest(IntPoint(point - widget->frameRect().location())); 1025cad810f21b803229eb11403f9209855525a25d57Steve Block } 1026cad810f21b803229eb11403f9209855525a25d57Steve Block 1027cad810f21b803229eb11403f9209855525a25d57Steve Block return const_cast<AccessibilityObject*>(this); 1028cad810f21b803229eb11403f9209855525a25d57Steve Block} 1029cad810f21b803229eb11403f9209855525a25d57Steve Block 1030cad810f21b803229eb11403f9209855525a25d57Steve BlockAXObjectCache* AccessibilityObject::axObjectCache() const 1031cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1032cad810f21b803229eb11403f9209855525a25d57Steve Block Document* doc = document(); 1033cad810f21b803229eb11403f9209855525a25d57Steve Block if (doc) 1034cad810f21b803229eb11403f9209855525a25d57Steve Block return doc->axObjectCache(); 1035cad810f21b803229eb11403f9209855525a25d57Steve Block return 0; 1036cad810f21b803229eb11403f9209855525a25d57Steve Block} 1037cad810f21b803229eb11403f9209855525a25d57Steve Block 1038cad810f21b803229eb11403f9209855525a25d57Steve BlockAccessibilityObject* AccessibilityObject::focusedUIElement() const 1039cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1040cad810f21b803229eb11403f9209855525a25d57Steve Block Document* doc = document(); 1041cad810f21b803229eb11403f9209855525a25d57Steve Block if (!doc) 1042cad810f21b803229eb11403f9209855525a25d57Steve Block return 0; 1043cad810f21b803229eb11403f9209855525a25d57Steve Block 1044cad810f21b803229eb11403f9209855525a25d57Steve Block Page* page = doc->page(); 1045cad810f21b803229eb11403f9209855525a25d57Steve Block if (!page) 1046cad810f21b803229eb11403f9209855525a25d57Steve Block return 0; 1047cad810f21b803229eb11403f9209855525a25d57Steve Block 1048cad810f21b803229eb11403f9209855525a25d57Steve Block return AXObjectCache::focusedUIElementForPage(page); 1049cad810f21b803229eb11403f9209855525a25d57Steve Block} 1050cad810f21b803229eb11403f9209855525a25d57Steve Block 10512fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockAccessibilitySortDirection AccessibilityObject::sortDirection() const 10522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 10532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const AtomicString& sortAttribute = getAttribute(aria_sortAttr); 10542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equalIgnoringCase(sortAttribute, "ascending")) 10552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return SortDirectionAscending; 10562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (equalIgnoringCase(sortAttribute, "descending")) 10572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return SortDirectionDescending; 10582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return SortDirectionNone; 10602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 10612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1062cad810f21b803229eb11403f9209855525a25d57Steve Blockbool AccessibilityObject::supportsARIAExpanded() const 1063cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1064cad810f21b803229eb11403f9209855525a25d57Steve Block return !getAttribute(aria_expandedAttr).isEmpty(); 1065cad810f21b803229eb11403f9209855525a25d57Steve Block} 1066cad810f21b803229eb11403f9209855525a25d57Steve Block 1067cad810f21b803229eb11403f9209855525a25d57Steve Blockbool AccessibilityObject::isExpanded() const 1068cad810f21b803229eb11403f9209855525a25d57Steve Block{ 1069cad810f21b803229eb11403f9209855525a25d57Steve Block if (equalIgnoringCase(getAttribute(aria_expandedAttr), "true")) 1070cad810f21b803229eb11403f9209855525a25d57Steve Block return true; 1071cad810f21b803229eb11403f9209855525a25d57Steve Block 1072cad810f21b803229eb11403f9209855525a25d57Steve Block return false; 1073cad810f21b803229eb11403f9209855525a25d57Steve Block} 1074967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 10750617145a89917ae7735fe1c9538688ab9a577df5Kristian MonsenAccessibilityButtonState AccessibilityObject::checkboxOrRadioValue() const 1076967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 1077967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // If this is a real checkbox or radio button, AccessibilityRenderObject will handle. 1078967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // If it's an ARIA checkbox or radio, the aria-checked attribute should be used. 1079d0825bca7fe65beaee391d30da42e937db621564Steve Block 10800617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen const AtomicString& result = getAttribute(aria_checkedAttr); 10810617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (equalIgnoringCase(result, "true")) 10820617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return ButtonStateOn; 10830617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (equalIgnoringCase(result, "mixed")) 10840617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return ButtonStateMixed; 1085967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 10860617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return ButtonStateOff; 1087967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 1088635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 10898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore 1090