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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 113 |
114 if (!firstChild && isInlineWithContinuation(layoutObject)) | 114 if (!firstChild && isInlineWithContinuation(layoutObject)) |
115 firstChild = firstChildInContinuation(toLayoutInline(*layoutObject)); | 115 firstChild = firstChildInContinuation(toLayoutInline(*layoutObject)); |
116 | 116 |
117 return firstChild; | 117 return firstChild; |
118 } | 118 } |
119 | 119 |
120 static inline LayoutInline* startOfContinuations(LayoutObject* r) | 120 static inline LayoutInline* startOfContinuations(LayoutObject* r) |
121 { | 121 { |
122 if (r->isInlineElementContinuation()) { | 122 if (r->isInlineElementContinuation()) { |
123 return toLayoutInline(r->node()->renderer()); | 123 return toLayoutInline(r->node()->layoutObject()); |
124 } | 124 } |
125 | 125 |
126 // Blocks with a previous continuation always have a next continuation | 126 // Blocks with a previous continuation always have a next continuation |
127 if (r->isLayoutBlock() && toLayoutBlock(r)->inlineElementContinuation()) | 127 if (r->isLayoutBlock() && toLayoutBlock(r)->inlineElementContinuation()) |
128 return toLayoutInline(toLayoutBlock(r)->inlineElementContinuation()->nod
e()->renderer()); | 128 return toLayoutInline(toLayoutBlock(r)->inlineElementContinuation()->nod
e()->layoutObject()); |
129 | 129 |
130 return 0; | 130 return 0; |
131 } | 131 } |
132 | 132 |
133 static inline LayoutObject* endOfContinuations(LayoutObject* layoutObject) | 133 static inline LayoutObject* endOfContinuations(LayoutObject* layoutObject) |
134 { | 134 { |
135 LayoutObject* prev = layoutObject; | 135 LayoutObject* prev = layoutObject; |
136 LayoutObject* cur = layoutObject; | 136 LayoutObject* cur = layoutObject; |
137 | 137 |
138 if (!cur->isLayoutInline() && !cur->isLayoutBlock()) | 138 if (!cur->isLayoutInline() && !cur->isLayoutBlock()) |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 if (!layoutObject) | 413 if (!layoutObject) |
414 return false; | 414 return false; |
415 // Widgets are the replaced elements that we represent to AX as attachments | 415 // Widgets are the replaced elements that we represent to AX as attachments |
416 bool isLayoutPart = layoutObject->isLayoutPart(); | 416 bool isLayoutPart = layoutObject->isLayoutPart(); |
417 ASSERT(!isLayoutPart || (layoutObject->isReplaced() && !isImage())); | 417 ASSERT(!isLayoutPart || (layoutObject->isReplaced() && !isImage())); |
418 return isLayoutPart; | 418 return isLayoutPart; |
419 } | 419 } |
420 | 420 |
421 static bool isLinkable(const AXObject& object) | 421 static bool isLinkable(const AXObject& object) |
422 { | 422 { |
423 if (!object.renderer()) | 423 if (!object.layoutObject()) |
424 return false; | 424 return false; |
425 | 425 |
426 // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the element
s | 426 // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the element
s |
427 // Mozilla considers linkable. | 427 // Mozilla considers linkable. |
428 return object.isLink() || object.isImage() || object.renderer()->isText(); | 428 return object.isLink() || object.isImage() || object.layoutObject()->isText(
); |
429 } | 429 } |
430 | 430 |
431 bool AXLayoutObject::isLinked() const | 431 bool AXLayoutObject::isLinked() const |
432 { | 432 { |
433 if (!isLinkable(*this)) | 433 if (!isLinkable(*this)) |
434 return false; | 434 return false; |
435 | 435 |
436 Element* anchor = anchorElement(); | 436 Element* anchor = anchorElement(); |
437 if (!isHTMLAnchorElement(anchor)) | 437 if (!isHTMLAnchorElement(anchor)) |
438 return false; | 438 return false; |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 | 874 |
875 return KURL(); | 875 return KURL(); |
876 } | 876 } |
877 | 877 |
878 // | 878 // |
879 // Load inline text boxes. | 879 // Load inline text boxes. |
880 // | 880 // |
881 | 881 |
882 void AXLayoutObject::loadInlineTextBoxes() | 882 void AXLayoutObject::loadInlineTextBoxes() |
883 { | 883 { |
884 if (!renderer() || !renderer()->isText()) | 884 if (!layoutObject() || !layoutObject()->isText()) |
885 return; | 885 return; |
886 | 886 |
887 clearChildren(); | 887 clearChildren(); |
888 addInlineTextBoxChildren(true); | 888 addInlineTextBoxChildren(true); |
889 } | 889 } |
890 | 890 |
891 // | 891 // |
892 // Properties of interactive elements. | 892 // Properties of interactive elements. |
893 // | 893 // |
894 | 894 |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 // Allow the hit test to return media control buttons. | 1352 // Allow the hit test to return media control buttons. |
1353 if (node->isInShadowTree() && (!isHTMLInputElement(*node) || !node->isMediaC
ontrolElement())) | 1353 if (node->isInShadowTree() && (!isHTMLInputElement(*node) || !node->isMediaC
ontrolElement())) |
1354 node = node->shadowHost(); | 1354 node = node->shadowHost(); |
1355 | 1355 |
1356 if (isHTMLAreaElement(node)) | 1356 if (isHTMLAreaElement(node)) |
1357 return accessibilityImageMapHitTest(toHTMLAreaElement(node), point); | 1357 return accessibilityImageMapHitTest(toHTMLAreaElement(node), point); |
1358 | 1358 |
1359 if (isHTMLOptionElement(node)) | 1359 if (isHTMLOptionElement(node)) |
1360 node = toHTMLOptionElement(*node).ownerSelectElement(); | 1360 node = toHTMLOptionElement(*node).ownerSelectElement(); |
1361 | 1361 |
1362 LayoutObject* obj = node->renderer(); | 1362 LayoutObject* obj = node->layoutObject(); |
1363 if (!obj) | 1363 if (!obj) |
1364 return 0; | 1364 return 0; |
1365 | 1365 |
1366 AXObject* result = axObjectCache()->getOrCreate(obj); | 1366 AXObject* result = axObjectCache()->getOrCreate(obj); |
1367 result->updateChildrenIfNecessary(); | 1367 result->updateChildrenIfNecessary(); |
1368 | 1368 |
1369 // Allow the element to perform any hit-testing it might need to do to reach
non-layout children. | 1369 // Allow the element to perform any hit-testing it might need to do to reach
non-layout children. |
1370 result = result->elementAccessibilityHitTest(point); | 1370 result = result->elementAccessibilityHitTest(point); |
1371 | 1371 |
1372 if (result && result->accessibilityIsIgnored()) { | 1372 if (result && result->accessibilityIsIgnored()) { |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1630 } | 1630 } |
1631 | 1631 |
1632 // bail if none found | 1632 // bail if none found |
1633 if (!currLayoutObject) | 1633 if (!currLayoutObject) |
1634 return 0; | 1634 return 0; |
1635 | 1635 |
1636 // search up the DOM tree for an anchor element | 1636 // search up the DOM tree for an anchor element |
1637 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent | 1637 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent |
1638 Node* node = currLayoutObject->node(); | 1638 Node* node = currLayoutObject->node(); |
1639 for ( ; node; node = node->parentNode()) { | 1639 for ( ; node; node = node->parentNode()) { |
1640 if (isHTMLAnchorElement(*node) || (node->renderer() && cache->getOrCreat
e(node->renderer())->isAnchor())) | 1640 if (isHTMLAnchorElement(*node) || (node->layoutObject() && cache->getOrC
reate(node->layoutObject())->isAnchor())) |
1641 return toElement(node); | 1641 return toElement(node); |
1642 } | 1642 } |
1643 | 1643 |
1644 return 0; | 1644 return 0; |
1645 } | 1645 } |
1646 | 1646 |
1647 Widget* AXLayoutObject::widgetForAttachmentView() const | 1647 Widget* AXLayoutObject::widgetForAttachmentView() const |
1648 { | 1648 { |
1649 if (!isAttachment()) | 1649 if (!isAttachment()) |
1650 return 0; | 1650 return 0; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 | 1727 |
1728 box->scrollToOffset(IntSize(point.x(), point.y())); | 1728 box->scrollToOffset(IntSize(point.x(), point.y())); |
1729 } | 1729 } |
1730 | 1730 |
1731 // | 1731 // |
1732 // Notifications that this object may have changed. | 1732 // Notifications that this object may have changed. |
1733 // | 1733 // |
1734 | 1734 |
1735 void AXLayoutObject::handleActiveDescendantChanged() | 1735 void AXLayoutObject::handleActiveDescendantChanged() |
1736 { | 1736 { |
1737 Element* element = toElement(renderer()->node()); | 1737 Element* element = toElement(layoutObject()->node()); |
1738 if (!element) | 1738 if (!element) |
1739 return; | 1739 return; |
1740 Document& doc = renderer()->document(); | 1740 Document& doc = layoutObject()->document(); |
1741 if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() !
= element) | 1741 if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() !
= element) |
1742 return; | 1742 return; |
1743 AXLayoutObject* activedescendant = toAXLayoutObject(activeDescendant()); | 1743 AXLayoutObject* activedescendant = toAXLayoutObject(activeDescendant()); |
1744 | 1744 |
1745 if (activedescendant && shouldNotifyActiveDescendant()) | 1745 if (activedescendant && shouldNotifyActiveDescendant()) |
1746 toAXObjectCacheImpl(doc.axObjectCache())->postNotification(m_layoutObjec
t, AXObjectCacheImpl::AXActiveDescendantChanged, true); | 1746 toAXObjectCacheImpl(doc.axObjectCache())->postNotification(m_layoutObjec
t, AXObjectCacheImpl::AXActiveDescendantChanged, true); |
1747 } | 1747 } |
1748 | 1748 |
1749 void AXLayoutObject::handleAriaExpandedChanged() | 1749 void AXLayoutObject::handleAriaExpandedChanged() |
1750 { | 1750 { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 | 1870 |
1871 return TextIterator::rangeLength(range.get()); | 1871 return TextIterator::rangeLength(range.get()); |
1872 } | 1872 } |
1873 | 1873 |
1874 void AXLayoutObject::addInlineTextBoxChildren(bool force) | 1874 void AXLayoutObject::addInlineTextBoxChildren(bool force) |
1875 { | 1875 { |
1876 Settings* settings = document()->settings(); | 1876 Settings* settings = document()->settings(); |
1877 if (!force && (!settings || !settings->inlineTextBoxAccessibilityEnabled())) | 1877 if (!force && (!settings || !settings->inlineTextBoxAccessibilityEnabled())) |
1878 return; | 1878 return; |
1879 | 1879 |
1880 if (!renderer() || !renderer()->isText()) | 1880 if (!layoutObject() || !layoutObject()->isText()) |
1881 return; | 1881 return; |
1882 | 1882 |
1883 if (renderer()->needsLayout()) { | 1883 if (layoutObject()->needsLayout()) { |
1884 // If a LayoutText needs layout, its inline text boxes are either | 1884 // If a LayoutText needs layout, its inline text boxes are either |
1885 // nonexistent or invalid, so defer until the layout happens and | 1885 // nonexistent or invalid, so defer until the layout happens and |
1886 // the layoutObject calls AXObjectCacheImpl::inlineTextBoxesUpdated. | 1886 // the layoutObject calls AXObjectCacheImpl::inlineTextBoxesUpdated. |
1887 return; | 1887 return; |
1888 } | 1888 } |
1889 | 1889 |
1890 LayoutText* layoutText = toLayoutText(renderer()); | 1890 LayoutText* layoutText = toLayoutText(layoutObject()); |
1891 for (RefPtr<AbstractInlineTextBox> box = layoutText->firstAbstractInlineText
Box(); box.get(); box = box->nextInlineTextBox()) { | 1891 for (RefPtr<AbstractInlineTextBox> box = layoutText->firstAbstractInlineText
Box(); box.get(); box = box->nextInlineTextBox()) { |
1892 AXObject* axObject = axObjectCache()->getOrCreate(box.get()); | 1892 AXObject* axObject = axObjectCache()->getOrCreate(box.get()); |
1893 if (!axObject->accessibilityIsIgnored()) | 1893 if (!axObject->accessibilityIsIgnored()) |
1894 m_children.append(axObject); | 1894 m_children.append(axObject); |
1895 } | 1895 } |
1896 } | 1896 } |
1897 | 1897 |
1898 void AXLayoutObject::lineBreaks(Vector<int>& lineBreaks) const | 1898 void AXLayoutObject::lineBreaks(Vector<int>& lineBreaks) const |
1899 { | 1899 { |
1900 if (!isTextControl()) | 1900 if (!isTextControl()) |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 if (startOfConts) { | 2076 if (startOfConts) { |
2077 // Case 2: node's parent is an inline which is some node's continuation;
parent is | 2077 // Case 2: node's parent is an inline which is some node's continuation;
parent is |
2078 // the earliest node in the continuation chain. | 2078 // the earliest node in the continuation chain. |
2079 return startOfConts; | 2079 return startOfConts; |
2080 } | 2080 } |
2081 | 2081 |
2082 LayoutObject* firstChild = parent ? parent->slowFirstChild() : 0; | 2082 LayoutObject* firstChild = parent ? parent->slowFirstChild() : 0; |
2083 if (firstChild && firstChild->node()) { | 2083 if (firstChild && firstChild->node()) { |
2084 // Case 3: The first sibling is the beginning of a continuation chain. F
ind the origin of that continuation. | 2084 // Case 3: The first sibling is the beginning of a continuation chain. F
ind the origin of that continuation. |
2085 // Get the node's layoutObject and follow that continuation chain until
the first child is found. | 2085 // Get the node's layoutObject and follow that continuation chain until
the first child is found. |
2086 for (LayoutObject* nodeLayoutFirstChild = firstChild->node()->renderer()
; nodeLayoutFirstChild != firstChild; nodeLayoutFirstChild = firstChild->node()-
>renderer()) { | 2086 for (LayoutObject* nodeLayoutFirstChild = firstChild->node()->layoutObje
ct(); nodeLayoutFirstChild != firstChild; nodeLayoutFirstChild = firstChild->nod
e()->layoutObject()) { |
2087 for (LayoutObject* contsTest = nodeLayoutFirstChild; contsTest; cont
sTest = nextContinuation(contsTest)) { | 2087 for (LayoutObject* contsTest = nodeLayoutFirstChild; contsTest; cont
sTest = nextContinuation(contsTest)) { |
2088 if (contsTest == firstChild) { | 2088 if (contsTest == firstChild) { |
2089 parent = nodeLayoutFirstChild->parent(); | 2089 parent = nodeLayoutFirstChild->parent(); |
2090 break; | 2090 break; |
2091 } | 2091 } |
2092 } | 2092 } |
2093 LayoutObject* newFirstChild = parent->slowFirstChild(); | 2093 LayoutObject* newFirstChild = parent->slowFirstChild(); |
2094 if (firstChild == newFirstChild) | 2094 if (firstChild == newFirstChild) |
2095 break; | 2095 break; |
2096 firstChild = newFirstChild; | 2096 firstChild = newFirstChild; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2156 void AXLayoutObject::addHiddenChildren() | 2156 void AXLayoutObject::addHiddenChildren() |
2157 { | 2157 { |
2158 Node* node = this->node(); | 2158 Node* node = this->node(); |
2159 if (!node) | 2159 if (!node) |
2160 return; | 2160 return; |
2161 | 2161 |
2162 // First do a quick run through to determine if we have any hidden nodes (mo
st often we will not). | 2162 // First do a quick run through to determine if we have any hidden nodes (mo
st often we will not). |
2163 // If we do have hidden nodes, we need to determine where to insert them so
they match DOM order as close as possible. | 2163 // If we do have hidden nodes, we need to determine where to insert them so
they match DOM order as close as possible. |
2164 bool shouldInsertHiddenNodes = false; | 2164 bool shouldInsertHiddenNodes = false; |
2165 for (Node* child = node->firstChild(); child; child = child->nextSibling())
{ | 2165 for (Node* child = node->firstChild(); child; child = child->nextSibling())
{ |
2166 if (!child->renderer() && isNodeAriaVisible(child)) { | 2166 if (!child->layoutObject() && isNodeAriaVisible(child)) { |
2167 shouldInsertHiddenNodes = true; | 2167 shouldInsertHiddenNodes = true; |
2168 break; | 2168 break; |
2169 } | 2169 } |
2170 } | 2170 } |
2171 | 2171 |
2172 if (!shouldInsertHiddenNodes) | 2172 if (!shouldInsertHiddenNodes) |
2173 return; | 2173 return; |
2174 | 2174 |
2175 // Iterate through all of the children, including those that may have alread
y been added, and | 2175 // Iterate through all of the children, including those that may have alread
y been added, and |
2176 // try to insert hidden nodes in the correct place in the DOM order. | 2176 // try to insert hidden nodes in the correct place in the DOM order. |
2177 unsigned insertionIndex = 0; | 2177 unsigned insertionIndex = 0; |
2178 for (Node* child = node->firstChild(); child; child = child->nextSibling())
{ | 2178 for (Node* child = node->firstChild(); child; child = child->nextSibling())
{ |
2179 if (child->renderer()) { | 2179 if (child->layoutObject()) { |
2180 // Find out where the last layout sibling is located within m_childr
en. | 2180 // Find out where the last layout sibling is located within m_childr
en. |
2181 AXObject* childObject = axObjectCache()->get(child->renderer()); | 2181 AXObject* childObject = axObjectCache()->get(child->layoutObject()); |
2182 if (childObject && childObject->accessibilityIsIgnored()) { | 2182 if (childObject && childObject->accessibilityIsIgnored()) { |
2183 AccessibilityChildrenVector children = childObject->children(); | 2183 AccessibilityChildrenVector children = childObject->children(); |
2184 if (children.size()) | 2184 if (children.size()) |
2185 childObject = children.last().get(); | 2185 childObject = children.last().get(); |
2186 else | 2186 else |
2187 childObject = 0; | 2187 childObject = 0; |
2188 } | 2188 } |
2189 | 2189 |
2190 if (childObject) | 2190 if (childObject) |
2191 insertionIndex = m_children.find(childObject) + 1; | 2191 insertionIndex = m_children.find(childObject) + 1; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2368 } | 2368 } |
2369 | 2369 |
2370 LayoutRect AXLayoutObject::computeElementRect() const | 2370 LayoutRect AXLayoutObject::computeElementRect() const |
2371 { | 2371 { |
2372 LayoutObject* obj = m_layoutObject; | 2372 LayoutObject* obj = m_layoutObject; |
2373 | 2373 |
2374 if (!obj) | 2374 if (!obj) |
2375 return LayoutRect(); | 2375 return LayoutRect(); |
2376 | 2376 |
2377 if (obj->node()) // If we are a continuation, we want to make sure to use th
e primary layoutObject. | 2377 if (obj->node()) // If we are a continuation, we want to make sure to use th
e primary layoutObject. |
2378 obj = obj->node()->renderer(); | 2378 obj = obj->node()->layoutObject(); |
2379 | 2379 |
2380 // absoluteFocusRingBoundingBox will query the hierarchy below this element,
which for large webpages can be very slow. | 2380 // absoluteFocusRingBoundingBox will query the hierarchy below this element,
which for large webpages can be very slow. |
2381 // For a web area, which will have the most elements of any element, absolut
eQuads should be used. | 2381 // For a web area, which will have the most elements of any element, absolut
eQuads should be used. |
2382 // We should also use absoluteQuads for SVG elements, otherwise transforms w
on't be applied. | 2382 // We should also use absoluteQuads for SVG elements, otherwise transforms w
on't be applied. |
2383 | 2383 |
2384 LayoutRect result; | 2384 LayoutRect result; |
2385 if (obj->isText()) { | 2385 if (obj->isText()) { |
2386 Vector<FloatQuad> quads; | 2386 Vector<FloatQuad> quads; |
2387 toLayoutText(obj)->absoluteQuads(quads, 0, LayoutText::ClipToEllipsis); | 2387 toLayoutText(obj)->absoluteQuads(quads, 0, LayoutText::ClipToEllipsis); |
2388 result = LayoutRect(boundingBoxForQuads(obj, quads)); | 2388 result = LayoutRect(boundingBoxForQuads(obj, quads)); |
(...skipping 12 matching lines...) Expand all Loading... |
2401 result.moveBy(IntPoint(popupOrigin - mainOrigin)); | 2401 result.moveBy(IntPoint(popupOrigin - mainOrigin)); |
2402 } | 2402 } |
2403 | 2403 |
2404 // The size of the web area should be the content size, not the clipped size
. | 2404 // The size of the web area should be the content size, not the clipped size
. |
2405 if (isWebArea() && obj->frame()->view()) | 2405 if (isWebArea() && obj->frame()->view()) |
2406 result.setSize(LayoutSize(obj->frame()->view()->contentsSize())); | 2406 result.setSize(LayoutSize(obj->frame()->view()->contentsSize())); |
2407 | 2407 |
2408 // Checkboxes and radio buttons include their label as part of their rect. | 2408 // Checkboxes and radio buttons include their label as part of their rect. |
2409 if (isCheckboxOrRadio()) { | 2409 if (isCheckboxOrRadio()) { |
2410 HTMLLabelElement* label = labelForElement(toElement(m_layoutObject->node
())); | 2410 HTMLLabelElement* label = labelForElement(toElement(m_layoutObject->node
())); |
2411 if (label && label->renderer()) { | 2411 if (label && label->layoutObject()) { |
2412 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR
ect(); | 2412 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR
ect(); |
2413 result.unite(labelRect); | 2413 result.unite(labelRect); |
2414 } | 2414 } |
2415 } | 2415 } |
2416 | 2416 |
2417 return result; | 2417 return result; |
2418 } | 2418 } |
2419 | 2419 |
2420 } // namespace blink | 2420 } // namespace blink |
OLD | NEW |