| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 if (layoutObject->isLayoutInline() && !layoutObject->isAtomicInlineLevel()) | 173 if (layoutObject->isLayoutInline() && !layoutObject->isAtomicInlineLevel()) |
| 174 return toLayoutInline(layoutObject)->continuation(); | 174 return toLayoutInline(layoutObject)->continuation(); |
| 175 if (layoutObject->isLayoutBlockFlow()) | 175 if (layoutObject->isLayoutBlockFlow()) |
| 176 return toLayoutBlockFlow(layoutObject)->inlineElementContinuation(); | 176 return toLayoutBlockFlow(layoutObject)->inlineElementContinuation(); |
| 177 return 0; | 177 return 0; |
| 178 } | 178 } |
| 179 | 179 |
| 180 AXLayoutObject::AXLayoutObject(LayoutObject* layoutObject, AXObjectCacheImpl& ax
ObjectCache) | 180 AXLayoutObject::AXLayoutObject(LayoutObject* layoutObject, AXObjectCacheImpl& ax
ObjectCache) |
| 181 : AXNodeObject(layoutObject->node(), axObjectCache) | 181 : AXNodeObject(layoutObject->node(), axObjectCache) |
| 182 , m_layoutObject(layoutObject) | 182 , m_layoutObject(layoutObject) |
| 183 , m_cachedElementRectDirty(true) | |
| 184 { | 183 { |
| 185 #if ENABLE(ASSERT) | 184 #if ENABLE(ASSERT) |
| 186 m_layoutObject->setHasAXObject(true); | 185 m_layoutObject->setHasAXObject(true); |
| 187 #endif | 186 #endif |
| 188 } | 187 } |
| 189 | 188 |
| 190 AXLayoutObject* AXLayoutObject::create(LayoutObject* layoutObject, AXObjectCache
Impl& axObjectCache) | 189 AXLayoutObject* AXLayoutObject::create(LayoutObject* layoutObject, AXObjectCache
Impl& axObjectCache) |
| 191 { | 190 { |
| 192 return new AXLayoutObject(layoutObject, axObjectCache); | 191 return new AXLayoutObject(layoutObject, axObjectCache); |
| 193 } | 192 } |
| 194 | 193 |
| 195 AXLayoutObject::~AXLayoutObject() | 194 AXLayoutObject::~AXLayoutObject() |
| 196 { | 195 { |
| 197 ASSERT(isDetached()); | 196 ASSERT(isDetached()); |
| 198 } | 197 } |
| 199 | 198 |
| 200 LayoutRect AXLayoutObject::elementRect() const | |
| 201 { | |
| 202 if (!m_explicitElementRect.isEmpty()) { | |
| 203 LayoutRect bounds = m_explicitElementRect; | |
| 204 AXObject* canvas = axObjectCache().objectFromAXID(m_explicitContainerID)
; | |
| 205 if (canvas) | |
| 206 bounds.moveBy(canvas->elementRect().location()); | |
| 207 return bounds; | |
| 208 } | |
| 209 | |
| 210 // FIXME(dmazzoni): use relative bounds instead since this is a bottleneck. | |
| 211 // http://crbug.com/618120 | |
| 212 return computeElementRect(); | |
| 213 } | |
| 214 | |
| 215 SkMatrix44 AXLayoutObject::transformFromLocalParentFrame() const | |
| 216 { | |
| 217 if (!m_layoutObject) | |
| 218 return SkMatrix44(); | |
| 219 LayoutView* layoutView = toLayoutView(LayoutAPIShim::layoutObjectFrom(docume
ntFrameView()->layoutViewItem())); | |
| 220 | |
| 221 FrameView* parentFrameView = documentFrameView()->parentFrameView(); | |
| 222 if (!parentFrameView) | |
| 223 return SkMatrix44(); | |
| 224 LayoutView* parentLayoutView = toLayoutView(LayoutAPIShim::layoutObjectFrom(
parentFrameView->layoutViewItem())); | |
| 225 | |
| 226 TransformationMatrix accumulatedTransform = layoutView->localToAncestorTrans
form(parentLayoutView, TraverseDocumentBoundaries); | |
| 227 IntPoint scrollPosition = documentFrameView()->scrollPosition(); | |
| 228 accumulatedTransform.translate(scrollPosition.x(), scrollPosition.y()); | |
| 229 return TransformationMatrix::toSkMatrix44(accumulatedTransform); | |
| 230 } | |
| 231 | |
| 232 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const | 199 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const |
| 233 { | 200 { |
| 234 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) | 201 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) |
| 235 return 0; | 202 return 0; |
| 236 return toLayoutBoxModelObject(m_layoutObject); | 203 return toLayoutBoxModelObject(m_layoutObject); |
| 237 } | 204 } |
| 238 | 205 |
| 239 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const | 206 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const |
| 240 { | 207 { |
| 241 if (isWebArea()) | 208 if (isWebArea()) |
| 242 return documentFrameView(); | 209 return documentFrameView(); |
| 243 | 210 |
| 244 if (!m_layoutObject || !m_layoutObject->isBox()) | 211 if (!m_layoutObject || !m_layoutObject->isBox()) |
| 245 return 0; | 212 return 0; |
| 246 | 213 |
| 247 LayoutBox* box = toLayoutBox(m_layoutObject); | 214 LayoutBox* box = toLayoutBox(m_layoutObject); |
| 248 if (!box->canBeScrolledAndHasScrollableArea()) | 215 if (!box->canBeScrolledAndHasScrollableArea()) |
| 249 return 0; | 216 return 0; |
| 250 | 217 |
| 251 return box->getScrollableArea(); | 218 return box->getScrollableArea(); |
| 252 } | 219 } |
| 253 | 220 |
| 254 void AXLayoutObject::getRelativeBounds(AXObject** outContainer, FloatRect& outBo
undsInContainer, SkMatrix44& outContainerTransform) const | |
| 255 { | |
| 256 *outContainer = nullptr; | |
| 257 outBoundsInContainer = FloatRect(); | |
| 258 outContainerTransform.setIdentity(); | |
| 259 | |
| 260 // First check if it has explicit bounds, for example if this element is tie
d to a | |
| 261 // canvas path. When explicit coordinates are provided, the ID of the explic
it container | |
| 262 // element that the coordinates are relative to must be provided too. | |
| 263 if (!m_explicitElementRect.isEmpty()) { | |
| 264 *outContainer = axObjectCache().objectFromAXID(m_explicitContainerID); | |
| 265 if (*outContainer) { | |
| 266 outBoundsInContainer = FloatRect(m_explicitElementRect); | |
| 267 return; | |
| 268 } | |
| 269 } | |
| 270 | |
| 271 if (!m_layoutObject) | |
| 272 return; | |
| 273 | |
| 274 if (isWebArea()) { | |
| 275 if (m_layoutObject->frame()->view()) | |
| 276 outBoundsInContainer.setSize(FloatSize(m_layoutObject->frame()->view
()->contentsSize())); | |
| 277 return; | |
| 278 } | |
| 279 | |
| 280 // First compute the container. The container must be an ancestor in the acc
essibility tree, and | |
| 281 // its LayoutObject must be an ancestor in the layout tree. Get the first su
ch ancestor that's | |
| 282 // either scrollable or has a paint layer. | |
| 283 AXObject* container = parentObjectUnignored(); | |
| 284 LayoutObject* containerLayoutObject = nullptr; | |
| 285 while (container) { | |
| 286 containerLayoutObject = container->getLayoutObject(); | |
| 287 if (containerLayoutObject && containerLayoutObject->isBoxModelObject() &
& m_layoutObject->isDescendantOf(containerLayoutObject)) { | |
| 288 if (container->isScrollableContainer() || containerLayoutObject->has
Layer()) | |
| 289 break; | |
| 290 } | |
| 291 | |
| 292 container = container->parentObjectUnignored(); | |
| 293 } | |
| 294 | |
| 295 if (!container) | |
| 296 return; | |
| 297 *outContainer = container; | |
| 298 | |
| 299 // Next get the local bounds of this LayoutObject, which is typically | |
| 300 // a rect at point (0, 0) with the width and height of the LayoutObject. | |
| 301 LayoutRect localBounds; | |
| 302 if (m_layoutObject->isText()) { | |
| 303 Vector<FloatQuad> quads; | |
| 304 toLayoutText(m_layoutObject)->quads(quads, LayoutText::ClipToEllipsis, L
ayoutText::LocalQuads); | |
| 305 for (const FloatQuad& quad : quads) | |
| 306 localBounds.unite(LayoutRect(quad.boundingBox())); | |
| 307 } else if (m_layoutObject->isLayoutInline()) { | |
| 308 Vector<LayoutRect> rects; | |
| 309 toLayoutInline(m_layoutObject)->addOutlineRects(rects, LayoutPoint(), La
youtObject::IncludeBlockVisualOverflow); | |
| 310 localBounds = unionRect(rects); | |
| 311 } else if (m_layoutObject->isBox()) { | |
| 312 localBounds = LayoutRect(LayoutPoint(), toLayoutBox(m_layoutObject)->siz
e()); | |
| 313 } else if (m_layoutObject->isSVG()) { | |
| 314 localBounds = LayoutRect(m_layoutObject->strokeBoundingBox()); | |
| 315 } else { | |
| 316 DCHECK(false); | |
| 317 } | |
| 318 outBoundsInContainer = FloatRect(localBounds); | |
| 319 | |
| 320 // If the container has a scroll offset, subtract that out because we want o
ur | |
| 321 // bounds to be relative to the *unscrolled* position of the container objec
t. | |
| 322 ScrollableArea* scrollableArea = container->getScrollableAreaIfScrollable(); | |
| 323 if (scrollableArea && !container->isWebArea()) { | |
| 324 IntPoint scrollPosition = scrollableArea->scrollPosition(); | |
| 325 outBoundsInContainer.move(FloatSize(scrollPosition.x(), scrollPosition.y
())); | |
| 326 } | |
| 327 | |
| 328 // Compute the transform between the container's coordinate space and this o
bject. | |
| 329 // If the transform is just a simple translation, apply that to the bounding
box, but | |
| 330 // if it's a non-trivial transformation like a rotation, scaling, etc. then
return | |
| 331 // the full matrix instead. | |
| 332 TransformationMatrix transform = m_layoutObject->localToAncestorTransform(to
LayoutBoxModelObject(containerLayoutObject)); | |
| 333 if (transform.isIdentityOr2DTranslation()) { | |
| 334 outBoundsInContainer.move(transform.to2DTranslation()); | |
| 335 } else { | |
| 336 outContainerTransform = TransformationMatrix::toSkMatrix44(transform); | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 static bool isImageOrAltText(LayoutBoxModelObject* box, Node* node) | 221 static bool isImageOrAltText(LayoutBoxModelObject* box, Node* node) |
| 341 { | 222 { |
| 342 if (box && box->isImage()) | 223 if (box && box->isImage()) |
| 343 return true; | 224 return true; |
| 344 if (isHTMLImageElement(node)) | 225 if (isHTMLImageElement(node)) |
| 345 return true; | 226 return true; |
| 346 if (isHTMLInputElement(node) && toHTMLInputElement(node)->hasFallbackContent
()) | 227 if (isHTMLInputElement(node) && toHTMLInputElement(node)->hasFallbackContent
()) |
| 347 return true; | 228 return true; |
| 348 return false; | 229 return false; |
| 349 } | 230 } |
| (...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 } | 1314 } |
| 1434 return elementAttributeValue(aria_atomicAttr); | 1315 return elementAttributeValue(aria_atomicAttr); |
| 1435 } | 1316 } |
| 1436 | 1317 |
| 1437 bool AXLayoutObject::liveRegionBusy() const | 1318 bool AXLayoutObject::liveRegionBusy() const |
| 1438 { | 1319 { |
| 1439 return elementAttributeValue(aria_busyAttr); | 1320 return elementAttributeValue(aria_busyAttr); |
| 1440 } | 1321 } |
| 1441 | 1322 |
| 1442 // | 1323 // |
| 1443 // Position and size. | |
| 1444 // | |
| 1445 | |
| 1446 void AXLayoutObject::checkCachedElementRect() const | |
| 1447 { | |
| 1448 if (m_cachedElementRectDirty) | |
| 1449 return; | |
| 1450 | |
| 1451 if (!m_layoutObject) | |
| 1452 return; | |
| 1453 | |
| 1454 if (!m_layoutObject->isBox()) | |
| 1455 return; | |
| 1456 | |
| 1457 bool dirty = false; | |
| 1458 LayoutBox* box = toLayoutBox(m_layoutObject); | |
| 1459 if (box->frameRect() != m_cachedFrameRect) | |
| 1460 dirty = true; | |
| 1461 | |
| 1462 if (box->canBeScrolledAndHasScrollableArea()) { | |
| 1463 ScrollableArea* scrollableArea = box->getScrollableArea(); | |
| 1464 if (scrollableArea && scrollableArea->scrollPosition() != m_cachedScroll
Position) | |
| 1465 dirty = true; | |
| 1466 } | |
| 1467 | |
| 1468 if (dirty) | |
| 1469 markCachedElementRectDirty(); | |
| 1470 } | |
| 1471 | |
| 1472 void AXLayoutObject::updateCachedElementRect() const | |
| 1473 { | |
| 1474 if (!m_cachedElementRectDirty) | |
| 1475 return; | |
| 1476 | |
| 1477 if (!m_layoutObject) | |
| 1478 return; | |
| 1479 | |
| 1480 if (!m_layoutObject->isBox()) | |
| 1481 return; | |
| 1482 | |
| 1483 LayoutBox* box = toLayoutBox(m_layoutObject); | |
| 1484 m_cachedFrameRect = box->frameRect(); | |
| 1485 | |
| 1486 if (box->canBeScrolledAndHasScrollableArea()) { | |
| 1487 ScrollableArea* scrollableArea = box->getScrollableArea(); | |
| 1488 if (scrollableArea) | |
| 1489 m_cachedScrollPosition = scrollableArea->scrollPosition(); | |
| 1490 } | |
| 1491 | |
| 1492 m_cachedElementRect = computeElementRect(); | |
| 1493 m_cachedElementRectDirty = false; | |
| 1494 } | |
| 1495 | |
| 1496 void AXLayoutObject::markCachedElementRectDirty() const | |
| 1497 { | |
| 1498 if (m_cachedElementRectDirty) | |
| 1499 return; | |
| 1500 | |
| 1501 // Marks children recursively, if this element changed. | |
| 1502 m_cachedElementRectDirty = true; | |
| 1503 for (AXObject* child = rawFirstChild(); child; child = child->rawNextSibling
()) | |
| 1504 child->markCachedElementRectDirty(); | |
| 1505 } | |
| 1506 | |
| 1507 IntPoint AXLayoutObject::clickPoint() | |
| 1508 { | |
| 1509 // Headings are usually much wider than their textual content. If the mid po
int is used, often it can be wrong. | |
| 1510 if (isHeading() && children().size() == 1) | |
| 1511 return children()[0]->clickPoint(); | |
| 1512 | |
| 1513 // use the default position unless this is an editable web area, in which ca
se we use the selection bounds. | |
| 1514 if (!isWebArea() || isReadOnly()) | |
| 1515 return AXObject::clickPoint(); | |
| 1516 | |
| 1517 IntRect bounds = pixelSnappedIntRect(elementRect()); | |
| 1518 return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.heig
ht() / 2)); | |
| 1519 } | |
| 1520 | |
| 1521 // | |
| 1522 // Hit testing. | 1324 // Hit testing. |
| 1523 // | 1325 // |
| 1524 | 1326 |
| 1525 AXObject* AXLayoutObject::accessibilityHitTest(const IntPoint& point) const | 1327 AXObject* AXLayoutObject::accessibilityHitTest(const IntPoint& point) const |
| 1526 { | 1328 { |
| 1527 if (!m_layoutObject || !m_layoutObject->hasLayer()) | 1329 if (!m_layoutObject || !m_layoutObject->hasLayer()) |
| 1528 return nullptr; | 1330 return nullptr; |
| 1529 | 1331 |
| 1530 PaintLayer* layer = toLayoutBox(m_layoutObject)->layer(); | 1332 PaintLayer* layer = toLayoutBox(m_layoutObject)->layer(); |
| 1531 | 1333 |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 AXObject* AXLayoutObject::accessibilityImageMapHitTest(HTMLAreaElement* area, co
nst IntPoint& point) const | 2143 AXObject* AXLayoutObject::accessibilityImageMapHitTest(HTMLAreaElement* area, co
nst IntPoint& point) const |
| 2342 { | 2144 { |
| 2343 if (!area) | 2145 if (!area) |
| 2344 return 0; | 2146 return 0; |
| 2345 | 2147 |
| 2346 AXObject* parent = axObjectCache().getOrCreate(area->imageElement()); | 2148 AXObject* parent = axObjectCache().getOrCreate(area->imageElement()); |
| 2347 if (!parent) | 2149 if (!parent) |
| 2348 return 0; | 2150 return 0; |
| 2349 | 2151 |
| 2350 for (const auto& child : parent->children()) { | 2152 for (const auto& child : parent->children()) { |
| 2351 if (child->elementRect().contains(point)) | 2153 if (child->getBoundsInFrameCoordinates().contains(point)) |
| 2352 return child.get(); | 2154 return child.get(); |
| 2353 } | 2155 } |
| 2354 | 2156 |
| 2355 return 0; | 2157 return 0; |
| 2356 } | 2158 } |
| 2357 | 2159 |
| 2358 LayoutObject* AXLayoutObject::layoutParentObject() const | 2160 LayoutObject* AXLayoutObject::layoutParentObject() const |
| 2359 { | 2161 { |
| 2360 if (!m_layoutObject) | 2162 if (!m_layoutObject) |
| 2361 return 0; | 2163 return 0; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2415 // remote SVG document. I'm disabling this support until it can be fixed pro
perly. | 2217 // remote SVG document. I'm disabling this support until it can be fixed pro
perly. |
| 2416 return 0; | 2218 return 0; |
| 2417 } | 2219 } |
| 2418 | 2220 |
| 2419 AXObject* AXLayoutObject::remoteSVGElementHitTest(const IntPoint& point) const | 2221 AXObject* AXLayoutObject::remoteSVGElementHitTest(const IntPoint& point) const |
| 2420 { | 2222 { |
| 2421 AXObject* remote = remoteSVGRootElement(); | 2223 AXObject* remote = remoteSVGRootElement(); |
| 2422 if (!remote) | 2224 if (!remote) |
| 2423 return 0; | 2225 return 0; |
| 2424 | 2226 |
| 2425 IntSize offset = point - roundedIntPoint(elementRect().location()); | 2227 IntSize offset = point - roundedIntPoint(getBoundsInFrameCoordinates().locat
ion()); |
| 2426 return remote->accessibilityHitTest(IntPoint(offset)); | 2228 return remote->accessibilityHitTest(IntPoint(offset)); |
| 2427 } | 2229 } |
| 2428 | 2230 |
| 2429 // The boundingBox for elements within the remote SVG element needs to be offset
by its position | 2231 // The boundingBox for elements within the remote SVG element needs to be offset
by its position |
| 2430 // within the parent page, otherwise they are in relative coordinates only. | 2232 // within the parent page, otherwise they are in relative coordinates only. |
| 2431 void AXLayoutObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect& rect) cons
t | 2233 void AXLayoutObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect& rect) cons
t |
| 2432 { | 2234 { |
| 2433 for (AXObject* parent = parentObject(); parent; parent = parent->parentObjec
t()) { | 2235 for (AXObject* parent = parentObject(); parent; parent = parent->parentObjec
t()) { |
| 2434 if (parent->isAXSVGRoot()) { | 2236 if (parent->isAXSVGRoot()) { |
| 2435 rect.moveBy(parent->parentObject()->elementRect().location()); | 2237 rect.moveBy(parent->parentObject()->getBoundsInFrameCoordinates().lo
cation()); |
| 2436 break; | 2238 break; |
| 2437 } | 2239 } |
| 2438 } | 2240 } |
| 2439 } | 2241 } |
| 2440 | 2242 |
| 2441 // Hidden children are those that are not laid out or visible, but are specifica
lly marked as aria-hidden=false, | 2243 // Hidden children are those that are not laid out or visible, but are specifica
lly marked as aria-hidden=false, |
| 2442 // meaning that they should be exposed to the AX hierarchy. | 2244 // meaning that they should be exposed to the AX hierarchy. |
| 2443 void AXLayoutObject::addHiddenChildren() | 2245 void AXLayoutObject::addHiddenChildren() |
| 2444 { | 2246 { |
| 2445 Node* node = this->getNode(); | 2247 Node* node = this->getNode(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2567 } | 2369 } |
| 2568 | 2370 |
| 2569 bool AXLayoutObject::elementAttributeValue(const QualifiedName& attributeName) c
onst | 2371 bool AXLayoutObject::elementAttributeValue(const QualifiedName& attributeName) c
onst |
| 2570 { | 2372 { |
| 2571 if (!m_layoutObject) | 2373 if (!m_layoutObject) |
| 2572 return false; | 2374 return false; |
| 2573 | 2375 |
| 2574 return equalIgnoringCase(getAttribute(attributeName), "true"); | 2376 return equalIgnoringCase(getAttribute(attributeName), "true"); |
| 2575 } | 2377 } |
| 2576 | 2378 |
| 2577 LayoutRect AXLayoutObject::computeElementRect() const | |
| 2578 { | |
| 2579 LayoutObject* obj = m_layoutObject; | |
| 2580 | |
| 2581 if (!obj) | |
| 2582 return LayoutRect(); | |
| 2583 | |
| 2584 if (obj->node()) // If we are a continuation, we want to make sure to use th
e primary layoutObject. | |
| 2585 obj = obj->node()->layoutObject(); | |
| 2586 | |
| 2587 // absoluteFocusRingBoundingBox will query the hierarchy below this element,
which for large webpages can be very slow. | |
| 2588 // For a web area, which will have the most elements of any element, absolut
eQuads should be used. | |
| 2589 // We should also use absoluteQuads for SVG elements, otherwise transforms w
on't be applied. | |
| 2590 | |
| 2591 LayoutRect result; | |
| 2592 if (obj->isText()) { | |
| 2593 Vector<FloatQuad> quads; | |
| 2594 toLayoutText(obj)->quads(quads, LayoutText::ClipToEllipsis, LayoutText::
AbsoluteQuads); | |
| 2595 result = LayoutRect(boundingBoxForQuads(obj, quads)); | |
| 2596 } else if (isWebArea() || obj->isSVGRoot()) { | |
| 2597 result = LayoutRect(obj->absoluteBoundingBoxRect()); | |
| 2598 } else { | |
| 2599 result = LayoutRect(obj->absoluteElementBoundingBoxRect()); | |
| 2600 } | |
| 2601 | |
| 2602 Document* document = this->getDocument(); | |
| 2603 if (document && document->isSVGDocument()) | |
| 2604 offsetBoundingBoxForRemoteSVGElement(result); | |
| 2605 if (document && document->frame() && document->frame()->pagePopupOwner()) { | |
| 2606 IntPoint popupOrigin = document->view()->contentsToScreen(IntRect()).loc
ation(); | |
| 2607 IntPoint mainOrigin = axObjectCache().rootObject()->documentFrameView()-
>contentsToScreen(IntRect()).location(); | |
| 2608 result.moveBy(IntPoint(popupOrigin - mainOrigin)); | |
| 2609 } | |
| 2610 | |
| 2611 // The size of the web area should be the content size, not the clipped size
. | |
| 2612 if (isWebArea() && obj->frame()->view()) | |
| 2613 result.setSize(LayoutSize(obj->frame()->view()->contentsSize())); | |
| 2614 | |
| 2615 // Checkboxes and radio buttons include their labels as part of their rect. | |
| 2616 if (isCheckboxOrRadio() && isLabelableElement(obj->node())) { | |
| 2617 LabelsNodeList* labels = toLabelableElement(obj->node())->labels(); | |
| 2618 if (labels) { | |
| 2619 for (unsigned labelIndex = 0; labelIndex < labels->length(); ++label
Index) { | |
| 2620 AXObject* labelAXObject = axObjectCache().getOrCreate(labels->it
em(labelIndex)); | |
| 2621 if (labelAXObject) { | |
| 2622 LayoutRect labelRect = labelAXObject->elementRect(); | |
| 2623 result.unite(labelRect); | |
| 2624 } | |
| 2625 } | |
| 2626 } | |
| 2627 } | |
| 2628 | |
| 2629 return result; | |
| 2630 } | |
| 2631 | |
| 2632 } // namespace blink | 2379 } // namespace blink |
| OLD | NEW |