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

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 in response to review comments 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
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/AssignedElementTraversal.h"
36 #include "core/dom/shadow/ElementShadow.h" 37 #include "core/dom/shadow/ElementShadow.h"
37 #include "core/dom/shadow/ShadowRoot.h" 38 #include "core/dom/shadow/ShadowRoot.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 focusNavigationScopeOf(const Element& root, con st 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 explicit ScopedFocusNavigation(TreeScope*, const Element*);
86 ContainerNode& rootNode() const; 93 explicit 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))
92 { 102 {
93 ASSERT(treeScope); 103 ASSERT(treeScope);
94 } 104 }
95 105
96 ContainerNode& FocusNavigationScope::rootNode() const 106 ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement* slot, const Elemen t* current)
107 : m_rootSlot(slot)
108 , m_current(const_cast<Element*>(current))
97 { 109 {
98 return m_rootTreeScope->rootNode(); 110 ASSERT(slot);
99 } 111 }
100 112
101 Element* FocusNavigationScope::firstElement() const 113 Element* ScopedFocusNavigation::currentElement() const
102 { 114 {
103 ContainerNode& root = rootNode(); 115 return m_current;
104 return root.isElementNode() ? &toElement(root) : ElementTraversal::next(root );
105 } 116 }
106 117
107 Element* FocusNavigationScope::lastElement() const 118 void ScopedFocusNavigation::setCurrentElement(Element* element)
108 { 119 {
109 return ElementTraversal::lastWithin(rootNode()); 120 m_current = element;
121 }
kochi 2016/03/02 13:26:56 Insert newline here, between 2 functions.
yuzuchan 2016/03/03 04:12:43 Done.
122 void ScopedFocusNavigation::moveToNext()
123 {
124 if (m_current) {
kochi 2016/03/02 13:26:56 I think the previous structure look better. i.e.
yuzuchan 2016/03/03 04:12:43 Done.
125 if (m_rootSlot) {
126 m_current = AssignedElementTraversal::next(*m_current);
127 } else {
128 m_current = ElementTraversal::next(*m_current);
129 while (m_current && AssignedElementTraversal::isInAssignedScope(*m_c urrent))
130 m_current = ElementTraversal::next(*m_current);
131 }
132 }
110 } 133 }
111 134
112 Element* FocusNavigationScope::owner() const 135 void ScopedFocusNavigation::moveToPrevious()
113 { 136 {
114 ContainerNode& root = rootNode(); 137 if (m_current) {
kochi 2016/03/02 13:26:56 Same as previous function, please make this like
yuzuchan 2016/03/03 04:12:43 Done.
115 if (root.isShadowRoot()) { 138 if (m_rootSlot) {
116 ShadowRoot& shadowRoot = toShadowRoot(root); 139 m_current = AssignedElementTraversal::previous(*m_current);
140 } else {
141 m_current = ElementTraversal::previous(*m_current);
142 while (m_current && AssignedElementTraversal::isInAssignedScope(*m_c urrent))
143 m_current = ElementTraversal::previous(*m_current);
144 }
145 }
146 }
147
148 void ScopedFocusNavigation::moveToFirst()
149 {
150 if (m_rootSlot) {
151 if (!m_rootSlot->getAssignedNodes().isEmpty()) {
152 m_current = toElement(m_rootSlot->getAssignedNodes().first().get());
153 } else {
154 m_current = nullptr;
155 }
156 } else {
157 Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode);
158 while (first && AssignedElementTraversal::isInAssignedScope(*first))
159 first = ElementTraversal::next(*first, m_rootNode);
160 m_current = first;
161 }
162 }
163
164 void ScopedFocusNavigation::moveToLast()
165 {
166 if (m_rootSlot) {
167 if (!m_rootSlot->getAssignedNodes().isEmpty()) {
168 m_current = toElement(m_rootSlot->getAssignedNodes().last().get());
169 } else {
170 m_current = nullptr;
171 }
172 } else {
173 Element* last = ElementTraversal::lastWithin(*m_rootNode);
174 while (last && AssignedElementTraversal::isInAssignedScope(*last))
175 last = ElementTraversal::previous(*last, m_rootNode);
176 m_current = last;
177 }
178 }
179
180 Element* ScopedFocusNavigation::owner() const
181 {
182 if (m_rootSlot)
183 return m_rootSlot;
184 if (m_rootNode->isShadowRoot()) {
185 ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode);
117 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot(); 186 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot();
118 } 187 }
119 // FIXME: Figure out the right thing for OOPI here. 188 // FIXME: Figure out the right thing for OOPI here.
120 if (Frame* frame = root.document().frame()) 189 if (Frame* frame = m_rootNode->document().frame())
121 return frame->deprecatedLocalOwner(); 190 return frame->deprecatedLocalOwner();
122 return nullptr; 191 return nullptr;
123 } 192 }
124 193
125 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Element& element) 194 ScopedFocusNavigation ScopedFocusNavigation::focusNavigationScopeOf(const Elemen t& root, const Element* current)
126 { 195 {
127 return FocusNavigationScope(&element.treeScope()); 196 if (AssignedElementTraversal::isInAssignedScope(root))
197 return ScopedFocusNavigation(AssignedElementTraversal::slot(root), curre nt);
198 return ScopedFocusNavigation(&root.treeScope(), current);
128 } 199 }
129 200
130 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El ement& element) 201 ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner( Element& element)
131 { 202 {
132 if (isShadowHost(element)) 203 if (isShadowHost(element))
133 return FocusNavigationScope::ownedByShadowHost(element); 204 return ScopedFocusNavigation::ownedByShadowHost(element);
134 ASSERT(isShadowInsertionPointFocusScopeOwner(element)); 205 if (isShadowInsertionPointFocusScopeOwner(element))
135 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement (element)); 206 return ScopedFocusNavigation::ownedByShadowInsertionPoint(toHTMLShadowEl ement(element));
207 ASSERT(isHTMLSlotElement(element));
208 return ScopedFocusNavigation::ownedByHTMLSlotElement(toHTMLSlotElement(eleme nt));
136 } 209 }
137 210
138 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Element& elem ent) 211 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowHost(const Element& el ement)
139 { 212 {
140 ASSERT(isShadowHost(element)); 213 ASSERT(isShadowHost(element));
141 return FocusNavigationScope(&element.shadow()->youngestShadowRoot()); 214 return ScopedFocusNavigation(&element.shadow()->youngestShadowRoot(), nullpt r);
142 } 215 }
143 216
144 FocusNavigationScope FocusNavigationScope::ownedByIFrame(const HTMLFrameOwnerEle ment& frame) 217 ScopedFocusNavigation ScopedFocusNavigation::ownedByIFrame(const HTMLFrameOwnerE lement& frame)
145 { 218 {
146 ASSERT(frame.contentFrame()); 219 ASSERT(frame.contentFrame());
147 ASSERT(frame.contentFrame()->isLocalFrame()); 220 ASSERT(frame.contentFrame()->isLocalFrame());
148 return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document()); 221 return ScopedFocusNavigation(toLocalFrame(frame.contentFrame())->document(), nullptr);
149 } 222 }
150 223
151 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado wElement& shadowInsertionPoint) 224 ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowInsertionPoint(HTMLSha dowElement& shadowInsertionPoint)
152 { 225 {
153 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint)); 226 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint));
154 return FocusNavigationScope(shadowInsertionPoint.olderShadowRoot()); 227 return ScopedFocusNavigation(shadowInsertionPoint.olderShadowRoot(), nullptr );
228 }
229
230 ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSl otElement& element)
231 {
232 return ScopedFocusNavigation(const_cast<HTMLSlotElement*>(&element), nullptr );
155 } 233 }
156 234
157 inline void dispatchBlurEvent(const Document& document, Element& focusedElement) 235 inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
158 { 236 {
159 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage); 237 focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage);
160 if (focusedElement == document.focusedElement()) { 238 if (focusedElement == document.focusedElement()) {
161 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr); 239 focusedElement.dispatchFocusOutEvent(EventTypeNames::focusout, nullptr);
162 if (focusedElement == document.focusedElement()) 240 if (focusedElement == document.focusedElement())
163 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr); 241 focusedElement.dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, nu llptr);
164 } 242 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable(); 305 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable();
228 } 306 }
229 307
230 inline bool isKeyboardFocusableShadowHost(const Element& element) 308 inline bool isKeyboardFocusableShadowHost(const Element& element)
231 { 309 {
232 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable(); 310 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable();
233 } 311 }
234 312
235 inline bool isNonFocusableFocusScopeOwner(Element& element) 313 inline bool isNonFocusableFocusScopeOwner(Element& element)
236 { 314 {
237 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element); 315 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element) || isHTMLSlotElement(element);
238 } 316 }
239 317
240 inline bool isShadowHostDelegatesFocus(const Element& element) 318 inline bool isShadowHostDelegatesFocus(const Element& element)
241 { 319 {
242 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus(); 320 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus();
243 } 321 }
244 322
245 inline int adjustedTabIndex(Element& element) 323 inline int adjustedTabIndex(Element& element)
246 { 324 {
247 return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex(); 325 return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex();
248 } 326 }
249 327
250 inline bool shouldVisit(Element& element) 328 inline bool shouldVisit(Element& element)
251 { 329 {
252 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t); 330 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t);
253 } 331 }
254 332
255 Element* findElementWithExactTabIndex(Element* start, int tabIndex, WebFocusType type) 333 Element* findElementWithExactTabIndex(ScopedFocusNavigation& scope, int tabIndex , WebFocusType type)
256 { 334 {
257 // Search is inclusive of start 335 // Search is inclusive of start
258 for (Element* element = start; element; element = type == WebFocusTypeForwar d ? ElementTraversal::next(*element) : ElementTraversal::previous(*element)) { 336 for (; scope.currentElement(); type == WebFocusTypeForward ? scope.moveToNex t() : scope.moveToPrevious()) {
259 if (shouldVisit(*element) && adjustedTabIndex(*element) == tabIndex) 337 Element* current = scope.currentElement();
260 return element; 338 if (shouldVisit(*current) && adjustedTabIndex(*current) == tabIndex)
339 return current;
261 } 340 }
262 return nullptr; 341 return nullptr;
263 } 342 }
264 343
265 Element* nextElementWithGreaterTabIndex(Element* start, int tabIndex) 344 Element* nextElementWithGreaterTabIndex(ScopedFocusNavigation& scope, int tabInd ex)
266 { 345 {
267 // Search is inclusive of start 346 // Search is inclusive of start
268 int winningTabIndex = std::numeric_limits<short>::max() + 1; 347 int winningTabIndex = std::numeric_limits<short>::max() + 1;
269 Element* winner = nullptr; 348 Element* winner = nullptr;
270 for (Element& element : ElementTraversal::startsAt(start)) { 349 for (; scope.currentElement(); scope.moveToNext()) {
271 int currentTabIndex = adjustedTabIndex(element); 350 Element* current = scope.currentElement();
272 if (shouldVisit(element) && currentTabIndex > tabIndex && currentTabInde x < winningTabIndex) { 351 int currentTabIndex = adjustedTabIndex(*current);
273 winner = &element; 352 if (shouldVisit(*current) && currentTabIndex > tabIndex && currentTabInd ex < winningTabIndex) {
353 winner = current;
274 winningTabIndex = currentTabIndex; 354 winningTabIndex = currentTabIndex;
275 } 355 }
276 } 356 }
277 return winner; 357 return winner;
278 } 358 }
279 359
280 Element* previousElementWithLowerTabIndex(Element* start, int tabIndex) 360 Element* previousElementWithLowerTabIndex(ScopedFocusNavigation& scope, int tabI ndex)
281 { 361 {
282 // Search is inclusive of start 362 // Search is inclusive of start
283 int winningTabIndex = 0; 363 int winningTabIndex = 0;
284 Element* winner = nullptr; 364 Element* winner = nullptr;
285 for (Element* element = start; element; element = ElementTraversal::previous (*element)) { 365 for (; scope.currentElement(); scope.moveToPrevious()) {
286 int currentTabIndex = adjustedTabIndex(*element); 366 Element* current = scope.currentElement();
287 if (shouldVisit(*element) && currentTabIndex < tabIndex && currentTabInd ex > winningTabIndex) { 367 int currentTabIndex = adjustedTabIndex(*current);
288 winner = element; 368 if (shouldVisit(*current) && currentTabIndex < tabIndex && currentTabInd ex > winningTabIndex) {
369 winner = current;
289 winningTabIndex = currentTabIndex; 370 winningTabIndex = currentTabIndex;
290 } 371 }
291 } 372 }
292 return winner; 373 return winner;
293 } 374 }
294 375
295 Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start) 376 Element* nextFocusableElement(ScopedFocusNavigation& scope)
296 { 377 {
297 if (start) { 378 Element* current = scope.currentElement();
298 int tabIndex = adjustedTabIndex(*start); 379 if (current) {
380 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 381 // If an element is excluded from the normal tabbing cycle, the next foc usable element is determined by tree order
300 if (tabIndex < 0) { 382 if (tabIndex < 0) {
301 for (Element& element : ElementTraversal::startsAfter(*start)) { 383 for (scope.moveToNext(); scope.currentElement(); scope.moveToNext()) {
302 if (shouldVisit(element) && adjustedTabIndex(element) >= 0) 384 current = scope.currentElement();
303 return &element; 385 if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
386 return current;
304 } 387 }
305 } else { 388 } else {
306 // First try to find an element with the same tabindex as start that comes after start in the scope. 389 // 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)) 390 scope.moveToNext();
391 if (Element* winner = findElementWithExactTabIndex(scope, tabIndex, WebFocusTypeForward))
308 return winner; 392 return winner;
309 } 393 }
310 if (!tabIndex) { 394 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. 395 // 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; 396 return nullptr;
313 } 397 }
314 } 398 }
315 399
316 // Look for the first element in the scope that: 400 // 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 401 // 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. 402 // 2) comes first in the scope, if there's a tie.
319 if (Element* winner = nextElementWithGreaterTabIndex(scope.firstElement(), s tart ? adjustedTabIndex(*start) : 0)) 403 scope.moveToFirst();
404 if (Element* winner = nextElementWithGreaterTabIndex(scope, current ? adjust edTabIndex(*current) : 0)) {
320 return winner; 405 return winner;
406 }
321 407
322 // There are no elements with a tabindex greater than start's tabindex, 408 // There are no elements with a tabindex greater than start's tabindex,
323 // so find the first element with a tabindex of 0. 409 // so find the first element with a tabindex of 0.
324 return findElementWithExactTabIndex(scope.firstElement(), 0, WebFocusTypeFor ward); 410 scope.moveToFirst();
411 return findElementWithExactTabIndex(scope, 0, WebFocusTypeForward);
325 } 412 }
326 413
327 Element* previousFocusableElement(const FocusNavigationScope& scope, Element* st art) 414 Element* previousFocusableElement(ScopedFocusNavigation& scope)
328 { 415 {
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. 416 // 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 . 417 // If start is null, find the last element in the scope with a tabindex of 0 .
333 Element* startElement;
334 int startTabIndex; 418 int startTabIndex;
335 if (start) { 419 Element* current = scope.currentElement();
336 startElement = ElementTraversal::previous(*start); 420 if (current) {
337 startTabIndex = adjustedTabIndex(*start); 421 scope.moveToPrevious();
422 startTabIndex = adjustedTabIndex(*current);
338 } else { 423 } else {
339 startElement = lastElement; 424 scope.moveToLast();
340 startTabIndex = 0; 425 startTabIndex = 0;
341 } 426 }
342 427
343 // However, if an element is excluded from the normal tabbing cycle, the pre vious focusable element is determined by tree order 428 // 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) { 429 if (startTabIndex < 0) {
345 for (Element* element = startElement; element; element = ElementTraversa l::previous(*element)) { 430 scope.moveToPrevious();
346 if (shouldVisit(*element) && adjustedTabIndex(*element) >= 0) 431 for (; scope.currentElement(); scope.moveToPrevious()) {
347 return element; 432 current = scope.currentElement();
433 if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
434 return current;
348 } 435 }
349 } else { 436 } else {
350 if (Element* winner = findElementWithExactTabIndex(startElement, startTa bIndex, WebFocusTypeBackward)) 437 if (Element* winner = findElementWithExactTabIndex(scope, startTabIndex, WebFocusTypeBackward))
351 return winner; 438 return winner;
352 } 439 }
353 440
354 // There are no elements before start with the same tabindex as start, so lo ok for an element that: 441 // 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 442 // 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. 443 // 2) comes last in the scope, if there's a tie.
357 startTabIndex = (start && startTabIndex) ? startTabIndex : std::numeric_limi ts<short>::max(); 444 startTabIndex = (current && startTabIndex) ? startTabIndex : std::numeric_li mits<short>::max();
358 return previousElementWithLowerTabIndex(lastElement, startTabIndex); 445 scope.moveToLast();
446
447 return previousElementWithLowerTabIndex(scope, startTabIndex);
359 } 448 }
360 449
361 // Searches through the given tree scope, starting from start element, for the n ext/previous 450 // Searches through the given tree scope, starting from start element, for the n ext/previous
362 // selectable element that comes after/before start element. 451 // 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 452 // 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). 453 // 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 454 // The search algorithm also conforms the Shadow DOM spec[2], which inserts sequ ence in a shadow
366 // tree into its host. 455 // tree into its host.
367 // 456 //
368 // @param start The element from which to start searching. The element after thi s will be focused. 457 // @param start The element from which to start searching. The element after thi s will be focused.
369 // May be null. 458 // May be null.
370 // @return The focus element that comes after/before start element. 459 // @return The focus element that comes after/before start element.
371 // 460 //
372 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation 461 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation
373 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation 462 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
374 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Element* element) 463 inline Element* findFocusableElementInternal(WebFocusType type, ScopedFocusNavig ation& scope)
375 { 464 {
376 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, element) : previousFocusableElement(scope, element); 465 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope) : previousFocusableElement(scope);
377 return found; 466 return found;
378 } 467 }
379 468
380 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Element* start) 469 Element* findFocusableElementRecursivelyForward(ScopedFocusNavigation& scope)
381 { 470 {
382 // Starting element is exclusive. 471 // Starting element is exclusive.
383 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art); 472 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope);
384 while (found) { 473 while (found) {
385 if (isShadowHostDelegatesFocus(*found)) { 474 if (isShadowHostDelegatesFocus(*found)) {
386 // If tabindex is positive, find focusable element inside its shadow tree. 475 // If tabindex is positive, find focusable element inside its shadow tree.
387 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) { 476 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) {
388 FocusNavigationScope innerScope = FocusNavigationScope::ownedByS hadowHost(*found); 477 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedB yShadowHost(*found);
389 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope, nullptr)) 478 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope))
390 return foundInInnerFocusScope; 479 return foundInInnerFocusScope;
391 } 480 }
392 // Skip to the next element in the same scope. 481 // Skip to the next element in the same scope.
393 found = findFocusableElementInternal(WebFocusTypeForward, scope, fou nd); 482 found = findFocusableElementInternal(WebFocusTypeForward, scope);
394 continue; 483 continue;
395 } 484 }
396 if (!isNonFocusableFocusScopeOwner(*found)) 485 if (!isNonFocusableFocusScopeOwner(*found))
397 return found; 486 return found;
398 487
399 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>) 488 // 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 489 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same
401 // scope. 490 // scope.
402 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found); 491 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNonFocu sableFocusScopeOwner(*found);
403 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope, nullptr)) 492 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope))
404 return foundInInnerFocusScope; 493 return foundInInnerFocusScope;
405 494
406 found = findFocusableElementInternal(WebFocusTypeForward, scope, found); 495 scope.setCurrentElement(found);
496 found = findFocusableElementInternal(WebFocusTypeForward, scope);
407 } 497 }
408 return nullptr; 498 return nullptr;
409 } 499 }
410 500
411 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Element* start) 501 Element* findFocusableElementRecursivelyBackward(ScopedFocusNavigation& scope)
412 { 502 {
413 // Starting element is exclusive. 503 // Starting element is exclusive.
414 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart); 504 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope);
505
415 while (found) { 506 while (found) {
416 // Now |found| is on a focusable shadow host. 507 // Now |found| is on a focusable shadow host.
417 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return 508 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return
418 // the host itself. 509 // the host itself.
419 if (isKeyboardFocusableShadowHost(*found)) { 510 if (isKeyboardFocusableShadowHost(*found)) {
420 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found); 511 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedBySha dowHost(*found);
421 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 512 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope);
422 if (foundInInnerFocusScope) 513 if (foundInInnerFocusScope)
423 return foundInInnerFocusScope; 514 return foundInInnerFocusScope;
424 if (isShadowHostDelegatesFocus(*found)) { 515 if (isShadowHostDelegatesFocus(*found)) {
425 found = findFocusableElementInternal(WebFocusTypeBackward, scope , found); 516 found = findFocusableElementInternal(WebFocusTypeBackward, scope );
426 continue; 517 continue;
427 } 518 }
428 return found; 519 return found;
429 } 520 }
430 521
431 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the 522 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the
432 // shadow host. 523 // shadow host.
433 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) { 524 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) {
434 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 525 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
435 continue; 526 continue;
436 } 527 }
437 528
438 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>). 529 // 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 530 // Find focusable element in descendant scope. If not found, find next f ocusable element within the
440 // current scope. 531 // current scope.
441 if (isNonFocusableFocusScopeOwner(*found)) { 532 if (isNonFocusableFocusScopeOwner(*found)) {
442 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFo cusableFocusScopeOwner(*found); 533 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNon FocusableFocusScopeOwner(*found);
443 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 534 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope);
535
536
444 if (foundInInnerFocusScope) 537 if (foundInInnerFocusScope)
445 return foundInInnerFocusScope; 538 return foundInInnerFocusScope;
446 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 539 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
447 continue; 540 continue;
448 } 541 }
449 if (!isShadowHostDelegatesFocus(*found)) 542 if (!isShadowHostDelegatesFocus(*found))
450 return found; 543 return found;
451 found = findFocusableElementInternal(WebFocusTypeBackward, scope, found) ; 544
545 scope.setCurrentElement(found);
546 found = findFocusableElementInternal(WebFocusTypeBackward, scope);
452 } 547 }
453 return nullptr; 548 return nullptr;
454 } 549 }
455 550
456 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Element* start) 551 Element* findFocusableElementRecursively(WebFocusType type, ScopedFocusNavigatio n& scope)
457 { 552 {
458 return (type == WebFocusTypeForward) ? 553 return (type == WebFocusTypeForward) ?
459 findFocusableElementRecursivelyForward(scope, start) : 554 findFocusableElementRecursivelyForward(scope) :
460 findFocusableElementRecursivelyBackward(scope, start); 555 findFocusableElementRecursivelyBackward(scope);
461 } 556 }
462 557
463 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element) 558 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element)
464 { 559 {
465 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either: 560 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either:
466 // 1) a focusable element, or 561 // 1) a focusable element, or
467 // 2) the deepest-nested HTMLFrameOwnerElement. 562 // 2) the deepest-nested HTMLFrameOwnerElement.
468 while (element && element->isFrameOwnerElement()) { 563 while (element && element->isFrameOwnerElement()) {
469 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); 564 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element);
470 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) 565 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame())
471 break; 566 break;
472 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets(); 567 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets();
473 Element* foundElement = findFocusableElementRecursively(type, FocusNavig ationScope::ownedByIFrame(owner), nullptr); 568 ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByIFrame(owner );
569 Element* foundElement = findFocusableElementRecursively(type, scope);
474 if (!foundElement) 570 if (!foundElement)
475 break; 571 break;
476 ASSERT(element != foundElement); 572 ASSERT(element != foundElement);
477 element = foundElement; 573 element = foundElement;
478 } 574 }
479 return element; 575 return element;
480 } 576 }
481 577
482 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Element* current) 578 Element* findFocusableElementAcrossFocusScopesForward(ScopedFocusNavigation& sco pe)
483 { 579 {
580 Element* current = scope.currentElement();
484 ASSERT(!current || !isNonFocusableShadowHost(*current)); 581 ASSERT(!current || !isNonFocusableShadowHost(*current));
485 Element* found; 582 Element* found;
486 if (current && isShadowHostWithoutCustomFocusLogic(*current)) { 583 if (current && isShadowHostWithoutCustomFocusLogic(*current)) {
487 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*current); 584 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowH ost(*current);
488 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr); 585 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope);
489 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, current); 586 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope);
490 } else { 587 } else {
491 found = findFocusableElementRecursivelyForward(scope, current); 588 found = findFocusableElementRecursivelyForward(scope);
492 } 589 }
493 590
494 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one. 591 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
495 FocusNavigationScope currentScope = scope; 592 ScopedFocusNavigation currentScope = scope;
496 while (!found) { 593 while (!found) {
497 Element* owner = currentScope.owner(); 594 Element* owner = currentScope.owner();
498 if (!owner) 595 if (!owner)
499 break; 596 break;
500 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 597 currentScope = ScopedFocusNavigation::focusNavigationScopeOf(*owner, own er);
501 found = findFocusableElementRecursivelyForward(currentScope, owner); 598 found = findFocusableElementRecursivelyForward(currentScope);
502 } 599 }
503 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found); 600 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found);
504 } 601 }
505 602
506 Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScop e& scope, Element* current) 603 Element* findFocusableElementAcrossFocusScopesBackward(ScopedFocusNavigation& sc ope)
507 { 604 {
508 ASSERT(!current || !isNonFocusableShadowHost(*current)); 605 ASSERT(!scope.currentElement() || !isNonFocusableShadowHost(*scope.currentEl ement()));
509 Element* found = findFocusableElementRecursivelyBackward(scope, current); 606 Element* found = findFocusableElementRecursivelyBackward(scope);
510 607
511 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one. 608 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
512 FocusNavigationScope currentScope = scope; 609 ScopedFocusNavigation currentScope = scope;
513 while (!found) { 610 while (!found) {
514 Element* owner = currentScope.owner(); 611 Element* owner = currentScope.owner();
515 if (!owner) 612 if (!owner)
516 break; 613 break;
517 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 614 currentScope = ScopedFocusNavigation::focusNavigationScopeOf(*owner, own er);
518 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) { 615 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) {
519 found = owner; 616 found = owner;
520 break; 617 break;
521 } 618 }
522 found = findFocusableElementRecursivelyBackward(currentScope, owner); 619 found = findFocusableElementRecursivelyBackward(currentScope);
523 } 620 }
524 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found); 621 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found);
525 } 622 }
526 623
527 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNav igationScope& scope, Element* current) 624 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, ScopedFocusNav igation& scope)
528 { 625 {
529 return (type == WebFocusTypeForward) ? 626 return (type == WebFocusTypeForward) ?
530 findFocusableElementAcrossFocusScopesForward(scope, current) : 627 findFocusableElementAcrossFocusScopesForward(scope) :
531 findFocusableElementAcrossFocusScopesBackward(scope, current); 628 findFocusableElementAcrossFocusScopesBackward(scope);
532 } 629 }
533 630
534 inline Element* adjustToElement(Node* node, WebFocusType type) 631 inline Element* adjustToElement(Node* node, WebFocusType type)
535 { 632 {
536 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); 633 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
537 if (!node) 634 if (!node)
538 return nullptr; 635 return nullptr;
539 if (node->isElementNode()) 636 if (node->isElementNode())
540 return toElement(node); 637 toElement(node);
kochi 2016/03/02 13:26:56 It looks you need "return" here.
kochi 2016/03/03 00:54:17 Probably the layout test failure is due to this. C
yuzuchan 2016/03/03 04:12:43 I accidentally removed return here and then I put
541 // The returned element is used as an *exclusive* start element. Thus, we sh ould return the result of ElementTraversal::previous(*node), 638 // 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. 639 // 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|. 640 // The caller will call ElementTraversal::{next/previous} for the returned v alue and get the {next|previous} element of the |node|.
641
642 // TODO(yuzus) Use ScopedFocusNavigation traversal here.
544 return (type == WebFocusTypeForward) ? ElementTraversal::previous(*node) : E lementTraversal::next(*node); 643 return (type == WebFocusTypeForward) ? ElementTraversal::previous(*node) : E lementTraversal::next(*node);
545 } 644 }
546 645
547 } // anonymous namespace 646 } // anonymous namespace
548 647
549 FocusController::FocusController(Page* page) 648 FocusController::FocusController(Page* page)
550 : m_page(page) 649 : m_page(page)
551 , m_isActive(false) 650 , m_isActive(false)
552 , m_isFocused(false) 651 , m_isFocused(false)
553 , m_isChangingFocusedFrame(false) 652 , m_isChangingFocusedFrame(false)
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 if (!current) 847 if (!current)
749 current = document->sequentialFocusNavigationStartingPoint(type); 848 current = document->sequentialFocusNavigationStartingPoint(type);
750 849
751 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself 850 // 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(); 851 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled();
753 852
754 if (caretBrowsing && !current) 853 if (caretBrowsing && !current)
755 current = adjustToElement(frame->selection().start().anchorNode(), type) ; 854 current = adjustToElement(frame->selection().start().anchorNode(), type) ;
756 855
757 document->updateLayoutIgnorePendingStylesheets(); 856 document->updateLayoutIgnorePendingStylesheets();
758 857 ScopedFocusNavigation scope = ScopedFocusNavigation::focusNavigationScopeOf( current ? *current : *document->documentElement(), current);
759 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, FocusNavigationScope::focusNavigationScopeOf(current ? *current : *documen t->documentElement()), current); 858 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, scope);
760 859
761 if (!element) { 860 if (!element) {
762 // If there's a RemoteFrame on the ancestor chain, we need to continue 861 // If there's a RemoteFrame on the ancestor chain, we need to continue
763 // searching for focusable elements there. 862 // searching for focusable elements there.
764 if (frame->localFrameRoot() != frame->tree().top()) { 863 if (frame->localFrameRoot() != frame->tree().top()) {
765 document->clearFocusedElement(); 864 document->clearFocusedElement();
766 document->setSequentialFocusNavigationStartingPoint(nullptr); 865 document->setSequentialFocusNavigationStartingPoint(nullptr);
767 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot()); 866 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot());
768 return true; 867 return true;
769 } 868 }
770 869
771 // We didn't find an element to focus, so we should try to pass focus to Chrome. 870 // 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)) { 871 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) {
773 document->clearFocusedElement(); 872 document->clearFocusedElement();
774 document->setSequentialFocusNavigationStartingPoint(nullptr); 873 document->setSequentialFocusNavigationStartingPoint(nullptr);
775 setFocusedFrame(nullptr); 874 setFocusedFrame(nullptr);
776 m_page->chromeClient().takeFocus(type); 875 m_page->chromeClient().takeFocus(type);
777 return true; 876 return true;
778 } 877 }
779 878
780 // Chrome doesn't want focus, so we should wrap focus. 879 // 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); 880 ScopedFocusNavigation scope = ScopedFocusNavigation::focusNavigationScop eOf(*toLocalFrame(m_page->mainFrame())->document()->documentElement(), nullptr);
881 element = findFocusableElementRecursively(type, scope);
782 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get()); 882 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get());
783 883
784 if (!element) 884 if (!element)
785 return false; 885 return false;
786 } 886 }
787 887
788 ASSERT(element); 888 ASSERT(element);
789 889
790 if (element == document->focusedElement()) { 890 if (element == document->focusedElement()) {
791 // Focus wrapped around to the same element. 891 // Focus wrapped around to the same element.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 } 931 }
832 932
833 element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, sourceCapa bilities)); 933 element->focus(FocusParams(SelectionBehaviorOnFocus::Reset, type, sourceCapa bilities));
834 return true; 934 return true;
835 } 935 }
836 936
837 Element* FocusController::findFocusableElement(WebFocusType type, Element& eleme nt) 937 Element* FocusController::findFocusableElement(WebFocusType type, Element& eleme nt)
838 { 938 {
839 // FIXME: No spacial navigation code yet. 939 // FIXME: No spacial navigation code yet.
840 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); 940 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
841 return findFocusableElementAcrossFocusScopes(type, FocusNavigationScope::foc usNavigationScopeOf(element), &element); 941 ScopedFocusNavigation scope = ScopedFocusNavigation::focusNavigationScopeOf( element, &element);
942 return findFocusableElementAcrossFocusScopes(type, scope);
842 } 943 }
843 944
844 Element* FocusController::findFocusableElementInShadowHost(const Element& shadow Host) 945 Element* FocusController::findFocusableElementInShadowHost(const Element& shadow Host)
845 { 946 {
846 ASSERT(shadowHost.authorShadowRoot()); 947 ASSERT(shadowHost.authorShadowRoot());
847 return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, FocusNavig ationScope::ownedByShadowHost(shadowHost), nullptr); 948 ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByShadowHost(shado wHost);
949 return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, scope);
848 } 950 }
849 951
850 static bool relinquishesEditingFocus(const Element& element) 952 static bool relinquishesEditingFocus(const Element& element)
851 { 953 {
852 ASSERT(element.hasEditableStyle()); 954 ASSERT(element.hasEditableStyle());
853 return element.document().frame() && element.rootEditableElement(); 955 return element.document().frame() && element.rootEditableElement();
854 } 956 }
855 957
856 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF ocusedFrame, Element* newFocusedElement) 958 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF ocusedFrame, Element* newFocusedElement)
857 { 959 {
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 return consumed; 1242 return consumed;
1141 } 1243 }
1142 1244
1143 DEFINE_TRACE(FocusController) 1245 DEFINE_TRACE(FocusController)
1144 { 1246 {
1145 visitor->trace(m_page); 1247 visitor->trace(m_page);
1146 visitor->trace(m_focusedFrame); 1248 visitor->trace(m_focusedFrame);
1147 } 1249 }
1148 1250
1149 } // namespace blink 1251 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698