/* -*- 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 "HTMLListAccessible.h" #include "DocAccessible.h" #include "nsAccUtils.h" #include "Role.h" #include "States.h" #include "EventTree.h" #include "nsBlockFrame.h" #include "nsBulletFrame.h" using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // HTMLListAccessible //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED0(HTMLListAccessible, HyperTextAccessible) role HTMLListAccessible::NativeRole() { a11y::role r = GetAccService()->MarkupRole(mContent); return r != roles::NOTHING ? r : roles::LIST; } uint64_t HTMLListAccessible::NativeState() { return HyperTextAccessibleWrap::NativeState() | states::READONLY; } //////////////////////////////////////////////////////////////////////////////// // HTMLLIAccessible //////////////////////////////////////////////////////////////////////////////// HTMLLIAccessible:: HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc) : HyperTextAccessibleWrap(aContent, aDoc), mBullet(nullptr) { mType = eHTMLLiType; nsBlockFrame* blockFrame = do_QueryFrame(GetFrame()); if (blockFrame && blockFrame->HasBullet()) { mBullet = new HTMLListBulletAccessible(mContent, mDoc); Document()->BindToDocument(mBullet, nullptr); AppendChild(mBullet); } } NS_IMPL_ISUPPORTS_INHERITED0(HTMLLIAccessible, HyperTextAccessible) void HTMLLIAccessible::Shutdown() { mBullet = nullptr; HyperTextAccessibleWrap::Shutdown(); } role HTMLLIAccessible::NativeRole() { a11y::role r = GetAccService()->MarkupRole(mContent); return r != roles::NOTHING ? r : roles::LISTITEM; } uint64_t HTMLLIAccessible::NativeState() { return HyperTextAccessibleWrap::NativeState() | states::READONLY; } nsIntRect HTMLLIAccessible::Bounds() const { nsIntRect rect = AccessibleWrap::Bounds(); if (rect.IsEmpty() || !mBullet || mBullet->IsInside()) return rect; nsIntRect bulletRect = mBullet->Bounds(); rect.width += rect.x - bulletRect.x; rect.x = bulletRect.x; // Move x coordinate of list item over to cover bullet as well return rect; } bool HTMLLIAccessible::InsertChildAt(uint32_t aIndex, Accessible* aChild) { // Adjust index if there's a bullet. if (mBullet && aIndex == 0 && aChild != mBullet) { return HyperTextAccessible::InsertChildAt(aIndex + 1, aChild); } return HyperTextAccessible::InsertChildAt(aIndex, aChild); } //////////////////////////////////////////////////////////////////////////////// // HTMLLIAccessible: public void HTMLLIAccessible::UpdateBullet(bool aHasBullet) { if (aHasBullet == !!mBullet) { NS_NOTREACHED("Bullet and accessible are in sync already!"); return; } TreeMutation mt(this); if (aHasBullet) { mBullet = new HTMLListBulletAccessible(mContent, mDoc); mDoc->BindToDocument(mBullet, nullptr); InsertChildAt(0, mBullet); mt.AfterInsertion(mBullet); } else { mt.BeforeRemoval(mBullet); RemoveChild(mBullet); mBullet = nullptr; } mt.Done(); } //////////////////////////////////////////////////////////////////////////////// // HTMLListBulletAccessible //////////////////////////////////////////////////////////////////////////////// HTMLListBulletAccessible:: HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc) : LeafAccessible(aContent, aDoc) { mGenericTypes |= eText; mStateFlags |= eSharedNode; } //////////////////////////////////////////////////////////////////////////////// // HTMLListBulletAccessible: Accessible nsIFrame* HTMLListBulletAccessible::GetFrame() const { nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); return blockFrame ? blockFrame->GetBullet() : nullptr; } ENameValueFlag HTMLListBulletAccessible::Name(nsString &aName) { aName.Truncate(); // Native anonymous content, ARIA can't be used. Get list bullet text. nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); if (blockFrame) { blockFrame->GetSpokenBulletText(aName); } return eNameOK; } role HTMLListBulletAccessible::NativeRole() { return roles::STATICTEXT; } uint64_t HTMLListBulletAccessible::NativeState() { return LeafAccessible::NativeState() | states::READONLY; } void HTMLListBulletAccessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset, uint32_t aLength) { nsAutoString bulletText; nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); if (blockFrame) blockFrame->GetSpokenBulletText(bulletText); aText.Append(Substring(bulletText, aStartOffset, aLength)); } //////////////////////////////////////////////////////////////////////////////// // HTMLListBulletAccessible: public bool HTMLListBulletAccessible::IsInside() const { nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); return blockFrame ? blockFrame->HasInsideBullet() : false; }