| 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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 inline bool hasCustomFocusLogic(const Element& element) | 357 inline bool hasCustomFocusLogic(const Element& element) |
| 358 { | 358 { |
| 359 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic
(); | 359 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic
(); |
| 360 } | 360 } |
| 361 | 361 |
| 362 inline bool isShadowHostWithoutCustomFocusLogic(const Element& element) | 362 inline bool isShadowHostWithoutCustomFocusLogic(const Element& element) |
| 363 { | 363 { |
| 364 return isShadowHost(element) && !hasCustomFocusLogic(element); | 364 return isShadowHost(element) && !hasCustomFocusLogic(element); |
| 365 } | 365 } |
| 366 | 366 |
| 367 #if ENABLE(ASSERT) | |
| 368 inline bool isNonFocusableShadowHost(const Element& element) | |
| 369 { | |
| 370 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable(
); | |
| 371 } | |
| 372 #endif | |
| 373 | |
| 374 inline bool isNonKeyboardFocusableShadowHost(const Element& element) | 367 inline bool isNonKeyboardFocusableShadowHost(const Element& element) |
| 375 { | 368 { |
| 376 return isShadowHostWithoutCustomFocusLogic(element) && !(element.shadowRootI
fV1() ? element.isFocusable() : element.isKeyboardFocusable()); | 369 return isShadowHostWithoutCustomFocusLogic(element) && !(element.shadowRootI
fV1() ? element.isFocusable() : element.isKeyboardFocusable()); |
| 377 } | 370 } |
| 378 | 371 |
| 379 inline bool isKeyboardFocusableShadowHost(const Element& element) | 372 inline bool isKeyboardFocusableShadowHost(const Element& element) |
| 380 { | 373 { |
| 381 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc
usable(); | 374 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc
usable(); |
| 382 } | 375 } |
| 383 | 376 |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 break; | 632 break; |
| 640 ASSERT(element != foundElement); | 633 ASSERT(element != foundElement); |
| 641 element = foundElement; | 634 element = foundElement; |
| 642 } | 635 } |
| 643 return element; | 636 return element; |
| 644 } | 637 } |
| 645 | 638 |
| 646 Element* findFocusableElementAcrossFocusScopesForward(ScopedFocusNavigation& sco
pe) | 639 Element* findFocusableElementAcrossFocusScopesForward(ScopedFocusNavigation& sco
pe) |
| 647 { | 640 { |
| 648 Element* current = scope.currentElement(); | 641 Element* current = scope.currentElement(); |
| 649 ASSERT(!current || !isNonFocusableShadowHost(*current)); | |
| 650 Element* found; | 642 Element* found; |
| 651 if (current && isShadowHostWithoutCustomFocusLogic(*current)) { | 643 if (current && isShadowHostWithoutCustomFocusLogic(*current)) { |
| 652 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowH
ost(*current); | 644 ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowH
ost(*current); |
| 653 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward
(innerScope); | 645 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward
(innerScope); |
| 654 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE
lementRecursivelyForward(scope); | 646 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE
lementRecursivelyForward(scope); |
| 655 } else { | 647 } else { |
| 656 found = findFocusableElementRecursivelyForward(scope); | 648 found = findFocusableElementRecursivelyForward(scope); |
| 657 } | 649 } |
| 658 | 650 |
| 659 // If there's no focusable element to advance to, move up the focus scopes u
ntil we find one. | 651 // If there's no focusable element to advance to, move up the focus scopes u
ntil we find one. |
| 660 ScopedFocusNavigation currentScope = scope; | 652 ScopedFocusNavigation currentScope = scope; |
| 661 while (!found) { | 653 while (!found) { |
| 662 Element* owner = currentScope.owner(); | 654 Element* owner = currentScope.owner(); |
| 663 if (!owner) | 655 if (!owner) |
| 664 break; | 656 break; |
| 665 currentScope = ScopedFocusNavigation::createFor(*owner); | 657 currentScope = ScopedFocusNavigation::createFor(*owner); |
| 666 found = findFocusableElementRecursivelyForward(currentScope); | 658 found = findFocusableElementRecursivelyForward(currentScope); |
| 667 } | 659 } |
| 668 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa
rd, found); | 660 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa
rd, found); |
| 669 } | 661 } |
| 670 | 662 |
| 671 Element* findFocusableElementAcrossFocusScopesBackward(ScopedFocusNavigation& sc
ope) | 663 Element* findFocusableElementAcrossFocusScopesBackward(ScopedFocusNavigation& sc
ope) |
| 672 { | 664 { |
| 673 ASSERT(!scope.currentElement() || !isNonFocusableShadowHost(*scope.currentEl
ement())); | |
| 674 Element* found = findFocusableElementRecursivelyBackward(scope); | 665 Element* found = findFocusableElementRecursivelyBackward(scope); |
| 675 | 666 |
| 676 // If there's no focusable element to advance to, move up the focus scopes u
ntil we find one. | 667 // If there's no focusable element to advance to, move up the focus scopes u
ntil we find one. |
| 677 ScopedFocusNavigation currentScope = scope; | 668 ScopedFocusNavigation currentScope = scope; |
| 678 while (!found) { | 669 while (!found) { |
| 679 Element* owner = currentScope.owner(); | 670 Element* owner = currentScope.owner(); |
| 680 if (!owner) | 671 if (!owner) |
| 681 break; | 672 break; |
| 682 currentScope = ScopedFocusNavigation::createFor(*owner); | 673 currentScope = ScopedFocusNavigation::createFor(*owner); |
| 683 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { | 674 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 // element of the child frame. | 889 // element of the child frame. |
| 899 Element* start = nullptr; | 890 Element* start = nullptr; |
| 900 if (from->tree().parent() == to) { | 891 if (from->tree().parent() == to) { |
| 901 ASSERT(from->owner()->isLocal()); | 892 ASSERT(from->owner()->isLocal()); |
| 902 start = toHTMLFrameOwnerElement(from->owner()); | 893 start = toHTMLFrameOwnerElement(from->owner()); |
| 903 } | 894 } |
| 904 | 895 |
| 905 return advanceFocusInDocumentOrder(to, start, type, false, sourceCapabilitie
s); | 896 return advanceFocusInDocumentOrder(to, start, type, false, sourceCapabilitie
s); |
| 906 } | 897 } |
| 907 | 898 |
| 899 |
| 900 #if ENABLE(ASSERT) |
| 901 inline bool isNonFocusableShadowHost(const Element& element) |
| 902 { |
| 903 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable(
); |
| 904 } |
| 905 #endif |
| 906 |
| 908 bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
art, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabi
lities) | 907 bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
art, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCapabi
lities) |
| 909 { | 908 { |
| 910 ASSERT(frame); | 909 ASSERT(frame); |
| 911 Document* document = frame->document(); | 910 Document* document = frame->document(); |
| 912 document->updateDistribution(); | 911 document->updateDistribution(); |
| 913 | 912 |
| 914 Element* current = start; | 913 Element* current = start; |
| 914 ASSERT(!current || !isNonFocusableShadowHost(*current)); |
| 915 if (!current && !initialFocus) | 915 if (!current && !initialFocus) |
| 916 current = document->sequentialFocusNavigationStartingPoint(type); | 916 current = document->sequentialFocusNavigationStartingPoint(type); |
| 917 | 917 |
| 918 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself | 918 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself |
| 919 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); | 919 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); |
| 920 | 920 |
| 921 if (caretBrowsing && !current) | 921 if (caretBrowsing && !current) |
| 922 current = adjustToElement(frame->selection().start().anchorNode(), type)
; | 922 current = adjustToElement(frame->selection().start().anchorNode(), type)
; |
| 923 | 923 |
| 924 document->updateLayoutIgnorePendingStylesheets(); | 924 document->updateLayoutIgnorePendingStylesheets(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 945 | 945 |
| 946 // Chrome doesn't want focus, so we should wrap focus. | 946 // Chrome doesn't want focus, so we should wrap focus. |
| 947 ScopedFocusNavigation scope = ScopedFocusNavigation::createForDocument(*
toLocalFrame(m_page->mainFrame())->document()); | 947 ScopedFocusNavigation scope = ScopedFocusNavigation::createForDocument(*
toLocalFrame(m_page->mainFrame())->document()); |
| 948 element = findFocusableElementRecursively(type, scope); | 948 element = findFocusableElementRecursively(type, scope); |
| 949 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem
ent); | 949 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem
ent); |
| 950 | 950 |
| 951 if (!element) | 951 if (!element) |
| 952 return false; | 952 return false; |
| 953 } | 953 } |
| 954 | 954 |
| 955 ASSERT(element); | |
| 956 | |
| 957 if (element == document->focusedElement()) { | 955 if (element == document->focusedElement()) { |
| 958 // Focus wrapped around to the same element. | 956 // Focus wrapped around to the same element. |
| 959 return true; | 957 return true; |
| 960 } | 958 } |
| 961 | 959 |
| 962 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el
ement->isKeyboardFocusable())) { | 960 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el
ement->isKeyboardFocusable())) { |
| 963 // We focus frames rather than frame owners. | 961 // We focus frames rather than frame owners. |
| 964 // FIXME: We should not focus frames that have no scrollbars, as focusin
g them isn't useful to the user. | 962 // FIXME: We should not focus frames that have no scrollbars, as focusin
g them isn't useful to the user. |
| 965 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); | 963 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); |
| 966 if (!owner->contentFrame()) | 964 if (!owner->contentFrame()) |
| 967 return false; | 965 return false; |
| 968 | 966 |
| 969 document->clearFocusedElement(); | 967 document->clearFocusedElement(); |
| 970 setFocusedFrame(owner->contentFrame()); | 968 setFocusedFrame(owner->contentFrame()); |
| 971 | 969 |
| 972 // If contentFrame is remote, continue the search for focusable | 970 // If contentFrame is remote, continue the search for focusable |
| 973 // elements in that frame's process. | 971 // elements in that frame's process. |
| 974 // clearFocusedElement() fires events that might detach the | 972 // clearFocusedElement() fires events that might detach the |
| 975 // contentFrame, hence the need to null-check it again. | 973 // contentFrame, hence the need to null-check it again. |
| 976 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) | 974 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) |
| 977 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); | 975 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); |
| 978 | 976 |
| 979 return true; | 977 return true; |
| 980 } | 978 } |
| 981 | 979 |
| 980 ASSERT(element->isFocusable()); |
| 981 |
| 982 // FIXME: It would be nice to just be able to call setFocusedElement(element
) | 982 // FIXME: It would be nice to just be able to call setFocusedElement(element
) |
| 983 // here, but we can't do that because some elements (e.g. HTMLInputElement | 983 // here, but we can't do that because some elements (e.g. HTMLInputElement |
| 984 // and HTMLTextAreaElement) do extra work in their focus() methods. | 984 // and HTMLTextAreaElement) do extra work in their focus() methods. |
| 985 Document& newDocument = element->document(); | 985 Document& newDocument = element->document(); |
| 986 | 986 |
| 987 if (&newDocument != document) { | 987 if (&newDocument != document) { |
| 988 // Focus is going away from this document, so clear the focused element. | 988 // Focus is going away from this document, so clear the focused element. |
| 989 document->clearFocusedElement(); | 989 document->clearFocusedElement(); |
| 990 } | 990 } |
| 991 | 991 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1306 return consumed; | 1306 return consumed; |
| 1307 } | 1307 } |
| 1308 | 1308 |
| 1309 DEFINE_TRACE(FocusController) | 1309 DEFINE_TRACE(FocusController) |
| 1310 { | 1310 { |
| 1311 visitor->trace(m_page); | 1311 visitor->trace(m_page); |
| 1312 visitor->trace(m_focusedFrame); | 1312 visitor->trace(m_focusedFrame); |
| 1313 } | 1313 } |
| 1314 | 1314 |
| 1315 } // namespace blink | 1315 } // namespace blink |
| OLD | NEW |