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; for (scrollableArea = 0; scrollParent && !(scrollableArea = scrollParent->getScrollableAreaIfScrollable()); scrollParent = scrollParent->parentObject()) { } if (!scrollableArea) return; LayoutRect objectRect = 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)); // Recursively make sure the scroll parent itself is visible. if (scrollParent->parentObject()) scrollParent->scrollToMakeVisible(); }
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(); LayoutRect innerRect = inner->isAXScrollView() ? inner->parentObject()->elementRect() : inner->elementRect(); LayoutRect 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::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 && !scrollParent->isAXScrollView()) break; scrollParent = scrollParent->parentObject(); } if (!scrollParent || !scrollableArea) return; IntRect objectRect = pixelSnappedIntRect(elementRect()); 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()); } 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->setScrollOffset(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); }