| OLD | NEW |
| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 { | 65 { |
| 66 return isActiveShadowInsertionPoint(node) && toHTMLShadowElement(node).older
ShadowRoot(); | 66 return isActiveShadowInsertionPoint(node) && toHTMLShadowElement(node).older
ShadowRoot(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 class FocusNavigationScope { | 69 class FocusNavigationScope { |
| 70 STACK_ALLOCATED(); | 70 STACK_ALLOCATED(); |
| 71 public: | 71 public: |
| 72 Node* rootNode() const; | 72 Node* rootNode() const; |
| 73 Element* owner() const; | 73 Element* owner() const; |
| 74 static FocusNavigationScope focusNavigationScopeOf(const Node&); | 74 static FocusNavigationScope focusNavigationScopeOf(const Node&); |
| 75 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Node&); | 75 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&); |
| 76 static FocusNavigationScope ownedByShadowHost(const Node&); | 76 static FocusNavigationScope ownedByShadowHost(const Element&); |
| 77 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&); | 77 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&); |
| 78 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&); | 78 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&); |
| 79 | 79 |
| 80 private: | 80 private: |
| 81 explicit FocusNavigationScope(TreeScope*); | 81 explicit FocusNavigationScope(TreeScope*); |
| 82 RawPtrWillBeMember<TreeScope> m_rootTreeScope; | 82 RawPtrWillBeMember<TreeScope> m_rootTreeScope; |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 // FIXME: Some of Node* return values and Node* arguments should be Element*. | 85 // FIXME: Some of Node* return values and Node* arguments should be Element*. |
| 86 | 86 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 111 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Node& no
de) | 111 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Node& no
de) |
| 112 { | 112 { |
| 113 const Node* root = &node; | 113 const Node* root = &node; |
| 114 for (const Node* n = &node; n; n = n->parentNode()) | 114 for (const Node* n = &node; n; n = n->parentNode()) |
| 115 root = n; | 115 root = n; |
| 116 // The result is not always a ShadowRoot nor a DocumentNode since | 116 // The result is not always a ShadowRoot nor a DocumentNode since |
| 117 // a starting node is in an orphaned tree in composed shadow tree. | 117 // a starting node is in an orphaned tree in composed shadow tree. |
| 118 return FocusNavigationScope(&root->treeScope()); | 118 return FocusNavigationScope(&root->treeScope()); |
| 119 } | 119 } |
| 120 | 120 |
| 121 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(No
de& node) | 121 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El
ement& element) |
| 122 { | 122 { |
| 123 if (isShadowHost(node)) | 123 if (isShadowHost(element)) |
| 124 return FocusNavigationScope::ownedByShadowHost(node); | 124 return FocusNavigationScope::ownedByShadowHost(element); |
| 125 ASSERT(isShadowInsertionPointFocusScopeOwner(node)); | 125 ASSERT(isShadowInsertionPointFocusScopeOwner(element)); |
| 126 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement
(node)); | 126 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement
(element)); |
| 127 } | 127 } |
| 128 | 128 |
| 129 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Node& node) | 129 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Element& elem
ent) |
| 130 { | 130 { |
| 131 ASSERT(isShadowHost(node)); | 131 ASSERT(isShadowHost(element)); |
| 132 return FocusNavigationScope(toElement(node).shadow()->youngestShadowRoot()); | 132 return FocusNavigationScope(element.shadow()->youngestShadowRoot()); |
| 133 } | 133 } |
| 134 | 134 |
| 135 FocusNavigationScope FocusNavigationScope::ownedByIFrame(const HTMLFrameOwnerEle
ment& frame) | 135 FocusNavigationScope FocusNavigationScope::ownedByIFrame(const HTMLFrameOwnerEle
ment& frame) |
| 136 { | 136 { |
| 137 ASSERT(frame.contentFrame()); | 137 ASSERT(frame.contentFrame()); |
| 138 ASSERT(frame.contentFrame()->isLocalFrame()); | 138 ASSERT(frame.contentFrame()->isLocalFrame()); |
| 139 return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document()); | 139 return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document()); |
| 140 } | 140 } |
| 141 | 141 |
| 142 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado
wElement& shadowInsertionPoint) | 142 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado
wElement& shadowInsertionPoint) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 158 static inline void dispatchFocusEvent(const Document& document, Element& focused
Element) | 158 static inline void dispatchFocusEvent(const Document& document, Element& focused
Element) |
| 159 { | 159 { |
| 160 focusedElement.dispatchFocusEvent(0, WebFocusTypePage); | 160 focusedElement.dispatchFocusEvent(0, WebFocusTypePage); |
| 161 if (focusedElement == document.focusedElement()) { | 161 if (focusedElement == document.focusedElement()) { |
| 162 focusedElement.dispatchFocusInEvent(EventTypeNames::focusin, nullptr, We
bFocusTypePage); | 162 focusedElement.dispatchFocusInEvent(EventTypeNames::focusin, nullptr, We
bFocusTypePage); |
| 163 if (focusedElement == document.focusedElement()) | 163 if (focusedElement == document.focusedElement()) |
| 164 focusedElement.dispatchFocusInEvent(EventTypeNames::DOMFocusIn, null
ptr, WebFocusTypePage); | 164 focusedElement.dispatchFocusInEvent(EventTypeNames::DOMFocusIn, null
ptr, WebFocusTypePage); |
| 165 } | 165 } |
| 166 } | 166 } |
| 167 | 167 |
| 168 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
focused) | 168 static inline void dispatchEventsOnWindowAndFocusedElement(Document* document, b
ool focused) |
| 169 { | 169 { |
| 170 ASSERT(document); | 170 ASSERT(document); |
| 171 // If we have a focused node we should dispatch blur on it before we blur th
e window. | 171 // If we have a focused element we should dispatch blur on it before we blur
the window. |
| 172 // If we have a focused node we should dispatch focus on it after we focus t
he window. | 172 // If we have a focused element we should dispatch focus on it after we focu
s the window. |
| 173 // https://bugs.webkit.org/show_bug.cgi?id=27105 | 173 // https://bugs.webkit.org/show_bug.cgi?id=27105 |
| 174 | 174 |
| 175 if (document->focusedElement() && isHTMLPlugInElement(document->focusedEleme
nt())) | 175 if (document->focusedElement() && isHTMLPlugInElement(document->focusedEleme
nt())) |
| 176 toHTMLPlugInElement(document->focusedElement())->setPluginFocus(focused)
; | 176 toHTMLPlugInElement(document->focusedElement())->setPluginFocus(focused)
; |
| 177 | 177 |
| 178 // Do not fire events while modal dialogs are up. See https://bugs.webkit.o
rg/show_bug.cgi?id=33962 | 178 // Do not fire events while modal dialogs are up. See https://bugs.webkit.o
rg/show_bug.cgi?id=33962 |
| 179 if (Page* page = document->page()) { | 179 if (Page* page = document->page()) { |
| 180 if (page->defersLoading()) | 180 if (page->defersLoading()) |
| 181 return; | 181 return; |
| 182 } | 182 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 if (!m_isFocused && focusedOrMainFrame()->isLocalFrame()) | 339 if (!m_isFocused && focusedOrMainFrame()->isLocalFrame()) |
| 340 toLocalFrame(focusedOrMainFrame())->eventHandler().stopAutoscroll(); | 340 toLocalFrame(focusedOrMainFrame())->eventHandler().stopAutoscroll(); |
| 341 | 341 |
| 342 if (!m_focusedFrame) | 342 if (!m_focusedFrame) |
| 343 setFocusedFrame(m_page->mainFrame()); | 343 setFocusedFrame(m_page->mainFrame()); |
| 344 | 344 |
| 345 // setFocusedFrame above might reject to update m_focusedFrame, or | 345 // setFocusedFrame above might reject to update m_focusedFrame, or |
| 346 // m_focusedFrame might be changed by blur/focus event handlers. | 346 // m_focusedFrame might be changed by blur/focus event handlers. |
| 347 if (m_focusedFrame && m_focusedFrame->isLocalFrame() && toLocalFrame(m_focus
edFrame.get())->view()) { | 347 if (m_focusedFrame && m_focusedFrame->isLocalFrame() && toLocalFrame(m_focus
edFrame.get())->view()) { |
| 348 toLocalFrame(m_focusedFrame.get())->selection().setFocused(focused); | 348 toLocalFrame(m_focusedFrame.get())->selection().setFocused(focused); |
| 349 dispatchEventsOnWindowAndFocusedNode(toLocalFrame(m_focusedFrame.get())-
>document(), focused); | 349 dispatchEventsOnWindowAndFocusedElement(toLocalFrame(m_focusedFrame.get(
))->document(), focused); |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 | 352 |
| 353 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(WebFocusT
ype type, Node* node) | 353 Element* FocusController::findFocusableElementDescendingDownIntoFrameDocument(We
bFocusType type, Element* element) |
| 354 { | 354 { |
| 355 // The node we found might be a HTMLFrameOwnerElement, so descend down the t
ree until we find either: | 355 // The element we found might be a HTMLFrameOwnerElement, so descend down th
e tree until we find either: |
| 356 // 1) a focusable node, or | 356 // 1) a focusable element, or |
| 357 // 2) the deepest-nested HTMLFrameOwnerElement. | 357 // 2) the deepest-nested HTMLFrameOwnerElement. |
| 358 while (node && node->isFrameOwnerElement()) { | 358 while (element && element->isFrameOwnerElement()) { |
| 359 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*node); | 359 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); |
| 360 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) | 360 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) |
| 361 break; | 361 break; |
| 362 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin
gStylesheets(); | 362 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin
gStylesheets(); |
| 363 Element* foundElement = findFocusableElement(type, FocusNavigationScope:
:ownedByIFrame(owner), nullptr); | 363 Element* foundElement = findFocusableElement(type, FocusNavigationScope:
:ownedByIFrame(owner), nullptr); |
| 364 if (!foundElement) | 364 if (!foundElement) |
| 365 break; | 365 break; |
| 366 ASSERT(node != foundElement); | 366 ASSERT(element != foundElement); |
| 367 node = foundElement; | 367 element = foundElement; |
| 368 } | 368 } |
| 369 return node; | 369 return element; |
| 370 } | 370 } |
| 371 | 371 |
| 372 bool FocusController::setInitialFocus(WebFocusType type) | 372 bool FocusController::setInitialFocus(WebFocusType type) |
| 373 { | 373 { |
| 374 bool didAdvanceFocus = advanceFocus(type, true); | 374 bool didAdvanceFocus = advanceFocus(type, true); |
| 375 | 375 |
| 376 // If focus is being set initially, accessibility needs to be informed that
system focus has moved | 376 // If focus is being set initially, accessibility needs to be informed that
system focus has moved |
| 377 // into the web area again, even if focus did not change within WebCore. Pos
tNotification is called instead | 377 // into the web area again, even if focus did not change within WebCore. Pos
tNotification is called instead |
| 378 // of handleFocusedUIElementChanged, because this will send the notification
even if the element is the same. | 378 // of handleFocusedUIElementChanged, because this will send the notification
even if the element is the same. |
| 379 if (focusedOrMainFrame()->isLocalFrame()) { | 379 if (focusedOrMainFrame()->isLocalFrame()) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 415 |
| 416 Node* currentNode = document->focusedElement(); | 416 Node* currentNode = document->focusedElement(); |
| 417 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself | 417 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself |
| 418 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); | 418 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); |
| 419 | 419 |
| 420 if (caretBrowsing && !currentNode) | 420 if (caretBrowsing && !currentNode) |
| 421 currentNode = frame->selection().start().deprecatedNode(); | 421 currentNode = frame->selection().start().deprecatedNode(); |
| 422 | 422 |
| 423 document->updateLayoutIgnorePendingStylesheets(); | 423 document->updateLayoutIgnorePendingStylesheets(); |
| 424 | 424 |
| 425 RefPtrWillBeRawPtr<Node> node = findFocusableNodeAcrossFocusScopes(type, Foc
usNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode : *document
), currentNode); | 425 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes(
type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode :
*document), currentNode); |
| 426 | 426 |
| 427 if (!node) { | 427 if (!element) { |
| 428 // We didn't find a node to focus, so we should try to pass focus to Chr
ome. | 428 // We didn't find an element to focus, so we should try to pass focus to
Chrome. |
| 429 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { | 429 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { |
| 430 document->setFocusedElement(nullptr); | 430 document->setFocusedElement(nullptr); |
| 431 setFocusedFrame(nullptr); | 431 setFocusedFrame(nullptr); |
| 432 m_page->chromeClient().takeFocus(type); | 432 m_page->chromeClient().takeFocus(type); |
| 433 return true; | 433 return true; |
| 434 } | 434 } |
| 435 | 435 |
| 436 // Chrome doesn't want focus, so we should wrap focus. | 436 // Chrome doesn't want focus, so we should wrap focus. |
| 437 if (!m_page->mainFrame()->isLocalFrame()) | 437 if (!m_page->mainFrame()->isLocalFrame()) |
| 438 return false; | 438 return false; |
| 439 node = findFocusableElementRecursively(type, FocusNavigationScope::focus
NavigationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); | 439 element = findFocusableElementRecursively(type, FocusNavigationScope::fo
cusNavigationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); |
| 440 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get())
; | 440 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem
ent.get()); |
| 441 | 441 |
| 442 if (!node) | 442 if (!element) |
| 443 return false; | 443 return false; |
| 444 } | 444 } |
| 445 | 445 |
| 446 ASSERT(node); | 446 ASSERT(element); |
| 447 | 447 |
| 448 if (node == document->focusedElement()) | 448 if (element == document->focusedElement()) |
| 449 // Focus wrapped around to the same node. | 449 // Focus wrapped around to the same node. |
| 450 return true; | 450 return true; |
| 451 | 451 |
| 452 if (!node->isElementNode()) | |
| 453 // FIXME: May need a way to focus a document here. | |
| 454 return false; | |
| 455 | |
| 456 Element* element = toElement(node); | |
| 457 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el
ement->isKeyboardFocusable())) { | 452 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el
ement->isKeyboardFocusable())) { |
| 458 // We focus frames rather than frame owners. | 453 // We focus frames rather than frame owners. |
| 459 // FIXME: We should not focus frames that have no scrollbars, as focusin
g them isn't useful to the user. | 454 // FIXME: We should not focus frames that have no scrollbars, as focusin
g them isn't useful to the user. |
| 460 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); | 455 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); |
| 461 if (!owner->contentFrame()) | 456 if (!owner->contentFrame()) |
| 462 return false; | 457 return false; |
| 463 | 458 |
| 464 document->setFocusedElement(nullptr); | 459 document->setFocusedElement(nullptr); |
| 465 setFocusedFrame(owner->contentFrame()); | 460 setFocusedFrame(owner->contentFrame()); |
| 466 return true; | 461 return true; |
| 467 } | 462 } |
| 468 | 463 |
| 469 // FIXME: It would be nice to just be able to call setFocusedElement(node) | 464 // FIXME: It would be nice to just be able to call setFocusedElement(node) |
| 470 // here, but we can't do that because some elements (e.g. HTMLInputElement | 465 // here, but we can't do that because some elements (e.g. HTMLInputElement |
| 471 // and HTMLTextAreaElement) do extra work in their focus() methods. | 466 // and HTMLTextAreaElement) do extra work in their focus() methods. |
| 472 Document& newDocument = element->document(); | 467 Document& newDocument = element->document(); |
| 473 | 468 |
| 474 if (&newDocument != document) { | 469 if (&newDocument != document) { |
| 475 // Focus is going away from this document, so clear the focused node. | 470 // Focus is going away from this document, so clear the focused node. |
| 476 document->setFocusedElement(nullptr); | 471 document->setFocusedElement(nullptr); |
| 477 } | 472 } |
| 478 | 473 |
| 479 setFocusedFrame(newDocument.frame()); | 474 setFocusedFrame(newDocument.frame()); |
| 480 | 475 |
| 481 if (caretBrowsing) { | 476 if (caretBrowsing) { |
| 482 Position position = firstPositionInOrBeforeNode(element); | 477 Position position = firstPositionInOrBeforeNode(element.get()); |
| 483 VisibleSelection newSelection(position, position, DOWNSTREAM); | 478 VisibleSelection newSelection(position, position, DOWNSTREAM); |
| 484 frame->selection().setSelection(newSelection); | 479 frame->selection().setSelection(newSelection); |
| 485 } | 480 } |
| 486 | 481 |
| 487 element->focus(false, type); | 482 element->focus(false, type); |
| 488 return true; | 483 return true; |
| 489 } | 484 } |
| 490 | 485 |
| 491 Node* FocusController::findFocusableNodeAcrossFocusScopes(WebFocusType type, con
st FocusNavigationScope& scope, Node* currentNode) | 486 Element* FocusController::findFocusableElementAcrossFocusScopes(WebFocusType typ
e, const FocusNavigationScope& scope, Node* currentNode) |
| 492 { | 487 { |
| 493 return (type == WebFocusTypeForward) ? | 488 return (type == WebFocusTypeForward) ? |
| 494 findFocusableNodeAcrossFocusScopesForward(scope, currentNode) : | 489 findFocusableElementAcrossFocusScopesForward(scope, currentNode) : |
| 495 findFocusableNodeAcrossFocusScopesBackward(scope, currentNode); | 490 findFocusableElementAcrossFocusScopesBackward(scope, currentNode); |
| 496 } | 491 } |
| 497 | 492 |
| 498 Node* FocusController::findFocusableNodeAcrossFocusScopesForward(const FocusNavi
gationScope& scope, Node* currentNode) | 493 Element* FocusController::findFocusableElementAcrossFocusScopesForward(const Foc
usNavigationScope& scope, Node* currentNode) |
| 499 { | 494 { |
| 500 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); | 495 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); |
| 501 Node* found; | 496 Element* found; |
| 502 if (currentNode && isShadowHostWithoutCustomFocusLogic(*currentNode)) { | 497 if (currentNode && isShadowHostWithoutCustomFocusLogic(*currentNode)) { |
| 503 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*currentNode); | 498 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*toElement(currentNode)); |
| 504 Node* foundInInnerFocusScope = findFocusableElementRecursivelyForward(in
nerScope, nullptr); | 499 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward
(innerScope, nullptr); |
| 505 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE
lementRecursivelyForward(scope, currentNode); | 500 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE
lementRecursivelyForward(scope, currentNode); |
| 506 } else { | 501 } else { |
| 507 found = findFocusableElementRecursivelyForward(scope, currentNode); | 502 found = findFocusableElementRecursivelyForward(scope, currentNode); |
| 508 } | 503 } |
| 509 | 504 |
| 510 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. | 505 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. |
| 511 FocusNavigationScope currentScope = scope; | 506 FocusNavigationScope currentScope = scope; |
| 512 while (!found) { | 507 while (!found) { |
| 513 Node* owner = currentScope.owner(); | 508 Element* owner = currentScope.owner(); |
| 514 if (!owner) | 509 if (!owner) |
| 515 break; | 510 break; |
| 516 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); | 511 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); |
| 517 found = findFocusableElementRecursivelyForward(currentScope, owner); | 512 found = findFocusableElementRecursivelyForward(currentScope, owner); |
| 518 } | 513 } |
| 519 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeForward,
found); | 514 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa
rd, found); |
| 520 } | 515 } |
| 521 | 516 |
| 522 Node* FocusController::findFocusableNodeAcrossFocusScopesBackward(const FocusNav
igationScope& scope, Node* currentNode) | 517 Element* FocusController::findFocusableElementAcrossFocusScopesBackward(const Fo
cusNavigationScope& scope, Node* currentNode) |
| 523 { | 518 { |
| 524 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); | 519 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); |
| 525 Node* found = findFocusableElementRecursivelyBackward(scope, currentNode); | 520 Element* found = findFocusableElementRecursivelyBackward(scope, currentNode)
; |
| 526 | 521 |
| 527 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. | 522 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. |
| 528 FocusNavigationScope currentScope = scope; | 523 FocusNavigationScope currentScope = scope; |
| 529 while (!found) { | 524 while (!found) { |
| 530 Node* owner = currentScope.owner(); | 525 Element* owner = currentScope.owner(); |
| 531 if (!owner) | 526 if (!owner) |
| 532 break; | 527 break; |
| 533 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); | 528 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); |
| 534 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { | 529 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { |
| 535 found = owner; | 530 found = owner; |
| 536 break; | 531 break; |
| 537 } | 532 } |
| 538 found = findFocusableElementRecursivelyBackward(currentScope, owner); | 533 found = findFocusableElementRecursivelyBackward(currentScope, owner); |
| 539 } | 534 } |
| 540 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeBackward,
found); | 535 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw
ard, found); |
| 541 } | 536 } |
| 542 | 537 |
| 543 Element* FocusController::findFocusableElementRecursively(WebFocusType type, con
st FocusNavigationScope& scope, Node* start) | 538 Element* FocusController::findFocusableElementRecursively(WebFocusType type, con
st FocusNavigationScope& scope, Node* start) |
| 544 { | 539 { |
| 545 return (type == WebFocusTypeForward) ? | 540 return (type == WebFocusTypeForward) ? |
| 546 findFocusableElementRecursivelyForward(scope, start) : | 541 findFocusableElementRecursivelyForward(scope, start) : |
| 547 findFocusableElementRecursivelyBackward(scope, start); | 542 findFocusableElementRecursivelyBackward(scope, start); |
| 548 } | 543 } |
| 549 | 544 |
| 550 Element* FocusController::findFocusableElementRecursivelyForward(const FocusNavi
gationScope& scope, Node* start) | 545 Element* FocusController::findFocusableElementRecursivelyForward(const FocusNavi
gationScope& scope, Node* start) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*found); | 583 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*found); |
| 589 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); | 584 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); |
| 590 if (foundInInnerFocusScope) | 585 if (foundInInnerFocusScope) |
| 591 return foundInInnerFocusScope; | 586 return foundInInnerFocusScope; |
| 592 if (isShadowHostDelegatesFocus(*found)) | 587 if (isShadowHostDelegatesFocus(*found)) |
| 593 found = findFocusableElementRecursivelyBackward(scope, found); | 588 found = findFocusableElementRecursivelyBackward(scope, found); |
| 594 return found; | 589 return found; |
| 595 } | 590 } |
| 596 | 591 |
| 597 // Now |found| is on a non focusable scope owner (either shadow host or <sha
dow>). | 592 // Now |found| is on a non focusable scope owner (either shadow host or <sha
dow>). |
| 598 // Find focusable node in decendant scope. If not found, find next focusable
node within the | 593 // Find focusable node in descendant scope. If not found, find next focusabl
e node within the |
| 599 // current scope. | 594 // current scope. |
| 600 if (isNonFocusableFocusScopeOwner(*found)) { | 595 if (isNonFocusableFocusScopeOwner(*found)) { |
| 601 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa
bleFocusScopeOwner(*found); | 596 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa
bleFocusScopeOwner(*found); |
| 602 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); | 597 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); |
| 603 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableEl
ementRecursivelyBackward(scope, found); | 598 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableEl
ementRecursivelyBackward(scope, found); |
| 604 } | 599 } |
| 605 | 600 |
| 606 return !isShadowHostDelegatesFocus(*found) ? found : findFocusableElementRec
ursivelyBackward(scope, found); | 601 return !isShadowHostDelegatesFocus(*found) ? found : findFocusableElementRec
ursivelyBackward(scope, found); |
| 607 } | 602 } |
| 608 | 603 |
| 609 static Node* findNodeWithExactTabIndex(Node* start, int tabIndex, WebFocusType t
ype) | 604 static Element* findElementWithExactTabIndex(Node* start, int tabIndex, WebFocus
Type type) |
| 610 { | 605 { |
| 611 // Search is inclusive of start | 606 // Search is inclusive of start |
| 612 for (Node* node = start; node; node = type == WebFocusTypeForward ? NodeTrav
ersal::next(*node) : NodeTraversal::previous(*node)) { | 607 for (Node* node = start; node; node = type == WebFocusTypeForward ? NodeTrav
ersal::next(*node) : NodeTraversal::previous(*node)) { |
| 613 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) | 608 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) |
| 614 return node; | 609 return toElement(node); |
| 615 } | 610 } |
| 616 return nullptr; | 611 return nullptr; |
| 617 } | 612 } |
| 618 | 613 |
| 619 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex) | 614 static Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex) |
| 620 { | 615 { |
| 621 // Search is inclusive of start | 616 // Search is inclusive of start |
| 622 int winningTabIndex = std::numeric_limits<short>::max() + 1; | 617 int winningTabIndex = std::numeric_limits<short>::max() + 1; |
| 623 Node* winner = nullptr; | 618 Node* winner = nullptr; |
| 624 for (Node& node : NodeTraversal::startsAt(start)) { | 619 for (Node& node : NodeTraversal::startsAt(start)) { |
| 625 int currentTabIndex = adjustedTabIndex(node); | 620 int currentTabIndex = adjustedTabIndex(node); |
| 626 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex <
winningTabIndex) { | 621 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex <
winningTabIndex) { |
| 627 winner = &node; | 622 winner = &node; |
| 628 winningTabIndex = currentTabIndex; | 623 winningTabIndex = currentTabIndex; |
| 629 } | 624 } |
| 630 } | 625 } |
| 631 | 626 ASSERT(!winner || winner->isElementNode()); |
| 632 return winner; | 627 return toElement(winner); |
| 633 } | 628 } |
| 634 | 629 |
| 635 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex) | 630 static Element* previousElementWithLowerTabIndex(Node* start, int tabIndex) |
| 636 { | 631 { |
| 637 // Search is inclusive of start | 632 // Search is inclusive of start |
| 638 int winningTabIndex = 0; | 633 int winningTabIndex = 0; |
| 639 Node* winner = nullptr; | 634 Node* winner = nullptr; |
| 640 for (Node* node = start; node; node = NodeTraversal::previous(*node)) { | 635 for (Node* node = start; node; node = NodeTraversal::previous(*node)) { |
| 641 int currentTabIndex = adjustedTabIndex(*node); | 636 int currentTabIndex = adjustedTabIndex(*node); |
| 642 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex
> winningTabIndex) { | 637 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex
> winningTabIndex) { |
| 643 winner = node; | 638 winner = node; |
| 644 winningTabIndex = currentTabIndex; | 639 winningTabIndex = currentTabIndex; |
| 645 } | 640 } |
| 646 } | 641 } |
| 647 return winner; | 642 ASSERT(!winner || winner->isElementNode()); |
| 643 return toElement(winner); |
| 648 } | 644 } |
| 649 | 645 |
| 650 static Node* nextFocusableNode(const FocusNavigationScope& scope, Node* start) | 646 static Element* nextFocusableElement(const FocusNavigationScope& scope, Node* st
art) |
| 651 { | 647 { |
| 652 if (start) { | 648 if (start) { |
| 653 int tabIndex = adjustedTabIndex(*start); | 649 int tabIndex = adjustedTabIndex(*start); |
| 654 // If a node is excluded from the normal tabbing cycle, the next focusab
le node is determined by tree order | 650 // If a node is excluded from the normal tabbing cycle, the next focusab
le node is determined by tree order |
| 655 if (tabIndex < 0) { | 651 if (tabIndex < 0) { |
| 656 for (Node& node : NodeTraversal::startsAfter(*start)) { | 652 for (Node& node : NodeTraversal::startsAfter(*start)) { |
| 657 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) | 653 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) |
| 658 return &node; | 654 return &toElement(node); |
| 659 } | 655 } |
| 660 } else { | 656 } else { |
| 661 // First try to find a node with the same tabindex as start that com
es after start in the scope. | 657 // First try to find a node with the same tabindex as start that com
es after start in the scope. |
| 662 if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*st
art), tabIndex, WebFocusTypeForward)) | 658 if (Element* winner = findElementWithExactTabIndex(NodeTraversal::ne
xt(*start), tabIndex, WebFocusTypeForward)) |
| 663 return winner; | 659 return winner; |
| 664 } | 660 } |
| 665 if (!tabIndex) { | 661 if (!tabIndex) { |
| 666 // We've reached the last node in the document with a tabindex of 0.
This is the end of the tabbing order. | 662 // We've reached the last node in the document with a tabindex of 0.
This is the end of the tabbing order. |
| 667 return nullptr; | 663 return nullptr; |
| 668 } | 664 } |
| 669 } | 665 } |
| 670 | 666 |
| 671 // Look for the first node in the scope that: | 667 // Look for the first node in the scope that: |
| 672 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if
start is null), and | 668 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if
start is null), and |
| 673 // 2) comes first in the scope, if there's a tie. | 669 // 2) comes first in the scope, if there's a tie. |
| 674 if (Node* winner = nextNodeWithGreaterTabIndex(scope.rootNode(), start ? adj
ustedTabIndex(*start) : 0)) | 670 if (Element* winner = nextElementWithGreaterTabIndex(scope.rootNode(), start
? adjustedTabIndex(*start) : 0)) |
| 675 return winner; | 671 return winner; |
| 676 | 672 |
| 677 // There are no nodes with a tabindex greater than start's tabindex, | 673 // There are no nodes with a tabindex greater than start's tabindex, |
| 678 // so find the first node with a tabindex of 0. | 674 // so find the first node with a tabindex of 0. |
| 679 return findNodeWithExactTabIndex(scope.rootNode(), 0, WebFocusTypeForward); | 675 return findElementWithExactTabIndex(scope.rootNode(), 0, WebFocusTypeForward
); |
| 680 } | 676 } |
| 681 | 677 |
| 682 static Node* previousFocusableNode(const FocusNavigationScope& scope, Node* star
t) | 678 static Element* previousFocusableElement(const FocusNavigationScope& scope, Node
* start) |
| 683 { | 679 { |
| 684 Node* last = nullptr; | 680 Node* last = nullptr; |
| 685 for (Node* node = scope.rootNode(); node; node = node->lastChild()) | 681 for (Node* node = scope.rootNode(); node; node = node->lastChild()) |
| 686 last = node; | 682 last = node; |
| 687 ASSERT(last); | 683 ASSERT(last); |
| 688 | 684 |
| 689 // First try to find the last node in the scope that comes before start and
has the same tabindex as start. | 685 // First try to find the last node in the scope that comes before start and
has the same tabindex as start. |
| 690 // If start is null, find the last node in the scope with a tabindex of 0. | 686 // If start is null, find the last node in the scope with a tabindex of 0. |
| 691 Node* startingNode; | 687 Node* startingNode; |
| 692 int startingTabIndex; | 688 int startingTabIndex; |
| 693 if (start) { | 689 if (start) { |
| 694 startingNode = NodeTraversal::previous(*start); | 690 startingNode = NodeTraversal::previous(*start); |
| 695 startingTabIndex = adjustedTabIndex(*start); | 691 startingTabIndex = adjustedTabIndex(*start); |
| 696 } else { | 692 } else { |
| 697 startingNode = last; | 693 startingNode = last; |
| 698 startingTabIndex = 0; | 694 startingTabIndex = 0; |
| 699 } | 695 } |
| 700 | 696 |
| 701 // However, if a node is excluded from the normal tabbing cycle, the previou
s focusable node is determined by tree order | 697 // However, if a node is excluded from the normal tabbing cycle, the previou
s focusable node is determined by tree order |
| 702 if (startingTabIndex < 0) { | 698 if (startingTabIndex < 0) { |
| 703 for (Node* node = startingNode; node; node = NodeTraversal::previous(*no
de)) { | 699 for (Node* node = startingNode; node; node = NodeTraversal::previous(*no
de)) { |
| 704 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0) | 700 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0) |
| 705 return node; | 701 return toElement(node); |
| 706 } | 702 } |
| 707 } else { | 703 } else { |
| 708 if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIn
dex, WebFocusTypeBackward)) | 704 if (Element* winner = findElementWithExactTabIndex(startingNode, startin
gTabIndex, WebFocusTypeBackward)) |
| 709 return winner; | 705 return winner; |
| 710 } | 706 } |
| 711 | 707 |
| 712 // There are no nodes before start with the same tabindex as start, so look
for a node that: | 708 // There are no nodes before start with the same tabindex as start, so look
for a node that: |
| 713 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and | 709 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and |
| 714 // 2) comes last in the scope, if there's a tie. | 710 // 2) comes last in the scope, if there's a tie. |
| 715 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); | 711 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); |
| 716 return previousNodeWithLowerTabIndex(last, startingTabIndex); | 712 return previousElementWithLowerTabIndex(last, startingTabIndex); |
| 717 } | 713 } |
| 718 | 714 |
| 719 Element* FocusController::findFocusableElement(WebFocusType type, Node& node) | 715 Element* FocusController::findFocusableElement(WebFocusType type, Node& node) |
| 720 { | 716 { |
| 721 // FIXME: No spacial navigation code yet. | 717 // FIXME: No spacial navigation code yet. |
| 722 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); | 718 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); |
| 723 Node* found = findFocusableNodeAcrossFocusScopes(type, FocusNavigationScope:
:focusNavigationScopeOf(node), &node); | 719 Element* found = findFocusableElementAcrossFocusScopes(type, FocusNavigation
Scope::focusNavigationScopeOf(node), &node); |
| 724 ASSERT(!found || found->isElementNode()); | 720 return found; |
| 725 return toElement(found); | |
| 726 } | 721 } |
| 727 | 722 |
| 728 Element* FocusController::findFocusableElement(WebFocusType type, const FocusNav
igationScope& scope, Node* node) | 723 Element* FocusController::findFocusableElement(WebFocusType type, const FocusNav
igationScope& scope, Node* node) |
| 729 { | 724 { |
| 730 Node* found = (type == WebFocusTypeForward) ? nextFocusableNode(scope, node)
: previousFocusableNode(scope, node); | 725 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope,
node) : previousFocusableElement(scope, node); |
| 731 ASSERT(!found || found->isElementNode()); | 726 return found; |
| 732 return toElement(found); | |
| 733 } | 727 } |
| 734 | 728 |
| 735 static bool relinquishesEditingFocus(const Element& element) | 729 static bool relinquishesEditingFocus(const Element& element) |
| 736 { | 730 { |
| 737 ASSERT(element.hasEditableStyle()); | 731 ASSERT(element.hasEditableStyle()); |
| 738 return element.document().frame() && element.rootEditableElement(); | 732 return element.document().frame() && element.rootEditableElement(); |
| 739 } | 733 } |
| 740 | 734 |
| 741 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Node* newFocusedNode) | 735 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Element* newFocusedElement) |
| 742 { | 736 { |
| 743 if (!oldFocusedFrame || !newFocusedFrame) | 737 if (!oldFocusedFrame || !newFocusedFrame) |
| 744 return; | 738 return; |
| 745 | 739 |
| 746 if (oldFocusedFrame->document() != newFocusedFrame->document()) | 740 if (oldFocusedFrame->document() != newFocusedFrame->document()) |
| 747 return; | 741 return; |
| 748 | 742 |
| 749 FrameSelection& selection = oldFocusedFrame->selection(); | 743 FrameSelection& selection = oldFocusedFrame->selection(); |
| 750 if (selection.isNone()) | 744 if (selection.isNone()) |
| 751 return; | 745 return; |
| 752 | 746 |
| 753 bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled(); | 747 bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled(); |
| 754 if (caretBrowsing) | 748 if (caretBrowsing) |
| 755 return; | 749 return; |
| 756 | 750 |
| 757 Node* selectionStartNode = selection.selection().start().deprecatedNode(); | 751 Node* selectionStartNode = selection.selection().start().deprecatedNode(); |
| 758 if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendant
Of(newFocusedNode)) | 752 if (selectionStartNode == newFocusedElement || selectionStartNode->isDescend
antOf(newFocusedElement)) |
| 759 return; | 753 return; |
| 760 | 754 |
| 761 if (!enclosingTextFormControl(selectionStartNode)) | 755 if (!enclosingTextFormControl(selectionStartNode)) |
| 762 return; | 756 return; |
| 763 | 757 |
| 764 if (selectionStartNode->isInShadowTree() && selectionStartNode->shadowHost()
== newFocusedNode) | 758 if (selectionStartNode->isInShadowTree() && selectionStartNode->shadowHost()
== newFocusedElement) |
| 765 return; | 759 return; |
| 766 | 760 |
| 767 selection.clear(); | 761 selection.clear(); |
| 768 } | 762 } |
| 769 | 763 |
| 770 bool FocusController::setFocusedElement(Element* element, PassRefPtrWillBeRawPtr
<Frame> newFocusedFrame, WebFocusType type) | 764 bool FocusController::setFocusedElement(Element* element, PassRefPtrWillBeRawPtr
<Frame> newFocusedFrame, WebFocusType type) |
| 771 { | 765 { |
| 772 RefPtrWillBeRawPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame()
); | 766 RefPtrWillBeRawPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame()
); |
| 773 RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame
->document() : nullptr; | 767 RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame
->document() : nullptr; |
| 774 | 768 |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 return consumed; | 1013 return consumed; |
| 1020 } | 1014 } |
| 1021 | 1015 |
| 1022 DEFINE_TRACE(FocusController) | 1016 DEFINE_TRACE(FocusController) |
| 1023 { | 1017 { |
| 1024 visitor->trace(m_page); | 1018 visitor->trace(m_page); |
| 1025 visitor->trace(m_focusedFrame); | 1019 visitor->trace(m_focusedFrame); |
| 1026 } | 1020 } |
| 1027 | 1021 |
| 1028 } // namespace blink | 1022 } // namespace blink |
| OLD | NEW |