Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp

Issue 1841333002: Various fixes for aria-activedescendant. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed some Blink tests. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698