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

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

Issue 1707443003: Consider slots as a focus scope (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring for loops Created 4 years, 9 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/Source/core/dom/shadow/SlotScopedTraversal.cpp ('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 10 matching lines...) Expand all
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "core/page/FocusController.h" 27 #include "core/page/FocusController.h"
28 28
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/dom/AXObjectCache.h" 30 #include "core/dom/AXObjectCache.h"
31 #include "core/dom/ContainerNode.h"
31 #include "core/dom/Document.h" 32 #include "core/dom/Document.h"
32 #include "core/dom/Element.h" 33 #include "core/dom/Element.h"
33 #include "core/dom/ElementTraversal.h" 34 #include "core/dom/ElementTraversal.h"
34 #include "core/dom/NodeTraversal.h"
35 #include "core/dom/Range.h" 35 #include "core/dom/Range.h"
36 #include "core/dom/shadow/ElementShadow.h" 36 #include "core/dom/shadow/ElementShadow.h"
37 #include "core/dom/shadow/ShadowRoot.h" 37 #include "core/dom/shadow/ShadowRoot.h"
38 #include "core/dom/shadow/SlotScopedTraversal.h"
38 #include "core/editing/EditingUtilities.h" // For firstPositionInOrBeforeNode 39 #include "core/editing/EditingUtilities.h" // For firstPositionInOrBeforeNode
39 #include "core/editing/Editor.h" 40 #include "core/editing/Editor.h"
40 #include "core/editing/FrameSelection.h" 41 #include "core/editing/FrameSelection.h"
41 #include "core/events/Event.h" 42 #include "core/events/Event.h"
42 #include "core/frame/FrameClient.h" 43 #include "core/frame/FrameClient.h"
43 #include "core/frame/FrameView.h" 44 #include "core/frame/FrameView.h"
44 #include "core/frame/LocalDOMWindow.h" 45 #include "core/frame/LocalDOMWindow.h"
45 #include "core/frame/LocalFrame.h" 46 #include "core/frame/LocalFrame.h"
46 #include "core/frame/RemoteFrame.h" 47 #include "core/frame/RemoteFrame.h"
47 #include "core/frame/Settings.h" 48 #include "core/frame/Settings.h"
48 #include "core/html/HTMLAreaElement.h" 49 #include "core/html/HTMLAreaElement.h"
49 #include "core/html/HTMLImageElement.h" 50 #include "core/html/HTMLImageElement.h"
50 #include "core/html/HTMLPlugInElement.h" 51 #include "core/html/HTMLPlugInElement.h"
51 #include "core/html/HTMLShadowElement.h" 52 #include "core/html/HTMLShadowElement.h"
53 #include "core/html/HTMLSlotElement.h"
52 #include "core/html/HTMLTextFormControlElement.h" 54 #include "core/html/HTMLTextFormControlElement.h"
53 #include "core/input/EventHandler.h" 55 #include "core/input/EventHandler.h"
54 #include "core/page/ChromeClient.h" 56 #include "core/page/ChromeClient.h"
55 #include "core/page/FrameTree.h" 57 #include "core/page/FrameTree.h"
56 #include "core/page/Page.h" 58 #include "core/page/Page.h"
57 #include "core/layout/HitTestResult.h" 59 #include "core/layout/HitTestResult.h"
58 #include "core/page/SpatialNavigation.h" 60 #include "core/page/SpatialNavigation.h"
59 #include <limits> 61 #include <limits>
60 62
61 namespace blink { 63 namespace blink {
62 64
63 using namespace HTMLNames; 65 using namespace HTMLNames;
64 66
65 namespace { 67 namespace {
66 68
67 inline bool isShadowInsertionPointFocusScopeOwner(Element& element) 69 inline bool isShadowInsertionPointFocusScopeOwner(Element& element)
68 { 70 {
69 return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element) .olderShadowRoot(); 71 return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element) .olderShadowRoot();
70 } 72 }
71 73
72 class FocusNavigationScope { 74 class ScopedFocusNavigation {
73 STACK_ALLOCATED(); 75 STACK_ALLOCATED();
74 public: 76 public:
75 Element* firstElement() const; 77 Element* currentElement() const;
76 Element* lastElement() const; 78 void setCurrentElement(Element*);
79 void moveToNext();
80 void moveToPrevious();
81 void moveToFirst();
82 void moveToLast();
77 Element* owner() const; 83 Element* owner() const;
78 static FocusNavigationScope focusNavigationScopeOf(const Element&); 84 static ScopedFocusNavigation createScopedFocusNavigation(const Element& root , const Element* current);
79 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&); 85 static ScopedFocusNavigation ownedByNonFocusableFocusScopeOwner(Element&);
80 static FocusNavigationScope ownedByShadowHost(const Element&); 86 static ScopedFocusNavigation ownedByShadowHost(const Element&);
81 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&); 87 static ScopedFocusNavigation ownedByShadowInsertionPoint(HTMLShadowElement&) ;
82 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&); 88 static ScopedFocusNavigation ownedByHTMLSlotElement(const HTMLSlotElement&);
89 static ScopedFocusNavigation ownedByIFrame(const HTMLFrameOwnerElement&);
83 90
84 private: 91 private:
85 explicit FocusNavigationScope(TreeScope*); 92 ScopedFocusNavigation(TreeScope&, const Element*);
86 ContainerNode& rootNode() const; 93 ScopedFocusNavigation(HTMLSlotElement&, const Element*);
87 RawPtrWillBeMember<TreeScope> m_rootTreeScope; 94 RawPtrWillBeMember<ContainerNode> m_rootNode;
95 RawPtrWillBeMember<HTMLSlotElement> m_rootSlot;
96 RawPtrWillBeMember<Element> m_current;
88 }; 97 };
89 98
90 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope) 99 ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element * current)
91 : m_rootTreeScope(treeScope) 100 : m_rootNode(treeScope.rootNode())
101 , m_current(const_cast<Element*>(current))
hayato 2016/03/07 04:09:48 It looks all member variables will be raw pointers
yuzuchan 2016/03/07 04:40:41 Done. Thanks, this seems to resolve oilpan bot fai
92 { 102 {
93 ASSERT(treeScope);
94 } 103 }
95 104
96 ContainerNode& FocusNavigationScope::rootNode() const 105 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Elemen t* current)
106 : m_rootSlot(&slot)
107 , m_current(const_cast<Element*>(current))
97 { 108 {
98 return m_rootTreeScope->rootNode();
99 } 109 }
100 110
101 Element* FocusNavigationScope::firstElement() const 111 Element* ScopedFocusNavigation::currentElement() const
102 { 112 {
103 ContainerNode& root = rootNode(); 113 return m_current;
104 return root.isElementNode() ? &toElement(root) : ElementTraversal::next(root );
105 } 114 }
106 115
107 Element* FocusNavigationScope::lastElement() const 116 void ScopedFocusNavigation::setCurrentElement(Element* element)
108 { 117 {
109 return ElementTraversal::lastWithin(rootNode()); 118 m_current = element;
110 } 119 }
111 120
112 Element* FocusNavigationScope::owner() const 121 void ScopedFocusNavigation::moveToNext()
113 { 122 {
114 ContainerNode& root = rootNode(); 123 ASSERT(m_current);
115 if (root.isShadowRoot()) { 124 if (m_rootSlot) {
116 ShadowRoot& shadowRoot = toShadowRoot(root); 125 m_current = SlotScopedTraversal::next(*m_current);
126 } else {
127 m_current = ElementTraversal::next(*m_current);
128 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
129 m_current = ElementTraversal::next(*m_current);
130 }
131 }
132
133 void ScopedFocusNavigation::moveToPrevious()
134 {
135 ASSERT(m_current);
136 if (m_rootSlot) {
137 m_current = SlotScopedTraversal::previous(*m_current);
138 } else {
139 m_current = ElementTraversal::previous(*m_current);
140 while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
141 m_current = ElementTraversal::previous(*m_current);
142 }
143 }
144
145 void ScopedFocusNavigation::moveToFirst()
146 {
147 if (m_rootSlot) {
148 if (!m_rootSlot->getAssignedNodes().isEmpty()) {
149 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
150 for (auto assignedNode : assignedNodes) {
151 if (assignedNode->isElementNode()) {
152 m_current = toElement(assignedNode);
153 break;
154 }
155 }
156 } else {
157 m_current = nullptr;
158 }
159 } else {
160 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode);
161 while (first && SlotScopedTraversal::isSlotScoped(*first))
162 first = ElementTraversal::next(*first, m_rootNode);
163 m_current = first;
164 }
165 }
166
167 void ScopedFocusNavigation::moveToLast()
168 {
169 if (m_rootSlot) {
170 if (!m_rootSlot->getAssignedNodes().isEmpty()) {
171 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlo t->getAssignedNodes();
172 for (auto assignedNode = assignedNodes.rbegin(); assignedNode != ass ignedNodes.rend(); ++assignedNode) {
173 if ((*assignedNode)->isElementNode()) {
174 Element* lastWithin = ElementTraversal::lastWithin(*toElemen t(*assignedNode));
175 if (lastWithin)
176 m_current = lastWithin;
177 else
178 m_current = toElement(*assignedNode);
179 break;
180 }
181 }
182 } else {
183 m_current = nullptr;
184 }
185 } else {
186 Element* last = ElementTraversal::lastWithin(*m_rootNode);
187 while (last && SlotScopedTraversal::isSlotScoped(*last))
188 last = ElementTraversal::previous(*last, m_rootNode);
189 m_current = last;
190 }
191 }
192
193 Element* ScopedFocusNavigation::owner() const
194 {
195 if (m_rootSlot)
196 return m_rootSlot;
197 if (m_rootNode->isShadowRoot()) {
198 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode);
117 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot(); 199 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot();
118 } 200 }
119 // FIXME: Figure out the right thing for OOPI here. 201 // FIXME: Figure out the right thing for OOPI here.
120 if (Frame* frame = root.document().frame()) 202 if (Frame* frame = m_rootNode->document().frame())
121 return frame->deprecatedLocalOwner(); 203 return frame->deprecatedLocalOwner();
122 return nullptr; 204 return nullptr;
123 } 205 }
124 206
125 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Element& element) 207 ScopedFocusNavigation ScopedFocusNavigation::createScopedFocusNavigation(const E lement& root, const Element* current)
126 { 208 {
127 return FocusNavigationScope(&element.treeScope()); 209 if (SlotScopedTraversal::isSlotScoped(root))
210 return ScopedFocusNavigation(*SlotScopedTraversal::findScopeOwnerSlot(ro ot), current);
211 return ScopedFocusNavigation(*&root.treeScope(), current);
128 } 212 }
129 213
130 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El ement& element) 214 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element)
131 { 215 {
132 if (isShadowHost(element)) 216 if (isShadowHost(element))
133 return FocusNavigationScope::ownedByShadowHost(element); 217 return ScopedFocusNavigation::ownedByShadowHost(element);
134 ASSERT(isShadowInsertionPointFocusScopeOwner(element)); 218 if (isShadowInsertionPointFocusScopeOwner(element))
135 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement (element)); 219 return ScopedFocusNavigation::ownedByShadowInsertionPoint(toHTMLShadowEl ement(element));
220 ASSERT(isHTMLSlotElement(element));
221 return ScopedFocusNavigation::ownedByHTMLSlotElement(toHTMLSlotElement(eleme nt));
136 } 222 }
137 223
138 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Element& elem ent) 224 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowHost(const Element& el ement)
139 { 225 {
140 ASSERT(isShadowHost(element)); 226 ASSERT(isShadowHost(element));
141 return FocusNavigationScope(&element.shadow()->youngestShadowRoot()); 227 return ScopedFocusNavigation(*&element.shadow()->youngestShadowRoot(), nullp tr);
142 } 228 }
143 229
144 FocusNavigationScope FocusNavigationScope::ownedByIFrame(const HTMLFrameOwnerEle ment& frame) 230 ScopedFocusNavigation ScopedFocusNavigation::ownedByIFrame(const HTMLFrameOwnerE lement& frame)
145 { 231 {
146 ASSERT(frame.contentFrame()); 232 ASSERT(frame.contentFrame());
147 ASSERT(frame.contentFrame()->isLocalFrame()); 233 ASSERT(frame.contentFrame()->isLocalFrame());
148 return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document()); 234 toLocalFrame(frame.contentFrame())->document()->updateDistribution();
235 return ScopedFocusNavigation(*toLocalFrame(frame.contentFrame())->document() , nullptr);
149 } 236 }
150 237
151 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado wElement& shadowInsertionPoint) 238 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowInsertionPoint(HTMLSha dowElement& shadowInsertionPoint)
152 { 239 {
153 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint)); 240 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint));
154 return FocusNavigationScope(shadowInsertionPoint.olderShadowRoot()); 241 return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullpt r);
242 }
243
244 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element)
245 {
246 return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr) ;
155 } 247 }
156 248
157 inline void dispatchBlurEvent(const Document& document, Element& focusedElement) 249 inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
158 { 250 {
159 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage); 251 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage);
160 if (focusedElement == document.focusedElement()) { 252 if (focusedElement == document.focusedElement()) {
161 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr); 253 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr);
162 if (focusedElement == document.focusedElement()) 254 if (focusedElement == document.focusedElement())
163 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr); 255 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr);
164 } 256 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable(); 319 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable();
228 } 320 }
229 321
230 inline bool isKeyboardFocusableShadowHost(const Element& element) 322 inline bool isKeyboardFocusableShadowHost(const Element& element)
231 { 323 {
232 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable(); 324 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable();
233 } 325 }
234 326
235 inline bool isNonFocusableFocusScopeOwner(Element& element) 327 inline bool isNonFocusableFocusScopeOwner(Element& element)
236 { 328 {
237 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element); 329 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element) || isHTMLSlotElement(element);
238 } 330 }
239 331
240 inline bool isShadowHostDelegatesFocus(const Element& element) 332 inline bool isShadowHostDelegatesFocus(const Element& element)
241 { 333 {
242 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus(); 334 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus();
243 } 335 }
244 336
245 inline int adjustedTabIndex(Element& element) 337 inline int adjustedTabIndex(Element& element)
246 { 338 {
247 return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex(); 339 return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex();
248 } 340 }
249 341
250 inline bool shouldVisit(Element& element) 342 inline bool shouldVisit(Element& element)
251 { 343 {
252 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t); 344 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t);
253 } 345 }
254 346
255 Element* findElementWithExactTabIndex(Element* start, int tabIndex, WebFocusType type) 347 Element* findElementWithExactTabIndex(ScopedFocusNavigation& scope, int tabIndex , WebFocusType type)
256 { 348 {
257 // Search is inclusive of start 349 // Search is inclusive of start
258 for (Element* element = start; element; element = type == WebFocusTypeForwar d ? ElementTraversal::next(*element) : ElementTraversal::previous(*element)) { 350 for (; scope.currentElement(); type == WebFocusTypeForward ? scope.moveToNex t() : scope.moveToPrevious()) {
259 if (shouldVisit(*element) && adjustedTabIndex(*element) == tabIndex) 351 Element* current = scope.currentElement();
260 return element; 352 if (shouldVisit(*current) && adjustedTabIndex(*current) == tabIndex)
353 return current;
261 } 354 }
262 return nullptr; 355 return nullptr;
263 } 356 }
264 357
265 Element* nextElementWithGreaterTabIndex(Element* start, int tabIndex) 358 Element* nextElementWithGreaterTabIndex(ScopedFocusNavigation& scope, int tabInd ex)
266 { 359 {
267 // Search is inclusive of start 360 // Search is inclusive of start
268 int winningTabIndex = std::numeric_limits<short>::max() + 1; 361 int winningTabIndex = std::numeric_limits<short>::max() + 1;
269 Element* winner = nullptr; 362 Element* winner = nullptr;
270 for (Element& element : ElementTraversal::startsAt(start)) { 363 for (; scope.currentElement(); scope.moveToNext()) {
271 int currentTabIndex = adjustedTabIndex(element); 364 Element* current = scope.currentElement();
272 if (shouldVisit(element) && currentTabIndex > tabIndex && currentTabInde x < winningTabIndex) { 365 int currentTabIndex = adjustedTabIndex(*current);
273 winner = &element; 366 if (shouldVisit(*current) && currentTabIndex > tabIndex && currentTabInd ex < winningTabIndex) {
367 winner = current;
274 winningTabIndex = currentTabIndex; 368 winningTabIndex = currentTabIndex;
275 } 369 }
276 } 370 }
277 return winner; 371 return winner;
278 } 372 }
279 373
280 Element* previousElementWithLowerTabIndex(Element* start, int tabIndex) 374 Element* previousElementWithLowerTabIndex(ScopedFocusNavigation& scope, int tabI ndex)
281 { 375 {
282 // Search is inclusive of start 376 // Search is inclusive of start
283 int winningTabIndex = 0; 377 int winningTabIndex = 0;
284 Element* winner = nullptr; 378 Element* winner = nullptr;
285 for (Element* element = start; element; element = ElementTraversal::previous (*element)) { 379 for (; scope.currentElement(); scope.moveToPrevious()) {
286 int currentTabIndex = adjustedTabIndex(*element); 380 Element* current = scope.currentElement();
287 if (shouldVisit(*element) && currentTabIndex < tabIndex && currentTabInd ex > winningTabIndex) { 381 int currentTabIndex = adjustedTabIndex(*current);
288 winner = element; 382 if (shouldVisit(*current) && currentTabIndex < tabIndex && currentTabInd ex > winningTabIndex) {
383 winner = current;
289 winningTabIndex = currentTabIndex; 384 winningTabIndex = currentTabIndex;
290 } 385 }
291 } 386 }
292 return winner; 387 return winner;
293 } 388 }
294 389
295 Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start) 390 Element* nextFocusableElement(ScopedFocusNavigation& scope)
296 { 391 {
297 if (start) { 392 Element* current = scope.currentElement();
298 int tabIndex = adjustedTabIndex(*start); 393 if (current) {
394 int tabIndex = adjustedTabIndex(*current);
299 // If an element is excluded from the normal tabbing cycle, the next foc usable element is determined by tree order 395 // If an element is excluded from the normal tabbing cycle, the next foc usable element is determined by tree order
300 if (tabIndex < 0) { 396 if (tabIndex < 0) {
301 for (Element& element : ElementTraversal::startsAfter(*start)) { 397 for (scope.moveToNext(); scope.currentElement(); scope.moveToNext()) {
302 if (shouldVisit(element) && adjustedTabIndex(element) >= 0) 398 current = scope.currentElement();
303 return &element; 399 if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
400 return current;
304 } 401 }
305 } else { 402 } else {
306 // First try to find an element with the same tabindex as start that comes after start in the scope. 403 // First try to find an element with the same tabindex as start that comes after start in the scope.
307 if (Element* winner = findElementWithExactTabIndex(ElementTraversal: :next(*start), tabIndex, WebFocusTypeForward)) 404 scope.moveToNext();
405 if (Element* winner = findElementWithExactTabIndex(scope, tabIndex, WebFocusTypeForward))
308 return winner; 406 return winner;
309 } 407 }
310 if (!tabIndex) { 408 if (!tabIndex) {
311 // We've reached the last element in the document with a tabindex of 0. This is the end of the tabbing order. 409 // We've reached the last element in the document with a tabindex of 0. This is the end of the tabbing order.
312 return nullptr; 410 return nullptr;
313 } 411 }
314 } 412 }
315 413
316 // Look for the first element in the scope that: 414 // Look for the first element in the scope that:
317 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and 415 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
318 // 2) comes first in the scope, if there's a tie. 416 // 2) comes first in the scope, if there's a tie.
319 if (Element* winner = nextElementWithGreaterTabIndex(scope.firstElement(), s tart ? adjustedTabIndex(*start) : 0)) 417 scope.moveToFirst();
418 if (Element* winner = nextElementWithGreaterTabIndex(scope, current ? adjust edTabIndex(*current) : 0)) {
320 return winner; 419 return winner;
420 }
321 421
322 // There are no elements with a tabindex greater than start's tabindex, 422 // There are no elements with a tabindex greater than start's tabindex,
323 // so find the first element with a tabindex of 0. 423 // so find the first element with a tabindex of 0.
324 return findElementWithExactTabIndex(scope.firstElement(), 0, WebFocusTypeFor ward); 424 scope.moveToFirst();
425 return findElementWithExactTabIndex(scope, 0, WebFocusTypeForward);
325 } 426 }
326 427
327 Element* previousFocusableElement(const FocusNavigationScope& scope, Element* st art) 428 Element* previousFocusableElement(ScopedFocusNavigation& scope)
328 { 429 {
329 Element* lastElement = scope.lastElement();
330
331 // First try to find the last element in the scope that comes before start a nd has the same tabindex as start. 430 // First try to find the last element in the scope that comes before start a nd has the same tabindex as start.
332 // If start is null, find the last element in the scope with a tabindex of 0 . 431 // If start is null, find the last element in the scope with a tabindex of 0 .
333 Element* startElement; 432 int tabIndex;
334 int startTabIndex; 433 Element* current = scope.currentElement();
335 if (start) { 434 if (current) {
336 startElement = ElementTraversal::previous(*start); 435 scope.moveToPrevious();
337 startTabIndex = adjustedTabIndex(*start); 436 tabIndex = adjustedTabIndex(*current);
338 } else { 437 } else {
339 startElement = lastElement; 438 scope.moveToLast();
340 startTabIndex = 0; 439 tabIndex = 0;
341 } 440 }
342 441
343 // However, if an element is excluded from the normal tabbing cycle, the pre vious focusable element is determined by tree order 442 // However, if an element is excluded from the normal tabbing cycle, the pre vious focusable element is determined by tree order
344 if (startTabIndex < 0) { 443 if (tabIndex < 0) {
345 for (Element* element = startElement; element; element = ElementTraversa l::previous(*element)) { 444 for (; scope.currentElement(); scope.moveToPrevious()) {
346 if (shouldVisit(*element) && adjustedTabIndex(*element) >= 0) 445 current = scope.currentElement();
347 return element; 446 if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
447 return current;
348 } 448 }
349 } else { 449 } else {
350 if (Element* winner = findElementWithExactTabIndex(startElement, startTa bIndex, WebFocusTypeBackward)) 450 if (Element* winner = findElementWithExactTabIndex(scope, tabIndex, WebF ocusTypeBackward))
351 return winner; 451 return winner;
352 } 452 }
353 453
354 // There are no elements before start with the same tabindex as start, so lo ok for an element that: 454 // There are no elements before start with the same tabindex as start, so lo ok for an element that:
355 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and 455 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and
356 // 2) comes last in the scope, if there's a tie. 456 // 2) comes last in the scope, if there's a tie.
357 startTabIndex = (start && startTabIndex) ? startTabIndex : std::numeric_limi ts<short>::max(); 457 tabIndex = (current && tabIndex) ? tabIndex : std::numeric_limits<short>::ma x();
358 return previousElementWithLowerTabIndex(lastElement, startTabIndex); 458 scope.moveToLast();
459 return previousElementWithLowerTabIndex(scope, tabIndex);
359 } 460 }
360 461
361 // Searches through the given tree scope, starting from start element, for the n ext/previous 462 // Searches through the given tree scope, starting from start element, for the n ext/previous
362 // selectable element that comes after/before start element. 463 // selectable element that comes after/before start element.
363 // The order followed is as specified in the HTML spec[1], which is elements wit h tab indexes 464 // The order followed is as specified in the HTML spec[1], which is elements wit h tab indexes
364 // first (from lowest to highest), and then elements without tab indexes (in doc ument order). 465 // first (from lowest to highest), and then elements without tab indexes (in doc ument order).
365 // The search algorithm also conforms the Shadow DOM spec[2], which inserts sequ ence in a shadow 466 // The search algorithm also conforms the Shadow DOM spec[2], which inserts sequ ence in a shadow
366 // tree into its host. 467 // tree into its host.
367 // 468 //
368 // @param start The element from which to start searching. The element after thi s will be focused. 469 // @param start The element from which to start searching. The element after thi s will be focused.
369 // May be null. 470 // May be null.
370 // @return The focus element that comes after/before start element. 471 // @return The focus element that comes after/before start element.
371 // 472 //
372 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation 473 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation
373 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation 474 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
374 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Element* element) 475 inline Element* findFocusableElementInternal(WebFocusType type, ScopedFocusNavig ation& scope)
375 { 476 {
376 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, element) : previousFocusableElement(scope, element); 477 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope) : previousFocusableElement(scope);
377 return found; 478 return found;
378 } 479 }
379 480
380 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Element* start) 481 Element* findFocusableElementRecursivelyForward(ScopedFocusNavigation& scope)
381 { 482 {
382 // Starting element is exclusive. 483 // Starting element is exclusive.
383 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art); 484 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope);
384 while (found) { 485 while (found) {
385 if (isShadowHostDelegatesFocus(*found)) { 486 if (isShadowHostDelegatesFocus(*found)) {
386 // If tabindex is positive, find focusable element inside its shadow tree. 487 // If tabindex is positive, find focusable element inside its shadow tree.
387 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) { 488 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) {
388 FocusNavigationScope innerScope = FocusNavigationScope::ownedByS hadowHost(*found); 489 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedB yShadowHost(*found);
389 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope, nullptr)) 490 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope))
390 return foundInInnerFocusScope; 491 return foundInInnerFocusScope;
391 } 492 }
392 // Skip to the next element in the same scope. 493 // Skip to the next element in the same scope.
393 found = findFocusableElementInternal(WebFocusTypeForward, scope, fou nd); 494 found = findFocusableElementInternal(WebFocusTypeForward, scope);
394 continue; 495 continue;
395 } 496 }
396 if (!isNonFocusableFocusScopeOwner(*found)) 497 if (!isNonFocusableFocusScopeOwner(*found))
397 return found; 498 return found;
398 499
399 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>) 500 // Now |found| is on a non focusable scope owner (either shadow host or <shadow> or slot)
400 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same 501 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same
401 // scope. 502 // scope.
402 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found); 503 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNonFocu sableFocusScopeOwner(*found);
403 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope, nullptr)) 504 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope))
404 return foundInInnerFocusScope; 505 return foundInInnerFocusScope;
405 506
406 found = findFocusableElementInternal(WebFocusTypeForward, scope, found); 507 scope.setCurrentElement(found);
508 found = findFocusableElementInternal(WebFocusTypeForward, scope);
407 } 509 }
408 return nullptr; 510 return nullptr;
409 } 511 }
410 512
411 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Element* start) 513 Element* findFocusableElementRecursivelyBackward(ScopedFocusNavigation& scope)
412 { 514 {
413 // Starting element is exclusive. 515 // Starting element is exclusive.
414 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart); 516 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope);
517
415 while (found) { 518 while (found) {
416 // Now |found| is on a focusable shadow host. 519 // Now |found| is on a focusable shadow host.
417 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return 520 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return
418 // the host itself. 521 // the host itself.
419 if (isKeyboardFocusableShadowHost(*found)) { 522 if (isKeyboardFocusableShadowHost(*found)) {
420 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found); 523 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedBySha dowHost(*found);
421 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 524 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope);
422 if (foundInInnerFocusScope) 525 if (foundInInnerFocusScope)
423 return foundInInnerFocusScope; 526 return foundInInnerFocusScope;
424 if (isShadowHostDelegatesFocus(*found)) { 527 if (isShadowHostDelegatesFocus(*found)) {
425 found = findFocusableElementInternal(WebFocusTypeBackward, scope , found); 528 found = findFocusableElementInternal(WebFocusTypeBackward, scope );
426 continue; 529 continue;
427 } 530 }
428 return found; 531 return found;
429 } 532 }
430 533
431 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the 534 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the
432 // shadow host. 535 // shadow host.
433 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) { 536 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) {
434 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 537 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
435 continue; 538 continue;
436 } 539 }
437 540
438 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>). 541 // Now |found| is on a non focusable scope owner (either shadow host or <shadow> or slot).
439 // Find focusable element in descendant scope. If not found, find next f ocusable element within the 542 // Find focusable element in descendant scope. If not found, find next f ocusable element within the
440 // current scope. 543 // current scope.
441 if (isNonFocusableFocusScopeOwner(*found)) { 544 if (isNonFocusableFocusScopeOwner(*found)) {
442 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFo cusableFocusScopeOwner(*found); 545 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNon FocusableFocusScopeOwner(*found);
443 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 546 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope);
547
548
444 if (foundInInnerFocusScope) 549 if (foundInInnerFocusScope)
445 return foundInInnerFocusScope; 550 return foundInInnerFocusScope;
446 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 551 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
447 continue; 552 continue;
448 } 553 }
449 if (!isShadowHostDelegatesFocus(*found)) 554 if (!isShadowHostDelegatesFocus(*found))
450 return found; 555 return found;
451 found = findFocusableElementInternal(WebFocusTypeBackward, scope, found) ; 556
557 scope.setCurrentElement(found);
558 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
452 } 559 }
453 return nullptr; 560 return nullptr;
454 } 561 }
455 562
456 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Element* start) 563 Element* findFocusableElementRecursively(WebFocusType type, ScopedFocusNavigatio n& scope)
457 { 564 {
458 return (type == WebFocusTypeForward) ? 565 return (type == WebFocusTypeForward) ?
459 findFocusableElementRecursivelyForward(scope, start) : 566 findFocusableElementRecursivelyForward(scope) :
460 findFocusableElementRecursivelyBackward(scope, start); 567 findFocusableElementRecursivelyBackward(scope);
461 } 568 }
462 569
463 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element) 570 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element)
464 { 571 {
465 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either: 572 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either:
466 // 1) a focusable element, or 573 // 1) a focusable element, or
467 // 2) the deepest-nested HTMLFrameOwnerElement. 574 // 2) the deepest-nested HTMLFrameOwnerElement.
468 while (element && element->isFrameOwnerElement()) { 575 while (element && element->isFrameOwnerElement()) {
469 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); 576 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element);
470 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) 577 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame())
471 break; 578 break;
472 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets(); 579 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets();
473 Element* foundElement = findFocusableElementRecursively(type, FocusNavig ationScope::ownedByIFrame(owner), nullptr); 580 ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByIFrame(owner );
581 Element* foundElement = findFocusableElementRecursively(type, scope);
474 if (!foundElement) 582 if (!foundElement)
475 break; 583 break;
476 ASSERT(element != foundElement); 584 ASSERT(element != foundElement);
477 element = foundElement; 585 element = foundElement;
478 } 586 }
479 return element; 587 return element;
480 } 588 }
481 589
482 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Element* current) 590 Element* findFocusableElementAcrossFocusScopesForward(ScopedFocusNavigation& sco pe)
483 { 591 {
592 Element* current = scope.currentElement();
484 ASSERT(!current || !isNonFocusableShadowHost(*current)); 593 ASSERT(!current || !isNonFocusableShadowHost(*current));
485 Element* found; 594 Element* found;
486 if (current && isShadowHostWithoutCustomFocusLogic(*current)) { 595 if (current && isShadowHostWithoutCustomFocusLogic(*current)) {
487 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*current); 596 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowH ost(*current);
488 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr); 597 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope);
489 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, current); 598 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope);
490 } else { 599 } else {
491 found = findFocusableElementRecursivelyForward(scope, current); 600 found = findFocusableElementRecursivelyForward(scope);
492 } 601 }
493 602
494 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one. 603 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
495 FocusNavigationScope currentScope = scope; 604 ScopedFocusNavigation currentScope = scope;
496 while (!found) { 605 while (!found) {
497 Element* owner = currentScope.owner(); 606 Element* owner = currentScope.owner();
498 if (!owner) 607 if (!owner)
499 break; 608 break;
500 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 609 currentScope = ScopedFocusNavigation::createScopedFocusNavigation(*owner , owner);
501 found = findFocusableElementRecursivelyForward(currentScope, owner); 610 found = findFocusableElementRecursivelyForward(currentScope);
502 } 611 }
503 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found); 612 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found);
504 } 613 }
505 614
506 Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScop e& scope, Element* current) 615 Element* findFocusableElementAcrossFocusScopesBackward(ScopedFocusNavigation& sc ope)
507 { 616 {
508 ASSERT(!current || !isNonFocusableShadowHost(*current)); 617 ASSERT(!scope.currentElement() || !isNonFocusableShadowHost(*scope.currentEl ement()));
509 Element* found = findFocusableElementRecursivelyBackward(scope, current); 618 Element* found = findFocusableElementRecursivelyBackward(scope);
510 619
511 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one. 620 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
512 FocusNavigationScope currentScope = scope; 621 ScopedFocusNavigation currentScope = scope;
513 while (!found) { 622 while (!found) {
514 Element* owner = currentScope.owner(); 623 Element* owner = currentScope.owner();
515 if (!owner) 624 if (!owner)
516 break; 625 break;
517 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 626 currentScope = ScopedFocusNavigation::createScopedFocusNavigation(*owner , owner);
518 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) { 627 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) {
519 found = owner; 628 found = owner;
520 break; 629 break;
521 } 630 }
522 found = findFocusableElementRecursivelyBackward(currentScope, owner); 631 found = findFocusableElementRecursivelyBackward(currentScope);
523 } 632 }
524 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found); 633 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found);
525 } 634 }
526 635
527 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNav igationScope& scope, Element* current) 636 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, ScopedFocusNav igation& scope)
528 { 637 {
529 return (type == WebFocusTypeForward) ? 638 return (type == WebFocusTypeForward) ?
530 findFocusableElementAcrossFocusScopesForward(scope, current) : 639 findFocusableElementAcrossFocusScopesForward(scope) :
531 findFocusableElementAcrossFocusScopesBackward(scope, current); 640 findFocusableElementAcrossFocusScopesBackward(scope);
532 } 641 }
533 642
534 inline Element* adjustToElement(Node* node, WebFocusType type) 643 inline Element* adjustToElement(Node* node, WebFocusType type)
535 { 644 {
536 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); 645 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
537 if (!node) 646 if (!node)
538 return nullptr; 647 return nullptr;
539 if (node->isElementNode()) 648 if (node->isElementNode())
540 return toElement(node); 649 return toElement(node);
541 // The returned element is used as an *exclusive* start element. Thus, we sh ould return the result of ElementTraversal::previous(*node), 650 // The returned element is used as an *exclusive* start element. Thus, we sh ould return the result of ElementTraversal::previous(*node),
542 // instead of ElementTraversal::next(*node), if type == WebFocusTypeForward, and vice-versa. 651 // instead of ElementTraversal::next(*node), if type == WebFocusTypeForward, and vice-versa.
543 // The caller will call ElementTraversal::{next/previous} for the returned v alue and get the {next|previous} element of the |node|. 652 // The caller will call ElementTraversal::{next/previous} for the returned v alue and get the {next|previous} element of the |node|.
653
654 // TODO(yuzus) Use ScopedFocusNavigation traversal here.
544 return (type == WebFocusTypeForward) ? ElementTraversal::previous(*node) : E lementTraversal::next(*node); 655 return (type == WebFocusTypeForward) ? ElementTraversal::previous(*node) : E lementTraversal::next(*node);
545 } 656 }
546 657
547 } // anonymous namespace 658 } // anonymous namespace
548 659
549 FocusController::FocusController(Page* page) 660 FocusController::FocusController(Page* page)
550 : m_page(page) 661 : m_page(page)
551 , m_isActive(false) 662 , m_isActive(false)
552 , m_isFocused(false) 663 , m_isFocused(false)
553 , m_isChangingFocusedFrame(false) 664 , m_isChangingFocusedFrame(false)
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 } 847 }
737 848
738 return advanceFocusInDocumentOrder(to, start, type, false, sourceCapabilitie s); 849 return advanceFocusInDocumentOrder(to, start, type, false, sourceCapabilitie s);
739 } 850 }
740 851
741 bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st art, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabi lities) 852 bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st art, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabi lities)
742 { 853 {
743 ASSERT(frame); 854 ASSERT(frame);
744 Document* document = frame->document(); 855 Document* document = frame->document();
745 ASSERT(document->documentElement()); 856 ASSERT(document->documentElement());
857 document->updateDistribution();
746 858
747 Element* current = start; 859 Element* current = start;
748 if (!current && !initialFocus) 860 if (!current && !initialFocus)
749 current = document->sequentialFocusNavigationStartingPoint(type); 861 current = document->sequentialFocusNavigationStartingPoint(type);
750 862
751 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself 863 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself
752 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled(); 864 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled();
753 865
754 if (caretBrowsing && !current) 866 if (caretBrowsing && !current)
755 current = adjustToElement(frame->selection().start().anchorNode(), type) ; 867 current = adjustToElement(frame->selection().start().anchorNode(), type) ;
756 868
757 document->updateLayoutIgnorePendingStylesheets(); 869 document->updateLayoutIgnorePendingStylesheets();
758 870 ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNaviga tion(current ? *current : *document->documentElement(), current);
759 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, FocusNavigationScope::focusNavigationScopeOf(current ? *current : *documen t->documentElement()), current); 871 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, scope);
760 872
761 if (!element) { 873 if (!element) {
762 // If there's a RemoteFrame on the ancestor chain, we need to continue 874 // If there's a RemoteFrame on the ancestor chain, we need to continue
763 // searching for focusable elements there. 875 // searching for focusable elements there.
764 if (frame->localFrameRoot() != frame->tree().top()) { 876 if (frame->localFrameRoot() != frame->tree().top()) {
765 document->clearFocusedElement(); 877 document->clearFocusedElement();
766 document->setSequentialFocusNavigationStartingPoint(nullptr); 878 document->setSequentialFocusNavigationStartingPoint(nullptr);
767 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot()); 879 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot());
768 return true; 880 return true;
769 } 881 }
770 882
771 // We didn't find an element to focus, so we should try to pass focus to Chrome. 883 // We didn't find an element to focus, so we should try to pass focus to Chrome.
772 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { 884 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) {
773 document->clearFocusedElement(); 885 document->clearFocusedElement();
774 document->setSequentialFocusNavigationStartingPoint(nullptr); 886 document->setSequentialFocusNavigationStartingPoint(nullptr);
775 setFocusedFrame(nullptr); 887 setFocusedFrame(nullptr);
776 m_page->chromeClient().takeFocus(type); 888 m_page->chromeClient().takeFocus(type);
777 return true; 889 return true;
778 } 890 }
779 891
780 // Chrome doesn't want focus, so we should wrap focus. 892 // Chrome doesn't want focus, so we should wrap focus.
781 element = findFocusableElementRecursively(type, FocusNavigationScope::fo cusNavigationScopeOf(*toLocalFrame(m_page->mainFrame())->document()->documentEle ment()), nullptr); 893 ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNa vigation(*toLocalFrame(m_page->mainFrame())->document()->documentElement(), null ptr);
894 element = findFocusableElementRecursively(type, scope);
782 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get()); 895 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get());
783 896
784 if (!element) 897 if (!element)
785 return false; 898 return false;
786 } 899 }
787 900
788 ASSERT(element); 901 ASSERT(element);
789 902
790 if (element == document->focusedElement()) { 903 if (element == document->focusedElement()) {
791 // Focus wrapped around to the same element. 904 // Focus wrapped around to the same element.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 } 944 }
832 945
833 element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, sourceCapa bilities)); 946 element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, sourceCapa bilities));
834 return true; 947 return true;
835 } 948 }
836 949
837 Element* FocusController::findFocusableElement(WebFocusType type, Element& eleme nt) 950 Element* FocusController::findFocusableElement(WebFocusType type, Element& eleme nt)
838 { 951 {
839 // FIXME: No spacial navigation code yet. 952 // FIXME: No spacial navigation code yet.
840 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); 953 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
841 return findFocusableElementAcrossFocusScopes(type, FocusNavigationScope::foc usNavigationScopeOf(element), &element); 954 ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNaviga tion(element, &element);
955 return findFocusableElementAcrossFocusScopes(type, scope);
842 } 956 }
843 957
844 Element* FocusController::findFocusableElementInShadowHost(const Element& shadow Host) 958 Element* FocusController::findFocusableElementInShadowHost(const Element& shadow Host)
845 { 959 {
846 ASSERT(shadowHost.authorShadowRoot()); 960 ASSERT(shadowHost.authorShadowRoot());
847 return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, FocusNavig ationScope::ownedByShadowHost(shadowHost), nullptr); 961 ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByShadowHost(shado wHost);
962 return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, scope);
848 } 963 }
849 964
850 static bool relinquishesEditingFocus(const Element& element) 965 static bool relinquishesEditingFocus(const Element& element)
851 { 966 {
852 ASSERT(element.hasEditableStyle()); 967 ASSERT(element.hasEditableStyle());
853 return element.document().frame() && element.rootEditableElement(); 968 return element.document().frame() && element.rootEditableElement();
854 } 969 }
855 970
856 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF ocusedFrame, Element* newFocusedElement) 971 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF ocusedFrame, Element* newFocusedElement)
857 { 972 {
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 return consumed; 1255 return consumed;
1141 } 1256 }
1142 1257
1143 DEFINE_TRACE(FocusController) 1258 DEFINE_TRACE(FocusController)
1144 { 1259 {
1145 visitor->trace(m_page); 1260 visitor->trace(m_page);
1146 visitor->trace(m_focusedFrame); 1261 visitor->trace(m_focusedFrame);
1147 } 1262 }
1148 1263
1149 } // namespace blink 1264 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698