| 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 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 return TransformationMatrix::toSkMatrix44(accumulatedTransform); | 236 return TransformationMatrix::toSkMatrix44(accumulatedTransform); |
| 237 } | 237 } |
| 238 | 238 |
| 239 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const | 239 LayoutBoxModelObject* AXLayoutObject::getLayoutBoxModelObject() const |
| 240 { | 240 { |
| 241 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) | 241 if (!m_layoutObject || !m_layoutObject->isBoxModelObject()) |
| 242 return 0; | 242 return 0; |
| 243 return toLayoutBoxModelObject(m_layoutObject); | 243 return toLayoutBoxModelObject(m_layoutObject); |
| 244 } | 244 } |
| 245 | 245 |
| 246 bool AXLayoutObject::shouldNotifyActiveDescendant() const | |
| 247 { | |
| 248 // We want to notify that the combo box has changed its active descendant, | |
| 249 // but we do not want to change the focus, because focus should remain with
the combo box. | |
| 250 if (isComboBox()) | |
| 251 return true; | |
| 252 | |
| 253 return shouldFocusActiveDescendant(); | |
| 254 } | |
| 255 | |
| 256 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const | 246 ScrollableArea* AXLayoutObject::getScrollableAreaIfScrollable() const |
| 257 { | 247 { |
| 258 if (isWebArea()) | 248 if (isWebArea()) |
| 259 return documentFrameView(); | 249 return documentFrameView(); |
| 260 | 250 |
| 261 if (!m_layoutObject || !m_layoutObject->isBox()) | 251 if (!m_layoutObject || !m_layoutObject->isBox()) |
| 262 return 0; | 252 return 0; |
| 263 | 253 |
| 264 LayoutBox* box = toLayoutBox(m_layoutObject); | 254 LayoutBox* box = toLayoutBox(m_layoutObject); |
| 265 if (!box->canBeScrolledAndHasScrollableArea()) | 255 if (!box->canBeScrolledAndHasScrollableArea()) |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 // FIXME: Is it a privacy violation to expose visited information to accessi
bility APIs? | 456 // FIXME: Is it a privacy violation to expose visited information to accessi
bility APIs? |
| 467 return m_layoutObject->style()->isLink() && m_layoutObject->style()->insideL
ink() == InsideVisitedLink; | 457 return m_layoutObject->style()->isLink() && m_layoutObject->style()->insideL
ink() == InsideVisitedLink; |
| 468 } | 458 } |
| 469 | 459 |
| 470 // | 460 // |
| 471 // Check object state. | 461 // Check object state. |
| 472 // | 462 // |
| 473 | 463 |
| 474 bool AXLayoutObject::isFocused() const | 464 bool AXLayoutObject::isFocused() const |
| 475 { | 465 { |
| 476 if (!m_layoutObject) | 466 if (!getDocument()) |
| 477 return false; | 467 return false; |
| 478 | 468 |
| 479 Document& document = m_layoutObject->document(); | 469 Element* focusedElement = getDocument()->focusedElement(); |
| 480 Element* focusedElement = document.focusedElement(); | |
| 481 if (!focusedElement) | 470 if (!focusedElement) |
| 482 return false; | 471 return false; |
| 472 AXObject* focusedObject = axObjectCache().getOrCreate(focusedElement); |
| 473 if (!focusedObject || !focusedObject->isAXLayoutObject()) |
| 474 return false; |
| 483 | 475 |
| 484 // A web area is represented by the Document node in the DOM tree, which isn
't focusable. | 476 // A web area is represented by the Document node in the DOM tree, which isn
't focusable. |
| 485 // Check instead if the frame's selection controller is focused | 477 // Check instead if the frame's selection controller is focused |
| 486 if (focusedElement == m_layoutObject->node() | 478 if (focusedObject == this |
| 487 || (roleValue() == WebAreaRole && document.frame()->selection().isFocuse
dAndActive())) | 479 || (roleValue() == WebAreaRole && getDocument()->frame()->selection().is
FocusedAndActive())) |
| 488 return true; | 480 return true; |
| 489 | 481 |
| 490 return false; | 482 return false; |
| 491 } | 483 } |
| 492 | 484 |
| 493 bool AXLayoutObject::isSelected() const | 485 bool AXLayoutObject::isSelected() const |
| 494 { | 486 { |
| 495 if (!m_layoutObject) | 487 if (!getLayoutObject() || !getNode()) |
| 496 return false; | |
| 497 | |
| 498 Node* node = m_layoutObject->node(); | |
| 499 if (!node) | |
| 500 return false; | 488 return false; |
| 501 | 489 |
| 502 const AtomicString& ariaSelected = getAttribute(aria_selectedAttr); | 490 const AtomicString& ariaSelected = getAttribute(aria_selectedAttr); |
| 503 if (equalIgnoringCase(ariaSelected, "true")) | 491 if (equalIgnoringCase(ariaSelected, "true")) |
| 504 return true; | 492 return true; |
| 505 | 493 |
| 494 AXObject* focusedObject = axObjectCache().focusedObject(); |
| 495 if (ariaRoleAttribute() == ListBoxOptionRole && focusedObject |
| 496 && focusedObject->activeDescendant() == this) { |
| 497 return true; |
| 498 } |
| 499 |
| 506 if (isTabItem() && isTabItemSelected()) | 500 if (isTabItem() && isTabItemSelected()) |
| 507 return true; | 501 return true; |
| 508 | 502 |
| 509 return false; | 503 return false; |
| 510 } | 504 } |
| 511 | 505 |
| 512 // | 506 // |
| 513 // Whether objects are ignored, i.e. not included in the tree. | 507 // Whether objects are ignored, i.e. not included in the tree. |
| 514 // | 508 // |
| 515 | 509 |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 } | 1162 } |
| 1169 } | 1163 } |
| 1170 | 1164 |
| 1171 return AXNodeObject::textAlternative(recursive, inAriaLabelledByTraversal, v
isited, nameFrom, relatedObjects, nameSources); | 1165 return AXNodeObject::textAlternative(recursive, inAriaLabelledByTraversal, v
isited, nameFrom, relatedObjects, nameSources); |
| 1172 } | 1166 } |
| 1173 | 1167 |
| 1174 // | 1168 // |
| 1175 // ARIA attributes. | 1169 // ARIA attributes. |
| 1176 // | 1170 // |
| 1177 | 1171 |
| 1178 AXObject* AXLayoutObject::activeDescendant() const | |
| 1179 { | |
| 1180 if (!m_layoutObject) | |
| 1181 return 0; | |
| 1182 | |
| 1183 if (m_layoutObject->node() && !m_layoutObject->node()->isElementNode()) | |
| 1184 return 0; | |
| 1185 | |
| 1186 Element* element = toElement(m_layoutObject->node()); | |
| 1187 if (!element) | |
| 1188 return 0; | |
| 1189 | |
| 1190 const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_act
ivedescendantAttr); | |
| 1191 if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty()) | |
| 1192 return 0; | |
| 1193 | |
| 1194 Element* target = element->treeScope().getElementById(activeDescendantAttrSt
r); | |
| 1195 if (!target) | |
| 1196 return 0; | |
| 1197 | |
| 1198 AXObject* obj = axObjectCache().getOrCreate(target); | |
| 1199 | |
| 1200 // An activedescendant is only useful if it has a layoutObject, because that
's what's needed to post the notification. | |
| 1201 if (obj && obj->isAXLayoutObject()) | |
| 1202 return obj; | |
| 1203 | |
| 1204 return 0; | |
| 1205 } | |
| 1206 | |
| 1207 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const | 1172 void AXLayoutObject::ariaFlowToElements(AXObjectVector& flowTo) const |
| 1208 { | 1173 { |
| 1209 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); | 1174 accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo); |
| 1210 } | 1175 } |
| 1211 | 1176 |
| 1212 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const | 1177 void AXLayoutObject::ariaControlsElements(AXObjectVector& controls) const |
| 1213 { | 1178 { |
| 1214 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); | 1179 accessibilityChildrenFromAttribute(aria_controlsAttr, controls); |
| 1215 } | 1180 } |
| 1216 | 1181 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 // AXMenuListOptions, which are not AXLayoutObjects.) | 1227 // AXMenuListOptions, which are not AXLayoutObjects.) |
| 1263 if (parent->isMenuList()) | 1228 if (parent->isMenuList()) |
| 1264 break; | 1229 break; |
| 1265 | 1230 |
| 1266 parent = parent->parentObjectIfExists(); | 1231 parent = parent->parentObjectIfExists(); |
| 1267 } | 1232 } |
| 1268 | 1233 |
| 1269 return parent; | 1234 return parent; |
| 1270 } | 1235 } |
| 1271 | 1236 |
| 1272 bool AXLayoutObject::shouldFocusActiveDescendant() const | |
| 1273 { | |
| 1274 switch (ariaRoleAttribute()) { | |
| 1275 case ComboBoxRole: | |
| 1276 case GridRole: | |
| 1277 case GroupRole: | |
| 1278 case ListBoxRole: | |
| 1279 case MenuRole: | |
| 1280 case MenuBarRole: | |
| 1281 case OutlineRole: | |
| 1282 case PopUpButtonRole: | |
| 1283 case ProgressIndicatorRole: | |
| 1284 case RadioGroupRole: | |
| 1285 case RowRole: | |
| 1286 case TabListRole: | |
| 1287 case ToolbarRole: | |
| 1288 case TreeRole: | |
| 1289 case TreeGridRole: | |
| 1290 return true; | |
| 1291 default: | |
| 1292 return false; | |
| 1293 } | |
| 1294 } | |
| 1295 | |
| 1296 bool AXLayoutObject::supportsARIADragging() const | 1237 bool AXLayoutObject::supportsARIADragging() const |
| 1297 { | 1238 { |
| 1298 const AtomicString& grabbed = getAttribute(aria_grabbedAttr); | 1239 const AtomicString& grabbed = getAttribute(aria_grabbedAttr); |
| 1299 return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "fal
se"); | 1240 return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "fal
se"); |
| 1300 } | 1241 } |
| 1301 | 1242 |
| 1302 bool AXLayoutObject::supportsARIADropping() const | 1243 bool AXLayoutObject::supportsARIADropping() const |
| 1303 { | 1244 { |
| 1304 const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr); | 1245 const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr); |
| 1305 return !dropEffect.isEmpty(); | 1246 return !dropEffect.isEmpty(); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 return frame->loader().progress().estimatedProgress(); | 1654 return frame->loader().progress().estimatedProgress(); |
| 1714 return 0; | 1655 return 0; |
| 1715 } | 1656 } |
| 1716 | 1657 |
| 1717 // | 1658 // |
| 1718 // DOM and layout tree access. | 1659 // DOM and layout tree access. |
| 1719 // | 1660 // |
| 1720 | 1661 |
| 1721 Node* AXLayoutObject::getNode() const | 1662 Node* AXLayoutObject::getNode() const |
| 1722 { | 1663 { |
| 1723 return m_layoutObject ? m_layoutObject->node() : 0; | 1664 return getLayoutObject() ? getLayoutObject()->node() : nullptr; |
| 1724 } | 1665 } |
| 1725 | 1666 |
| 1726 Document* AXLayoutObject::getDocument() const | 1667 Document* AXLayoutObject::getDocument() const |
| 1727 { | 1668 { |
| 1728 if (!m_layoutObject) | 1669 if (!getLayoutObject()) |
| 1729 return 0; | 1670 return nullptr; |
| 1730 return &m_layoutObject->document(); | 1671 return &getLayoutObject()->document(); |
| 1731 } | 1672 } |
| 1732 | 1673 |
| 1733 FrameView* AXLayoutObject::documentFrameView() const | 1674 FrameView* AXLayoutObject::documentFrameView() const |
| 1734 { | 1675 { |
| 1735 if (!m_layoutObject) | 1676 if (!m_layoutObject) |
| 1736 return 0; | 1677 return 0; |
| 1737 | 1678 |
| 1738 // this is the LayoutObject's Document's LocalFrame's FrameView | 1679 // this is the LayoutObject's Document's LocalFrame's FrameView |
| 1739 return m_layoutObject->document().view(); | 1680 return m_layoutObject->document().view(); |
| 1740 } | 1681 } |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2018 else if (layoutObject->isTextArea() && isHTMLTextAreaElement(*getNode())) | 1959 else if (layoutObject->isTextArea() && isHTMLTextAreaElement(*getNode())) |
| 2019 toHTMLTextAreaElement(*getNode()).setValue(string, DispatchInputAndChang
eEvent); | 1960 toHTMLTextAreaElement(*getNode()).setValue(string, DispatchInputAndChang
eEvent); |
| 2020 } | 1961 } |
| 2021 | 1962 |
| 2022 // | 1963 // |
| 2023 // Notifications that this object may have changed. | 1964 // Notifications that this object may have changed. |
| 2024 // | 1965 // |
| 2025 | 1966 |
| 2026 void AXLayoutObject::handleActiveDescendantChanged() | 1967 void AXLayoutObject::handleActiveDescendantChanged() |
| 2027 { | 1968 { |
| 2028 Element* element = toElement(getLayoutObject()->node()); | 1969 if (!getLayoutObject()) |
| 2029 if (!element) | |
| 2030 return; | 1970 return; |
| 2031 Document& doc = getLayoutObject()->document(); | |
| 2032 if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() !
= element) | |
| 2033 return; | |
| 2034 AXLayoutObject* activedescendant = toAXLayoutObject(activeDescendant()); | |
| 2035 | 1971 |
| 2036 if (activedescendant && shouldNotifyActiveDescendant()) | 1972 AXObject* focusedObject = axObjectCache().focusedObject(); |
| 2037 toAXObjectCacheImpl(doc.axObjectCache())->postNotification(m_layoutObjec
t, AXObjectCacheImpl::AXActiveDescendantChanged); | 1973 if (focusedObject == this && supportsActiveDescendant()) { |
| 1974 axObjectCache().postNotification( |
| 1975 getLayoutObject(), AXObjectCacheImpl::AXActiveDescendantChanged); |
| 1976 } |
| 2038 } | 1977 } |
| 2039 | 1978 |
| 2040 void AXLayoutObject::handleAriaExpandedChanged() | 1979 void AXLayoutObject::handleAriaExpandedChanged() |
| 2041 { | 1980 { |
| 2042 // Find if a parent of this object should handle aria-expanded changes. | 1981 // Find if a parent of this object should handle aria-expanded changes. |
| 2043 AXObject* containerParent = this->parentObject(); | 1982 AXObject* containerParent = this->parentObject(); |
| 2044 while (containerParent) { | 1983 while (containerParent) { |
| 2045 bool foundParent = false; | 1984 bool foundParent = false; |
| 2046 | 1985 |
| 2047 switch (containerParent->roleValue()) { | 1986 switch (containerParent->roleValue()) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2200 if (treeAncestor) { | 2139 if (treeAncestor) { |
| 2201 AccessibilityRole role = roleValue(); | 2140 AccessibilityRole role = roleValue(); |
| 2202 if (role != TreeItemRole && role != StaticTextRole) | 2141 if (role != TreeItemRole && role != StaticTextRole) |
| 2203 return treeAncestor; | 2142 return treeAncestor; |
| 2204 } | 2143 } |
| 2205 return 0; | 2144 return 0; |
| 2206 } | 2145 } |
| 2207 | 2146 |
| 2208 bool AXLayoutObject::isTabItemSelected() const | 2147 bool AXLayoutObject::isTabItemSelected() const |
| 2209 { | 2148 { |
| 2210 if (!isTabItem() || !m_layoutObject) | 2149 if (!isTabItem() || !getLayoutObject()) |
| 2211 return false; | 2150 return false; |
| 2212 | 2151 |
| 2213 Node* node = m_layoutObject->node(); | 2152 Node* node = getNode(); |
| 2214 if (!node || !node->isElementNode()) | 2153 if (!node || !node->isElementNode()) |
| 2215 return false; | 2154 return false; |
| 2216 | 2155 |
| 2217 // The ARIA spec says a tab item can also be selected if it is aria-labeled
by a tabpanel | 2156 // The ARIA spec says a tab item can also be selected if it is aria-labeled
by a tabpanel |
| 2218 // that has keyboard focus inside of it, or if a tabpanel in its aria-contro
ls list has KB | 2157 // that has keyboard focus inside of it, or if a tabpanel in its aria-contro
ls list has KB |
| 2219 // focus inside of it. | 2158 // focus inside of it. |
| 2220 AXObject* focusedElement = axObjectCache().focusedObject(); | 2159 AXObject* focusedElement = axObjectCache().focusedObject(); |
| 2221 if (!focusedElement) | 2160 if (!focusedElement) |
| 2222 return false; | 2161 return false; |
| 2223 | 2162 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2523 if (label && label->layoutObject()) { | 2462 if (label && label->layoutObject()) { |
| 2524 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); | 2463 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); |
| 2525 result.unite(labelRect); | 2464 result.unite(labelRect); |
| 2526 } | 2465 } |
| 2527 } | 2466 } |
| 2528 | 2467 |
| 2529 return result; | 2468 return result; |
| 2530 } | 2469 } |
| 2531 | 2470 |
| 2532 } // namespace blink | 2471 } // namespace blink |
| OLD | NEW |