Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(354)

Unified Diff: Source/core/accessibility/AXObject.cpp

Issue 713933002: Create Source/modules/accessibility/ and move most of core/accessibility/* into it (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/accessibility/AXObject.h ('k') | Source/core/accessibility/AXObjectCache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/accessibility/AXObject.cpp
diff --git a/Source/core/accessibility/AXObject.cpp b/Source/core/accessibility/AXObject.cpp
deleted file mode 100644
index 7594b3baa1e10134854cb8c17eb2ea84a2225654..0000000000000000000000000000000000000000
--- a/Source/core/accessibility/AXObject.cpp
+++ /dev/null
@@ -1,988 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/accessibility/AXObject.h"
-
-#include "core/accessibility/AXObjectCacheImpl.h"
-#include "core/dom/NodeTraversal.h"
-#include "core/editing/VisibleUnits.h"
-#include "core/editing/htmlediting.h"
-#include "core/frame/LocalFrame.h"
-#include "core/frame/Settings.h"
-#include "core/rendering/RenderListItem.h"
-#include "core/rendering/RenderTheme.h"
-#include "core/rendering/RenderView.h"
-#include "platform/UserGestureIndicator.h"
-#include "platform/text/PlatformLocale.h"
-#include "wtf/StdLibExtras.h"
-#include "wtf/text/WTFString.h"
-
-using blink::WebLocalizedString;
-
-namespace blink {
-
-using namespace HTMLNames;
-
-typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap;
-
-struct RoleEntry {
- String ariaRole;
- AccessibilityRole webcoreRole;
-};
-
-static ARIARoleMap* createARIARoleMap()
-{
- const RoleEntry roles[] = {
- { "alert", AlertRole },
- { "alertdialog", AlertDialogRole },
- { "application", ApplicationRole },
- { "article", ArticleRole },
- { "banner", BannerRole },
- { "button", ButtonRole },
- { "checkbox", CheckBoxRole },
- { "complementary", ComplementaryRole },
- { "contentinfo", ContentInfoRole },
- { "dialog", DialogRole },
- { "directory", DirectoryRole },
- { "grid", GridRole },
- { "gridcell", CellRole },
- { "columnheader", ColumnHeaderRole },
- { "combobox", ComboBoxRole },
- { "definition", DefinitionRole },
- { "document", DocumentRole },
- { "rowheader", RowHeaderRole },
- { "form", FormRole },
- { "group", GroupRole },
- { "heading", HeadingRole },
- { "img", ImageRole },
- { "link", LinkRole },
- { "list", ListRole },
- { "listitem", ListItemRole },
- { "listbox", ListBoxRole },
- { "log", LogRole },
- // "option" isn't here because it may map to different roles depending on the parent element's role
- { "main", MainRole },
- { "marquee", MarqueeRole },
- { "math", MathRole },
- { "menu", MenuRole },
- { "menubar", MenuBarRole },
- { "menuitem", MenuItemRole },
- { "menuitemcheckbox", MenuItemCheckBoxRole },
- { "menuitemradio", MenuItemRadioRole },
- { "note", NoteRole },
- { "navigation", NavigationRole },
- { "none", NoneRole },
- { "option", ListBoxOptionRole },
- { "presentation", PresentationalRole },
- { "progressbar", ProgressIndicatorRole },
- { "radio", RadioButtonRole },
- { "radiogroup", RadioGroupRole },
- { "region", RegionRole },
- { "row", RowRole },
- { "scrollbar", ScrollBarRole },
- { "search", SearchRole },
- { "separator", SplitterRole },
- { "slider", SliderRole },
- { "spinbutton", SpinButtonRole },
- { "status", StatusRole },
- { "tab", TabRole },
- { "tablist", TabListRole },
- { "tabpanel", TabPanelRole },
- { "text", StaticTextRole },
- { "textbox", TextAreaRole },
- { "timer", TimerRole },
- { "toolbar", ToolbarRole },
- { "tooltip", UserInterfaceTooltipRole },
- { "tree", TreeRole },
- { "treegrid", TreeGridRole },
- { "treeitem", TreeItemRole }
- };
- ARIARoleMap* roleMap = new ARIARoleMap;
-
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i)
- roleMap->set(roles[i].ariaRole, roles[i].webcoreRole);
- return roleMap;
-}
-
-AXObject::AXObject()
- : m_id(0)
- , m_haveChildren(false)
- , m_role(UnknownRole)
- , m_lastKnownIsIgnoredValue(DefaultBehavior)
- , m_detached(false)
- , m_parent(0)
- , m_lastModificationCount(-1)
- , m_cachedIsIgnored(false)
- , m_cachedLiveRegionRoot(0)
-{
-}
-
-AXObject::~AXObject()
-{
- ASSERT(isDetached());
-}
-
-void AXObject::detach()
-{
- // Clear any children and call detachFromParent on them so that
- // no children are left with dangling pointers to their parent.
- clearChildren();
-
- m_detached = true;
-}
-
-bool AXObject::isDetached() const
-{
- return m_detached;
-}
-
-AXObjectCacheImpl* AXObject::axObjectCache() const
-{
- Document* doc = document();
- if (doc)
- return toAXObjectCacheImpl(doc->axObjectCache());
- return 0;
-}
-
-bool AXObject::isARIATextControl() const
-{
- return ariaRoleAttribute() == TextAreaRole || ariaRoleAttribute() == TextFieldRole;
-}
-
-bool AXObject::isButton() const
-{
- AccessibilityRole role = roleValue();
-
- return role == ButtonRole || role == PopUpButtonRole || role == ToggleButtonRole;
-}
-
-bool AXObject::isLandmarkRelated() const
-{
- switch (roleValue()) {
- case ApplicationRole:
- case ArticleRole:
- case BannerRole:
- case ComplementaryRole:
- case ContentInfoRole:
- case FooterRole:
- case FormRole:
- case MainRole:
- case NavigationRole:
- case RegionRole:
- case SearchRole:
- return true;
- default:
- return false;
- }
-}
-
-bool AXObject::isMenuRelated() const
-{
- switch (roleValue()) {
- case MenuRole:
- case MenuBarRole:
- case MenuButtonRole:
- case MenuItemRole:
- case MenuItemCheckBoxRole:
- case MenuItemRadioRole:
- return true;
- default:
- return false;
- }
-}
-
-bool AXObject::isPasswordFieldAndShouldHideValue() const
-{
- Settings* settings = document()->settings();
- if (!settings || settings->accessibilityPasswordValuesEnabled())
- return false;
-
- return isPasswordField();
-}
-
-bool AXObject::isTextControl() const
-{
- switch (roleValue()) {
- case TextAreaRole:
- case TextFieldRole:
- case ComboBoxRole:
- return true;
- default:
- return false;
- }
-}
-
-bool AXObject::isClickable() const
-{
- switch (roleValue()) {
- case ButtonRole:
- case CheckBoxRole:
- case ColorWellRole:
- case ComboBoxRole:
- case EditableTextRole:
- case ImageMapLinkRole:
- case LinkRole:
- case ListBoxOptionRole:
- case MenuButtonRole:
- case PopUpButtonRole:
- case RadioButtonRole:
- case TabRole:
- case TextAreaRole:
- case TextFieldRole:
- case ToggleButtonRole:
- return true;
- default:
- return false;
- }
-}
-
-bool AXObject::accessibilityIsIgnored() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedIsIgnored;
-}
-
-void AXObject::updateCachedAttributeValuesIfNeeded() const
-{
- AXObjectCacheImpl* cache = axObjectCache();
- if (!cache)
- return;
-
- if (cache->modificationCount() == m_lastModificationCount)
- return;
-
- m_lastModificationCount = cache->modificationCount();
- m_cachedIsIgnored = computeAccessibilityIsIgnored();
- m_cachedLiveRegionRoot = isLiveRegion() ?
- this :
- (parentObjectIfExists() ? parentObjectIfExists()->liveRegionRoot() : 0);
-}
-
-bool AXObject::accessibilityIsIgnoredByDefault() const
-{
- return defaultObjectInclusion() == IgnoreObject;
-}
-
-AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const
-{
- if (isMenuListPopup() || isMenuListOption())
- return IncludeObject;
-
- return DefaultBehavior;
-}
-
-AXObjectInclusion AXObject::defaultObjectInclusion() const
-{
- if (isInertOrAriaHidden())
- return IgnoreObject;
-
- if (isPresentationalChildOfAriaRole())
- return IgnoreObject;
-
- return accessibilityPlatformIncludesObject();
-}
-
-bool AXObject::isInertOrAriaHidden() const
-{
- bool mightBeInInertSubtree = true;
- for (const AXObject* object = this; object; object = object->parentObject()) {
- if (equalIgnoringCase(object->getAttribute(aria_hiddenAttr), "true"))
- return true;
- if (mightBeInInertSubtree && object->node()) {
- if (object->node()->isInert())
- return true;
- mightBeInInertSubtree = false;
- }
- }
-
- return false;
-}
-
-bool AXObject::lastKnownIsIgnoredValue()
-{
- if (m_lastKnownIsIgnoredValue == DefaultBehavior)
- m_lastKnownIsIgnoredValue = accessibilityIsIgnored() ? IgnoreObject : IncludeObject;
-
- return m_lastKnownIsIgnoredValue == IgnoreObject;
-}
-
-void AXObject::setLastKnownIsIgnoredValue(bool isIgnored)
-{
- m_lastKnownIsIgnoredValue = isIgnored ? IgnoreObject : IncludeObject;
-}
-
-// Lacking concrete evidence of orientation, horizontal means width > height. vertical is height > width;
-AccessibilityOrientation AXObject::orientation() const
-{
- LayoutRect bounds = elementRect();
- if (bounds.size().width() > bounds.size().height())
- return AccessibilityOrientationHorizontal;
- if (bounds.size().height() > bounds.size().width())
- return AccessibilityOrientationVertical;
-
- // A tie goes to horizontal.
- return AccessibilityOrientationHorizontal;
-}
-
-static String queryString(WebLocalizedString::Name name)
-{
- return Locale::defaultLocale().queryString(name);
-}
-
-String AXObject::actionVerb() const
-{
- // FIXME: Need to add verbs for select elements.
-
- switch (roleValue()) {
- case ButtonRole:
- case ToggleButtonRole:
- return queryString(WebLocalizedString::AXButtonActionVerb);
- case TextFieldRole:
- case TextAreaRole:
- return queryString(WebLocalizedString::AXTextFieldActionVerb);
- case RadioButtonRole:
- return queryString(WebLocalizedString::AXRadioButtonActionVerb);
- case CheckBoxRole:
- return queryString(isChecked() ? WebLocalizedString::AXCheckedCheckBoxActionVerb : WebLocalizedString::AXUncheckedCheckBoxActionVerb);
- case LinkRole:
- return queryString(WebLocalizedString::AXLinkActionVerb);
- case PopUpButtonRole:
- // FIXME: Implement.
- return String();
- case MenuListPopupRole:
- // FIXME: Implement.
- return String();
- default:
- return emptyString();
- }
-}
-
-AccessibilityButtonState AXObject::checkboxOrRadioValue() const
-{
- // If this is a real checkbox or radio button, AXRenderObject will handle.
- // If it's an ARIA checkbox or radio, the aria-checked attribute should be used.
-
- const AtomicString& result = getAttribute(aria_checkedAttr);
- if (equalIgnoringCase(result, "true"))
- return ButtonStateOn;
- if (equalIgnoringCase(result, "mixed"))
- return ButtonStateMixed;
-
- return ButtonStateOff;
-}
-
-bool AXObject::ariaIsMultiline() const
-{
- return equalIgnoringCase(getAttribute(aria_multilineAttr), "true");
-}
-
-bool AXObject::ariaPressedIsPresent() const
-{
- return !getAttribute(aria_pressedAttr).isEmpty();
-}
-
-bool AXObject::supportsARIAAttributes() const
-{
- return isLiveRegion()
- || supportsARIADragging()
- || supportsARIADropping()
- || supportsARIAFlowTo()
- || supportsARIAOwns()
- || hasAttribute(aria_labelAttr);
-}
-
-bool AXObject::supportsRangeValue() const
-{
- return isProgressIndicator()
- || isSlider()
- || isScrollbar()
- || isSpinButton();
-}
-
-void AXObject::ariaTreeRows(AccessibilityChildrenVector& result)
-{
- AccessibilityChildrenVector axChildren = children();
- unsigned count = axChildren.size();
- for (unsigned k = 0; k < count; ++k) {
- AXObject* obj = axChildren[k].get();
-
- // Add tree items as the rows.
- if (obj->roleValue() == TreeItemRole)
- result.append(obj);
-
- // Now see if this item also has rows hiding inside of it.
- obj->ariaTreeRows(result);
- }
-}
-
-bool AXObject::isLiveRegion() const
-{
- const AtomicString& liveRegion = liveRegionStatus();
- return equalIgnoringCase(liveRegion, "polite") || equalIgnoringCase(liveRegion, "assertive");
-}
-
-const AXObject* AXObject::liveRegionRoot() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedLiveRegionRoot;
-}
-
-const AtomicString& AXObject::containerLiveRegionStatus() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionStatus() : nullAtom;
-}
-
-const AtomicString& AXObject::containerLiveRegionRelevant() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionRelevant() : nullAtom;
-}
-
-bool AXObject::containerLiveRegionAtomic() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionAtomic() : false;
-}
-
-bool AXObject::containerLiveRegionBusy() const
-{
- updateCachedAttributeValuesIfNeeded();
- return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionBusy() : false;
-}
-
-void AXObject::markCachedElementRectDirty() const
-{
- for (unsigned i = 0; i < m_children.size(); ++i)
- m_children[i].get()->markCachedElementRectDirty();
-}
-
-IntPoint AXObject::clickPoint()
-{
- LayoutRect rect = elementRect();
- return roundedIntPoint(LayoutPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2));
-}
-
-IntRect AXObject::boundingBoxForQuads(RenderObject* obj, const Vector<FloatQuad>& quads)
-{
- ASSERT(obj);
- if (!obj)
- return IntRect();
-
- size_t count = quads.size();
- if (!count)
- return IntRect();
-
- IntRect result;
- for (size_t i = 0; i < count; ++i) {
- IntRect r = quads[i].enclosingBoundingBox();
- if (!r.isEmpty()) {
- if (obj->style()->hasAppearance())
- RenderTheme::theme().adjustPaintInvalidationRect(obj, r);
- result.unite(r);
- }
- }
- return result;
-}
-
-AXObject* AXObject::elementAccessibilityHitTest(const IntPoint& point) const
-{
- // Send the hit test back into the sub-frame if necessary.
- if (isAttachment()) {
- Widget* widget = widgetForAttachmentView();
- // Normalize the point for the widget's bounds.
- if (widget && widget->isFrameView())
- return axObjectCache()->getOrCreate(widget)->accessibilityHitTest(IntPoint(point - widget->frameRect().location()));
- }
-
- // Check if there are any mock elements that need to be handled.
- size_t count = m_children.size();
- for (size_t k = 0; k < count; k++) {
- if (m_children[k]->isMockObject() && m_children[k]->elementRect().contains(point))
- return m_children[k]->elementAccessibilityHitTest(point);
- }
-
- return const_cast<AXObject*>(this);
-}
-
-const AXObject::AccessibilityChildrenVector& AXObject::children()
-{
- updateChildrenIfNecessary();
-
- return m_children;
-}
-
-AXObject* AXObject::parentObject() const
-{
- if (m_detached)
- return 0;
-
- if (m_parent)
- return m_parent;
-
- return computeParent();
-}
-
-AXObject* AXObject::parentObjectIfExists() const
-{
- if (m_detached)
- return 0;
-
- if (m_parent)
- return m_parent;
-
- return computeParentIfExists();
-}
-
-AXObject* AXObject::parentObjectUnignored() const
-{
- AXObject* parent;
- for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
- }
-
- return parent;
-}
-
-AXObject* AXObject::firstAccessibleObjectFromNode(const Node* node)
-{
- if (!node)
- return 0;
-
- AXObjectCacheImpl* cache = toAXObjectCacheImpl(node->document().axObjectCache());
- AXObject* accessibleObject = cache->getOrCreate(node->renderer());
- while (accessibleObject && accessibleObject->accessibilityIsIgnored()) {
- node = NodeTraversal::next(*node);
-
- while (node && !node->renderer())
- node = NodeTraversal::nextSkippingChildren(*node);
-
- if (!node)
- return 0;
-
- accessibleObject = cache->getOrCreate(node->renderer());
- }
-
- return accessibleObject;
-}
-
-void AXObject::updateChildrenIfNecessary()
-{
- if (!hasChildren())
- addChildren();
-}
-
-void AXObject::clearChildren()
-{
- // Detach all weak pointers from objects to their parents.
- size_t length = m_children.size();
- for (size_t i = 0; i < length; i++)
- m_children[i]->detachFromParent();
-
- m_children.clear();
- m_haveChildren = false;
-}
-
-AXObject* AXObject::focusedUIElement() const
-{
- Document* doc = document();
- if (!doc)
- return 0;
-
- Page* page = doc->page();
- if (!page)
- return 0;
-
- return AXObjectCacheImpl::focusedUIElementForPage(page);
-}
-
-Document* AXObject::document() const
-{
- FrameView* frameView = documentFrameView();
- if (!frameView)
- return 0;
-
- return frameView->frame().document();
-}
-
-FrameView* AXObject::documentFrameView() const
-{
- const AXObject* object = this;
- while (object && !object->isAXRenderObject())
- object = object->parentObject();
-
- if (!object)
- return 0;
-
- return object->documentFrameView();
-}
-
-String AXObject::language() const
-{
- const AtomicString& lang = getAttribute(langAttr);
- if (!lang.isEmpty())
- return lang;
-
- AXObject* parent = parentObject();
-
- // as a last resort, fall back to the content language specified in the meta tag
- if (!parent) {
- Document* doc = document();
- if (doc)
- return doc->contentLanguage();
- return nullAtom;
- }
-
- return parent->language();
-}
-
-bool AXObject::hasAttribute(const QualifiedName& attribute) const
-{
- Node* elementNode = node();
- if (!elementNode)
- return false;
-
- if (!elementNode->isElementNode())
- return false;
-
- Element* element = toElement(elementNode);
- return element->fastHasAttribute(attribute);
-}
-
-const AtomicString& AXObject::getAttribute(const QualifiedName& attribute) const
-{
- Node* elementNode = node();
- if (!elementNode)
- return nullAtom;
-
- if (!elementNode->isElementNode())
- return nullAtom;
-
- Element* element = toElement(elementNode);
- return element->fastGetAttribute(attribute);
-}
-
-bool AXObject::press() const
-{
- Element* actionElem = actionElement();
- if (!actionElem)
- return false;
- UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
- actionElem->accessKeyAction(true);
- return true;
-}
-
-void AXObject::scrollToMakeVisible() const
-{
- IntRect objectRect = pixelSnappedIntRect(elementRect());
- objectRect.setLocation(IntPoint());
- scrollToMakeVisibleWithSubFocus(objectRect);
-}
-
-// This is a 1-dimensional scroll offset helper function that's applied
-// separately in the horizontal and vertical directions, because the
-// logic is the same. The goal is to compute the best scroll offset
-// in order to make an object visible within a viewport.
-//
-// If the object is already fully visible, returns the same scroll
-// offset.
-//
-// In case the whole object cannot fit, you can specify a
-// subfocus - a smaller region within the object that should
-// be prioritized. If the whole object can fit, the subfocus is
-// ignored.
-//
-// If possible, the object and subfocus are centered within the
-// viewport.
-//
-// Example 1: the object is already visible, so nothing happens.
-// +----------Viewport---------+
-// +---Object---+
-// +--SubFocus--+
-//
-// Example 2: the object is not fully visible, so it's centered
-// within the viewport.
-// Before:
-// +----------Viewport---------+
-// +---Object---+
-// +--SubFocus--+
-//
-// After:
-// +----------Viewport---------+
-// +---Object---+
-// +--SubFocus--+
-//
-// Example 3: the object is larger than the viewport, so the
-// viewport moves to show as much of the object as possible,
-// while also trying to center the subfocus.
-// Before:
-// +----------Viewport---------+
-// +---------------Object--------------+
-// +-SubFocus-+
-//
-// After:
-// +----------Viewport---------+
-// +---------------Object--------------+
-// +-SubFocus-+
-//
-// When constraints cannot be fully satisfied, the min
-// (left/top) position takes precedence over the max (right/bottom).
-//
-// Note that the return value represents the ideal new scroll offset.
-// This may be out of range - the calling function should clip this
-// to the available range.
-static int computeBestScrollOffset(int currentScrollOffset, int subfocusMin, int subfocusMax, int objectMin, int objectMax, int viewportMin, int viewportMax)
-{
- int viewportSize = viewportMax - viewportMin;
-
- // If the object size is larger than the viewport size, consider
- // only a portion that's as large as the viewport, centering on
- // the subfocus as much as possible.
- if (objectMax - objectMin > viewportSize) {
- // Since it's impossible to fit the whole object in the
- // viewport, exit now if the subfocus is already within the viewport.
- if (subfocusMin - currentScrollOffset >= viewportMin
- && subfocusMax - currentScrollOffset <= viewportMax)
- return currentScrollOffset;
-
- // Subfocus must be within focus.
- subfocusMin = std::max(subfocusMin, objectMin);
- subfocusMax = std::min(subfocusMax, objectMax);
-
- // Subfocus must be no larger than the viewport size; favor top/left.
- if (subfocusMax - subfocusMin > viewportSize)
- subfocusMax = subfocusMin + viewportSize;
-
- // Compute the size of an object centered on the subfocus, the size of the viewport.
- int centeredObjectMin = (subfocusMin + subfocusMax - viewportSize) / 2;
- int centeredObjectMax = centeredObjectMin + viewportSize;
-
- objectMin = std::max(objectMin, centeredObjectMin);
- objectMax = std::min(objectMax, centeredObjectMax);
- }
-
- // Exit now if the focus is already within the viewport.
- if (objectMin - currentScrollOffset >= viewportMin
- && objectMax - currentScrollOffset <= viewportMax)
- return currentScrollOffset;
-
- // Center the object in the viewport.
- return (objectMin + objectMax - viewportMin - viewportMax) / 2;
-}
-
-void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const
-{
- // Search up the parent chain until we find the first one that's scrollable.
- AXObject* scrollParent = parentObject();
- ScrollableArea* scrollableArea = 0;
- while (scrollParent) {
- scrollableArea = scrollParent->getScrollableAreaIfScrollable();
- if (scrollableArea)
- break;
- scrollParent = scrollParent->parentObject();
- }
- if (!scrollableArea)
- return;
-
- IntRect objectRect = pixelSnappedIntRect(elementRect());
- IntPoint scrollPosition = scrollableArea->scrollPosition();
- IntRect scrollVisibleRect = scrollableArea->visibleContentRect();
-
- int desiredX = computeBestScrollOffset(
- scrollPosition.x(),
- objectRect.x() + subfocus.x(), objectRect.x() + subfocus.maxX(),
- objectRect.x(), objectRect.maxX(),
- 0, scrollVisibleRect.width());
- int desiredY = computeBestScrollOffset(
- scrollPosition.y(),
- objectRect.y() + subfocus.y(), objectRect.y() + subfocus.maxY(),
- objectRect.y(), objectRect.maxY(),
- 0, scrollVisibleRect.height());
-
- scrollParent->scrollTo(IntPoint(desiredX, desiredY));
-
- // Convert the subfocus into the coordinates of the scroll parent.
- IntRect newSubfocus = subfocus;
- IntRect newElementRect = pixelSnappedIntRect(elementRect());
- IntRect scrollParentRect = pixelSnappedIntRect(scrollParent->elementRect());
- newSubfocus.move(newElementRect.x(), newElementRect.y());
- newSubfocus.move(-scrollParentRect.x(), -scrollParentRect.y());
-
- // Recursively make sure the scroll parent itself is visible.
- if (scrollParent->parentObject())
- scrollParent->scrollToMakeVisibleWithSubFocus(newSubfocus);
-}
-
-void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
-{
- // Search up the parent chain and create a vector of all scrollable parent objects
- // and ending with this object itself.
- Vector<const AXObject*> objects;
- AXObject* parentObject;
- for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) {
- if (parentObject->getScrollableAreaIfScrollable())
- objects.prepend(parentObject);
- }
- objects.append(this);
-
- // Start with the outermost scrollable (the main window) and try to scroll the
- // next innermost object to the given point.
- int offsetX = 0, offsetY = 0;
- IntPoint point = globalPoint;
- size_t levels = objects.size() - 1;
- for (size_t i = 0; i < levels; i++) {
- const AXObject* outer = objects[i];
- const AXObject* inner = objects[i + 1];
-
- ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();
-
- IntRect innerRect = inner->isAXScrollView() ? pixelSnappedIntRect(inner->parentObject()->elementRect()) : pixelSnappedIntRect(inner->elementRect());
- IntRect objectRect = innerRect;
- IntPoint scrollPosition = scrollableArea->scrollPosition();
-
- // Convert the object rect into local coordinates.
- objectRect.move(offsetX, offsetY);
- if (!outer->isAXScrollView())
- objectRect.move(scrollPosition.x(), scrollPosition.y());
-
- int desiredX = computeBestScrollOffset(
- 0,
- objectRect.x(), objectRect.maxX(),
- objectRect.x(), objectRect.maxX(),
- point.x(), point.x());
- int desiredY = computeBestScrollOffset(
- 0,
- objectRect.y(), objectRect.maxY(),
- objectRect.y(), objectRect.maxY(),
- point.y(), point.y());
- outer->scrollTo(IntPoint(desiredX, desiredY));
-
- if (outer->isAXScrollView() && !inner->isAXScrollView()) {
- // If outer object we just scrolled is a scroll view (main window or iframe) but the
- // inner object is not, keep track of the coordinate transformation to apply to
- // future nested calculations.
- scrollPosition = scrollableArea->scrollPosition();
- offsetX -= (scrollPosition.x() + point.x());
- offsetY -= (scrollPosition.y() + point.y());
- point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y());
- } else if (inner->isAXScrollView()) {
- // Otherwise, if the inner object is a scroll view, reset the coordinate transformation.
- offsetX = 0;
- offsetY = 0;
- }
- }
-}
-
-void AXObject::notifyIfIgnoredValueChanged()
-{
- bool isIgnored = accessibilityIsIgnored();
- if (lastKnownIsIgnoredValue() != isIgnored) {
- axObjectCache()->childrenChanged(parentObject());
- setLastKnownIsIgnoredValue(isIgnored);
- }
-}
-
-void AXObject::selectionChanged()
-{
- if (AXObject* parent = parentObjectIfExists())
- parent->selectionChanged();
-}
-
-int AXObject::lineForPosition(const VisiblePosition& visiblePos) const
-{
- if (visiblePos.isNull() || !node())
- return -1;
-
- // If the position is not in the same editable region as this AX object, return -1.
- Node* containerNode = visiblePos.deepEquivalent().containerNode();
- if (!containerNode->containsIncludingShadowDOM(node()) && !node()->containsIncludingShadowDOM(containerNode))
- return -1;
-
- int lineCount = -1;
- VisiblePosition currentVisiblePos = visiblePos;
- VisiblePosition savedVisiblePos;
-
- // move up until we get to the top
- // FIXME: This only takes us to the top of the rootEditableElement, not the top of the
- // top document.
- do {
- savedVisiblePos = currentVisiblePos;
- VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0, HasEditableAXRole);
- currentVisiblePos = prevVisiblePos;
- ++lineCount;
- } while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos)));
-
- return lineCount;
-}
-
-bool AXObject::isARIAControl(AccessibilityRole ariaRole)
-{
- return isARIAInput(ariaRole) || ariaRole == TextAreaRole || ariaRole == ButtonRole
- || ariaRole == ComboBoxRole || ariaRole == SliderRole;
-}
-
-bool AXObject::isARIAInput(AccessibilityRole ariaRole)
-{
- return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole;
-}
-
-AccessibilityRole AXObject::ariaRoleToWebCoreRole(const String& value)
-{
- ASSERT(!value.isEmpty());
-
- static const ARIARoleMap* roleMap = createARIARoleMap();
-
- Vector<String> roleVector;
- value.split(' ', roleVector);
- AccessibilityRole role = UnknownRole;
- unsigned size = roleVector.size();
- for (unsigned i = 0; i < size; ++i) {
- String roleName = roleVector[i];
- role = roleMap->get(roleName);
- if (role)
- return role;
- }
-
- return role;
-}
-
-AccessibilityRole AXObject::buttonRoleType() const
-{
- // If aria-pressed is present, then it should be exposed as a toggle button.
- // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed
- if (ariaPressedIsPresent())
- return ToggleButtonRole;
- if (ariaHasPopup())
- return PopUpButtonRole;
- // We don't contemplate RadioButtonRole, as it depends on the input
- // type.
-
- return ButtonRole;
-}
-
-} // namespace blink
« no previous file with comments | « Source/core/accessibility/AXObject.h ('k') | Source/core/accessibility/AXObjectCache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698