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 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 // If we are shifting focus from a child frame to its parent, the | 926 // If we are shifting focus from a child frame to its parent, the |
927 // child frame has no more focusable elements, and we should continue | 927 // child frame has no more focusable elements, and we should continue |
928 // looking for focusable elements in the parent, starting from the <iframe> | 928 // looking for focusable elements in the parent, starting from the <iframe> |
929 // element of the child frame. | 929 // element of the child frame. |
930 Element* start = nullptr; | 930 Element* start = nullptr; |
931 if (from->tree().parent() == to) { | 931 if (from->tree().parent() == to) { |
932 DCHECK(from->owner()->isLocal()); | 932 DCHECK(from->owner()->isLocal()); |
933 start = toHTMLFrameOwnerElement(from->owner()); | 933 start = toHTMLFrameOwnerElement(from->owner()); |
934 } | 934 } |
935 | 935 |
936 // If we're coming from a parent frame, we need to restart from the first or | 936 return advanceFocusInDocumentOrder(to, start, type, false, |
937 // last focusable element. | |
938 bool initialFocus = to->tree().parent() == from; | |
939 | |
940 return advanceFocusInDocumentOrder(to, start, type, initialFocus, | |
941 sourceCapabilities); | 937 sourceCapabilities); |
942 } | 938 } |
943 | 939 |
944 #if DCHECK_IS_ON() | 940 #if DCHECK_IS_ON() |
945 inline bool isNonFocusableShadowHost(const Element& element) { | 941 inline bool isNonFocusableShadowHost(const Element& element) { |
946 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable(); | 942 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable(); |
947 } | 943 } |
948 #endif | 944 #endif |
949 | 945 |
950 bool FocusController::advanceFocusInDocumentOrder( | 946 bool FocusController::advanceFocusInDocumentOrder( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 *toLocalFrame(m_page->mainFrame())->document()); | 991 *toLocalFrame(m_page->mainFrame())->document()); |
996 element = findFocusableElementRecursively(type, scope); | 992 element = findFocusableElementRecursively(type, scope); |
997 element = | 993 element = |
998 findFocusableElementDescendingDownIntoFrameDocument(type, element); | 994 findFocusableElementDescendingDownIntoFrameDocument(type, element); |
999 | 995 |
1000 if (!element) | 996 if (!element) |
1001 return false; | 997 return false; |
1002 } | 998 } |
1003 | 999 |
1004 if (element == document->focusedElement()) { | 1000 if (element == document->focusedElement()) { |
1005 // Focus is either coming from a remote frame or has wrapped around. | 1001 // Focus wrapped around to the same element. |
1006 if (focusedFrame() != document->frame()) { | |
1007 setFocusedFrame(document->frame()); | |
1008 dispatchFocusEvent(*document, *element); | |
1009 } | |
1010 return true; | 1002 return true; |
1011 } | 1003 } |
1012 | 1004 |
1013 if (element->isFrameOwnerElement() && | 1005 if (element->isFrameOwnerElement() && |
1014 (!isHTMLPlugInElement(*element) || !element->isKeyboardFocusable())) { | 1006 (!isHTMLPlugInElement(*element) || !element->isKeyboardFocusable())) { |
1015 // We focus frames rather than frame owners. | 1007 // We focus frames rather than frame owners. |
1016 // FIXME: We should not focus frames that have no scrollbars, as focusing | 1008 // FIXME: We should not focus frames that have no scrollbars, as focusing |
1017 // them isn't useful to the user. | 1009 // them isn't useful to the user. |
1018 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); | 1010 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); |
1019 if (!owner->contentFrame()) | 1011 if (!owner->contentFrame()) |
1020 return false; | 1012 return false; |
1021 | 1013 |
1022 document->clearFocusedElement(); | 1014 document->clearFocusedElement(); |
| 1015 setFocusedFrame(owner->contentFrame()); |
1023 | 1016 |
1024 // If contentFrame is remote, continue the search for focusable elements in | 1017 // If contentFrame is remote, continue the search for focusable |
1025 // that frame's process. The target contentFrame's process will grab focus | 1018 // elements in that frame's process. |
1026 // from inside advanceFocusInDocumentOrder(). | 1019 // clearFocusedElement() fires events that might detach the |
1027 // | 1020 // contentFrame, hence the need to null-check it again. |
1028 // clearFocusedElement() fires events that might detach the contentFrame, | |
1029 // hence the need to null-check it again. | |
1030 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) | 1021 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) |
1031 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); | 1022 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); |
1032 else | |
1033 setFocusedFrame(owner->contentFrame()); | |
1034 | 1023 |
1035 return true; | 1024 return true; |
1036 } | 1025 } |
1037 | 1026 |
1038 DCHECK(element->isFocusable()); | 1027 DCHECK(element->isFocusable()); |
1039 | 1028 |
1040 // FIXME: It would be nice to just be able to call setFocusedElement(element) | 1029 // FIXME: It would be nice to just be able to call setFocusedElement(element) |
1041 // here, but we can't do that because some elements (e.g. HTMLInputElement | 1030 // here, but we can't do that because some elements (e.g. HTMLInputElement |
1042 // and HTMLTextAreaElement) do extra work in their focus() methods. | 1031 // and HTMLTextAreaElement) do extra work in their focus() methods. |
1043 Document& newDocument = element->document(); | 1032 Document& newDocument = element->document(); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 it->focusedFrameChanged(); | 1418 it->focusedFrameChanged(); |
1430 } | 1419 } |
1431 | 1420 |
1432 DEFINE_TRACE(FocusController) { | 1421 DEFINE_TRACE(FocusController) { |
1433 visitor->trace(m_page); | 1422 visitor->trace(m_page); |
1434 visitor->trace(m_focusedFrame); | 1423 visitor->trace(m_focusedFrame); |
1435 visitor->trace(m_focusChangedObservers); | 1424 visitor->trace(m_focusChangedObservers); |
1436 } | 1425 } |
1437 | 1426 |
1438 } // namespace blink | 1427 } // namespace blink |
OLD | NEW |