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

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: Refactor 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
« no previous file with comments | « third_party/WebKit/LayoutTests/shadow-dom/slot-fallback-focus.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 void moveToFirst(); 81 void moveToFirst();
82 void moveToLast(); 82 void moveToLast();
83 Element* owner() const; 83 Element* owner() const;
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 static HTMLSlotElement* findFallbackScopeOwnerSlot(const Element&);
92 static bool isSlotFallbackScoped(const Element&);
93 static bool isSlotFallbackScopedForThisSlot(const HTMLSlotElement&, const El ement&);
91 94
92 private: 95 private:
93 ScopedFocusNavigation(TreeScope&, const Element*); 96 ScopedFocusNavigation(TreeScope&, const Element*);
94 ScopedFocusNavigation(HTMLSlotElement&, const Element*); 97 ScopedFocusNavigation(HTMLSlotElement&, const Element*);
95 Member<ContainerNode> m_rootNode; 98 RawPtrWillBeMember<ContainerNode> m_rootNode;
96 Member<HTMLSlotElement> m_rootSlot; 99 RawPtrWillBeMember<HTMLSlotElement> m_rootSlot;
97 Member<Element> m_current; 100 RawPtrWillBeMember<Element> m_current;
101 bool m_slotFallbackTraversal;
98 }; 102 };
99 103
100 ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element * current) 104 ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element * current)
101 : m_rootNode(treeScope.rootNode()) 105 : m_rootNode(treeScope.rootNode())
102 , m_rootSlot(nullptr) 106 , m_rootSlot(nullptr)
103 , m_current(const_cast<Element*>(current)) 107 , m_current(const_cast<Element*>(current))
104 { 108 {
105 } 109 }
106 110
107 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Elemen t* current) 111 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Elemen t* current)
108 : m_rootNode(nullptr) 112 : m_rootNode(nullptr)
109 , m_rootSlot(&slot) 113 , m_rootSlot(&slot)
110 , m_current(const_cast<Element*>(current)) 114 , m_current(const_cast<Element*>(current))
115 , m_slotFallbackTraversal(slot.getAssignedNodes().isEmpty())
111 { 116 {
112 } 117 }
113 118
114 Element* ScopedFocusNavigation::currentElement() const 119 Element* ScopedFocusNavigation::currentElement() const
115 { 120 {
116 return m_current; 121 return m_current;
117 } 122 }
118 123
119 void ScopedFocusNavigation::setCurrentElement(Element* element) 124 void ScopedFocusNavigation::setCurrentElement(Element* element)
120 { 125 {
121 m_current = element; 126 m_current = element;
122 } 127 }
123 128
124 void ScopedFocusNavigation::moveToNext() 129 void ScopedFocusNavigation::moveToNext()
125 { 130 {
126 ASSERT(m_current); 131 ASSERT(m_current);
127 if (m_rootSlot) { 132 if (m_rootSlot) {
128 m_current = SlotScopedTraversal::next(*m_current); 133 if (m_slotFallbackTraversal) {
134 m_current = ElementTraversal::next(*m_current, m_rootSlot);
135 while (m_current && !ScopedFocusNavigation::isSlotFallbackScopedForT hisSlot(*m_rootSlot, *m_current))
136 m_current = ElementTraversal::next(*m_current, m_rootSlot);
137 } else {
138 m_current = SlotScopedTraversal::next(*m_current);
139 }
129 } else { 140 } else {
130 m_current = ElementTraversal::next(*m_current); 141 m_current = ElementTraversal::next(*m_current);
131 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current)) 142 while (m_current && (SlotScopedTraversal::isSlotScoped(*m_current) || Sc opedFocusNavigation::isSlotFallbackScoped(*m_current)))
132 m_current = ElementTraversal::next(*m_current); 143 m_current = ElementTraversal::next(*m_current);
133 } 144 }
134 } 145 }
135 146
136 void ScopedFocusNavigation::moveToPrevious() 147 void ScopedFocusNavigation::moveToPrevious()
137 { 148 {
138 ASSERT(m_current); 149 ASSERT(m_current);
139 if (m_rootSlot) { 150 if (m_rootSlot) {
140 m_current = SlotScopedTraversal::previous(*m_current); 151 if (m_slotFallbackTraversal) {
152 m_current = ElementTraversal::previous(*m_current, m_rootSlot);
153 if (m_current == m_rootSlot)
154 m_current = nullptr;
155 while (m_current && !ScopedFocusNavigation::isSlotFallbackScopedForT hisSlot(*m_rootSlot, *m_current))
156 m_current = ElementTraversal::previous(*m_current);
157 } else {
158 m_current = SlotScopedTraversal::previous(*m_current);
159 }
141 } else { 160 } else {
142 m_current = ElementTraversal::previous(*m_current); 161 m_current = ElementTraversal::previous(*m_current);
143 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current)) 162 while (m_current && (SlotScopedTraversal::isSlotScoped(*m_current) || Sc opedFocusNavigation::isSlotFallbackScoped(*m_current)))
144 m_current = ElementTraversal::previous(*m_current); 163 m_current = ElementTraversal::previous(*m_current);
145 } 164 }
146 } 165 }
147 166
148 void ScopedFocusNavigation::moveToFirst() 167 void ScopedFocusNavigation::moveToFirst()
149 { 168 {
150 if (m_rootSlot) { 169 if (m_rootSlot) {
151 if (!m_rootSlot->getAssignedNodes().isEmpty()) { 170 if (!m_slotFallbackTraversal) {
152 HeapVector<Member<Node>> assignedNodes = m_rootSlot->getAssignedNode s(); 171 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
153 for (auto assignedNode : assignedNodes) { 172 for (auto assignedNode : assignedNodes) {
154 if (assignedNode->isElementNode()) { 173 if (assignedNode->isElementNode()) {
155 m_current = toElement(assignedNode); 174 m_current = toElement(assignedNode);
156 break; 175 break;
157 } 176 }
158 } 177 }
159 } else { 178 } else {
160 m_current = nullptr; 179 Element* first = ElementTraversal::firstChild(*m_rootSlot);
180 while (first && !ScopedFocusNavigation::isSlotFallbackScopedForThisS lot(*m_rootSlot, *first))
181 first = ElementTraversal::next(*first, m_rootSlot);
182 m_current = first;
161 } 183 }
162 } else { 184 } else {
163 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode); 185 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode);
164 while (first && SlotScopedTraversal::isSlotScoped(*first)) 186 while (first && (SlotScopedTraversal::isSlotScoped(*first) || ScopedFocu sNavigation::isSlotFallbackScoped(*first)))
165 first = ElementTraversal::next(*first, m_rootNode); 187 first = ElementTraversal::next(*first, m_rootNode);
166 m_current = first; 188 m_current = first;
167 } 189 }
190
168 } 191 }
169 192
170 void ScopedFocusNavigation::moveToLast() 193 void ScopedFocusNavigation::moveToLast()
171 { 194 {
172 if (m_rootSlot) { 195 if (m_rootSlot) {
173 if (!m_rootSlot->getAssignedNodes().isEmpty()) { 196 if (!m_slotFallbackTraversal) {
174 HeapVector<Member<Node>> assignedNodes = m_rootSlot->getAssignedNode s(); 197 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
175 for (auto assignedNode = assignedNodes.rbegin(); assignedNode != ass ignedNodes.rend(); ++assignedNode) { 198 for (auto assignedNode = assignedNodes.rbegin(); assignedNode != ass ignedNodes.rend(); ++assignedNode) {
176 if ((*assignedNode)->isElementNode()) { 199 if ((*assignedNode)->isElementNode()) {
177 m_current = ElementTraversal::lastWithinOrSelf(*toElement(*a ssignedNode)); 200 m_current = ElementTraversal::lastWithinOrSelf(*toElement(*a ssignedNode));
178 break; 201 break;
179 } 202 }
180 } 203 }
181 } else { 204 } else {
182 m_current = nullptr; 205 Element* last = ElementTraversal::lastWithin(*m_rootSlot);
206 while (last && !ScopedFocusNavigation::isSlotFallbackScopedForThisSl ot(*m_rootSlot, *last))
207 last = ElementTraversal::previous(*last, m_rootSlot);
208 m_current = last;
183 } 209 }
184 } else { 210 } else {
185 Element* last = ElementTraversal::lastWithin(*m_rootNode); 211 Element* last = ElementTraversal::lastWithin(*m_rootNode);
186 while (last && SlotScopedTraversal::isSlotScoped(*last)) 212 while (last && (SlotScopedTraversal::isSlotScoped(*last) || ScopedFocusN avigation::isSlotFallbackScoped(*last)))
187 last = ElementTraversal::previous(*last, m_rootNode); 213 last = ElementTraversal::previous(*last, m_rootNode);
188 m_current = last; 214 m_current = last;
189 } 215 }
190 } 216 }
191 217
192 Element* ScopedFocusNavigation::owner() const 218 Element* ScopedFocusNavigation::owner() const
193 { 219 {
194 if (m_rootSlot) 220 if (m_rootSlot)
195 return m_rootSlot; 221 return m_rootSlot;
222 ASSERT(m_rootNode);
196 if (m_rootNode->isShadowRoot()) { 223 if (m_rootNode->isShadowRoot()) {
197 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode); 224 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode);
198 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot(); 225 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot();
199 } 226 }
200 // FIXME: Figure out the right thing for OOPI here. 227 // FIXME: Figure out the right thing for OOPI here.
201 if (Frame* frame = m_rootNode->document().frame()) 228 if (Frame* frame = m_rootNode->document().frame())
202 return frame->deprecatedLocalOwner(); 229 return frame->deprecatedLocalOwner();
203 return nullptr; 230 return nullptr;
204 } 231 }
205 232
206 ScopedFocusNavigation ScopedFocusNavigation::createFor(const Element& current) 233 ScopedFocusNavigation ScopedFocusNavigation::createFor(const Element& current)
207 { 234 {
208 if (SlotScopedTraversal::isSlotScoped(current)) 235 if (HTMLSlotElement* slot = SlotScopedTraversal::findScopeOwnerSlot(current) )
209 return ScopedFocusNavigation(*SlotScopedTraversal::findScopeOwnerSlot(cu rrent), &current); 236 return ScopedFocusNavigation(*slot, &current);
237 if (HTMLSlotElement* slot = ScopedFocusNavigation::findFallbackScopeOwnerSlo t(current))
238 return ScopedFocusNavigation(*slot, &current);
210 return ScopedFocusNavigation(current.treeScope(), &current); 239 return ScopedFocusNavigation(current.treeScope(), &current);
211 } 240 }
212 241
213 ScopedFocusNavigation ScopedFocusNavigation::createForDocument(Document& documen t) 242 ScopedFocusNavigation ScopedFocusNavigation::createForDocument(Document& documen t)
214 { 243 {
215 return ScopedFocusNavigation(document, nullptr); 244 return ScopedFocusNavigation(document, nullptr);
216 } 245 }
217 246
218 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element) 247 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element)
219 { 248 {
(...skipping 23 matching lines...) Expand all
243 { 272 {
244 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint)); 273 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint));
245 return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullpt r); 274 return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullpt r);
246 } 275 }
247 276
248 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element) 277 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element)
249 { 278 {
250 return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr) ; 279 return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr) ;
251 } 280 }
252 281
282 HTMLSlotElement* ScopedFocusNavigation::findFallbackScopeOwnerSlot(const Element & element)
283 {
284 Element* parent = const_cast<Element*>(element.parentElement());
285 while (parent) {
286 if (isHTMLSlotElement(parent))
287 return toHTMLSlotElement(parent)->getAssignedNodes().isEmpty() ? toH TMLSlotElement(parent) : nullptr;
288 parent = parent->parentElement();
289 }
290 return nullptr;
291 }
292
293 bool ScopedFocusNavigation::isSlotFallbackScoped(const Element& element)
294 {
295 return ScopedFocusNavigation::findFallbackScopeOwnerSlot(element);
296 }
297
298 bool ScopedFocusNavigation::isSlotFallbackScopedForThisSlot(const HTMLSlotElemen t& slot, const Element& current)
299 {
300 Element* parent = current.parentElement();
301 while (parent) {
302 if (isHTMLSlotElement(parent) && toHTMLSlotElement(parent)->getAssignedN odes().isEmpty())
303 return !SlotScopedTraversal::isSlotScoped(current) && toHTMLSlotElem ent(parent) == slot;
304 parent = parent->parentElement();
305 }
306 return false;
307 }
308
253 inline void dispatchBlurEvent(const Document& document, Element& focusedElement) 309 inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
254 { 310 {
255 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage); 311 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage);
256 if (focusedElement == document.focusedElement()) { 312 if (focusedElement == document.focusedElement()) {
257 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr); 313 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr);
258 if (focusedElement == document.focusedElement()) 314 if (focusedElement == document.focusedElement())
259 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr); 315 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr);
260 } 316 }
261 } 317 }
262 318
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 current = document->sequentialFocusNavigationStartingPoint(type); 916 current = document->sequentialFocusNavigationStartingPoint(type);
861 917
862 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself 918 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself
863 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled(); 919 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled();
864 920
865 if (caretBrowsing && !current) 921 if (caretBrowsing && !current)
866 current = adjustToElement(frame->selection().start().anchorNode(), type) ; 922 current = adjustToElement(frame->selection().start().anchorNode(), type) ;
867 923
868 document->updateLayoutIgnorePendingStylesheets(); 924 document->updateLayoutIgnorePendingStylesheets();
869 ScopedFocusNavigation scope = current ? ScopedFocusNavigation::createFor(*cu rrent) : ScopedFocusNavigation::createForDocument(*document); 925 ScopedFocusNavigation scope = current ? ScopedFocusNavigation::createFor(*cu rrent) : ScopedFocusNavigation::createForDocument(*document);
870 RawPtr<Element> element = findFocusableElementAcrossFocusScopes(type, scope) ; 926 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, scope);
871
872 if (!element) { 927 if (!element) {
873 // If there's a RemoteFrame on the ancestor chain, we need to continue 928 // If there's a RemoteFrame on the ancestor chain, we need to continue
874 // searching for focusable elements there. 929 // searching for focusable elements there.
875 if (frame->localFrameRoot() != frame->tree().top()) { 930 if (frame->localFrameRoot() != frame->tree().top()) {
876 document->clearFocusedElement(); 931 document->clearFocusedElement();
877 document->setSequentialFocusNavigationStartingPoint(nullptr); 932 document->setSequentialFocusNavigationStartingPoint(nullptr);
878 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot()); 933 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot());
879 return true; 934 return true;
880 } 935 }
881 936
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 return consumed; 1309 return consumed;
1255 } 1310 }
1256 1311
1257 DEFINE_TRACE(FocusController) 1312 DEFINE_TRACE(FocusController)
1258 { 1313 {
1259 visitor->trace(m_page); 1314 visitor->trace(m_page);
1260 visitor->trace(m_focusedFrame); 1315 visitor->trace(m_focusedFrame);
1261 } 1316 }
1262 1317
1263 } // namespace blink 1318 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/shadow-dom/slot-fallback-focus.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698