summaryrefslogtreecommitdiffstats
path: root/dom/base/nsFocusManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/nsFocusManager.cpp')
-rw-r--r--dom/base/nsFocusManager.cpp107
1 files changed, 74 insertions, 33 deletions
diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
index 08a2641333..5a4cf78d65 100644
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -3358,7 +3358,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
}
return GetNextTabbableContent(presShell, startContent, nullptr,
startContent, true, 1, false, false,
- aNavigateByKey, false, aNextContent);
+ aNavigateByKey, false, false, aNextContent);
}
if (aType == MOVEFOCUS_LAST) {
if (!aStartContent) {
@@ -3366,7 +3366,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
}
return GetNextTabbableContent(presShell, startContent, nullptr,
startContent, false, 0, false, false,
- aNavigateByKey, false, aNextContent);
+ aNavigateByKey, false, false, aNextContent);
}
bool forward = (aType == MOVEFOCUS_FORWARD || aType == MOVEFOCUS_FORWARDDOC ||
@@ -3537,7 +3537,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
MOZ_KnownLive(skipOriginalContentCheck ? nullptr
: originalStartContent.get()),
startContent, forward, tabIndex, ignoreTabIndex,
- forDocumentNavigation, aNavigateByKey, false,
+ forDocumentNavigation, aNavigateByKey, false, false,
getter_AddRefs(nextFocus));
NS_ENSURE_SUCCESS(rv, rv);
if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
@@ -3660,15 +3660,16 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
// If the focus started in this window outside a popup however, we should
// continue by looping around to the end again.
if (forDocumentNavigation && (forward || mayFocusRoot || popupFrame)) {
- // HTML content documents can have their root element focused (a focus
- // ring appears around the entire content area frame). This root
- // appears in the tab order before all of the elements in the document.
- // Chrome documents however cannot be focused directly, so instead we
- // focus the first focusable element within the window.
+ // HTML content documents can have their root element focused by
+ // pressing F6(a focus ring appears around the entire content area
+ // frame). This root appears in the tab order before all of the elements
+ // in the document. Chrome documents however cannot be focused directly,
+ // so instead we focus the first focusable element within the window.
// For example, the urlbar.
RefPtr<Element> rootElementForFocus =
GetRootForFocus(piWindow, doc, true, true);
- return FocusFirst(rootElementForFocus, aNextContent);
+ return FocusFirst(rootElementForFocus, aNextContent,
+ true /* aReachedToEndForDocumentNavigation */);
}
// Once we have hit the top-level and have iterated to the end again, we
@@ -3889,7 +3890,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
nsIContent* aOwner, nsIContent* aStartContent,
nsIContent* aOriginalStartContent, bool aForward, int32_t aCurrentTabIndex,
bool aIgnoreTabIndex, bool aForDocumentNavigation, bool aNavigateByKey,
- bool aSkipOwner) {
+ bool aSkipOwner, bool aReachedToEndForDocumentNavigation) {
MOZ_ASSERT(
IsHostOrSlot(aOwner) || IsOpenPopoverWithInvoker(aOwner),
"Scope owner should be host, slot or an open popover with invoker set.");
@@ -3972,6 +3973,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
if (TryToMoveFocusToSubDocument(iterContent, aOriginalStartContent,
aForward, aForDocumentNavigation,
aNavigateByKey,
+ aReachedToEndForDocumentNavigation,
getter_AddRefs(elementInFrame))) {
return elementInFrame;
}
@@ -3984,7 +3986,8 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
iterContent, iterContent, aOriginalStartContent, aForward,
aForward ? 1 : 0, aIgnoreTabIndex, aForDocumentNavigation,
- aNavigateByKey, false /* aSkipOwner */);
+ aNavigateByKey, false /* aSkipOwner */,
+ aReachedToEndForDocumentNavigation);
if (contentToFocus) {
return contentToFocus;
}
@@ -4024,7 +4027,8 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
nsIContent* nsFocusManager::GetNextTabbableContentInAncestorScopes(
nsIContent* aStartOwner, nsCOMPtr<nsIContent>& aStartContent /* inout */,
nsIContent* aOriginalStartContent, bool aForward, int32_t* aCurrentTabIndex,
- bool* aIgnoreTabIndex, bool aForDocumentNavigation, bool aNavigateByKey) {
+ bool* aIgnoreTabIndex, bool aForDocumentNavigation, bool aNavigateByKey,
+ bool aReachedToEndForDocumentNavigation) {
MOZ_ASSERT(aStartOwner == FindScopeOwner(aStartContent),
"aStartOWner should be the scope owner of aStartContent");
MOZ_ASSERT(IsHostOrSlot(aStartOwner), "scope owner should be host or slot");
@@ -4043,7 +4047,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInAncestorScopes(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
owner, startContent, aOriginalStartContent, aForward, tabIndex,
tabIndex < 0, aForDocumentNavigation, aNavigateByKey,
- false /* aSkipOwner */);
+ false /* aSkipOwner */, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
return contentToFocus;
}
@@ -4089,7 +4093,8 @@ nsresult nsFocusManager::GetNextTabbableContent(
PresShell* aPresShell, nsIContent* aRootContent,
nsIContent* aOriginalStartContent, nsIContent* aStartContent, bool aForward,
int32_t aCurrentTabIndex, bool aIgnoreTabIndex, bool aForDocumentNavigation,
- bool aNavigateByKey, bool aSkipPopover, nsIContent** aResultContent) {
+ bool aNavigateByKey, bool aSkipPopover,
+ bool aReachedToEndForDocumentNavigation, nsIContent** aResultContent) {
*aResultContent = nullptr;
if (!aStartContent) {
@@ -4109,7 +4114,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
startContent, startContent, aOriginalStartContent, aForward, 1,
aIgnoreTabIndex, aForDocumentNavigation, aNavigateByKey,
- true /* aSkipOwner */);
+ true /* aSkipOwner */, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
return NS_OK;
@@ -4125,7 +4130,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
popover, popover, aOriginalStartContent, aForward, 1,
aIgnoreTabIndex, aForDocumentNavigation, aNavigateByKey,
- true /* aSkipOwner */);
+ true /* aSkipOwner */, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
return NS_OK;
@@ -4140,7 +4145,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
nsIContent* contentToFocus = GetNextTabbableContentInAncestorScopes(
owner, startContent /* inout */, aOriginalStartContent, aForward,
&aCurrentTabIndex, &aIgnoreTabIndex, aForDocumentNavigation,
- aNavigateByKey);
+ aNavigateByKey, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
return NS_OK;
@@ -4185,7 +4190,8 @@ nsresult nsFocusManager::GetNextTabbableContent(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
iterStartContent, iterStartContent, aOriginalStartContent,
aForward, aForward ? 1 : 0, aIgnoreTabIndex,
- aForDocumentNavigation, aNavigateByKey, true /* aSkipOwner */);
+ aForDocumentNavigation, aNavigateByKey, true /* aSkipOwner */,
+ aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
return NS_OK;
@@ -4276,7 +4282,8 @@ nsresult nsFocusManager::GetNextTabbableContent(
(aIgnoreTabIndex || aCurrentTabIndex == tabIndex)) {
nsresult rv = GetNextTabbableContent(
aPresShell, rootElement, nullptr, invokerContent, true,
- tabIndex, false, false, aNavigateByKey, true, aResultContent);
+ tabIndex, false, false, aNavigateByKey, true,
+ aReachedToEndForDocumentNavigation, aResultContent);
if (NS_SUCCEEDED(rv) && *aResultContent) {
return rv;
}
@@ -4298,7 +4305,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
nsIContent* contentToFocus = GetNextTabbableContentInScope(
popover, popover, aOriginalStartContent, aForward, 0,
aIgnoreTabIndex, aForDocumentNavigation, aNavigateByKey,
- true /* aSkipOwner */);
+ true /* aSkipOwner */, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
@@ -4340,7 +4347,8 @@ nsresult nsFocusManager::GetNextTabbableContent(
// want to locate the first content, not the first document.
nsresult rv = GetNextTabbableContent(
aPresShell, currentContent, nullptr, currentContent, true, 1,
- false, false, aNavigateByKey, false, aResultContent);
+ false, false, aNavigateByKey, false,
+ aReachedToEndForDocumentNavigation, aResultContent);
if (NS_SUCCEEDED(rv) && *aResultContent) {
return rv;
}
@@ -4368,7 +4376,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
currentTopLevelScopeOwner, currentTopLevelScopeOwner,
aOriginalStartContent, aForward, aForward ? 1 : 0,
aIgnoreTabIndex, aForDocumentNavigation, aNavigateByKey,
- true /* aSkipOwner */);
+ true /* aSkipOwner */, aReachedToEndForDocumentNavigation);
if (contentToFocus) {
NS_ADDREF(*aResultContent = contentToFocus);
return NS_OK;
@@ -4469,7 +4477,8 @@ nsresult nsFocusManager::GetNextTabbableContent(
// frame. If so, navigate into the child frame instead.
if (TryToMoveFocusToSubDocument(
currentContent, aOriginalStartContent, aForward,
- aForDocumentNavigation, aNavigateByKey, aResultContent)) {
+ aForDocumentNavigation, aNavigateByKey,
+ aReachedToEndForDocumentNavigation, aResultContent)) {
MOZ_ASSERT(*aResultContent);
return NS_OK;
}
@@ -4485,6 +4494,24 @@ nsresult nsFocusManager::GetNextTabbableContent(
NS_ADDREF(*aResultContent = currentContent);
return NS_OK;
}
+ } else if (currentContent && aReachedToEndForDocumentNavigation &&
+ StaticPrefs::dom_disable_tab_focus_to_root_element() &&
+ nsContentUtils::IsChromeDoc(
+ currentContent->GetComposedDoc())) {
+ // aReachedToEndForDocumentNavigation is true means
+ // 1. This is a document navigation (VK_F6)
+ // 2. This is the top-level document (Note that we may start from
+ // a subdocument)
+ // 3. We've searched through the this top-level document already
+ if (!GetRootForChildDocument(currentContent)) {
+ // We'd like to focus the first focusable element of this
+ // top-level chrome document.
+ if (currentContent == aRootContent ||
+ currentContent != startContent) {
+ NS_ADDREF(*aResultContent = currentContent);
+ return NS_OK;
+ }
+ }
}
}
} else if (aOriginalStartContent &&
@@ -4522,13 +4549,14 @@ nsresult nsFocusManager::GetNextTabbableContent(
if (aCurrentTabIndex == (aForward ? 0 : 1)) {
// if going backwards, the canvas should be focused once the beginning
// has been reached, so get the root element.
- if (!aForward) {
+ if (!aForward && !StaticPrefs::dom_disable_tab_focus_to_root_element()) {
nsCOMPtr<nsPIDOMWindowOuter> window = GetCurrentWindow(aRootContent);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
RefPtr<Element> docRoot = GetRootForFocus(
window, aRootContent->GetComposedDoc(), false, true);
- FocusFirst(docRoot, aResultContent);
+ FocusFirst(docRoot, aResultContent,
+ false /* aReachedToEndForDocumentNavigation */);
}
break;
}
@@ -4556,7 +4584,8 @@ bool nsFocusManager::TryDocumentNavigation(nsIContent* aCurrentContent,
// the frameset's frames and locate the first focusable frame.
if (!rootElementForChildDocument->IsHTMLElement(nsGkAtoms::frameset)) {
*aCheckSubDocument = false;
- Unused << FocusFirst(rootElementForChildDocument, aResultContent);
+ Unused << FocusFirst(rootElementForChildDocument, aResultContent,
+ false /* aReachedToEndForDocumentNavigation */);
return *aResultContent != nullptr;
}
} else {
@@ -4571,12 +4600,12 @@ bool nsFocusManager::TryDocumentNavigation(nsIContent* aCurrentContent,
bool nsFocusManager::TryToMoveFocusToSubDocument(
nsIContent* aCurrentContent, nsIContent* aOriginalStartContent,
bool aForward, bool aForDocumentNavigation, bool aNavigateByKey,
- nsIContent** aResultContent) {
+ bool aReachedToEndForDocumentNavigation, nsIContent** aResultContent) {
Document* doc = aCurrentContent->GetComposedDoc();
NS_ASSERTION(doc, "content not in document");
Document* subdoc = doc->GetSubDocumentFor(aCurrentContent);
if (subdoc && !subdoc->EventHandlingSuppressed()) {
- if (aForward) {
+ if (aForward && !StaticPrefs::dom_disable_tab_focus_to_root_element()) {
// When tabbing forward into a frame, return the root
// frame so that the canvas becomes focused.
if (nsCOMPtr<nsPIDOMWindowOuter> subframe = subdoc->GetWindow()) {
@@ -4592,11 +4621,19 @@ bool nsFocusManager::TryToMoveFocusToSubDocument(
nsresult rv = GetNextTabbableContent(
subPresShell, rootElement, aOriginalStartContent, rootElement,
aForward, (aForward ? 1 : 0), false, aForDocumentNavigation,
- aNavigateByKey, false, aResultContent);
+ aNavigateByKey, false, aReachedToEndForDocumentNavigation,
+ aResultContent);
NS_ENSURE_SUCCESS(rv, false);
if (*aResultContent) {
return true;
}
+ if (rootElement->IsEditable() &&
+ StaticPrefs::dom_disable_tab_focus_to_root_element()) {
+ // Only move to the root element with a valid reason
+ *aResultContent = rootElement;
+ NS_ADDREF(*aResultContent);
+ return true;
+ }
}
}
}
@@ -4711,7 +4748,8 @@ int32_t nsFocusManager::GetNextTabIndex(nsIContent* aParent,
}
nsresult nsFocusManager::FocusFirst(Element* aRootElement,
- nsIContent** aNextContent) {
+ nsIContent** aNextContent,
+ bool aReachedToEndForDocumentNavigation) {
if (!aRootElement) {
return NS_OK;
}
@@ -4741,9 +4779,12 @@ nsresult nsFocusManager::FocusFirst(Element* aRootElement,
// tabbable item so that the first item is focused. Note that we
// always go forward and not back here.
if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
- return GetNextTabbableContent(presShell, aRootElement, nullptr,
- aRootElement, true, 1, false, false, true,
- false, aNextContent);
+ return GetNextTabbableContent(
+ presShell, aRootElement, nullptr, aRootElement, true, 1, false,
+ StaticPrefs::dom_disable_tab_focus_to_root_element()
+ ? aReachedToEndForDocumentNavigation
+ : false,
+ true, false, aReachedToEndForDocumentNavigation, aNextContent);
}
}
}