| Index: third_party/WebKit/Source/modules/accessibility/AXObject.cpp
|
| diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
|
| index 9dad88c99054b016c89c6c7473b560664c83fde0..5d258921e26be54a0b31808858212a533b61c1be 100644
|
| --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
|
| +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
|
| @@ -28,6 +28,7 @@
|
|
|
| #include "modules/accessibility/AXObject.h"
|
|
|
| +#include "SkMatrix44.h"
|
| #include "core/editing/EditingUtilities.h"
|
| #include "core/editing/VisibleUnits.h"
|
| #include "core/frame/FrameView.h"
|
| @@ -36,6 +37,7 @@
|
| #include "core/html/HTMLDialogElement.h"
|
| #include "core/html/HTMLFrameOwnerElement.h"
|
| #include "core/html/parser/HTMLParserIdioms.h"
|
| +#include "core/layout/LayoutInline.h"
|
| #include "core/layout/LayoutTheme.h"
|
| #include "modules/accessibility/AXObjectCacheImpl.h"
|
| #include "platform/UserGestureIndicator.h"
|
| @@ -1130,51 +1132,11 @@ bool AXObject::containerLiveRegionBusy() const
|
| return m_cachedLiveRegionRoot && m_cachedLiveRegionRoot->liveRegionBusy();
|
| }
|
|
|
| -void AXObject::markCachedElementRectDirty() const
|
| -{
|
| - for (const auto& child : m_children)
|
| - child->markCachedElementRectDirty();
|
| -}
|
| -
|
| -IntPoint AXObject::clickPoint()
|
| -{
|
| - LayoutRect rect = elementRect();
|
| - return roundedIntPoint(LayoutPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2));
|
| -}
|
| -
|
| -SkMatrix44 AXObject::transformFromLocalParentFrame() const
|
| -{
|
| - return SkMatrix44();
|
| -}
|
| -
|
| -IntRect AXObject::boundingBoxForQuads(LayoutObject* 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()) {
|
| - // TODO(pdr): Should this be using visualOverflowRect?
|
| - if (obj->style()->hasAppearance())
|
| - LayoutTheme::theme().addVisualOverflow(*obj, r);
|
| - result.unite(r);
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| AXObject* AXObject::elementAccessibilityHitTest(const IntPoint& point) const
|
| {
|
| // Check if there are any mock elements that need to be handled.
|
| for (const auto& child : m_children) {
|
| - if (child->isMockObject() && child->elementRect().contains(point))
|
| + if (child->isMockObject() && child->getBoundsInFrameCoordinates().contains(point))
|
| return child->elementAccessibilityHitTest(point);
|
| }
|
|
|
| @@ -1350,11 +1312,111 @@ void AXObject::setScrollOffset(const IntPoint& offset) const
|
| area->setScrollPosition(DoublePoint(offset.x(), offset.y()), ProgrammaticScroll);
|
| }
|
|
|
| -void AXObject::getRelativeBounds(AXObject** container, FloatRect& boundsInContainer, SkMatrix44& containerTransform) const
|
| +void AXObject::getRelativeBounds(AXObject** outContainer, FloatRect& outBoundsInContainer, SkMatrix44& outContainerTransform) const
|
| {
|
| - *container = nullptr;
|
| - boundsInContainer = FloatRect();
|
| - containerTransform.setIdentity();
|
| + *outContainer = nullptr;
|
| + outBoundsInContainer = FloatRect();
|
| + outContainerTransform.setIdentity();
|
| +
|
| + // First check if it has explicit bounds, for example if this element is tied to a
|
| + // canvas path. When explicit coordinates are provided, the ID of the explicit container
|
| + // element that the coordinates are relative to must be provided too.
|
| + if (!m_explicitElementRect.isEmpty()) {
|
| + *outContainer = axObjectCache().objectFromAXID(m_explicitContainerID);
|
| + if (*outContainer) {
|
| + outBoundsInContainer = FloatRect(m_explicitElementRect);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + LayoutObject* layoutObject = layoutObjectForRelativeBounds();
|
| + if (!layoutObject)
|
| + return;
|
| +
|
| + if (isWebArea()) {
|
| + if (layoutObject->frame()->view())
|
| + outBoundsInContainer.setSize(FloatSize(layoutObject->frame()->view()->contentsSize()));
|
| + return;
|
| + }
|
| +
|
| + // First compute the container. The container must be an ancestor in the accessibility tree, and
|
| + // its LayoutObject must be an ancestor in the layout tree. Get the first such ancestor that's
|
| + // either scrollable or has a paint layer.
|
| + AXObject* container = parentObjectUnignored();
|
| + LayoutObject* containerLayoutObject = nullptr;
|
| + while (container) {
|
| + containerLayoutObject = container->getLayoutObject();
|
| + if (containerLayoutObject && containerLayoutObject->isBoxModelObject() && layoutObject->isDescendantOf(containerLayoutObject)) {
|
| + if (container->isScrollableContainer() || containerLayoutObject->hasLayer())
|
| + break;
|
| + }
|
| +
|
| + container = container->parentObjectUnignored();
|
| + }
|
| +
|
| + if (!container)
|
| + return;
|
| + *outContainer = container;
|
| +
|
| + // Next get the local bounds of this LayoutObject, which is typically
|
| + // a rect at point (0, 0) with the width and height of the LayoutObject.
|
| + LayoutRect localBounds;
|
| + if (layoutObject->isText()) {
|
| + Vector<FloatQuad> quads;
|
| + toLayoutText(layoutObject)->quads(quads, LayoutText::ClipToEllipsis, LayoutText::LocalQuads);
|
| + for (const FloatQuad& quad : quads)
|
| + localBounds.unite(LayoutRect(quad.boundingBox()));
|
| + } else if (layoutObject->isLayoutInline()) {
|
| + Vector<LayoutRect> rects;
|
| + toLayoutInline(layoutObject)->addOutlineRects(rects, LayoutPoint(), LayoutObject::IncludeBlockVisualOverflow);
|
| + localBounds = unionRect(rects);
|
| + } else if (layoutObject->isBox()) {
|
| + localBounds = LayoutRect(LayoutPoint(), toLayoutBox(layoutObject)->size());
|
| + } else if (layoutObject->isSVG()) {
|
| + localBounds = LayoutRect(layoutObject->strokeBoundingBox());
|
| + } else {
|
| + DCHECK(false);
|
| + }
|
| + outBoundsInContainer = FloatRect(localBounds);
|
| +
|
| + // If the container has a scroll offset, subtract that out because we want our
|
| + // bounds to be relative to the *unscrolled* position of the container object.
|
| + ScrollableArea* scrollableArea = container->getScrollableAreaIfScrollable();
|
| + if (scrollableArea && !container->isWebArea()) {
|
| + IntPoint scrollPosition = scrollableArea->scrollPosition();
|
| + outBoundsInContainer.move(FloatSize(scrollPosition.x(), scrollPosition.y()));
|
| + }
|
| +
|
| + // Compute the transform between the container's coordinate space and this object.
|
| + // If the transform is just a simple translation, apply that to the bounding box, but
|
| + // if it's a non-trivial transformation like a rotation, scaling, etc. then return
|
| + // the full matrix instead.
|
| + TransformationMatrix transform = layoutObject->localToAncestorTransform(toLayoutBoxModelObject(containerLayoutObject));
|
| + if (transform.isIdentityOr2DTranslation()) {
|
| + outBoundsInContainer.move(transform.to2DTranslation());
|
| + } else {
|
| + outContainerTransform = TransformationMatrix::toSkMatrix44(transform);
|
| + }
|
| +}
|
| +
|
| +LayoutRect AXObject::getBoundsInFrameCoordinates() const
|
| +{
|
| + AXObject* container = nullptr;
|
| + FloatRect bounds;
|
| + SkMatrix44 transform;
|
| + getRelativeBounds(&container, bounds, transform);
|
| + FloatRect computedBounds(0, 0, bounds.width(), bounds.height());
|
| + while (container && container != this) {
|
| + computedBounds.move(bounds.x(), bounds.y());
|
| + if (!container->isWebArea())
|
| + computedBounds.move(-container->scrollOffset().x(), -container->scrollOffset().y());
|
| + if (!transform.isIdentity()) {
|
| + TransformationMatrix transformationMatrix(transform);
|
| + transformationMatrix.mapRect(computedBounds);
|
| + }
|
| + container->getRelativeBounds(&container, bounds, transform);
|
| + }
|
| + return LayoutRect(computedBounds);
|
| }
|
|
|
| //
|
| @@ -1373,7 +1435,7 @@ bool AXObject::press() const
|
|
|
| void AXObject::scrollToMakeVisible() const
|
| {
|
| - IntRect objectRect = pixelSnappedIntRect(elementRect());
|
| + IntRect objectRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
|
| objectRect.setLocation(IntPoint());
|
| scrollToMakeVisibleWithSubFocus(objectRect);
|
| }
|
| @@ -1483,14 +1545,14 @@ void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const
|
| if (!scrollParent || !scrollableArea)
|
| return;
|
|
|
| - IntRect objectRect = pixelSnappedIntRect(elementRect());
|
| + IntRect objectRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
|
| IntPoint scrollPosition = scrollableArea->scrollPosition();
|
| IntRect scrollVisibleRect = scrollableArea->visibleContentRect();
|
|
|
| // Convert the object rect into local coordinates.
|
| if (!scrollParent->isWebArea()) {
|
| objectRect.moveBy(scrollPosition);
|
| - objectRect.moveBy(-pixelSnappedIntRect(scrollParent->elementRect()).location());
|
| + objectRect.moveBy(-pixelSnappedIntRect(scrollParent->getBoundsInFrameCoordinates()).location());
|
| }
|
|
|
| int desiredX = computeBestScrollOffset(
|
| @@ -1508,8 +1570,8 @@ void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const
|
|
|
| // Convert the subfocus into the coordinates of the scroll parent.
|
| IntRect newSubfocus = subfocus;
|
| - IntRect newElementRect = pixelSnappedIntRect(elementRect());
|
| - IntRect scrollParentRect = pixelSnappedIntRect(scrollParent->elementRect());
|
| + IntRect newElementRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
|
| + IntRect scrollParentRect = pixelSnappedIntRect(scrollParent->getBoundsInFrameCoordinates());
|
| newSubfocus.move(newElementRect.x(), newElementRect.y());
|
| newSubfocus.move(-scrollParentRect.x(), -scrollParentRect.y());
|
|
|
| @@ -1540,7 +1602,7 @@ void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
|
| const AXObject* inner = objects[i + 1];
|
| ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();
|
|
|
| - IntRect innerRect = inner->isWebArea() ? pixelSnappedIntRect(inner->parentObject()->elementRect()) : pixelSnappedIntRect(inner->elementRect());
|
| + IntRect innerRect = inner->isWebArea() ? pixelSnappedIntRect(inner->parentObject()->getBoundsInFrameCoordinates()) : pixelSnappedIntRect(inner->getBoundsInFrameCoordinates());
|
| IntRect objectRect = innerRect;
|
| IntPoint scrollPosition = scrollableArea->scrollPosition();
|
|
|
|
|