Changeset 200964 in webkit
- Timestamp:
- May 16, 2016 1:26:40 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r200960 r200964 1 2016-05-16 Ryosuke Niwa <rniwa@webkit.org> 2 3 Focus ordering should respect slot elements 4 https://bugs.webkit.org/show_bug.cgi?id=151379 5 6 Reviewed by Antti Koivisto. 7 8 Added regression tests for moving focus by tab and shift+tab across 9 user-defined shadow trees with slots and details element. 10 11 * fast/shadow-dom/focus-across-details-element-expected.txt: Added. 12 * fast/shadow-dom/focus-across-details-element.html: Added. 13 * fast/shadow-dom/focus-navigation-across-slots-expected.txt: Added. 14 * fast/shadow-dom/focus-navigation-across-slots.html: Added. 15 1 16 2016-05-16 Ryan Haddad <ryanhaddad@apple.com> 2 17 -
trunk/LayoutTests/platform/ios-simulator/TestExpectations
r200924 r200964 257 257 258 258 # No tab navigation support on iOS 259 fast/shadow-dom/focus-across-details-element.html [ Failure ] 260 fast/shadow-dom/focus-navigation-across-slots.html [ Failure ] 259 261 fast/shadow-dom/focus-on-iframe.html [ Failure ] 260 262 fast/shadow-dom/negative-tabindex-on-shadow-host.html [ Failure ] -
trunk/Source/WebCore/ChangeLog
r200963 r200964 1 2016-05-16 Ryosuke Niwa <rniwa@webkit.org> 2 3 Focus ordering should respect slot elements 4 https://bugs.webkit.org/show_bug.cgi?id=151379 5 6 Reviewed by Antti Koivisto. 7 8 Implemented the sequential focus navigation ordering as discussed on 9 https://github.com/w3c/webcomponents/issues/375 10 11 New behavior treats each shadow root and slot as a "focus scope". The focus navigation ordering 12 is defined within each "focus scope" using tabindex, treating any "focus scope owner" 13 (e.g. shadow host or a slot) as if it was having tabindex=0 if it wasn't itself focusable. 14 15 This patch modifies FocusNavigationScope to support a focus scope defined for a slot element in 16 addition to the one defined for a shadow tree and a document as previously supported. 17 18 Tests: fast/shadow-dom/focus-across-details-element.html 19 fast/shadow-dom/focus-navigation-across-slots.html 20 21 * dom/Node.cpp: 22 (WebCore::parentShadowRoot): Extracted from assignedSlot. 23 (WebCore::Node::assignedSlot): 24 (WebCore::Node::assignedSlotForBindings): Added. 25 * dom/Node.h: 26 * dom/NonDocumentTypeChildNode.idl: 27 * html/HTMLDetailsElement.h: 28 (HTMLDetailsElement::hasCustomFocusLogic): Added. Don't treat details element as a "focus scope". 29 * html/HTMLSummaryElement.h: 30 (HTMLSummaryElement::hasCustomFocusLogic): Ditto for summary element. 31 * page/FocusController.cpp: 32 (WebCore::hasCustomFocusLogic): Moved. 33 (WebCore::isFocusScopeOwner): Added. Returns true on a shadow host without a custom focus logic or 34 on a slot inside a shadow tree whose shadow host doesn't have a custom focus logic. 35 (WebCore::FocusNavigationScope::firstChildInScope): Now takes a reference. Call isFocusScopeOwner 36 to check for both slots and shadow roots instead of just the latter. This fixes a subtle bug that 37 focus may never get out of textarea in some cases due to its failure to check hasCustomFocusLogic. 38 (WebCore::FocusNavigationScope::lastChildInScope): Ditto. 39 (WebCore::FocusNavigationScope::parentInScope): Made this a member function since it needs to check 40 against m_slotElement inside the focus scope of a slot. 41 (WebCore::FocusNavigationScope::nextSiblingInScope): Added. Finds the next assigned node in a slot 42 in the focus scope defined for a slot. Just calls nextSibling() in the focus scope for shadow tree 43 and document. 44 (WebCore::FocusNavigationScope::previousSiblingInScope): Ditto for finding the previous sibling. 45 (WebCore::FocusNavigationScope::firstNodeInScope): Added. This function replaces rootNode() which 46 doesn't exist for the focus scope of a slot element. 47 (WebCore::FocusNavigationScope::lastNodeInScope): Ditto for the last node. 48 (WebCore::FocusNavigationScope::nextInScope): 49 (WebCore::FocusNavigationScope::previousInScope): 50 (WebCore::FocusNavigationScope::FocusNavigationScope): Added a variant that takes HTMLSlotElement. 51 (WebCore::FocusNavigationScope::owner): Added the support for slot elements. 52 (WebCore::FocusNavigationScope::scopeOf): Ditto. 53 (WebCore::FocusNavigationScope::scopeOwnedByScopeOwner): Ditto. 54 (WebCore::isFocusableElementOrScopeOwner): Added the support for slot elements and renamed from 55 isFocusableOrHasShadowTreeWithoutCustomFocusLogic. 56 (WebCore::isNonFocusableScopeOwner): Ditto. Renamed from isNonFocusableShadowHost. 57 (WebCore::isFocusableScopeOwner): Ditto. Renamed from isFocusableShadowHost. 58 (WebCore::shadowAdjustedTabIndex): Added the support for slot elements. 59 (WebCore::FocusController::findFocusableElementAcrossFocusScope): 60 (WebCore::FocusController::nextFocusableElementWithinScope): 61 (WebCore::FocusController::previousFocusableElementWithinScope): 62 (WebCore::FocusController::findElementWithExactTabIndex): 63 (WebCore::nextElementWithGreaterTabIndex): Call firstNodeInScope() instead of rootNode() here since 64 there is no root node for the focus scope defined for a slot element. 65 (WebCore::previousElementWithLowerTabIndex): Ditto for scope.lastNodeInScope(). 66 (WebCore::FocusController::nextFocusableElementOrScopeOwner): 67 (WebCore::FocusController::previousFocusableElementOrScopeOwner): 68 (WebCore::parentInScope): Deleted. 69 (WebCore::FocusNavigationScope::rootNode): Deleted. 70 (WebCore::FocusNavigationScope::scopeOwnedByShadowHost): Deleted. 71 (WebCore::isNonFocusableShadowHost): Deleted. 72 (WebCore::isFocusableShadowHost): Deleted. 73 (WebCore::isFocusableOrHasShadowTreeWithoutCustomFocusLogic): Deleted. 74 1 75 2016-05-16 Chris Dumez <cdumez@apple.com> 2 76 -
trunk/Source/WebCore/dom/Node.cpp
r200923 r200964 1124 1124 } 1125 1125 1126 #if ENABLE(SHADOW_DOM) 1126 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 1127 static inline ShadowRoot* parentShadowRoot(const Node& node) 1128 { 1129 if (auto* parent = node.parentElement()) 1130 return parent->shadowRoot(); 1131 return nullptr; 1132 } 1133 1127 1134 HTMLSlotElement* Node::assignedSlot() const 1128 1135 { 1129 auto* parent = parentElement(); 1130 if (!parent) 1131 return nullptr; 1132 1133 auto* shadowRoot = parent->shadowRoot(); 1134 if (!shadowRoot || shadowRoot->type() != ShadowRoot::Type::Open) 1135 return nullptr; 1136 1137 return shadowRoot->findAssignedSlot(*this); 1136 if (auto* shadowRoot = parentShadowRoot(*this)) 1137 return shadowRoot->findAssignedSlot(*this); 1138 return nullptr; 1139 } 1140 1141 HTMLSlotElement* Node::assignedSlotForBindings() const 1142 { 1143 auto* shadowRoot = parentShadowRoot(*this); 1144 if (shadowRoot && shadowRoot->type() == ShadowRoot::Type::Open) 1145 return shadowRoot->findAssignedSlot(*this); 1146 return nullptr; 1138 1147 } 1139 1148 #endif … … 1143 1152 ASSERT(isMainThreadOrGCThread()); 1144 1153 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 1145 if (auto* parent = parentElement()) { 1146 if (auto* shadowRoot = parent->shadowRoot()) { 1147 if (auto* assignedSlot = shadowRoot->findAssignedSlot(*this)) 1148 return assignedSlot; 1149 } 1150 } 1154 if (auto* slot = assignedSlot()) 1155 return slot; 1151 1156 #endif 1152 1157 if (is<ShadowRoot>(*this)) -
trunk/Source/WebCore/dom/Node.h
r200923 r200964 262 262 bool isUnclosedNode(const Node&) const; 263 263 264 #if ENABLE(SHADOW_DOM) 264 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 265 265 HTMLSlotElement* assignedSlot() const; 266 HTMLSlotElement* assignedSlotForBindings() const; 266 267 #endif 267 268 -
trunk/Source/WebCore/dom/NonDocumentTypeChildNode.idl
r197921 r200964 33 33 34 34 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT 35 [Conditional=SHADOW_DOM, EnabledAtRuntime=ShadowDOM ] readonly attribute HTMLSlotElement assignedSlot;35 [Conditional=SHADOW_DOM, EnabledAtRuntime=ShadowDOM, ImplementedAs=assignedSlotForBindings] readonly attribute HTMLSlotElement assignedSlot; 36 36 #endif 37 37 }; -
trunk/Source/WebCore/html/HTMLDetailsElement.h
r200041 r200964 44 44 void didAddUserAgentShadowRoot(ShadowRoot*) override; 45 45 bool canHaveUserAgentShadowRoot() const final { return true; } 46 bool hasCustomFocusLogic() const final { return true; } 46 47 47 48 bool m_isOpen { false }; -
trunk/Source/WebCore/html/HTMLSummaryElement.h
r200041 r200964 45 45 // FIXME: Shadow DOM spec says we should be able to create shadow root on this element 46 46 bool canHaveUserAgentShadowRoot() const final { return true; } 47 bool hasCustomFocusLogic() const final { return true; } 47 48 48 49 HTMLDetailsElement* detailsElement() const; -
trunk/Source/WebCore/page/FocusController.cpp
r200712 r200964 47 47 #include "HTMLNames.h" 48 48 #include "HTMLPlugInElement.h" 49 #include "HTMLSlotElement.h" 49 50 #include "HTMLTextAreaElement.h" 50 51 #include "HitTestResult.h" … … 68 69 using namespace HTMLNames; 69 70 71 static inline bool hasCustomFocusLogic(const Element& element) 72 { 73 return is<HTMLElement>(element) && downcast<HTMLElement>(element).hasCustomFocusLogic(); 74 } 75 76 static inline bool isFocusScopeOwner(const Element& element) 77 { 78 if (element.shadowRoot() && !hasCustomFocusLogic(element)) 79 return true; 80 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 81 if (is<HTMLSlotElement>(element) && downcast<HTMLSlotElement>(element).assignedNodes()) { 82 ShadowRoot* root = element.containingShadowRoot(); 83 if (root && root->host() && !hasCustomFocusLogic(*root->host())) 84 return true; 85 } 86 #endif 87 return false; 88 } 89 70 90 class FocusNavigationScope { 71 91 public: 72 ContainerNode& rootNode() const;73 92 Element* owner() const; 74 93 WEBCORE_EXPORT static FocusNavigationScope scopeOf(Node&); 75 static FocusNavigationScope scopeOwnedByS hadowHost(Element&);94 static FocusNavigationScope scopeOwnedByScopeOwner(Element&); 76 95 static FocusNavigationScope scopeOwnedByIFrame(HTMLFrameOwnerElement&); 77 96 97 Node* firstNodeInScope() const; 98 Node* lastNodeInScope() const; 78 99 Node* nextInScope(const Node*) const; 79 100 Node* previousInScope(const Node*) const; 80 Node* lastChildInScope(const Node *) const;101 Node* lastChildInScope(const Node&) const; 81 102 82 103 private: 83 Node* firstChildInScope(const Node*) const; 104 Node* firstChildInScope(const Node&) const; 105 106 Node* parentInScope(const Node&) const; 107 108 Node* nextSiblingInScope(const Node&) const; 109 Node* previousSiblingInScope(const Node&) const; 84 110 85 111 explicit FocusNavigationScope(TreeScope&); 86 TreeScope& m_rootTreeScope; 112 113 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 114 explicit FocusNavigationScope(HTMLSlotElement&); 115 #endif 116 117 TreeScope* m_rootTreeScope { nullptr }; 118 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 119 HTMLSlotElement* m_slotElement { nullptr }; 120 #endif 87 121 }; 88 122 89 123 // FIXME: Focus navigation should work with shadow trees that have slots. 90 Node* FocusNavigationScope::firstChildInScope(const Node* node) const 124 Node* FocusNavigationScope::firstChildInScope(const Node& node) const 125 { 126 if (is<Element>(node) && isFocusScopeOwner(downcast<Element>(node))) 127 return nullptr; 128 return node.firstChild(); 129 } 130 131 Node* FocusNavigationScope::lastChildInScope(const Node& node) const 132 { 133 if (is<Element>(node) && isFocusScopeOwner(downcast<Element>(node))) 134 return nullptr; 135 return node.lastChild(); 136 } 137 138 Node* FocusNavigationScope::parentInScope(const Node& node) const 139 { 140 if (is<Element>(node) && isFocusScopeOwner(downcast<Element>(node))) 141 return nullptr; 142 143 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 144 if (UNLIKELY(m_slotElement && m_slotElement == node.assignedSlot())) 145 return nullptr; 146 #endif 147 148 ContainerNode* parent = node.parentNode(); 149 if (parent && is<Element>(parent) && isFocusScopeOwner(downcast<Element>(*parent))) 150 return nullptr; 151 152 return parent; 153 } 154 155 Node* FocusNavigationScope::nextSiblingInScope(const Node& node) const 156 { 157 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 158 if (UNLIKELY(m_slotElement && m_slotElement == node.assignedSlot())) { 159 for (Node* current = node.nextSibling(); current; current = current->nextSibling()) { 160 if (current->assignedSlot() == m_slotElement) 161 return current; 162 } 163 return nullptr; 164 } 165 #endif 166 return node.nextSibling(); 167 } 168 169 Node* FocusNavigationScope::previousSiblingInScope(const Node& node) const 170 { 171 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 172 if (UNLIKELY(m_slotElement && m_slotElement == node.assignedSlot())) { 173 for (Node* current = node.previousSibling(); current; current = current->previousSibling()) { 174 if (current->assignedSlot() == m_slotElement) 175 return current; 176 } 177 return nullptr; 178 } 179 #endif 180 return node.previousSibling(); 181 } 182 183 Node* FocusNavigationScope::firstNodeInScope() const 184 { 185 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 186 if (UNLIKELY(m_slotElement)) { 187 auto* assigneNodes = m_slotElement->assignedNodes(); 188 ASSERT(assigneNodes); 189 return assigneNodes->first(); 190 } 191 #endif 192 ASSERT(m_rootTreeScope); 193 return &m_rootTreeScope->rootNode(); 194 } 195 196 Node* FocusNavigationScope::lastNodeInScope() const 197 { 198 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 199 if (UNLIKELY(m_slotElement)) { 200 auto* assigneNodes = m_slotElement->assignedNodes(); 201 ASSERT(assigneNodes); 202 return assigneNodes->last(); 203 } 204 #endif 205 ASSERT(m_rootTreeScope); 206 return &m_rootTreeScope->rootNode(); 207 } 208 209 Node* FocusNavigationScope::nextInScope(const Node* node) const 91 210 { 92 211 ASSERT(node); 93 if (node->shadowRoot()) 94 return nullptr; 95 return node->firstChild(); 96 } 97 98 Node* FocusNavigationScope::lastChildInScope(const Node* node) const 99 { 100 ASSERT(node); 101 if (node->shadowRoot()) 102 return nullptr; 103 return node->lastChild(); 104 } 105 106 static Node* parentInScope(const Node* node) 107 { 108 if (node->isShadowRoot()) 109 return nullptr; 110 111 ContainerNode* parent = node->parentNode(); 112 if (parent && parent->shadowRoot()) 113 return nullptr; 114 115 return parent; 116 } 117 118 Node* FocusNavigationScope::nextInScope(const Node* node) const 119 { 120 if (Node* next = firstChildInScope(node)) 212 if (Node* next = firstChildInScope(*node)) 121 213 return next; 122 if (Node* next = n ode->nextSibling())214 if (Node* next = nextSiblingInScope(*node)) 123 215 return next; 124 216 const Node* current = node; 125 while (current && ! current->nextSibling())126 current = parentInScope( current);127 return current ? current->nextSibling() : nullptr;217 while (current && !nextSiblingInScope(*current)) 218 current = parentInScope(*current); 219 return current ? nextSiblingInScope(*current) : nullptr; 128 220 } 129 221 130 222 Node* FocusNavigationScope::previousInScope(const Node* node) const 131 223 { 132 if (Node* current = node->previousSibling()) { 133 while (Node* child = lastChildInScope(current)) 224 ASSERT(node); 225 if (Node* current = previousSiblingInScope(*node)) { 226 while (Node* child = lastChildInScope(*current)) 134 227 current = child; 135 228 return current; 136 229 } 137 return parentInScope( node);230 return parentInScope(*node); 138 231 } 139 232 140 233 FocusNavigationScope::FocusNavigationScope(TreeScope& treeScope) 141 : m_rootTreeScope(treeScope) 142 { 143 } 144 145 ContainerNode& FocusNavigationScope::rootNode() const 146 { 147 return m_rootTreeScope.rootNode(); 148 } 234 : m_rootTreeScope(&treeScope) 235 { 236 } 237 238 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 239 FocusNavigationScope::FocusNavigationScope(HTMLSlotElement& slotElement) 240 : m_slotElement(&slotElement) 241 { 242 } 243 #endif 149 244 150 245 Element* FocusNavigationScope::owner() const 151 246 { 152 ContainerNode& root = rootNode(); 247 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 248 if (m_slotElement) 249 return m_slotElement; 250 #endif 251 252 ASSERT(m_rootTreeScope); 253 ContainerNode& root = m_rootTreeScope->rootNode(); 153 254 if (is<ShadowRoot>(root)) 154 255 return downcast<ShadowRoot>(root).host(); … … 160 261 FocusNavigationScope FocusNavigationScope::scopeOf(Node& startingNode) 161 262 { 263 ASSERT(startingNode.isInTreeScope()); 162 264 Node* root = nullptr; 163 for (Node* currentNode = &startingNode; currentNode; currentNode = parentInScope(currentNode))265 for (Node* currentNode = &startingNode; currentNode; currentNode = currentNode->parentNode()) { 164 266 root = currentNode; 165 // The result is not always a ShadowRoot nor a DocumentNode since 166 // a starting node is in an orphaned tree in composed shadow tree. 267 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 268 if (HTMLSlotElement* slot = currentNode->assignedSlot()) { 269 if (isFocusScopeOwner(*slot)) 270 return FocusNavigationScope(*slot); 271 } 272 #endif 273 if (is<ShadowRoot>(currentNode)) 274 return FocusNavigationScope(downcast<ShadowRoot>(*currentNode)); 275 } 276 ASSERT(root); 167 277 return FocusNavigationScope(root->treeScope()); 168 278 } 169 279 170 FocusNavigationScope FocusNavigationScope::scopeOwnedByShadowHost(Element& element) 171 { 172 ASSERT(element.shadowRoot()); 280 FocusNavigationScope FocusNavigationScope::scopeOwnedByScopeOwner(Element& element) 281 { 282 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) 283 ASSERT(element.shadowRoot() || is<HTMLSlotElement>(element)); 284 if (is<HTMLSlotElement>(element)) 285 return FocusNavigationScope(downcast<HTMLSlotElement>(element)); 286 #endif 173 287 return FocusNavigationScope(*element.shadowRoot()); 174 288 } … … 200 314 } 201 315 202 static inline bool hasCustomFocusLogic(Element& element)203 { 204 return is<HTMLElement>(element) && downcast<HTMLElement>(element).hasCustomFocusLogic();205 } 206 207 static inline bool isNonFocusableS hadowHost(Element& element, KeyboardEvent& event)208 { 209 return !element.isKeyboardFocusable(&event) && element.shadowRoot() && !hasCustomFocusLogic(element);210 } 211 212 static inline bool isFocusableS hadowHost(Node& node, KeyboardEvent& event)213 { 214 return is<Element>(node) && downcast<Element>(node).isKeyboardFocusable(&event) && downcast<Element>(node).shadowRoot() && !hasCustomFocusLogic(downcast<Element>(node));316 static inline bool isFocusableElementOrScopeOwner(Element& element, KeyboardEvent& event) 317 { 318 return element.isKeyboardFocusable(&event) || isFocusScopeOwner(element); 319 } 320 321 static inline bool isNonFocusableScopeOwner(Element& element, KeyboardEvent& event) 322 { 323 return !element.isKeyboardFocusable(&event) && isFocusScopeOwner(element); 324 } 325 326 static inline bool isFocusableScopeOwner(Element& element, KeyboardEvent& event) 327 { 328 return element.isKeyboardFocusable(&event) && isFocusScopeOwner(element); 215 329 } 216 330 217 331 static inline int shadowAdjustedTabIndex(Element& element, KeyboardEvent& event) 218 332 { 219 if (isNonFocusableS hadowHost(element, event)) {333 if (isNonFocusableScopeOwner(element, event)) { 220 334 if (!element.tabIndexSetExplicitly()) 221 335 return 0; // Treat a shadow host without tabindex if it has tabindex=0 even though HTMLElement::tabIndex returns -1 on such an element. 222 336 } 223 337 return element.tabIndex(); 224 }225 226 static inline bool isFocusableOrHasShadowTreeWithoutCustomFocusLogic(Element& element, KeyboardEvent& event)227 {228 return element.isKeyboardFocusable(&event) || isNonFocusableShadowHost(element, event);229 338 } 230 339 … … 420 529 Element* FocusController::findFocusableElementAcrossFocusScope(FocusDirection direction, const FocusNavigationScope& scope, Node* currentNode, KeyboardEvent* event) 421 530 { 422 ASSERT(!is<Element>(currentNode) || !isNonFocusableS hadowHost(*downcast<Element>(currentNode), *event));423 424 if (currentNode && direction == FocusDirectionForward && is FocusableShadowHost(*currentNode, *event)) {425 if (Element* candidateInInnerScope = findFocusableElementWithinScope(direction, FocusNavigationScope::scopeOwnedByS hadowHost(downcast<Element>(*currentNode)), 0, event))531 ASSERT(!is<Element>(currentNode) || !isNonFocusableScopeOwner(downcast<Element>(*currentNode), *event)); 532 533 if (currentNode && direction == FocusDirectionForward && is<Element>(currentNode) && isFocusableScopeOwner(downcast<Element>(*currentNode), *event)) { 534 if (Element* candidateInInnerScope = findFocusableElementWithinScope(direction, FocusNavigationScope::scopeOwnedByScopeOwner(downcast<Element>(*currentNode)), 0, event)) 426 535 return candidateInInnerScope; 427 536 } … … 433 542 Element* owner = scope.owner(); 434 543 while (owner) { 435 if (direction == FocusDirectionBackward && isFocusableS hadowHost(*owner, *event))544 if (direction == FocusDirectionBackward && isFocusableScopeOwner(*owner, *event)) 436 545 return findFocusableElementDescendingDownIntoFrameDocument(direction, owner, event); 437 546 … … 458 567 if (!found) 459 568 return nullptr; 460 if (isNonFocusableS hadowHost(*found, *event)) {461 if (Element* foundInInnerFocusScope = nextFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByS hadowHost(*found), 0, event))569 if (isNonFocusableScopeOwner(*found, *event)) { 570 if (Element* foundInInnerFocusScope = nextFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByScopeOwner(*found), 0, event)) 462 571 return foundInInnerFocusScope; 463 572 return nextFocusableElementWithinScope(scope, found, event); … … 471 580 if (!found) 472 581 return nullptr; 473 if (isFocusableS hadowHost(*found, *event)) {582 if (isFocusableScopeOwner(*found, *event)) { 474 583 // Search an inner focusable element in the shadow tree from the end. 475 if (Element* foundInInnerFocusScope = previousFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByS hadowHost(*found), 0, event))584 if (Element* foundInInnerFocusScope = previousFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByScopeOwner(*found), 0, event)) 476 585 return foundInInnerFocusScope; 477 586 return found; 478 587 } 479 if (isNonFocusableS hadowHost(*found, *event)) {480 if (Element* foundInInnerFocusScope = previousFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByS hadowHost(*found), 0, event))588 if (isNonFocusableScopeOwner(*found, *event)) { 589 if (Element* foundInInnerFocusScope = previousFocusableElementWithinScope(FocusNavigationScope::scopeOwnedByScopeOwner(*found), 0, event)) 481 590 return foundInInnerFocusScope; 482 591 return previousFocusableElementWithinScope(scope, found, event); … … 499 608 continue; 500 609 Element& element = downcast<Element>(*node); 501 if (isFocusable OrHasShadowTreeWithoutCustomFocusLogic(element, *event) && shadowAdjustedTabIndex(element, *event) == tabIndex)610 if (isFocusableElementOrScopeOwner(element, *event) && shadowAdjustedTabIndex(element, *event) == tabIndex) 502 611 return &element; 503 612 } … … 510 619 int winningTabIndex = std::numeric_limits<int>::max(); 511 620 Element* winner = nullptr; 512 for (Node* node = &scope.rootNode(); node; node = scope.nextInScope(node)) {621 for (Node* node = scope.firstNodeInScope(); node; node = scope.nextInScope(node)) { 513 622 if (!is<Element>(*node)) 514 623 continue; 515 624 Element& candidate = downcast<Element>(*node); 516 625 int candidateTabIndex = candidate.tabIndex(); 517 if (isFocusable OrHasShadowTreeWithoutCustomFocusLogic(candidate, event) && candidateTabIndex > tabIndex && (!winner || candidateTabIndex < winningTabIndex)) {626 if (isFocusableElementOrScopeOwner(candidate, event) && candidateTabIndex > tabIndex && (!winner || candidateTabIndex < winningTabIndex)) { 518 627 winner = &candidate; 519 628 winningTabIndex = candidateTabIndex; … … 534 643 Element& element = downcast<Element>(*node); 535 644 int currentTabIndex = shadowAdjustedTabIndex(element, event); 536 if (isFocusable OrHasShadowTreeWithoutCustomFocusLogic(element, event) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {645 if (isFocusableElementOrScopeOwner(element, event) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) { 537 646 winner = &element; 538 647 winningTabIndex = currentTabIndex; … … 569 678 continue; 570 679 Element& element = downcast<Element>(*node); 571 if (isFocusable OrHasShadowTreeWithoutCustomFocusLogic(element, *event) && shadowAdjustedTabIndex(element, *event) >= 0)680 if (isFocusableElementOrScopeOwner(element, *event) && shadowAdjustedTabIndex(element, *event) >= 0) 572 681 return &element; 573 682 } … … 590 699 // There are no nodes with a tabindex greater than start's tabindex, 591 700 // so find the first node with a tabindex of 0. 592 return findElementWithExactTabIndex(scope, &scope.rootNode(), 0, event, FocusDirectionForward);701 return findElementWithExactTabIndex(scope, scope.firstNodeInScope(), 0, event, FocusDirectionForward); 593 702 } 594 703 … … 596 705 { 597 706 Node* last = nullptr; 598 for (Node* node = &scope.rootNode(); node; node = scope.lastChildInScope(node))707 for (Node* node = scope.lastNodeInScope(); node; node = scope.lastChildInScope(*node)) 599 708 last = node; 600 709 ASSERT(last); … … 617 726 continue; 618 727 Element& element = downcast<Element>(*node); 619 if (isFocusable OrHasShadowTreeWithoutCustomFocusLogic(element, *event) && shadowAdjustedTabIndex(element, *event) >= 0)728 if (isFocusableElementOrScopeOwner(element, *event) && shadowAdjustedTabIndex(element, *event) >= 0) 620 729 return &element; 621 730 }
Note: See TracChangeset
for help on using the changeset viewer.