зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1351248 - Simplify nsIFrame::IsFocusable API. r=layout-reviewers,mats
We always compute the tabindex value, so just return it to the caller all the time. This allows us to use early-returns which makes the code a bit easier to follow. This patch shouldn't change behavior. Differential Revision: https://phabricator.services.mozilla.com/D100423
This commit is contained in:
Родитель
ea48adf8c2
Коммит
bd8cffdd58
|
@ -2033,8 +2033,7 @@ Element* nsFocusManager::FlushAndCheckIfFocusable(Element* aElement,
|
|||
: nullptr;
|
||||
}
|
||||
|
||||
return frame->IsFocusable(nullptr, aFlags & FLAG_BYMOUSE) ? aElement
|
||||
: nullptr;
|
||||
return frame->IsFocusable(aFlags & FLAG_BYMOUSE) ? aElement : nullptr;
|
||||
}
|
||||
|
||||
bool nsFocusManager::Blur(BrowsingContext* aBrowsingContextToClear,
|
||||
|
@ -3294,7 +3293,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
|
|||
if (startContent->IsHTMLElement(nsGkAtoms::area)) {
|
||||
startContent->IsFocusable(&tabIndex);
|
||||
} else if (frame) {
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
tabIndex = frame->IsFocusable().mTabIndex;
|
||||
} else {
|
||||
startContent->IsFocusable(&tabIndex);
|
||||
}
|
||||
|
@ -3528,7 +3527,7 @@ nsresult nsFocusManager::DetermineElementToMoveFocus(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
tabIndex = frame->IsFocusable().mTabIndex;
|
||||
if (tabIndex < 0) {
|
||||
tabIndex = 1;
|
||||
ignoreTabIndex = true;
|
||||
|
@ -3747,13 +3746,8 @@ static int32_t HostOrSlotTabIndexValue(const nsIContent* aContent,
|
|||
MOZ_ASSERT(IsHostOrSlot(aContent));
|
||||
|
||||
if (aIsFocusable) {
|
||||
*aIsFocusable = false;
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
int32_t tabIndex;
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
*aIsFocusable = tabIndex >= 0;
|
||||
}
|
||||
*aIsFocusable = frame && frame->IsFocusable().mTabIndex >= 0;
|
||||
}
|
||||
|
||||
const nsAttrValue* attrVal =
|
||||
|
@ -3777,10 +3771,11 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
|
|||
MOZ_ASSERT(IsHostOrSlot(aOwner), "Scope owner should be host or slot");
|
||||
|
||||
if (!aSkipOwner && (aForward && aOwner == aStartContent)) {
|
||||
int32_t tabIndex = -1;
|
||||
nsIFrame* frame = aOwner->GetPrimaryFrame();
|
||||
if (frame && frame->IsFocusable(&tabIndex, false) && tabIndex >= 0) {
|
||||
return aOwner;
|
||||
if (nsIFrame* frame = aOwner->GetPrimaryFrame()) {
|
||||
auto focusable = frame->IsFocusable();
|
||||
if (focusable && focusable.mTabIndex >= 0) {
|
||||
return aOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3821,7 +3816,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
|
|||
int32_t tabIndex = 0;
|
||||
if (iterContent->IsInNativeAnonymousSubtree() &&
|
||||
iterContent->GetPrimaryFrame()) {
|
||||
iterContent->GetPrimaryFrame()->IsFocusable(&tabIndex);
|
||||
tabIndex = iterContent->GetPrimaryFrame()->IsFocusable().mTabIndex;
|
||||
} else if (IsHostOrSlot(iterContent)) {
|
||||
tabIndex = HostOrSlotTabIndexValue(iterContent);
|
||||
} else {
|
||||
|
@ -3829,7 +3824,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
|
|||
if (!frame) {
|
||||
continue;
|
||||
}
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
tabIndex = frame->IsFocusable().mTabIndex;
|
||||
}
|
||||
if (tabIndex < 0 || !(aIgnoreTabIndex || tabIndex == aCurrentTabIndex)) {
|
||||
continue;
|
||||
|
@ -3888,10 +3883,11 @@ nsIContent* nsFocusManager::GetNextTabbableContentInScope(
|
|||
// Return scope owner at last for backward navigation if its tabindex
|
||||
// is non-negative
|
||||
if (!aSkipOwner && !aForward) {
|
||||
int32_t tabIndex = -1;
|
||||
nsIFrame* frame = aOwner->GetPrimaryFrame();
|
||||
if (frame && frame->IsFocusable(&tabIndex, false) && tabIndex >= 0) {
|
||||
return aOwner;
|
||||
if (nsIFrame* frame = aOwner->GetPrimaryFrame()) {
|
||||
auto focusable = frame->IsFocusable();
|
||||
if (focusable && focusable.mTabIndex >= 0) {
|
||||
return aOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3913,7 +3909,7 @@ nsIContent* nsFocusManager::GetNextTabbableContentInAncestorScopes(
|
|||
if (IsHostOrSlot(startContent)) {
|
||||
tabIndex = HostOrSlotTabIndexValue(startContent);
|
||||
} else if (nsIFrame* frame = startContent->GetPrimaryFrame()) {
|
||||
frame->IsFocusable(&tabIndex);
|
||||
tabIndex = frame->IsFocusable().mTabIndex;
|
||||
} else {
|
||||
startContent->IsFocusable(&tabIndex);
|
||||
}
|
||||
|
@ -4201,8 +4197,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
|
|||
// == 0 in normal tab order (last after positive tabindexed items)
|
||||
// > 0 can be tabbed to in the order specified by this value
|
||||
// clang-format on
|
||||
int32_t tabIndex;
|
||||
frame->IsFocusable(&tabIndex, 0);
|
||||
int32_t tabIndex = frame->IsFocusable().mTabIndex;
|
||||
|
||||
LOGCONTENTNAVIGATION("Next Tabbable %s:", frame->GetContent());
|
||||
LOGFOCUSNAVIGATION(
|
||||
|
|
|
@ -3339,8 +3339,7 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
break;
|
||||
}
|
||||
|
||||
int32_t tabIndexUnused;
|
||||
if (frame->IsFocusable(&tabIndexUnused, true)) {
|
||||
if (frame->IsFocusable(/* aWithMouse = */ true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,8 +74,7 @@ void HTMLLegendElement::Focus(const FocusOptions& aOptions,
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t tabIndex;
|
||||
if (frame->IsFocusable(&tabIndex, false)) {
|
||||
if (frame->IsFocusable()) {
|
||||
nsGenericHTMLElement::Focus(aOptions, aCallerType, aError);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -201,8 +201,7 @@ nsresult nsXULPopupListener::FireFocusOnTargetContent(
|
|||
nsIFrame* currFrame = targetFrame;
|
||||
// Look for the nearest enclosing focusable frame.
|
||||
while (currFrame) {
|
||||
int32_t tabIndexUnused;
|
||||
if (currFrame->IsFocusable(&tabIndexUnused, true) &&
|
||||
if (currFrame->IsFocusable(/* aWithMouse = */ true) &&
|
||||
currFrame->GetContent()->IsElement()) {
|
||||
newFocusElement = currFrame->GetContent()->AsElement();
|
||||
break;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIHapticFeedback.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -862,7 +863,7 @@ nsIFrame* AccessibleCaretManager::GetFocusableFrame(nsIFrame* aFrame) const {
|
|||
// Look for the nearest enclosing focusable frame.
|
||||
nsIFrame* focusableFrame = aFrame;
|
||||
while (focusableFrame) {
|
||||
if (focusableFrame->IsFocusable(nullptr, true)) {
|
||||
if (focusableFrame->IsFocusable(/* aWithMouse = */ true)) {
|
||||
break;
|
||||
}
|
||||
focusableFrame = focusableFrame->GetParent();
|
||||
|
|
|
@ -10086,58 +10086,88 @@ void nsIFrame::GetFirstLeaf(nsIFrame** aFrame) {
|
|||
}
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
bool nsIFrame::IsFocusable(int32_t* aTabIndex, bool aWithMouse) {
|
||||
int32_t tabIndex = -1;
|
||||
if (aTabIndex) {
|
||||
*aTabIndex = -1; // Default for early return is not focusable
|
||||
bool nsIFrame::IsFocusableDueToScrollFrame() {
|
||||
if (!IsScrollFrame()) {
|
||||
return false;
|
||||
}
|
||||
bool isFocusable = false;
|
||||
if (!mContent->IsHTMLElement()) {
|
||||
return false;
|
||||
}
|
||||
if (mContent->IsRootOfNativeAnonymousSubtree()) {
|
||||
return false;
|
||||
}
|
||||
if (!mContent->GetParent()) {
|
||||
return false;
|
||||
}
|
||||
if (mContent->AsElement()->HasAttr(nsGkAtoms::tabindex)) {
|
||||
return false;
|
||||
}
|
||||
// Elements with scrollable view are focusable with script & tabbable
|
||||
// Otherwise you couldn't scroll them with keyboard, which is an accessibility
|
||||
// issue (e.g. Section 508 rules) However, we don't make them to be focusable
|
||||
// with the mouse, because the extra focus outlines are considered
|
||||
// unnecessarily ugly. When clicked on, the selection position within the
|
||||
// element will be enough to make them keyboard scrollable.
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(this);
|
||||
if (!scrollFrame) {
|
||||
return false;
|
||||
}
|
||||
if (scrollFrame->IsForTextControlWithNoScrollbars()) {
|
||||
return false;
|
||||
}
|
||||
if (scrollFrame->GetScrollStyles().IsHiddenInBothDirections()) {
|
||||
return false;
|
||||
}
|
||||
if (scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIFrame::Focusable nsIFrame::IsFocusable(bool aWithMouse) {
|
||||
// cannot focus content in print preview mode. Only the root can be focused,
|
||||
// but that's handled elsewhere.
|
||||
if (PresContext()->Type() == nsPresContext::eContext_PrintPreview) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (mContent && mContent->IsElement() && IsVisibleConsideringAncestors() &&
|
||||
Style()->GetPseudoType() != PseudoStyleType::anonymousFlexItem &&
|
||||
Style()->GetPseudoType() != PseudoStyleType::anonymousGridItem &&
|
||||
StyleUI()->mInert != StyleInert::Inert) {
|
||||
const nsStyleUI* ui = StyleUI();
|
||||
if (ui->mUserFocus != StyleUserFocus::Ignore &&
|
||||
ui->mUserFocus != StyleUserFocus::None) {
|
||||
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
|
||||
tabIndex = 0;
|
||||
}
|
||||
isFocusable = mContent->IsFocusable(&tabIndex, aWithMouse);
|
||||
if (!isFocusable && !aWithMouse && IsScrollFrame() &&
|
||||
mContent->IsHTMLElement() &&
|
||||
!mContent->IsRootOfNativeAnonymousSubtree() && mContent->GetParent() &&
|
||||
!mContent->AsElement()->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::tabindex)) {
|
||||
// Elements with scrollable view are focusable with script & tabbable
|
||||
// Otherwise you couldn't scroll them with keyboard, which is
|
||||
// an accessibility issue (e.g. Section 508 rules)
|
||||
// However, we don't make them to be focusable with the mouse,
|
||||
// because the extra focus outlines are considered unnecessarily ugly.
|
||||
// When clicked on, the selection position within the element
|
||||
// will be enough to make them keyboard scrollable.
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(this);
|
||||
if (scrollFrame && !scrollFrame->IsForTextControlWithNoScrollbars() &&
|
||||
!scrollFrame->GetScrollStyles().IsHiddenInBothDirections() &&
|
||||
!scrollFrame->GetScrollRange().IsEqualEdges(nsRect(0, 0, 0, 0))) {
|
||||
// Scroll bars will be used for overflow
|
||||
isFocusable = true;
|
||||
tabIndex = 0;
|
||||
}
|
||||
}
|
||||
if (!mContent || !mContent->IsElement()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (aTabIndex) {
|
||||
*aTabIndex = tabIndex;
|
||||
if (!IsVisibleConsideringAncestors()) {
|
||||
return {};
|
||||
}
|
||||
return isFocusable;
|
||||
|
||||
const nsStyleUI* ui = StyleUI();
|
||||
if (ui->mInert == StyleInert::Inert) {
|
||||
return {};
|
||||
}
|
||||
|
||||
PseudoStyleType pseudo = Style()->GetPseudoType();
|
||||
if (pseudo == PseudoStyleType::anonymousFlexItem ||
|
||||
pseudo == PseudoStyleType::anonymousGridItem) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t tabIndex = -1;
|
||||
if (ui->mUserFocus != StyleUserFocus::Ignore &&
|
||||
ui->mUserFocus != StyleUserFocus::None) {
|
||||
// Pass in default tabindex of -1 for nonfocusable and 0 for focusable
|
||||
tabIndex = 0;
|
||||
}
|
||||
|
||||
if (mContent->IsFocusable(&tabIndex, aWithMouse)) {
|
||||
// If the content is focusable, then we're done.
|
||||
return {true, tabIndex};
|
||||
}
|
||||
|
||||
// If we're focusing with the mouse we never focus scroll areas.
|
||||
if (!aWithMouse && IsFocusableDueToScrollFrame()) {
|
||||
return {true, 0};
|
||||
}
|
||||
|
||||
return {false, tabIndex};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4200,6 +4200,17 @@ class nsIFrame : public nsQueryFrame {
|
|||
const nsStyleEffects* aEffects,
|
||||
const nsSize& aSize) const;
|
||||
|
||||
struct Focusable {
|
||||
bool mFocusable = false;
|
||||
// The computed tab index:
|
||||
// < 0 if not tabbable
|
||||
// == 0 if in normal tab order
|
||||
// > 0 can be tabbed to in the order specified by this value
|
||||
int32_t mTabIndex = -1;
|
||||
|
||||
explicit operator bool() const { return mFocusable; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this frame is focusable and in the current tab order.
|
||||
* Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
|
||||
|
@ -4211,14 +4222,10 @@ class nsIFrame : public nsQueryFrame {
|
|||
* Also, depending on the pref accessibility.tabfocus some widgets may be
|
||||
* focusable but removed from the tab order. This is the default on
|
||||
* Mac OS X, where fewer items are focusable.
|
||||
* @param [in, optional] aTabIndex the computed tab index
|
||||
* < 0 if not tabbable
|
||||
* == 0 if in normal tab order
|
||||
* > 0 can be tabbed to in the order specified by this value
|
||||
* @param [in, optional] aWithMouse, is this focus query for mouse clicking
|
||||
* @return whether the frame is focusable via mouse, kbd or script.
|
||||
*/
|
||||
bool IsFocusable(int32_t* aTabIndex = nullptr, bool aWithMouse = false);
|
||||
[[nodiscard]] Focusable IsFocusable(bool aWithMouse = false);
|
||||
|
||||
// BOX LAYOUT METHODS
|
||||
// These methods have been migrated from nsIBox and are in the process of
|
||||
|
@ -4321,6 +4328,9 @@ class nsIFrame : public nsQueryFrame {
|
|||
static nsIFrame* GetParentXULBox(const nsIFrame* aFrame);
|
||||
|
||||
protected:
|
||||
// Helper for IsFocusable.
|
||||
bool IsFocusableDueToScrollFrame();
|
||||
|
||||
/**
|
||||
* Returns true if this box clips its children, e.g., if this box is an
|
||||
* scrollbox.
|
||||
|
|
Загрузка…
Ссылка в новой задаче