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 25 matching lines...) Expand all Loading... | |
36 #include "core/dom/Range.h" | 36 #include "core/dom/Range.h" |
37 #include "core/dom/shadow/ElementShadow.h" | 37 #include "core/dom/shadow/ElementShadow.h" |
38 #include "core/dom/shadow/ShadowRoot.h" | 38 #include "core/dom/shadow/ShadowRoot.h" |
39 #include "core/editing/EditingUtilities.h" // For firstPositionInOrBeforeNode | 39 #include "core/editing/EditingUtilities.h" // For firstPositionInOrBeforeNode |
40 #include "core/editing/Editor.h" | 40 #include "core/editing/Editor.h" |
41 #include "core/editing/FrameSelection.h" | 41 #include "core/editing/FrameSelection.h" |
42 #include "core/events/Event.h" | 42 #include "core/events/Event.h" |
43 #include "core/frame/FrameView.h" | 43 #include "core/frame/FrameView.h" |
44 #include "core/frame/LocalDOMWindow.h" | 44 #include "core/frame/LocalDOMWindow.h" |
45 #include "core/frame/LocalFrame.h" | 45 #include "core/frame/LocalFrame.h" |
46 #include "core/frame/RemoteFrame.h" | |
46 #include "core/frame/Settings.h" | 47 #include "core/frame/Settings.h" |
47 #include "core/html/HTMLAreaElement.h" | 48 #include "core/html/HTMLAreaElement.h" |
48 #include "core/html/HTMLImageElement.h" | 49 #include "core/html/HTMLImageElement.h" |
49 #include "core/html/HTMLPlugInElement.h" | 50 #include "core/html/HTMLPlugInElement.h" |
50 #include "core/html/HTMLShadowElement.h" | 51 #include "core/html/HTMLShadowElement.h" |
51 #include "core/html/HTMLTextFormControlElement.h" | 52 #include "core/html/HTMLTextFormControlElement.h" |
52 #include "core/input/EventHandler.h" | 53 #include "core/input/EventHandler.h" |
53 #include "core/page/ChromeClient.h" | 54 #include "core/page/ChromeClient.h" |
54 #include "core/page/FrameTree.h" | 55 #include "core/page/FrameTree.h" |
55 #include "core/page/Page.h" | 56 #include "core/page/Page.h" |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
683 cache->handleInitialFocus(); | 684 cache->handleInitialFocus(); |
684 } | 685 } |
685 | 686 |
686 return didAdvanceFocus; | 687 return didAdvanceFocus; |
687 } | 688 } |
688 | 689 |
689 bool FocusController::advanceFocus(WebFocusType type, bool initialFocus, InputDe viceCapabilities* sourceCapabilities) | 690 bool FocusController::advanceFocus(WebFocusType type, bool initialFocus, InputDe viceCapabilities* sourceCapabilities) |
690 { | 691 { |
691 switch (type) { | 692 switch (type) { |
692 case WebFocusTypeForward: | 693 case WebFocusTypeForward: |
693 case WebFocusTypeBackward: | 694 case WebFocusTypeBackward: { |
694 return advanceFocusInDocumentOrder(type, initialFocus, sourceCapabilitie s); | 695 // We should never hit this when a RemoteFrame is focused, since the key |
696 // event that initiated focus advancement should've been routed to that | |
697 // frame's process from the beginning. | |
698 LocalFrame* startingFrame = toLocalFrame(focusedOrMainFrame()); | |
699 return advanceFocusInDocumentOrder(startingFrame, nullptr, type, initial Focus, sourceCapabilities); | |
700 } | |
695 case WebFocusTypeLeft: | 701 case WebFocusTypeLeft: |
696 case WebFocusTypeRight: | 702 case WebFocusTypeRight: |
697 case WebFocusTypeUp: | 703 case WebFocusTypeUp: |
698 case WebFocusTypeDown: | 704 case WebFocusTypeDown: |
699 return advanceFocusDirectionally(type); | 705 return advanceFocusDirectionally(type); |
700 default: | 706 default: |
701 ASSERT_NOT_REACHED(); | 707 ASSERT_NOT_REACHED(); |
702 } | 708 } |
703 | 709 |
704 return false; | 710 return false; |
705 } | 711 } |
706 | 712 |
707 bool FocusController::advanceFocusInDocumentOrder(WebFocusType type, bool initia lFocus, InputDeviceCapabilities* sourceCapabilities) | 713 bool FocusController::advanceFocusAcrossFrames(WebFocusType type, RemoteFrame* f rom, LocalFrame* to, InputDeviceCapabilities* sourceCapabilities) |
708 { | 714 { |
709 // FIXME: Focus advancement won't work with externally rendered frames until after | 715 // If we are shifting focus from a child frame to its parent, the |
710 // inter-frame focus control is moved out of Blink. | 716 // child frame has no more focusable elements, and we should continue |
711 if (!focusedOrMainFrame()->isLocalFrame()) | 717 // looking for focusable elements in the parent, starting from the <iframe> |
712 return false; | 718 // element of the child frame. |
713 LocalFrame* frame = toLocalFrame(focusedOrMainFrame()); | 719 Node* startingNode = nullptr; |
720 if (from->tree().parent() == to) { | |
721 ASSERT(from->owner()->isLocal()); | |
722 startingNode = toHTMLFrameOwnerElement(from->owner()); | |
723 } | |
724 | |
725 return advanceFocusInDocumentOrder(to, startingNode, type, false, sourceCapa bilities); | |
726 } | |
727 | |
728 bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Node* start ingNode, WebFocusType type, bool initialFocus, InputDeviceCapabilities* sourceCa pabilities) | |
729 { | |
714 ASSERT(frame); | 730 ASSERT(frame); |
715 Document* document = frame->document(); | 731 Document* document = frame->document(); |
716 | 732 |
717 Node* currentNode = document->focusedElement(); | 733 Node* currentNode = startingNode; |
734 if (!currentNode) | |
735 currentNode = document->focusedElement(); | |
736 | |
718 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself | 737 // FIXME: Not quite correct when it comes to focus transitions leaving/enter ing the WebView itself |
719 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled(); | 738 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn abled(); |
720 | 739 |
721 if (caretBrowsing && !currentNode) | 740 if (caretBrowsing && !currentNode) |
722 currentNode = frame->selection().start().anchorNode(); | 741 currentNode = frame->selection().start().anchorNode(); |
723 | 742 |
724 document->updateLayoutIgnorePendingStylesheets(); | 743 document->updateLayoutIgnorePendingStylesheets(); |
725 | 744 |
726 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode : *document), currentNode); | 745 RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes( type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode : *document), currentNode); |
727 | 746 |
728 if (!element) { | 747 if (!element) { |
748 // If there's a RemoteFrame on the ancestor chain, we need to continue | |
749 // searching for focusable elements there. | |
750 if (frame->localFrameRoot() != frame->tree().top()) { | |
751 document->clearFocusedElement(); | |
752 toRemoteFrame(frame->localFrameRoot()->tree().parent())->advanceFocu s(type, frame->localFrameRoot()); | |
753 return true; | |
754 } | |
755 | |
729 // We didn't find an element to focus, so we should try to pass focus to Chrome. | 756 // We didn't find an element to focus, so we should try to pass focus to Chrome. |
730 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { | 757 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { |
731 document->clearFocusedElement(); | 758 document->clearFocusedElement(); |
732 setFocusedFrame(nullptr); | 759 setFocusedFrame(nullptr); |
733 m_page->chromeClient().takeFocus(type); | 760 m_page->chromeClient().takeFocus(type); |
734 return true; | 761 return true; |
735 } | 762 } |
736 | 763 |
737 // Chrome doesn't want focus, so we should wrap focus. | 764 // Chrome doesn't want focus, so we should wrap focus. |
738 if (!m_page->mainFrame()->isLocalFrame()) | 765 if (!m_page->mainFrame()->isLocalFrame()) |
739 return false; | 766 return false; |
dcheng
2015/12/04 23:11:01
I think we should be able to remove this.
alexmos
2015/12/05 00:07:45
Done. Indeed, focus wrapping to Chrome should onl
| |
740 element = findFocusableElementRecursively(type, FocusNavigationScope::fo cusNavigationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); | 767 element = findFocusableElementRecursively(type, FocusNavigationScope::fo cusNavigationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); |
dcheng
2015/12/04 23:11:01
and we can just make this toLocalFrame(m_page->mai
alexmos
2015/12/05 00:07:45
Done.
| |
741 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get()); | 768 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get()); |
742 | 769 |
743 if (!element) | 770 if (!element) |
744 return false; | 771 return false; |
745 } | 772 } |
746 | 773 |
747 ASSERT(element); | 774 ASSERT(element); |
748 | 775 |
749 if (element == document->focusedElement()) { | 776 if (element == document->focusedElement()) { |
750 // Focus wrapped around to the same node. | 777 // Focus wrapped around to the same node. |
751 return true; | 778 return true; |
752 } | 779 } |
753 | 780 |
754 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el ement->isKeyboardFocusable())) { | 781 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el ement->isKeyboardFocusable())) { |
755 // We focus frames rather than frame owners. | 782 // We focus frames rather than frame owners. |
756 // FIXME: We should not focus frames that have no scrollbars, as focusin g them isn't useful to the user. | 783 // FIXME: We should not focus frames that have no scrollbars, as focusin g them isn't useful to the user. |
757 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); | 784 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); |
758 if (!owner->contentFrame()) | 785 if (!owner->contentFrame()) |
759 return false; | 786 return false; |
760 | 787 |
761 document->clearFocusedElement(); | 788 document->clearFocusedElement(); |
762 setFocusedFrame(owner->contentFrame()); | 789 setFocusedFrame(owner->contentFrame()); |
790 | |
791 // If contentFrame is remote, continue the search for focusable | |
792 // elements in that frame's process. | |
793 // clearFocusedElement() fires events that might detach the | |
794 // contentFrame, hence the need to null-check it again. | |
795 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) | |
796 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); | |
797 | |
763 return true; | 798 return true; |
764 } | 799 } |
765 | 800 |
766 // FIXME: It would be nice to just be able to call setFocusedElement(node) | 801 // FIXME: It would be nice to just be able to call setFocusedElement(node) |
767 // here, but we can't do that because some elements (e.g. HTMLInputElement | 802 // here, but we can't do that because some elements (e.g. HTMLInputElement |
768 // and HTMLTextAreaElement) do extra work in their focus() methods. | 803 // and HTMLTextAreaElement) do extra work in their focus() methods. |
769 Document& newDocument = element->document(); | 804 Document& newDocument = element->document(); |
770 | 805 |
771 if (&newDocument != document) { | 806 if (&newDocument != document) { |
772 // Focus is going away from this document, so clear the focused node. | 807 // Focus is going away from this document, so clear the focused node. |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1086 return consumed; | 1121 return consumed; |
1087 } | 1122 } |
1088 | 1123 |
1089 DEFINE_TRACE(FocusController) | 1124 DEFINE_TRACE(FocusController) |
1090 { | 1125 { |
1091 visitor->trace(m_page); | 1126 visitor->trace(m_page); |
1092 visitor->trace(m_focusedFrame); | 1127 visitor->trace(m_focusedFrame); |
1093 } | 1128 } |
1094 | 1129 |
1095 } // namespace blink | 1130 } // namespace blink |
OLD | NEW |