diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /accessible/xul/XULElementAccessibles.cpp | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | accessible/xul/XULElementAccessibles.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/accessible/xul/XULElementAccessibles.cpp b/accessible/xul/XULElementAccessibles.cpp new file mode 100644 index 0000000000..d2d200a7d1 --- /dev/null +++ b/accessible/xul/XULElementAccessibles.cpp @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "XULElementAccessibles.h" + +#include "Accessible-inl.h" +#include "BaseAccessibles.h" +#include "DocAccessible-inl.h" +#include "nsAccUtils.h" +#include "nsCoreUtils.h" +#include "nsTextEquivUtils.h" +#include "Relation.h" +#include "Role.h" +#include "States.h" +#include "TextUpdater.h" + +#ifdef A11Y_LOG +# include "Logging.h" +#endif + +#include "nsNameSpaceManager.h" +#include "nsNetUtil.h" +#include "nsString.h" +#include "nsTextBoxFrame.h" +#include "nsXULElement.h" + +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// XULLabelAccessible +//////////////////////////////////////////////////////////////////////////////// + +XULLabelAccessible::XULLabelAccessible(nsIContent* aContent, + DocAccessible* aDoc) + : HyperTextAccessibleWrap(aContent, aDoc) { + mType = eXULLabelType; + + // If @value attribute is given then it's rendered instead text content. In + // this case we need to create a text leaf accessible to make @value attribute + // accessible. + // XXX: text interface doesn't let you get the text by words. + nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame()); + if (textBoxFrame) { + mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc); + mDoc->BindToDocument(mValueTextLeaf, nullptr); + + nsAutoString text; + textBoxFrame->GetCroppedTitle(text); + mValueTextLeaf->SetText(text); + AppendChild(mValueTextLeaf); + } +} + +void XULLabelAccessible::Shutdown() { + mValueTextLeaf = nullptr; + HyperTextAccessibleWrap::Shutdown(); +} + +void XULLabelAccessible::DispatchClickEvent(nsIContent* aContent, + uint32_t aActionIndex) const { + // Bug 1578140: For labels inside buttons, The base implementation of + // DispatchClickEvent doesn't fire a command event on the button. + RefPtr<nsXULElement> el = nsXULElement::FromNodeOrNull(aContent); + if (el) { + el->Click(mozilla::dom::CallerType::System); + } +} + +ENameValueFlag XULLabelAccessible::NativeName(nsString& aName) const { + // if the value attr doesn't exist, the screen reader must get the accessible + // text from the accessible text interface or from the children + if (mValueTextLeaf) return mValueTextLeaf->Name(aName); + + return Accessible::NativeName(aName); +} + +role XULLabelAccessible::NativeRole() const { return roles::LABEL; } + +uint64_t XULLabelAccessible::NativeState() const { + // Labels and description have read only state + // They are not focusable or selectable + return HyperTextAccessibleWrap::NativeState() | states::READONLY; +} + +Relation XULLabelAccessible::RelationByType(RelationType aType) const { + Relation rel = HyperTextAccessibleWrap::RelationByType(aType); + + // The label for xul:groupbox is generated from the first xul:label + if (aType == RelationType::LABEL_FOR) { + Accessible* parent = Parent(); + if (parent && parent->Role() == roles::GROUPING && + parent->GetChildAt(0) == this) { + nsIContent* parentContent = parent->GetContent(); + if (parentContent && parentContent->IsXULElement(nsGkAtoms::groupbox)) { + rel.AppendTarget(parent); + } + } + } + + return rel; +} + +void XULLabelAccessible::UpdateLabelValue(const nsString& aValue) { +#ifdef A11Y_LOG + if (logging::IsEnabled(logging::eText)) { + logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)"); + logging::Node("container", mContent); + logging::MsgEntry("old text '%s'", + NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get()); + logging::MsgEntry("new text: '%s'", NS_ConvertUTF16toUTF8(aValue).get()); + logging::MsgEnd(); + } +#endif + + TextUpdater::Run(mDoc, mValueTextLeaf, aValue); +} + +//////////////////////////////////////////////////////////////////////////////// +// XULLabelTextLeafAccessible +//////////////////////////////////////////////////////////////////////////////// + +role XULLabelTextLeafAccessible::NativeRole() const { return roles::TEXT_LEAF; } + +uint64_t XULLabelTextLeafAccessible::NativeState() const { + return TextLeafAccessibleWrap::NativeState() | states::READONLY; +} + +//////////////////////////////////////////////////////////////////////////////// +// XULTooltipAccessible +//////////////////////////////////////////////////////////////////////////////// + +XULTooltipAccessible::XULTooltipAccessible(nsIContent* aContent, + DocAccessible* aDoc) + : LeafAccessible(aContent, aDoc) { + mType = eXULTooltipType; +} + +uint64_t XULTooltipAccessible::NativeState() const { + return LeafAccessible::NativeState() | states::READONLY; +} + +role XULTooltipAccessible::NativeRole() const { return roles::TOOLTIP; } + +//////////////////////////////////////////////////////////////////////////////// +// XULLinkAccessible +//////////////////////////////////////////////////////////////////////////////// + +XULLinkAccessible::XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) + : XULLabelAccessible(aContent, aDoc) {} + +XULLinkAccessible::~XULLinkAccessible() {} + +//////////////////////////////////////////////////////////////////////////////// +// XULLinkAccessible: Accessible + +void XULLinkAccessible::Value(nsString& aValue) const { + aValue.Truncate(); + + mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue); +} + +ENameValueFlag XULLinkAccessible::NativeName(nsString& aName) const { + mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName); + if (!aName.IsEmpty()) return eNameOK; + + nsTextEquivUtils::GetNameFromSubtree(this, aName); + return aName.IsEmpty() ? eNameOK : eNameFromSubtree; +} + +role XULLinkAccessible::NativeRole() const { return roles::LINK; } + +uint64_t XULLinkAccessible::NativeLinkState() const { return states::LINKED; } + +uint8_t XULLinkAccessible::ActionCount() const { return 1; } + +void XULLinkAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { + aName.Truncate(); + + if (aIndex == eAction_Jump) aName.AssignLiteral("jump"); +} + +bool XULLinkAccessible::DoAction(uint8_t aIndex) const { + if (aIndex != eAction_Jump) return false; + + DoCommand(); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// XULLinkAccessible: HyperLinkAccessible + +bool XULLinkAccessible::IsLink() const { + // Expose HyperLinkAccessible unconditionally. + return true; +} + +uint32_t XULLinkAccessible::StartOffset() { + // If XUL link accessible is not contained by hypertext accessible then + // start offset matches index in parent because the parent doesn't contains + // a text. + // XXX: accessible parent of XUL link accessible should be a hypertext + // accessible. + if (Accessible::IsLink()) return Accessible::StartOffset(); + return IndexInParent(); +} + +uint32_t XULLinkAccessible::EndOffset() { + if (Accessible::IsLink()) return Accessible::EndOffset(); + return IndexInParent() + 1; +} + +already_AddRefed<nsIURI> XULLinkAccessible::AnchorURIAt( + uint32_t aAnchorIndex) const { + if (aAnchorIndex != 0) return nullptr; + + nsAutoString href; + mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); + + dom::Document* document = mContent->OwnerDoc(); + + nsCOMPtr<nsIURI> anchorURI; + NS_NewURI(getter_AddRefs(anchorURI), href, + document->GetDocumentCharacterSet(), mContent->GetBaseURI()); + + return anchorURI.forget(); +} |