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 "XULTabAccessible.h" michael@0: michael@0: #include "nsAccUtils.h" michael@0: #include "Relation.h" michael@0: #include "Role.h" michael@0: #include "States.h" michael@0: michael@0: // NOTE: alphabetically ordered michael@0: #include "nsIAccessibleRelation.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsIDOMXULSelectCntrlEl.h" michael@0: #include "nsIDOMXULSelectCntrlItemEl.h" michael@0: #include "nsIDOMXULRelatedElement.h" michael@0: michael@0: using namespace mozilla::a11y; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULTabAccessible:: michael@0: XULTabAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: AccessibleWrap(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabAccessible: nsIAccessible michael@0: michael@0: uint8_t michael@0: XULTabAccessible::ActionCount() michael@0: { michael@0: return 1; michael@0: } michael@0: michael@0: /** Return the name of our only action */ michael@0: NS_IMETHODIMP michael@0: XULTabAccessible::GetActionName(uint8_t aIndex, nsAString& aName) michael@0: { michael@0: if (aIndex == eAction_Switch) { michael@0: aName.AssignLiteral("switch"); michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: /** Tell the tab to do its action */ michael@0: NS_IMETHODIMP michael@0: XULTabAccessible::DoAction(uint8_t index) michael@0: { michael@0: if (index == eAction_Switch) { michael@0: nsCOMPtr tab(do_QueryInterface(mContent)); michael@0: if ( tab ) michael@0: { michael@0: tab->Click(); michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: return NS_ERROR_INVALID_ARG; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabAccessible: Accessible michael@0: michael@0: role michael@0: XULTabAccessible::NativeRole() michael@0: { michael@0: return roles::PAGETAB; michael@0: } michael@0: michael@0: uint64_t michael@0: XULTabAccessible::NativeState() michael@0: { michael@0: // Possible states: focused, focusable, unavailable(disabled), offscreen. michael@0: michael@0: // get focus and disable status from base class michael@0: uint64_t state = AccessibleWrap::NativeState(); michael@0: michael@0: // Check whether the tab is selected and/or pinned michael@0: nsCOMPtr tab(do_QueryInterface(mContent)); michael@0: if (tab) { michael@0: bool selected = false; michael@0: if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected) michael@0: state |= states::SELECTED; michael@0: michael@0: if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned, michael@0: nsGkAtoms::_true, eCaseMatters)) michael@0: state |= states::PINNED; michael@0: michael@0: } michael@0: michael@0: return state; michael@0: } michael@0: michael@0: uint64_t michael@0: XULTabAccessible::NativeInteractiveState() const michael@0: { michael@0: uint64_t state = Accessible::NativeInteractiveState(); michael@0: return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE; michael@0: } michael@0: michael@0: // nsIAccessible michael@0: Relation michael@0: XULTabAccessible::RelationByType(RelationType aType) michael@0: { michael@0: Relation rel = AccessibleWrap::RelationByType(aType); michael@0: if (aType != RelationType::LABEL_FOR) michael@0: return rel; michael@0: michael@0: // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible. michael@0: nsCOMPtr tabsElm = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: if (!tabsElm) michael@0: return rel; michael@0: michael@0: nsCOMPtr domNode(DOMNode()); michael@0: nsCOMPtr tabpanelNode; michael@0: tabsElm->GetRelatedElement(domNode, getter_AddRefs(tabpanelNode)); michael@0: if (!tabpanelNode) michael@0: return rel; michael@0: michael@0: nsCOMPtr tabpanelContent(do_QueryInterface(tabpanelNode)); michael@0: rel.AppendTarget(mDoc, tabpanelContent); michael@0: return rel; michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabsAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULTabsAccessible:: michael@0: XULTabsAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: XULSelectControlAccessible(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: role michael@0: XULTabsAccessible::NativeRole() michael@0: { michael@0: return roles::PAGETABLIST; michael@0: } michael@0: michael@0: uint8_t michael@0: XULTabsAccessible::ActionCount() michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: void michael@0: XULTabsAccessible::Value(nsString& aValue) michael@0: { michael@0: aValue.Truncate(); michael@0: } michael@0: michael@0: ENameValueFlag michael@0: XULTabsAccessible::NativeName(nsString& aName) michael@0: { michael@0: // no name michael@0: return eNameOK; michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabpanelsAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: role michael@0: XULTabpanelsAccessible::NativeRole() michael@0: { michael@0: return roles::PANE; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // XULTabpanelAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: XULTabpanelAccessible:: michael@0: XULTabpanelAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: AccessibleWrap(aContent, aDoc) michael@0: { michael@0: } michael@0: michael@0: role michael@0: XULTabpanelAccessible::NativeRole() michael@0: { michael@0: return roles::PROPERTYPAGE; michael@0: } michael@0: michael@0: Relation michael@0: XULTabpanelAccessible::RelationByType(RelationType aType) michael@0: { michael@0: Relation rel = AccessibleWrap::RelationByType(aType); michael@0: if (aType != RelationType::LABELLED_BY) michael@0: return rel; michael@0: michael@0: // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible. michael@0: nsCOMPtr tabpanelsElm = michael@0: do_QueryInterface(mContent->GetParent()); michael@0: if (!tabpanelsElm) michael@0: return rel; michael@0: michael@0: nsCOMPtr domNode(DOMNode()); michael@0: nsCOMPtr tabNode; michael@0: tabpanelsElm->GetRelatedElement(domNode, getter_AddRefs(tabNode)); michael@0: if (!tabNode) michael@0: return rel; michael@0: michael@0: nsCOMPtr tabContent(do_QueryInterface(tabNode)); michael@0: rel.AppendTarget(mDoc, tabContent); michael@0: return rel; michael@0: }