michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "BaseAccessibles.h" michael@0: michael@0: #include "Accessible-inl.h" michael@0: #include "HyperTextAccessibleWrap.h" michael@0: #include "nsAccessibilityService.h" michael@0: #include "nsAccUtils.h" michael@0: #include "nsCoreUtils.h" michael@0: #include "Role.h" michael@0: #include "States.h" michael@0: #include "nsIURI.h" michael@0: michael@0: using namespace mozilla::a11y; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LeafAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: LeafAccessible:: michael@0: LeafAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: AccessibleWrap(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(LeafAccessible, Accessible) michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LeafAccessible: Accessible public michael@0: michael@0: Accessible* michael@0: LeafAccessible::ChildAtPoint(int32_t aX, int32_t aY, michael@0: EWhichChildAtPoint aWhichChild) michael@0: { michael@0: // Don't walk into leaf accessibles. michael@0: return this; michael@0: } michael@0: michael@0: bool michael@0: LeafAccessible::InsertChildAt(uint32_t aIndex, Accessible* aChild) michael@0: { michael@0: NS_NOTREACHED("InsertChildAt called on leaf accessible!"); michael@0: return false; michael@0: } michael@0: michael@0: bool michael@0: LeafAccessible::RemoveChild(Accessible* aChild) michael@0: { michael@0: NS_NOTREACHED("RemoveChild called on leaf accessible!"); michael@0: return false; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LeafAccessible: Accessible private michael@0: michael@0: void michael@0: LeafAccessible::CacheChildren() michael@0: { michael@0: // No children for leaf accessible. michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LinkableAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: LinkableAccessible:: michael@0: LinkableAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: AccessibleWrap(aContent, aDoc), michael@0: mActionAcc(nullptr), michael@0: mIsLink(false), michael@0: mIsOnclick(false) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(LinkableAccessible, AccessibleWrap) michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LinkableAccessible. nsIAccessible michael@0: michael@0: NS_IMETHODIMP michael@0: LinkableAccessible::TakeFocus() michael@0: { michael@0: return mActionAcc ? mActionAcc->TakeFocus() : AccessibleWrap::TakeFocus(); michael@0: } michael@0: michael@0: uint64_t michael@0: LinkableAccessible::NativeLinkState() const michael@0: { michael@0: if (mIsLink) michael@0: return states::LINKED | (mActionAcc->LinkState() & states::TRAVERSED); michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: void michael@0: LinkableAccessible::Value(nsString& aValue) michael@0: { michael@0: aValue.Truncate(); michael@0: michael@0: Accessible::Value(aValue); michael@0: if (!aValue.IsEmpty()) michael@0: return; michael@0: michael@0: if (aValue.IsEmpty() && mIsLink) michael@0: mActionAcc->Value(aValue); michael@0: } michael@0: michael@0: michael@0: uint8_t michael@0: LinkableAccessible::ActionCount() michael@0: { michael@0: return (mIsOnclick || mIsLink) ? 1 : 0; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: LinkableAccessible::GetActionName(uint8_t aIndex, nsAString& aName) michael@0: { michael@0: aName.Truncate(); michael@0: michael@0: // Action 0 (default action): Jump to link michael@0: if (aIndex == eAction_Jump) { michael@0: if (mIsLink) { michael@0: aName.AssignLiteral("jump"); michael@0: return NS_OK; michael@0: } michael@0: else if (mIsOnclick) { michael@0: aName.AssignLiteral("click"); michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: LinkableAccessible::DoAction(uint8_t aIndex) michael@0: { michael@0: if (aIndex != eAction_Jump) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: return mActionAcc ? mActionAcc->DoAction(aIndex) : michael@0: AccessibleWrap::DoAction(aIndex); michael@0: } michael@0: michael@0: KeyBinding michael@0: LinkableAccessible::AccessKey() const michael@0: { michael@0: return mActionAcc ? michael@0: mActionAcc->AccessKey() : Accessible::AccessKey(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LinkableAccessible. Accessible michael@0: michael@0: void michael@0: LinkableAccessible::Shutdown() michael@0: { michael@0: mIsLink = false; michael@0: mIsOnclick = false; michael@0: mActionAcc = nullptr; michael@0: AccessibleWrap::Shutdown(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LinkableAccessible: HyperLinkAccessible michael@0: michael@0: already_AddRefed michael@0: LinkableAccessible::AnchorURIAt(uint32_t aAnchorIndex) michael@0: { michael@0: if (mIsLink) { michael@0: NS_ASSERTION(mActionAcc->IsLink(), michael@0: "nsIAccessibleHyperLink isn't implemented."); michael@0: michael@0: if (mActionAcc->IsLink()) michael@0: return mActionAcc->AnchorURIAt(aAnchorIndex); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // LinkableAccessible: Accessible protected michael@0: michael@0: void michael@0: LinkableAccessible::BindToParent(Accessible* aParent, michael@0: uint32_t aIndexInParent) michael@0: { michael@0: AccessibleWrap::BindToParent(aParent, aIndexInParent); michael@0: michael@0: // Cache action content. michael@0: mActionAcc = nullptr; michael@0: mIsLink = false; michael@0: mIsOnclick = false; michael@0: michael@0: if (nsCoreUtils::HasClickListener(mContent)) { michael@0: mIsOnclick = true; michael@0: return; michael@0: } michael@0: michael@0: // XXX: The logic looks broken since the click listener may be registered michael@0: // on non accessible node in parent chain but this node is skipped when tree michael@0: // is traversed. michael@0: Accessible* walkUpAcc = this; michael@0: while ((walkUpAcc = walkUpAcc->Parent()) && !walkUpAcc->IsDoc()) { michael@0: if (walkUpAcc->LinkState() & states::LINKED) { michael@0: mIsLink = true; michael@0: mActionAcc = walkUpAcc; michael@0: return; michael@0: } michael@0: michael@0: if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) { michael@0: mActionAcc = walkUpAcc; michael@0: mIsOnclick = true; michael@0: return; michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: LinkableAccessible::UnbindFromParent() michael@0: { michael@0: mActionAcc = nullptr; michael@0: mIsLink = false; michael@0: mIsOnclick = false; michael@0: michael@0: AccessibleWrap::UnbindFromParent(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // EnumRoleAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: EnumRoleAccessible:: michael@0: EnumRoleAccessible(nsIContent* aNode, DocAccessible* aDoc, roles::Role aRole) : michael@0: AccessibleWrap(aNode, aDoc), mRole(aRole) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(EnumRoleAccessible, Accessible) michael@0: michael@0: role michael@0: EnumRoleAccessible::NativeRole() michael@0: { michael@0: return mRole; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // DummyAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: uint64_t michael@0: DummyAccessible::NativeState() michael@0: { michael@0: return 0; michael@0: } michael@0: uint64_t michael@0: DummyAccessible::NativeInteractiveState() const michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: uint64_t michael@0: DummyAccessible::NativeLinkState() const michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: bool michael@0: DummyAccessible::NativelyUnavailable() const michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: void michael@0: DummyAccessible::ApplyARIAState(uint64_t* aState) const michael@0: { michael@0: }