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

Side by Side Diff: third_party/WebKit/Source/core/page/FocusController.cpp

Issue 1840333002: Support slots' fallback contents in focus navigation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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) 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nuanti Ltd. 3 * Copyright (C) 2008 Nuanti Ltd.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 static ScopedFocusNavigation createFor(const Element&); 84 static ScopedFocusNavigation createFor(const Element&);
85 static ScopedFocusNavigation createForDocument(Document&); 85 static ScopedFocusNavigation createForDocument(Document&);
86 static ScopedFocusNavigation ownedByNonFocusableFocusScopeOwner(Element&); 86 static ScopedFocusNavigation ownedByNonFocusableFocusScopeOwner(Element&);
87 static ScopedFocusNavigation ownedByShadowHost(const Element&); 87 static ScopedFocusNavigation ownedByShadowHost(const Element&);
88 static ScopedFocusNavigation ownedByShadowInsertionPoint(HTMLShadowElement&) ; 88 static ScopedFocusNavigation ownedByShadowInsertionPoint(HTMLShadowElement&) ;
89 static ScopedFocusNavigation ownedByHTMLSlotElement(const HTMLSlotElement&); 89 static ScopedFocusNavigation ownedByHTMLSlotElement(const HTMLSlotElement&);
90 static ScopedFocusNavigation ownedByIFrame(const HTMLFrameOwnerElement&); 90 static ScopedFocusNavigation ownedByIFrame(const HTMLFrameOwnerElement&);
91 91
92 private: 92 private:
93 ScopedFocusNavigation(TreeScope&, const Element*); 93 ScopedFocusNavigation(TreeScope&, const Element*);
94 ScopedFocusNavigation(HTMLSlotElement&, const Element*); 94 ScopedFocusNavigation(HTMLSlotElement&, const Element*, bool);
kochi 2016/03/30 06:28:34 Can the third boolean argument be removed? If the
yuzuchan 2016/03/31 07:03:46 Gotcha! Thank you :)
95 RawPtrWillBeMember<ContainerNode> m_rootNode; 95 RawPtrWillBeMember<ContainerNode> m_rootNode;
96 RawPtrWillBeMember<HTMLSlotElement> m_rootSlot; 96 RawPtrWillBeMember<HTMLSlotElement> m_rootSlot;
97 RawPtrWillBeMember<Element> m_current; 97 RawPtrWillBeMember<Element> m_current;
98 bool m_slotFallbackTraversal;
98 }; 99 };
99 100
100 ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element * current) 101 ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element * current)
101 : m_rootNode(treeScope.rootNode()) 102 : m_rootNode(treeScope.rootNode())
102 , m_rootSlot(nullptr) 103 , m_rootSlot(nullptr)
103 , m_current(const_cast<Element*>(current)) 104 , m_current(const_cast<Element*>(current))
105 , m_slotFallbackTraversal(false)
104 { 106 {
105 } 107 }
106 108
107 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Elemen t* current) 109 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Elemen t* current, bool isFallbackScoped)
108 : m_rootNode(nullptr) 110 : m_rootNode(nullptr)
109 , m_rootSlot(&slot) 111 , m_rootSlot(&slot)
110 , m_current(const_cast<Element*>(current)) 112 , m_current(const_cast<Element*>(current))
113 , m_slotFallbackTraversal(isFallbackScoped)
111 { 114 {
112 } 115 }
113 116
114 Element* ScopedFocusNavigation::currentElement() const 117 Element* ScopedFocusNavigation::currentElement() const
115 { 118 {
116 return m_current; 119 return m_current;
117 } 120 }
118 121
119 void ScopedFocusNavigation::setCurrentElement(Element* element) 122 void ScopedFocusNavigation::setCurrentElement(Element* element)
120 { 123 {
121 m_current = element; 124 m_current = element;
122 } 125 }
123 126
124 void ScopedFocusNavigation::moveToNext() 127 void ScopedFocusNavigation::moveToNext()
125 { 128 {
126 ASSERT(m_current); 129 ASSERT(m_current);
127 if (m_rootSlot) { 130 if (m_rootSlot) {
128 m_current = SlotScopedTraversal::next(*m_current); 131 if (m_slotFallbackTraversal) {
132 m_current = ElementTraversal::next(*m_current, m_rootSlot);
133 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
134 m_current = ElementTraversal::next(*m_current);
135 } else {
136 m_current = SlotScopedTraversal::next(*m_current);
137 }
129 } else { 138 } else {
130 m_current = ElementTraversal::next(*m_current); 139 m_current = ElementTraversal::next(*m_current);
131 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current)) 140 while (m_current && (SlotScopedTraversal::isSlotScoped(*m_current) || Sl otScopedTraversal::isSlotFallbackScoped(*m_current)))
132 m_current = ElementTraversal::next(*m_current); 141 m_current = ElementTraversal::next(*m_current);
133 } 142 }
134 } 143 }
135 144
136 void ScopedFocusNavigation::moveToPrevious() 145 void ScopedFocusNavigation::moveToPrevious()
137 { 146 {
138 ASSERT(m_current); 147 ASSERT(m_current);
139 if (m_rootSlot) { 148 if (m_rootSlot) {
140 m_current = SlotScopedTraversal::previous(*m_current); 149 if (m_slotFallbackTraversal) {
150 m_current = ElementTraversal::previous(*m_current, m_rootSlot);
151 if (m_current == m_rootSlot)
152 m_current = nullptr;
153 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
154 m_current = ElementTraversal::previous(*m_current);
155 } else {
156 m_current = SlotScopedTraversal::previous(*m_current);
157 }
141 } else { 158 } else {
142 m_current = ElementTraversal::previous(*m_current); 159 m_current = ElementTraversal::previous(*m_current);
143 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current)) 160 while (m_current && (SlotScopedTraversal::isSlotScoped(*m_current) || Sl otScopedTraversal::isSlotFallbackScoped(*m_current)))
144 m_current = ElementTraversal::previous(*m_current); 161 m_current = ElementTraversal::previous(*m_current);
145 } 162 }
146 } 163 }
147 164
148 void ScopedFocusNavigation::moveToFirst() 165 void ScopedFocusNavigation::moveToFirst()
149 { 166 {
150 if (m_rootSlot) { 167 if (m_rootSlot) {
151 if (!m_rootSlot->getAssignedNodes().isEmpty()) { 168 if (!m_slotFallbackTraversal) {
152 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes(); 169 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
153 for (auto assignedNode : assignedNodes) { 170 for (auto assignedNode : assignedNodes) {
154 if (assignedNode->isElementNode()) { 171 if (assignedNode->isElementNode()) {
155 m_current = toElement(assignedNode); 172 m_current = toElement(assignedNode);
156 break; 173 break;
157 } 174 }
158 } 175 }
159 } else { 176 } else {
160 m_current = nullptr; 177 Element* first = ElementTraversal::firstChild(*m_rootSlot);
178 while (first && SlotScopedTraversal::isSlotScoped(*first))
179 first = ElementTraversal::next(*first, m_rootSlot);
180 m_current = first;
161 } 181 }
162 } else { 182 } else {
163 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode); 183 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode);
164 while (first && SlotScopedTraversal::isSlotScoped(*first)) 184 while (first && (SlotScopedTraversal::isSlotScoped(*first) || SlotScoped Traversal::isSlotFallbackScoped(*first)))
165 first = ElementTraversal::next(*first, m_rootNode); 185 first = ElementTraversal::next(*first, m_rootNode);
166 m_current = first; 186 m_current = first;
167 } 187 }
188
168 } 189 }
169 190
170 void ScopedFocusNavigation::moveToLast() 191 void ScopedFocusNavigation::moveToLast()
171 { 192 {
172 if (m_rootSlot) { 193 if (m_rootSlot) {
173 if (!m_rootSlot->getAssignedNodes().isEmpty()) { 194 if (!m_slotFallbackTraversal) {
174 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes(); 195 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
175 for (auto assignedNode = assignedNodes.rbegin(); assignedNode != ass ignedNodes.rend(); ++assignedNode) { 196 for (auto assignedNode = assignedNodes.rbegin(); assignedNode != ass ignedNodes.rend(); ++assignedNode) {
176 if ((*assignedNode)->isElementNode()) { 197 if ((*assignedNode)->isElementNode()) {
177 m_current = ElementTraversal::lastWithinOrSelf(*toElement(*a ssignedNode)); 198 m_current = ElementTraversal::lastWithinOrSelf(*toElement(*a ssignedNode));
178 break; 199 break;
179 } 200 }
180 } 201 }
181 } else { 202 } else {
182 m_current = nullptr; 203 Element* last = ElementTraversal::lastWithin(*m_rootSlot);
204 while (last && SlotScopedTraversal::isSlotScoped(*last))
205 last = ElementTraversal::previous(*last, m_rootSlot);
206 m_current = last;
183 } 207 }
184 } else { 208 } else {
185 Element* last = ElementTraversal::lastWithin(*m_rootNode); 209 Element* last = ElementTraversal::lastWithin(*m_rootNode);
186 while (last && SlotScopedTraversal::isSlotScoped(*last)) 210 while (last && (SlotScopedTraversal::isSlotScoped(*last) || SlotScopedTr aversal::isSlotFallbackScoped(*last)))
187 last = ElementTraversal::previous(*last, m_rootNode); 211 last = ElementTraversal::previous(*last, m_rootNode);
188 m_current = last; 212 m_current = last;
189 } 213 }
190 } 214 }
191 215
192 Element* ScopedFocusNavigation::owner() const 216 Element* ScopedFocusNavigation::owner() const
193 { 217 {
194 if (m_rootSlot) 218 if (m_rootSlot)
195 return m_rootSlot; 219 return m_rootSlot;
220 ASSERT(m_rootNode);
196 if (m_rootNode->isShadowRoot()) { 221 if (m_rootNode->isShadowRoot()) {
197 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode); 222 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode);
198 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot(); 223 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot();
199 } 224 }
200 // FIXME: Figure out the right thing for OOPI here. 225 // FIXME: Figure out the right thing for OOPI here.
201 if (Frame* frame = m_rootNode->document().frame()) 226 if (Frame* frame = m_rootNode->document().frame())
202 return frame->deprecatedLocalOwner(); 227 return frame->deprecatedLocalOwner();
203 return nullptr; 228 return nullptr;
204 } 229 }
205 230
206 ScopedFocusNavigation ScopedFocusNavigation::createFor(const Element& current) 231 ScopedFocusNavigation ScopedFocusNavigation::createFor(const Element& current)
207 { 232 {
208 if (SlotScopedTraversal::isSlotScoped(current)) 233 if (SlotScopedTraversal::isSlotScoped(current))
209 return ScopedFocusNavigation(*SlotScopedTraversal::findScopeOwnerSlot(cu rrent), &current); 234 return ScopedFocusNavigation(*SlotScopedTraversal::findScopeOwnerSlot(cu rrent), &current, false);
235 if (SlotScopedTraversal::isSlotFallbackScoped(current))
236 return ScopedFocusNavigation(*SlotScopedTraversal::findFallbackScopeOwne rSlot(current), &current, true);
210 return ScopedFocusNavigation(current.treeScope(), &current); 237 return ScopedFocusNavigation(current.treeScope(), &current);
211 } 238 }
212 239
213 ScopedFocusNavigation ScopedFocusNavigation::createForDocument(Document& documen t) 240 ScopedFocusNavigation ScopedFocusNavigation::createForDocument(Document& documen t)
214 { 241 {
215 return ScopedFocusNavigation(document, nullptr); 242 return ScopedFocusNavigation(document, nullptr);
216 } 243 }
217 244
218 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element) 245 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element)
219 { 246 {
(...skipping 20 matching lines...) Expand all
240 } 267 }
241 268
242 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowInsertionPoint(HTMLSha dowElement& shadowInsertionPoint) 269 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowInsertionPoint(HTMLSha dowElement& shadowInsertionPoint)
243 { 270 {
244 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint)); 271 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint));
245 return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullpt r); 272 return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullpt r);
246 } 273 }
247 274
248 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element) 275 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element)
249 { 276 {
250 return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr) ; 277 return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr, element.getAssignedNodes().isEmpty());
251 } 278 }
252 279
253 inline void dispatchBlurEvent(const Document& document, Element& focusedElement) 280 inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
254 { 281 {
255 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage); 282 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage);
256 if (focusedElement == document.focusedElement()) { 283 if (focusedElement == document.focusedElement()) {
257 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr); 284 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr);
258 if (focusedElement == document.focusedElement()) 285 if (focusedElement == document.focusedElement())
259 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr); 286 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr);
260 } 287 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 } 442 }
416 } 443 }
417 444
418 // Look for the first element in the scope that: 445 // Look for the first element in the scope that:
419 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and 446 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
420 // 2) comes first in the scope, if there's a tie. 447 // 2) comes first in the scope, if there's a tie.
421 scope.moveToFirst(); 448 scope.moveToFirst();
422 if (Element* winner = nextElementWithGreaterTabIndex(scope, current ? adjust edTabIndex(*current) : 0)) { 449 if (Element* winner = nextElementWithGreaterTabIndex(scope, current ? adjust edTabIndex(*current) : 0)) {
423 return winner; 450 return winner;
424 } 451 }
425
426 // There are no elements with a tabindex greater than start's tabindex, 452 // There are no elements with a tabindex greater than start's tabindex,
427 // so find the first element with a tabindex of 0. 453 // so find the first element with a tabindex of 0.
428 scope.moveToFirst(); 454 scope.moveToFirst();
429 return findElementWithExactTabIndex(scope, 0, WebFocusTypeForward); 455 return findElementWithExactTabIndex(scope, 0, WebFocusTypeForward);
430 } 456 }
431 457
432 Element* previousFocusableElement(ScopedFocusNavigation& scope) 458 Element* previousFocusableElement(ScopedFocusNavigation& scope)
433 { 459 {
434 // First try to find the last element in the scope that comes before start a nd has the same tabindex as start. 460 // First try to find the last element in the scope that comes before start a nd has the same tabindex as start.
435 // If start is null, find the last element in the scope with a tabindex of 0 . 461 // If start is null, find the last element in the scope with a tabindex of 0 .
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 return consumed; 1283 return consumed;
1258 } 1284 }
1259 1285
1260 DEFINE_TRACE(FocusController) 1286 DEFINE_TRACE(FocusController)
1261 { 1287 {
1262 visitor->trace(m_page); 1288 visitor->trace(m_page);
1263 visitor->trace(m_focusedFrame); 1289 visitor->trace(m_focusedFrame);
1264 } 1290 }
1265 1291
1266 } // namespace blink 1292 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698