| 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 |