Bug 1895208 - Refactor IsFocusable checks to take flags rather than bool arguments. r=smaug

This doesn't change behavior on its own, but it's likely we want to make
the tab focusability more complicated in bug 1895184, and this will make
changes to this area less painful.

Differential Revision: https://phabricator.services.mozilla.com/D209525
This commit is contained in:
Emilio Cobos Álvarez 2024-05-06 21:54:37 +00:00
parent da85a702a3
commit 3b42787268
49 changed files with 170 additions and 143 deletions

View File

@ -12,6 +12,7 @@
#include "DocAccessible-inl.h"
#include "DocAccessibleChild.h"
#include "FocusManager.h"
#include "mozilla/FocusModel.h"
#include "HTMLCanvasAccessible.h"
#include "HTMLElementAccessibles.h"
#include "HTMLImageMapAccessible.h"
@ -188,8 +189,7 @@ static bool MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument) {
// not create Accessibles for some focusable elements; e.g. a span with only
// a tabindex. Elements that are invisible within this document are excluded
// earlier in CreateAccessible.
if (frame->IsFocusable(/* aWithMouse */ false,
/* aCheckVisibility */ false)) {
if (frame->IsFocusable(IsFocusableFlags::IgnoreVisibility)) {
return true;
}
}

View File

@ -14,6 +14,7 @@
#include "mozilla/a11y/AccAttributes.h"
#include "mozilla/a11y/DocAccessibleChild.h"
#include "mozilla/a11y/Platform.h"
#include "mozilla/FocusModel.h"
#include "nsAccUtils.h"
#include "nsAccessibilityService.h"
#include "ApplicationAccessible.h"
@ -407,6 +408,7 @@ uint64_t LocalAccessible::NativeInteractiveState() const {
if (NativelyUnavailable()) return states::UNAVAILABLE;
nsIFrame* frame = GetFrame();
auto flags = IsFocusableFlags(0);
// If we're caching this remote document in the parent process, we
// need to cache focusability irrespective of visibility. Otherwise,
// if this document is invisible when it first loads, we'll cache that
@ -417,13 +419,12 @@ uint64_t LocalAccessible::NativeInteractiveState() const {
// Although ignoring visibility means IsFocusable will return true for
// visibility: hidden, etc., this isn't a problem because we don't include
// those hidden elements in the a11y tree anyway.
const bool ignoreVisibility = mDoc->IPCDoc();
if (frame && frame->IsFocusable(
/* aWithMouse */ false,
/* aCheckVisibility */ !ignoreVisibility)) {
if (mDoc->IPCDoc()) {
flags |= IsFocusableFlags::IgnoreVisibility;
}
if (frame && frame->IsFocusable(flags)) {
return states::FOCUSABLE;
}
return 0;
}

View File

@ -2,13 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TabFocusModel_h
#define mozilla_TabFocusModel_h
#ifndef mozilla_FocusModel_h
#define mozilla_FocusModel_h
#include "mozilla/StaticPrefs_accessibility.h"
#include "mozilla/TypedEnumBits.h"
namespace mozilla {
enum class IsFocusableFlags : uint8_t {
WithMouse = 1 << 0,
// Whether to treat an invisible frame as not focusable
IgnoreVisibility = 1 << 1,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(IsFocusableFlags);
enum class TabFocusableType : uint8_t {
TextControls = 1, // Textboxes and lists always tabbable
FormElements = 1 << 1, // Non-text form elements
@ -16,7 +25,7 @@ enum class TabFocusableType : uint8_t {
Any = TextControls | FormElements | Links,
};
class TabFocusModel final {
class FocusModel final {
public:
static bool AppliesToXUL() {
return StaticPrefs::accessibility_tabfocus_applies_to_xul();

View File

@ -1020,7 +1020,7 @@ void nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
}
}
Element* nsIContent::GetAutofocusDelegate(bool aWithMouse) const {
Element* nsIContent::GetAutofocusDelegate(IsFocusableFlags aFlags) const {
for (nsINode* node = GetFirstChild(); node; node = node->GetNextNode(this)) {
auto* descendant = Element::FromNode(*node);
if (!descendant || !descendant->GetBoolAttr(nsGkAtoms::autofocus)) {
@ -1028,14 +1028,14 @@ Element* nsIContent::GetAutofocusDelegate(bool aWithMouse) const {
}
nsIFrame* frame = descendant->GetPrimaryFrame();
if (frame && frame->IsFocusable(aWithMouse)) {
if (frame && frame->IsFocusable(aFlags)) {
return descendant;
}
}
return nullptr;
}
Element* nsIContent::GetFocusDelegate(bool aWithMouse) const {
Element* nsIContent::GetFocusDelegate(IsFocusableFlags aFlags) const {
const nsIContent* whereToLook = this;
if (ShadowRoot* root = GetShadowRoot()) {
if (!root->DelegatesFocus()) {
@ -1053,7 +1053,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const {
return {};
}
return frame->IsFocusable(aWithMouse);
return frame->IsFocusable(aFlags);
};
Element* potentialFocus = nullptr;
@ -1095,7 +1095,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const {
if (auto* shadow = el->GetShadowRoot()) {
if (shadow->DelegatesFocus()) {
if (Element* delegatedFocus = shadow->GetFocusDelegate(aWithMouse)) {
if (Element* delegatedFocus = shadow->GetFocusDelegate(aFlags)) {
if (autofocus) {
// This element has autofocus and we found an focus delegates
// in its descendants, so use the focus delegates
@ -1112,7 +1112,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const {
return potentialFocus;
}
Focusable nsIContent::IsFocusableWithoutStyle(bool aWithMouse) {
Focusable nsIContent::IsFocusableWithoutStyle(IsFocusableFlags) {
// Default, not tabbable
return {};
}

View File

@ -126,6 +126,7 @@ EXPORTS.mozilla += [
"ContentIterator.h",
"CORSMode.h",
"FlushType.h",
"FocusModel.h",
"FullscreenChange.h",
"GlobalTeardownObserver.h",
"IdentifierMapEntry.h",
@ -135,7 +136,6 @@ EXPORTS.mozilla += [
"ScriptableContentIterator.h",
"ScrollingMetrics.h",
"SelectionChangeEventDispatcher.h",
"TabFocusModel.h",
"TextInputProcessor.h",
"UseCounter.h",
]

View File

@ -45,6 +45,7 @@
#include "mozilla/AccessibleCaretEventHub.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/FocusModel.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
@ -5513,6 +5514,14 @@ bool nsFocusManager::CanSkipFocus(nsIContent* aContent) {
return false;
}
static IsFocusableFlags FocusManagerFlagsToIsFocusableFlags(uint32_t aFlags) {
auto flags = IsFocusableFlags(0);
if (aFlags & nsIFocusManager::FLAG_BYMOUSE) {
flags |= IsFocusableFlags::WithMouse;
}
return flags;
}
/* static */
Element* nsFocusManager::GetTheFocusableArea(Element* aTarget,
uint32_t aFlags) {
@ -5542,7 +5551,8 @@ Element* nsFocusManager::GetTheFocusableArea(Element* aTarget,
// 3. If focus target is a navigable container with a non-null content
// navigable
// nsIFrame::IsFocusable will effectively perform the checks for them.
if (frame->IsFocusable(aFlags & FLAG_BYMOUSE)) {
IsFocusableFlags flags = FocusManagerFlagsToIsFocusableFlags(aFlags);
if (frame->IsFocusable(flags)) {
return aTarget;
}
@ -5562,8 +5572,7 @@ Element* nsFocusManager::GetTheFocusableArea(Element* aTarget,
}
}
if (Element* firstFocusable =
root->GetFocusDelegate(aFlags & FLAG_BYMOUSE)) {
if (Element* firstFocusable = root->GetFocusDelegate(flags)) {
return firstFocusable;
}
}
@ -5581,7 +5590,7 @@ bool nsFocusManager::IsAreaElementFocusable(HTMLAreaElement& aArea) {
// GetPrimaryFrame() is not relevant as to whether it is focusable or
// not, so we have to do all the relevant checks manually for them.
return frame->IsVisibleConsideringAncestors() &&
aArea.IsFocusableWithoutStyle(false /* aWithMouse */);
aArea.IsFocusableWithoutStyle();
}
nsresult NS_NewFocusManager(nsIFocusManager** aResult) {

View File

@ -16,6 +16,7 @@ class nsTextFragment;
class nsIFrame;
namespace mozilla {
enum class IsFocusableFlags : uint8_t;
class EventChainPreVisitor;
class HTMLEditor;
struct URLExtraData;
@ -274,13 +275,14 @@ class nsIContent : public nsINode {
* some widgets may be focusable but removed from the tab order.
* @return whether the content is focusable via mouse, kbd or script.
*/
virtual Focusable IsFocusableWithoutStyle(bool aWithMouse = false);
virtual Focusable IsFocusableWithoutStyle(
mozilla::IsFocusableFlags = mozilla::IsFocusableFlags(0));
// https://html.spec.whatwg.org/multipage/interaction.html#focus-delegate
mozilla::dom::Element* GetFocusDelegate(bool aWithMouse) const;
mozilla::dom::Element* GetFocusDelegate(mozilla::IsFocusableFlags) const;
// https://html.spec.whatwg.org/multipage/interaction.html#autofocus-delegate
mozilla::dom::Element* GetAutofocusDelegate(bool aWithMouse) const;
mozilla::dom::Element* GetAutofocusDelegate(mozilla::IsFocusableFlags) const;
/*
* Get desired IME state for the content.

View File

@ -15,6 +15,7 @@
#include "mozilla/HTMLEditor.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/Likely.h"
#include "mozilla/FocusModel.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MouseEvents.h"
@ -3728,14 +3729,14 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
break;
}
if (frame->IsFocusable(/* aWithMouse = */ true)) {
auto flags = IsFocusableFlags::WithMouse;
if (frame->IsFocusable(flags)) {
break;
}
if (ShadowRoot* root = newFocus->GetShadowRoot()) {
if (root->DelegatesFocus()) {
if (Element* firstFocusable =
root->GetFocusDelegate(/* aWithMouse */ true)) {
if (Element* firstFocusable = root->GetFocusDelegate(flags)) {
newFocus = firstFocusable;
break;
}

View File

@ -1631,7 +1631,7 @@ MOZ_CAN_RUN_SCRIPT static bool IsNextFocusableElementTextControl(
// FIXME: Should probably use nsIFrame::IsFocusable if possible, to account
// for things like visibility: hidden or so.
if (!nextElement->IsFocusableWithoutStyle(false)) {
if (!nextElement->IsFocusableWithoutStyle()) {
return false;
}

View File

@ -14,7 +14,7 @@
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsGkAtoms.h"
#include "mozilla/TabFocusModel.h"
#include "mozilla/FocusModel.h"
#include "mozilla/dom/Document.h"
#include "nsPresContext.h"
#include "nsIURI.h"
@ -86,10 +86,10 @@ void HTMLAnchorElement::UnbindFromTree(UnbindContext& aContext) {
Link::UnbindFromTree();
}
bool HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLAnchorElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable,
aTabIndex)) {
if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) {
return true;
}
@ -119,7 +119,7 @@ bool HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
}
}
if (!TabFocusModel::IsTabFocusable(TabFocusableType::Links)) {
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
*aTabIndex = -1;
}
*aIsFocusable = true;

View File

@ -48,7 +48,7 @@ class HTMLAnchorElement final : public nsGenericHTMLElement,
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;

View File

@ -12,13 +12,13 @@
#include "nsAttrValueInlines.h"
#include "nsIContentInlines.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIFormControl.h"
#include "nsIFrame.h"
#include "nsIFormControlFrame.h"
#include "mozilla/dom/Document.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/FocusModel.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/MouseEvents.h"
@ -113,15 +113,14 @@ void HTMLButtonElement::GetType(nsAString& aType) {
int32_t HTMLButtonElement::TabIndexDefault() { return 0; }
bool HTMLButtonElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLButtonElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
aWithMouse, aIsFocusable, aTabIndex)) {
aFlags, aIsFocusable, aTabIndex)) {
return true;
}
*aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) && !IsDisabled();
*aIsFocusable = IsFormControlDefaultFocusable(aFlags) && !IsDisabled();
return false;
}

View File

@ -87,7 +87,7 @@ class HTMLButtonElement final : public nsGenericHTMLFormControlElementWithState,
nsAttrValue& aResult) override;
// nsGenericHTMLElement
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
bool IsDisabledForEvents(WidgetEvent* aEvent) override;

View File

@ -48,7 +48,7 @@ class HTMLDetailsElement final : public nsGenericHTMLElement {
void ToggleOpen() { SetOpen(!Open(), IgnoreErrors()); }
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
void HandleInvokeInternal(nsAtom* aAction, ErrorResult& aRv) override;

View File

@ -157,7 +157,7 @@ void HTMLDialogElement::FocusDialog() {
RefPtr<Element> control = HasAttr(nsGkAtoms::autofocus)
? this
: GetFocusDelegate(false /* aWithMouse */);
: GetFocusDelegate(IsFocusableFlags(0));
// If there isn't one of those either, then let control be subject.
if (!control) {

View File

@ -133,8 +133,8 @@ int32_t HTMLEmbedElement::TabIndexDefault() {
return Type() == ObjectType::Document ? 0 : -1;
}
bool HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) {
bool HTMLEmbedElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable, int32_t* aTabIndex) {
// Has non-plugin content: let the plugin decide what to do in terms of
// internal focus from mouse clicks
if (aTabIndex) {

View File

@ -38,7 +38,7 @@ class HTMLEmbedElement final : public nsGenericHTMLElement,
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
int32_t TabIndexDefault() override;

View File

@ -6,7 +6,7 @@
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/PresShell.h"
#include "mozilla/TabFocusModel.h"
#include "mozilla/FocusModel.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/HTMLImageElementBinding.h"
@ -489,14 +489,13 @@ nsINode* HTMLImageElement::GetScopeChainParent() const {
return nsGenericHTMLElement::GetScopeChainParent();
}
bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) {
bool HTMLImageElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable, int32_t* aTabIndex) {
int32_t tabIndex = TabIndex();
if (IsInComposedDoc() && FindImageMap()) {
// Use tab index on individual map areas.
*aTabIndex =
TabFocusModel::IsTabFocusable(TabFocusableType::Links) ? 0 : -1;
*aTabIndex = FocusModel::IsTabFocusable(TabFocusableType::Links) ? 0 : -1;
// Image map is not focusable itself, but flag as tabbable
// so that image map areas get walked into.
*aIsFocusable = false;
@ -504,10 +503,10 @@ bool HTMLImageElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
}
// Can be in tab order if tabindex >=0 and form controls are tabbable.
*aTabIndex = TabFocusModel::IsTabFocusable(TabFocusableType::FormElements)
*aTabIndex = FocusModel::IsTabFocusable(TabFocusableType::FormElements)
? tabIndex
: -1;
*aIsFocusable = IsFormControlDefaultFocusable(aWithMouse) &&
*aIsFocusable = IsFormControlDefaultFocusable(aFlags) &&
(tabIndex >= 0 || GetTabIndexAttrValue().isSome());
return false;

View File

@ -70,7 +70,7 @@ class HTMLImageElement final : public nsGenericHTMLElement,
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
nsINode* GetScopeChainParent() const override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;

View File

@ -6423,10 +6423,10 @@ void HTMLInputElement::RemoveFromRadioGroup() {
mRadioGroupContainer = nullptr;
}
bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) {
bool HTMLInputElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable, int32_t* aTabIndex) {
if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
aWithMouse, aIsFocusable, aTabIndex)) {
aFlags, aIsFocusable, aTabIndex)) {
return true;
}
@ -6440,7 +6440,7 @@ bool HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
return false;
}
const bool defaultFocusable = IsFormControlDefaultFocusable(aWithMouse);
const bool defaultFocusable = IsFormControlDefaultFocusable(aFlags);
if (CreatesDateTimeWidget()) {
if (aTabIndex) {
// We only want our native anonymous child to be tabable to, not ourself.

View File

@ -162,7 +162,7 @@ class HTMLInputElement final : public TextControlElement,
void FieldSetDisabledChanged(bool aNotify) override;
// nsIContent
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,

View File

@ -4838,10 +4838,9 @@ void HTMLMediaElement::DoneCreatingElement() {
}
}
bool HTMLMediaElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable,
aTabIndex)) {
bool HTMLMediaElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable, int32_t* aTabIndex) {
if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) {
return true;
}

View File

@ -196,24 +196,24 @@ class HTMLMediaElement : public nsGenericHTMLElement,
void NodeInfoChanged(Document* aOldDoc) override;
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
virtual void UnbindFromTree(UnbindContext&) override;
virtual void DoneCreatingElement() override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
void DoneCreatingElement() override;
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) override;
virtual int32_t TabIndexDefault() override;
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
int32_t TabIndexDefault() override;
// Called by the video decoder object, on the main thread,
// when it has read the metadata containing video dimensions,
// etc.
virtual void MetadataLoaded(const MediaInfo* aInfo,
UniquePtr<const MetadataTags> aTags) final;
void MetadataLoaded(const MediaInfo* aInfo,
UniquePtr<const MetadataTags> aTags) final;
// Called by the decoder object, on the main thread,
// when it has read the first frame of the video or audio.

View File

@ -135,7 +135,8 @@ void HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
}));
}
bool HTMLObjectElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLObjectElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
// TODO: this should probably be managed directly by IsHTMLFocusable.
// See bug 597242.

View File

@ -42,7 +42,7 @@ class HTMLObjectElement final : public nsGenericHTMLFormControlElement,
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
// Overriden nsIFormControl methods

View File

@ -1026,10 +1026,11 @@ void HTMLSelectElement::SetValue(const nsAString& aValue) {
int32_t HTMLSelectElement::TabIndexDefault() { return 0; }
bool HTMLSelectElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLSelectElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
aWithMouse, aIsFocusable, aTabIndex)) {
aFlags, aIsFocusable, aTabIndex)) {
return true;
}

View File

@ -198,7 +198,7 @@ class HTMLSelectElement final : public nsGenericHTMLFormControlElementWithState,
// nsIContent
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
void InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
bool aNotify, ErrorResult& aRv) override;

View File

@ -68,10 +68,11 @@ nsresult HTMLSummaryElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
return rv;
}
bool HTMLSummaryElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLSummaryElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
bool disallowOverridingFocusability = nsGenericHTMLElement::IsHTMLFocusable(
aWithMouse, aIsFocusable, aTabIndex);
bool disallowOverridingFocusability =
nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex);
if (disallowOverridingFocusability || !IsMainSummary()) {
return disallowOverridingFocusability;

View File

@ -30,7 +30,7 @@ class HTMLSummaryElement final : public nsGenericHTMLElement {
nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
int32_t TabIndexDefault() override;

View File

@ -133,10 +133,11 @@ HTMLTextAreaElement::SelectAll(nsPresContext* aPresContext) {
return NS_OK;
}
bool HTMLTextAreaElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool HTMLTextAreaElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
aWithMouse, aIsFocusable, aTabIndex)) {
aFlags, aIsFocusable, aTabIndex)) {
return true;
}

View File

@ -122,7 +122,7 @@ class HTMLTextAreaElement final : public TextControlElement,
nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
void DoneAddingChildren(bool aHaveNotified) override;

View File

@ -9,6 +9,7 @@
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/FocusModel.h"
#include "mozilla/IMEContentObserver.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/MappedDeclarationsBuilder.h"
@ -1766,8 +1767,8 @@ bool nsGenericHTMLElement::LegacyTouchAPIEnabled(JSContext* aCx,
}
bool nsGenericHTMLElement::IsFormControlDefaultFocusable(
bool aWithMouse) const {
if (!aWithMouse) {
IsFocusableFlags aFlags) const {
if (!(aFlags & IsFocusableFlags::WithMouse)) {
return true;
}
switch (StaticPrefs::accessibility_mouse_focuses_formcontrol()) {
@ -2312,7 +2313,8 @@ void nsGenericHTMLElement::Click(CallerType aCallerType) {
ClearHandlingClick();
}
bool nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool nsGenericHTMLElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
MOZ_ASSERT(aIsFocusable);
MOZ_ASSERT(aTabIndex);
@ -2598,15 +2600,15 @@ void nsGenericHTMLFormControlElement::GetAutocapitalize(
}
}
bool nsGenericHTMLFormControlElement::IsHTMLFocusable(bool aWithMouse,
bool nsGenericHTMLFormControlElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLFormElement::IsHTMLFocusable(aWithMouse, aIsFocusable,
if (nsGenericHTMLFormElement::IsHTMLFocusable(aFlags, aIsFocusable,
aTabIndex)) {
return true;
}
*aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aWithMouse);
*aIsFocusable = *aIsFocusable && IsFormControlDefaultFocusable(aFlags);
return false;
}
@ -3561,8 +3563,7 @@ void nsGenericHTMLElement::FocusPopover() {
RefPtr<Element> control = GetBoolAttr(nsGkAtoms::autofocus)
? this
: GetAutofocusDelegate(false /* aWithMouse */);
: GetAutofocusDelegate(IsFocusableFlags(0));
if (!control) {
return;
}

View File

@ -198,7 +198,7 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
}
/** Returns whether a form control should be default-focusable. */
bool IsFormControlDefaultFocusable(bool aWithMouse) const;
bool IsFormControlDefaultFocusable(mozilla::IsFocusableFlags) const;
/**
* Returns the count of descendants (inclusive of this node) in
@ -333,16 +333,17 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
Focusable IsFocusableWithoutStyle(bool aWithMouse) override {
Focusable IsFocusableWithoutStyle(mozilla::IsFocusableFlags aFlags =
mozilla::IsFocusableFlags(0)) override {
Focusable result;
IsHTMLFocusable(aWithMouse, &result.mFocusable, &result.mTabIndex);
IsHTMLFocusable(aFlags, &result.mFocusable, &result.mTabIndex);
return result;
}
/**
* Returns true if a subclass is not allowed to override the value returned
* in aIsFocusable.
*/
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
virtual bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex);
MOZ_CAN_RUN_SCRIPT
mozilla::Result<bool, nsresult> PerformAccesskey(
@ -1176,7 +1177,7 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
// nsGenericHTMLElement
// autocapitalize attribute support
void GetAutocapitalize(nsAString& aValue) const override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
// EventTarget

View File

@ -311,11 +311,10 @@ nsresult nsGenericHTMLFrameElement::CopyInnerTo(Element* aDest) {
return rv;
}
bool nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse,
bool nsGenericHTMLFrameElement::IsHTMLFocusable(IsFocusableFlags aFlags,
bool* aIsFocusable,
int32_t* aTabIndex) {
if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable,
aTabIndex)) {
if (nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex)) {
return true;
}

View File

@ -50,15 +50,15 @@ class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID)
// nsIContent
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) override;
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
virtual void UnbindFromTree(UnbindContext&) override;
virtual void DestroyContent() override;
bool IsHTMLFocusable(mozilla::IsFocusableFlags, bool* aIsFocusable,
int32_t* aTabIndex) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
void DestroyContent() override;
nsresult CopyInnerTo(mozilla::dom::Element* aDest);
virtual int32_t TabIndexDefault() override;
int32_t TabIndexDefault() override;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement)

View File

@ -7,7 +7,7 @@
#include "mozilla/dom/MathMLElement.h"
#include "base/compiler_specific.h"
#include "mozilla/TabFocusModel.h"
#include "mozilla/FocusModel.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/EventListenerManager.h"
@ -611,7 +611,7 @@ void MathMLElement::SetIncrementScriptLevel(bool aIncrementScriptLevel,
int32_t MathMLElement::TabIndexDefault() { return IsLink() ? 0 : -1; }
// XXX Bug 1586011: Share logic with other element classes.
Focusable MathMLElement::IsFocusableWithoutStyle(bool aWithMouse) {
Focusable MathMLElement::IsFocusableWithoutStyle(IsFocusableFlags) {
if (!IsInComposedDoc() || IsInDesignMode()) {
// In designMode documents we only allow focusing the document.
return {};
@ -636,7 +636,7 @@ Focusable MathMLElement::IsFocusableWithoutStyle(bool aWithMouse) {
return {};
}
if (!TabFocusModel::IsTabFocusable(TabFocusableType::Links)) {
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
tabIndex = -1;
}

View File

@ -74,7 +74,7 @@ class MathMLElement final : public MathMLElementBase, public Link {
int32_t TabIndexDefault() final;
Focusable IsFocusableWithoutStyle(bool aWithMouse) override;
Focusable IsFocusableWithoutStyle(IsFocusableFlags) override;
already_AddRefed<nsIURI> GetHrefURI() const override;
void NodeInfoChanged(Document* aOldDoc) override {

View File

@ -9,7 +9,7 @@
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/SVGAElementBinding.h"
#include "mozilla/TabFocusModel.h"
#include "mozilla/FocusModel.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsGkAtoms.h"
@ -157,7 +157,7 @@ void SVGAElement::UnbindFromTree(UnbindContext& aContext) {
int32_t SVGAElement::TabIndexDefault() { return 0; }
Focusable SVGAElement::IsFocusableWithoutStyle(bool aWithMouse) {
Focusable SVGAElement::IsFocusableWithoutStyle(IsFocusableFlags) {
Focusable result;
if (IsSVGFocusable(&result.mFocusable, &result.mTabIndex)) {
return result;
@ -181,7 +181,7 @@ Focusable SVGAElement::IsFocusableWithoutStyle(bool aWithMouse) {
return {};
}
}
if (!TabFocusModel::IsTabFocusable(TabFocusableType::Links)) {
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
result.mTabIndex = -1;
}
return result;

View File

@ -50,7 +50,7 @@ class SVGAElement final : public SVGAElementBase, public Link {
void UnbindFromTree(UnbindContext&) override;
int32_t TabIndexDefault() override;
Focusable IsFocusableWithoutStyle(bool aWithMouse) override;
Focusable IsFocusableWithoutStyle(IsFocusableFlags) override;
void GetLinkTarget(nsAString& aTarget) override;
already_AddRefed<nsIURI> GetHrefURI() const override;

View File

@ -25,7 +25,7 @@ class SVGDefsElement final : public SVGGraphicsElement {
public:
// defs elements are not focusable.
Focusable IsFocusableWithoutStyle(bool aWithMouse) override { return {}; }
Focusable IsFocusableWithoutStyle(IsFocusableFlags) override { return {}; }
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
};

View File

@ -164,7 +164,7 @@ bool SVGGraphicsElement::IsSVGFocusable(bool* aIsFocusable,
return false;
}
Focusable SVGGraphicsElement::IsFocusableWithoutStyle(bool aWithMouse) {
Focusable SVGGraphicsElement::IsFocusableWithoutStyle(IsFocusableFlags) {
Focusable result;
IsSVGFocusable(&result.mFocusable, &result.mTabIndex);
return result;

View File

@ -34,7 +34,7 @@ class SVGGraphicsElement : public SVGGraphicsElementBase, public SVGTests {
already_AddRefed<SVGMatrix> GetCTM();
already_AddRefed<SVGMatrix> GetScreenCTM();
Focusable IsFocusableWithoutStyle(bool aWithMouse) override;
Focusable IsFocusableWithoutStyle(IsFocusableFlags) override;
bool IsSVGGraphicsElement() const final { return true; }
using nsINode::Clone;

View File

@ -29,11 +29,11 @@ SVGSymbolElement::SVGSymbolElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: SVGSymbolElementBase(std::move(aNodeInfo)) {}
Focusable SVGSymbolElement::IsFocusableWithoutStyle(bool aWithMouse) {
Focusable SVGSymbolElement::IsFocusableWithoutStyle(IsFocusableFlags aFlags) {
if (!CouldBeRendered()) {
return {};
}
return SVGSymbolElementBase::IsFocusableWithoutStyle(aWithMouse);
return SVGSymbolElementBase::IsFocusableWithoutStyle(aFlags);
}
bool SVGSymbolElement::CouldBeRendered() const {

View File

@ -26,7 +26,7 @@ class SVGSymbolElement final : public SVGSymbolElementBase {
~SVGSymbolElement() = default;
JSObject* WrapNode(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
Focusable IsFocusableWithoutStyle(bool aWithMouse) override;
Focusable IsFocusableWithoutStyle(IsFocusableFlags) override;
public:
// interfaces:

View File

@ -37,6 +37,7 @@
#include "mozilla/EventQueue.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/FlushType.h"
#include "mozilla/FocusModel.h"
#include "mozilla/GlobalKeyListener.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/MacroForEach.h"
@ -50,7 +51,7 @@
#include "mozilla/StaticAnalysisFunctions.h"
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/TabFocusModel.h"
#include "mozilla/FocusModel.h"
#include "mozilla/TaskController.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/URLExtraData.h"
@ -374,12 +375,12 @@ static bool IsNonList(mozilla::dom::NodeInfo* aNodeInfo) {
}
nsXULElement::XULFocusability nsXULElement::GetXULFocusability(
bool aWithMouse) {
IsFocusableFlags aFlags) {
#ifdef XP_MACOSX
// On Mac, mouse interactions only focus the element if it's a list,
// or if it's a remote target, since the remote target must handle
// the focus.
if (aWithMouse && IsNonList(mNodeInfo) &&
if ((aFlags & IsFocusableFlags::WithMouse) && IsNonList(mNodeInfo) &&
!EventStateManager::IsTopLevelRemoteTarget(this)) {
return XULFocusability::NeverFocusable();
}
@ -403,8 +404,8 @@ nsXULElement::XULFocusability nsXULElement::GetXULFocusability(
result.mForcedFocusable.emplace(true);
result.mForcedTabIndexIfFocusable.emplace(attrVal.value());
}
if (xulControl && TabFocusModel::AppliesToXUL() &&
!TabFocusModel::IsTabFocusable(TabFocusableType::FormElements) &&
if (xulControl && FocusModel::AppliesToXUL() &&
!FocusModel::IsTabFocusable(TabFocusableType::FormElements) &&
IsNonList(mNodeInfo)) {
// By default, the tab focus model doesn't apply to xul element on any
// system but OS X. For compatibility, we only do this for controls,
@ -416,8 +417,8 @@ nsXULElement::XULFocusability nsXULElement::GetXULFocusability(
// XUL elements are not focusable unless explicitly opted-into it with
// -moz-user-focus: normal, or the tabindex attribute.
Focusable nsXULElement::IsFocusableWithoutStyle(bool aWithMouse) {
const auto focusability = GetXULFocusability(aWithMouse);
Focusable nsXULElement::IsFocusableWithoutStyle(IsFocusableFlags aFlags) {
const auto focusability = GetXULFocusability(aFlags);
const bool focusable = focusability.mDefaultFocusable;
return {focusable,
focusable ? focusability.mForcedTabIndexIfFocusable.valueOr(-1) : -1};

View File

@ -401,8 +401,8 @@ class nsXULElement : public nsStyledElement {
return {false, mozilla::Some(false), mozilla::Some(-1)};
}
};
XULFocusability GetXULFocusability(bool aWithMouse);
Focusable IsFocusableWithoutStyle(bool aWithMouse) override;
XULFocusability GetXULFocusability(mozilla::IsFocusableFlags);
Focusable IsFocusableWithoutStyle(mozilla::IsFocusableFlags) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;

View File

@ -19,6 +19,7 @@
#include "mozilla/dom/NodeFilterBinding.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/TreeWalker.h"
#include "mozilla/FocusModel.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/PresShell.h"
@ -879,7 +880,7 @@ nsIFrame* AccessibleCaretManager::GetFocusableFrame(nsIFrame* aFrame) const {
// Look for the nearest enclosing focusable frame.
nsIFrame* focusableFrame = aFrame;
while (focusableFrame) {
if (focusableFrame->IsFocusable(/* aWithMouse = */ true)) {
if (focusableFrame->IsFocusable(IsFocusableFlags::WithMouse)) {
break;
}
focusableFrame = focusableFrame->GetParent();

View File

@ -19,6 +19,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/EventForwards.h"
#include "mozilla/FocusModel.h"
#include "mozilla/dom/CSSAnimation.h"
#include "mozilla/dom/CSSTransition.h"
#include "mozilla/dom/ContentVisibilityAutoStateChangeEvent.h"
@ -10808,7 +10809,7 @@ bool nsIFrame::IsFocusableDueToScrollFrame() {
return true;
}
Focusable nsIFrame::IsFocusable(bool aWithMouse, bool aCheckVisibility) {
Focusable nsIFrame::IsFocusable(IsFocusableFlags aFlags) {
// cannot focus content in print preview mode. Only the root can be focused,
// but that's handled elsewhere.
if (PresContext()->Type() == nsPresContext::eContext_PrintPreview) {
@ -10819,7 +10820,8 @@ Focusable nsIFrame::IsFocusable(bool aWithMouse, bool aCheckVisibility) {
return {};
}
if (aCheckVisibility && !IsVisibleConsideringAncestors()) {
if (!(aFlags & IsFocusableFlags::IgnoreVisibility) &&
!IsVisibleConsideringAncestors()) {
return {};
}
@ -10839,14 +10841,14 @@ Focusable nsIFrame::IsFocusable(bool aWithMouse, bool aCheckVisibility) {
// As a legacy special-case, -moz-user-focus controls focusability and
// tabability of XUL elements in some circumstances (which default to
// -moz-user-focus: ignore).
auto focusability = xul->GetXULFocusability(aWithMouse);
auto focusability = xul->GetXULFocusability(aFlags);
focusable.mFocusable =
focusability.mForcedFocusable.valueOr(uf == StyleUserFocus::Normal);
if (focusable) {
focusable.mTabIndex = focusability.mForcedTabIndexIfFocusable.valueOr(0);
}
} else {
focusable = mContent->IsFocusableWithoutStyle(aWithMouse);
focusable = mContent->IsFocusableWithoutStyle(aFlags);
}
if (focusable) {
@ -10854,7 +10856,8 @@ Focusable nsIFrame::IsFocusable(bool aWithMouse, bool aCheckVisibility) {
}
// If we're focusing with the mouse we never focus scroll areas.
if (!aWithMouse && IsFocusableDueToScrollFrame()) {
if (!(aFlags & IsFocusableFlags::WithMouse) &&
IsFocusableDueToScrollFrame()) {
return {true, 0};
}

View File

@ -127,6 +127,7 @@ struct CharacterDataChangeInfo;
namespace mozilla {
enum class CaretAssociationHint;
enum class IsFocusableFlags : uint8_t;
enum class PeekOffsetOption : uint16_t;
enum class PseudoStyleType : uint8_t;
enum class TableSelectionMode : uint32_t;
@ -4387,13 +4388,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] aWithMouse, is this focus query for mouse clicking
* @param [in, optional] aCheckVisibility, whether to treat an invisible
* frame as not focusable
* @return whether the frame is focusable via mouse, kbd or script.
*/
[[nodiscard]] Focusable IsFocusable(bool aWithMouse = false,
bool aCheckVisibility = true);
[[nodiscard]] Focusable IsFocusable(
mozilla::IsFocusableFlags = mozilla::IsFocusableFlags(0));
protected:
// Helper for IsFocusable.