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()) |
(...skipping 14 matching lines...) Expand all Loading... |
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 |