summaryrefslogtreecommitdiffstats
path: root/accessible/generic/Accessible.h
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/generic/Accessible.h')
-rw-r--r--accessible/generic/Accessible.h1270
1 files changed, 1270 insertions, 0 deletions
diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h
new file mode 100644
index 0000000000..a867cd42c2
--- /dev/null
+++ b/accessible/generic/Accessible.h
@@ -0,0 +1,1270 @@
+/* -*- 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/. */
+
+#ifndef _Accessible_H_
+#define _Accessible_H_
+
+#include "mozilla/a11y/AccTypes.h"
+#include "mozilla/a11y/RelationType.h"
+#include "mozilla/a11y/Role.h"
+#include "mozilla/a11y/States.h"
+
+#include "mozilla/UniquePtr.h"
+
+#include "nsIContent.h"
+#include "nsTArray.h"
+#include "nsRefPtrHashtable.h"
+#include "nsRect.h"
+
+struct nsRoleMapEntry;
+
+class nsIFrame;
+class nsIPersistentProperties;
+
+namespace mozilla::dom {
+class Element;
+}
+
+namespace mozilla {
+namespace a11y {
+
+class Accessible;
+class AccEvent;
+class AccGroupInfo;
+class ApplicationAccessible;
+class DocAccessible;
+class EmbeddedObjCollector;
+class EventTree;
+class HTMLImageMapAccessible;
+class HTMLLIAccessible;
+class HTMLLinkAccessible;
+class HyperTextAccessible;
+class ImageAccessible;
+class KeyBinding;
+class OuterDocAccessible;
+class ProxyAccessible;
+class Relation;
+class RootAccessible;
+class TableAccessible;
+class TableCellAccessible;
+class TextLeafAccessible;
+class XULLabelAccessible;
+class XULTreeAccessible;
+
+#ifdef A11Y_LOG
+namespace logging {
+typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
+void Tree(const char* aTitle, const char* aMsgText, Accessible* aRoot,
+ GetTreePrefix aPrefixFunc, void* GetTreePrefixData);
+}; // namespace logging
+#endif
+
+/**
+ * Name type flags.
+ */
+enum ENameValueFlag {
+ /**
+ * Name either
+ * a) present (not empty): !name.IsEmpty()
+ * b) no name (was missed): name.IsVoid()
+ */
+ eNameOK,
+
+ /**
+ * Name was left empty by the author on purpose:
+ * name.IsEmpty() && !name.IsVoid().
+ */
+ eNoNameOnPurpose,
+
+ /**
+ * Name was computed from the subtree.
+ */
+ eNameFromSubtree,
+
+ /**
+ * Tooltip was used as a name.
+ */
+ eNameFromTooltip
+};
+
+/**
+ * Group position (level, position in set and set size).
+ */
+struct GroupPos {
+ GroupPos() : level(0), posInSet(0), setSize(0) {}
+ GroupPos(int32_t aLevel, int32_t aPosInSet, int32_t aSetSize)
+ : level(aLevel), posInSet(aPosInSet), setSize(aSetSize) {}
+
+ int32_t level;
+ int32_t posInSet;
+ int32_t setSize;
+};
+
+/**
+ * An index type. Assert if out of range value was attempted to be used.
+ */
+class index_t {
+ public:
+ MOZ_IMPLICIT index_t(int32_t aVal) : mVal(aVal) {}
+
+ operator uint32_t() const {
+ MOZ_ASSERT(mVal >= 0, "Attempt to use wrong index!");
+ return mVal;
+ }
+
+ bool IsValid() const { return mVal >= 0; }
+
+ private:
+ int32_t mVal;
+};
+
+typedef nsRefPtrHashtable<nsPtrHashKey<const void>, Accessible>
+ AccessibleHashtable;
+
+#define NS_ACCESSIBLE_IMPL_IID \
+ { /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */ \
+ 0x133c8bf4, 0x4913, 0x4355, { \
+ 0xbd, 0x50, 0x42, 0x6b, 0xd1, 0xd6, 0xe1, 0xad \
+ } \
+ }
+
+class Accessible : public nsISupports {
+ public:
+ Accessible(nsIContent* aContent, DocAccessible* aDoc);
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(Accessible)
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID)
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Public methods
+
+ /**
+ * Return the document accessible for this accessible.
+ */
+ DocAccessible* Document() const { return mDoc; }
+
+ /**
+ * Return the root document accessible for this accessible.
+ */
+ a11y::RootAccessible* RootAccessible() const;
+
+ /**
+ * Return frame for this accessible.
+ */
+ virtual nsIFrame* GetFrame() const;
+
+ /**
+ * Return DOM node associated with the accessible.
+ */
+ virtual nsINode* GetNode() const;
+
+ nsIContent* GetContent() const { return mContent; }
+ dom::Element* Elm() const;
+
+ /**
+ * Return node type information of DOM node associated with the accessible.
+ */
+ bool IsContent() const { return GetNode() && GetNode()->IsContent(); }
+
+ /**
+ * Return the unique identifier of the accessible.
+ */
+ void* UniqueID() { return static_cast<void*>(this); }
+
+ /**
+ * Return language associated with the accessible.
+ */
+ void Language(nsAString& aLocale);
+
+ /**
+ * Get the description of this accessible.
+ */
+ virtual void Description(nsString& aDescription);
+
+ /**
+ * Get the value of this accessible.
+ */
+ virtual void Value(nsString& aValue) const;
+
+ /**
+ * Get help string for the accessible.
+ */
+ void Help(nsString& aHelp) const { aHelp.Truncate(); }
+
+ /**
+ * Get the name of this accessible.
+ *
+ * Note: aName.IsVoid() when name was left empty by the author on purpose.
+ * aName.IsEmpty() when the author missed name, AT can try to repair a name.
+ */
+ virtual ENameValueFlag Name(nsString& aName) const;
+
+ /**
+ * Maps ARIA state attributes to state of accessible. Note the given state
+ * argument should hold states for accessible before you pass it into this
+ * method.
+ *
+ * @param [in/out] where to fill the states into.
+ */
+ virtual void ApplyARIAState(uint64_t* aState) const;
+
+ /**
+ * Return enumerated accessible role (see constants in Role.h).
+ */
+ mozilla::a11y::role Role() const;
+
+ /**
+ * Return true if ARIA role is specified on the element.
+ */
+ bool HasARIARole() const;
+ bool IsARIARole(nsAtom* aARIARole) const;
+ bool HasStrongARIARole() const;
+
+ /**
+ * Retrun ARIA role map if any.
+ */
+ const nsRoleMapEntry* ARIARoleMap() const;
+
+ /**
+ * Return accessible role specified by ARIA (see constants in
+ * roles).
+ */
+ mozilla::a11y::role ARIARole();
+
+ /**
+ * Return a landmark role if applied.
+ */
+ virtual nsAtom* LandmarkRole() const;
+
+ /**
+ * Returns enumerated accessible role from native markup (see constants in
+ * Role.h). Doesn't take into account ARIA roles.
+ */
+ virtual mozilla::a11y::role NativeRole() const;
+
+ /**
+ * Return all states of accessible (including ARIA states).
+ */
+ virtual uint64_t State();
+
+ /**
+ * Return interactive states present on the accessible
+ * (@see NativeInteractiveState).
+ */
+ uint64_t InteractiveState() const {
+ uint64_t state = NativeInteractiveState();
+ ApplyARIAState(&state);
+ return state;
+ }
+
+ /**
+ * Return link states present on the accessible.
+ */
+ uint64_t LinkState() const {
+ uint64_t state = NativeLinkState();
+ ApplyARIAState(&state);
+ return state;
+ }
+
+ /**
+ * Return the states of accessible, not taking into account ARIA states.
+ * Use State() to get complete set of states.
+ */
+ virtual uint64_t NativeState() const;
+
+ /**
+ * Return native interactice state (unavailable, focusable or selectable).
+ */
+ virtual uint64_t NativeInteractiveState() const;
+
+ /**
+ * Return native link states present on the accessible.
+ */
+ virtual uint64_t NativeLinkState() const;
+
+ /**
+ * Return bit set of invisible and offscreen states.
+ */
+ uint64_t VisibilityState() const;
+
+ /**
+ * Return true if native unavailable state present.
+ */
+ virtual bool NativelyUnavailable() const;
+
+ /**
+ * Return object attributes for the accessible.
+ */
+ virtual already_AddRefed<nsIPersistentProperties> Attributes();
+
+ /**
+ * Return group position (level, position in set and set size).
+ */
+ virtual mozilla::a11y::GroupPos GroupPosition();
+
+ /**
+ * Used by ChildAtPoint() method to get direct or deepest child at point.
+ */
+ enum EWhichChildAtPoint { eDirectChild, eDeepestChild };
+
+ /**
+ * Return direct or deepest child at the given point.
+ *
+ * @param aX [in] x coordinate relative screen
+ * @param aY [in] y coordinate relative screen
+ * @param aWhichChild [in] flag points if deepest or direct child
+ * should be returned
+ */
+ virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
+ EWhichChildAtPoint aWhichChild);
+
+ /**
+ * Return the focused child if any.
+ */
+ virtual Accessible* FocusedChild();
+
+ /**
+ * Return calculated group level based on accessible hierarchy.
+ */
+ virtual int32_t GetLevelInternal();
+
+ /**
+ * Calculate position in group and group size ('posinset' and 'setsize') based
+ * on accessible hierarchy.
+ *
+ * @param aPosInSet [out] accessible position in the group
+ * @param aSetSize [out] the group size
+ */
+ virtual void GetPositionAndSizeInternal(int32_t* aPosInSet,
+ int32_t* aSetSize);
+
+ /**
+ * Get the relation of the given type.
+ */
+ virtual Relation RelationByType(RelationType aType) const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Initializing methods
+
+ /**
+ * Shutdown this accessible object.
+ */
+ virtual void Shutdown();
+
+ /**
+ * Set the ARIA role map entry for a new accessible.
+ */
+ void SetRoleMapEntry(const nsRoleMapEntry* aRoleMapEntry);
+
+ /**
+ * Append/insert/remove a child. Return true if operation was successful.
+ */
+ bool AppendChild(Accessible* aChild) {
+ return InsertChildAt(mChildren.Length(), aChild);
+ }
+ virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
+
+ /**
+ * Inserts a child after given sibling. If the child cannot be inserted,
+ * then the child is unbound from the document, and false is returned. Make
+ * sure to null out any references on the child object as it may be destroyed.
+ */
+ bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild);
+
+ virtual bool RemoveChild(Accessible* aChild);
+
+ /**
+ * Reallocates the child within its parent.
+ */
+ virtual void RelocateChild(uint32_t aNewIndex, Accessible* aChild);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Accessible tree traverse methods
+
+ /**
+ * Return parent accessible.
+ */
+ Accessible* Parent() const { return mParent; }
+
+ /**
+ * Return child accessible at the given index.
+ */
+ virtual Accessible* GetChildAt(uint32_t aIndex) const;
+
+ /**
+ * Return child accessible count.
+ */
+ virtual uint32_t ChildCount() const;
+
+ /**
+ * Return index of the given child accessible.
+ */
+ int32_t GetIndexOf(const Accessible* aChild) const {
+ return (aChild->mParent != this) ? -1 : aChild->IndexInParent();
+ }
+
+ /**
+ * Return index in parent accessible.
+ */
+ virtual int32_t IndexInParent() const;
+
+ /**
+ * Return true if accessible has children;
+ */
+ bool HasChildren() const { return !!GetChildAt(0); }
+
+ /**
+ * Return first/last/next/previous sibling of the accessible.
+ */
+ inline Accessible* NextSibling() const { return GetSiblingAtOffset(1); }
+ inline Accessible* PrevSibling() const { return GetSiblingAtOffset(-1); }
+ inline Accessible* FirstChild() const { return GetChildAt(0); }
+ inline Accessible* LastChild() const {
+ uint32_t childCount = ChildCount();
+ return childCount != 0 ? GetChildAt(childCount - 1) : nullptr;
+ }
+
+ /**
+ * Return embedded accessible children count.
+ */
+ uint32_t EmbeddedChildCount();
+
+ /**
+ * Return embedded accessible child at the given index.
+ */
+ Accessible* GetEmbeddedChildAt(uint32_t aIndex);
+
+ /**
+ * Return index of the given embedded accessible child.
+ */
+ int32_t GetIndexOfEmbeddedChild(Accessible* aChild);
+
+ /**
+ * Return number of content children/content child at index. The content
+ * child is created from markup in contrast to it's never constructed by its
+ * parent accessible (like treeitem accessibles for XUL trees).
+ */
+ uint32_t ContentChildCount() const { return mChildren.Length(); }
+ Accessible* ContentChildAt(uint32_t aIndex) const {
+ return mChildren.ElementAt(aIndex);
+ }
+
+ /**
+ * Return true if the accessible is attached to tree.
+ */
+ bool IsBoundToParent() const { return !!mParent; }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Miscellaneous methods
+
+ /**
+ * Handle accessible event, i.e. process it, notifies observers and fires
+ * platform specific event.
+ */
+ virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
+
+ /**
+ * Return true if the accessible is an acceptable child.
+ */
+ virtual bool IsAcceptableChild(nsIContent* aEl) const {
+ return aEl &&
+ !aEl->IsAnyOfHTMLElements(nsGkAtoms::option, nsGkAtoms::optgroup);
+ }
+
+ /**
+ * Returns text of accessible if accessible has text role otherwise empty
+ * string.
+ *
+ * @param aText [in] returned text of the accessible
+ * @param aStartOffset [in, optional] start offset inside of the accessible,
+ * if missed entire text is appended
+ * @param aLength [in, optional] required length of text, if missed
+ * then text form start offset till the end is appended
+ */
+ virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
+ uint32_t aLength = UINT32_MAX);
+
+ /**
+ * Return boundaries in screen coordinates in app units.
+ */
+ virtual nsRect BoundsInAppUnits() const;
+
+ /**
+ * Return boundaries in screen coordinates.
+ */
+ virtual nsIntRect Bounds() const;
+
+ /**
+ * Return boundaries in screen coordinates in CSS pixels.
+ */
+ virtual nsIntRect BoundsInCSSPixels() const;
+
+ /**
+ * Return boundaries rect relative the bounding frame.
+ */
+ virtual nsRect RelativeBounds(nsIFrame** aRelativeFrame) const;
+
+ /**
+ * Selects the accessible within its container if applicable.
+ */
+ virtual void SetSelected(bool aSelect);
+
+ /**
+ * Select the accessible within its container.
+ */
+ void TakeSelection();
+
+ /**
+ * Focus the accessible.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void TakeFocus() const;
+
+ /**
+ * Scroll the accessible into view.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ virtual void ScrollTo(uint32_t aHow) const;
+
+ /**
+ * Scroll the accessible to the given point.
+ */
+ void ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY);
+
+ /**
+ * Get a pointer to accessibility interface for this node, which is specific
+ * to the OS/accessibility toolkit we're running on.
+ */
+ virtual void GetNativeInterface(void** aNativeAccessible);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Downcasting and types
+
+ inline bool IsAbbreviation() const {
+ return mContent->IsAnyOfHTMLElements(nsGkAtoms::abbr, nsGkAtoms::acronym);
+ }
+
+ bool IsAlert() const { return HasGenericType(eAlert); }
+
+ bool IsApplication() const { return mType == eApplicationType; }
+ ApplicationAccessible* AsApplication();
+
+ bool IsAutoComplete() const { return HasGenericType(eAutoComplete); }
+
+ bool IsAutoCompletePopup() const {
+ return HasGenericType(eAutoCompletePopup);
+ }
+
+ bool IsButton() const { return HasGenericType(eButton); }
+
+ bool IsCombobox() const { return HasGenericType(eCombobox); }
+
+ bool IsDoc() const { return HasGenericType(eDocument); }
+ DocAccessible* AsDoc();
+
+ bool IsGenericHyperText() const { return mType == eHyperTextType; }
+ bool IsHyperText() const { return HasGenericType(eHyperText); }
+ HyperTextAccessible* AsHyperText();
+
+ bool IsHTMLBr() const { return mType == eHTMLBRType; }
+ bool IsHTMLCaption() const { return mType == eHTMLCaptionType; }
+ bool IsHTMLCombobox() const { return mType == eHTMLComboboxType; }
+ bool IsHTMLFileInput() const { return mType == eHTMLFileInputType; }
+
+ bool IsHTMLListItem() const { return mType == eHTMLLiType; }
+ HTMLLIAccessible* AsHTMLListItem();
+
+ bool IsHTMLLink() const { return mType == eHTMLLinkType; }
+ HTMLLinkAccessible* AsHTMLLink();
+
+ bool IsHTMLOptGroup() const { return mType == eHTMLOptGroupType; }
+
+ bool IsHTMLTable() const { return mType == eHTMLTableType; }
+ bool IsHTMLTableRow() const { return mType == eHTMLTableRowType; }
+
+ bool IsImage() const { return mType == eImageType; }
+ ImageAccessible* AsImage();
+
+ bool IsImageMap() const { return mType == eImageMapType; }
+ HTMLImageMapAccessible* AsImageMap();
+
+ bool IsList() const { return HasGenericType(eList); }
+
+ bool IsListControl() const { return HasGenericType(eListControl); }
+
+ bool IsMenuButton() const { return HasGenericType(eMenuButton); }
+
+ bool IsMenuPopup() const { return mType == eMenuPopupType; }
+
+ bool IsProxy() const { return mType == eProxyType; }
+ ProxyAccessible* Proxy() const {
+ MOZ_ASSERT(IsProxy());
+ return mBits.proxy;
+ }
+ uint32_t ProxyInterfaces() const {
+ MOZ_ASSERT(IsProxy());
+ return mInt.mProxyInterfaces;
+ }
+ void SetProxyInterfaces(uint32_t aInterfaces) {
+ MOZ_ASSERT(IsProxy());
+ mInt.mProxyInterfaces = aInterfaces;
+ }
+
+ bool IsOuterDoc() const { return mType == eOuterDocType; }
+ OuterDocAccessible* AsOuterDoc();
+
+ bool IsProgress() const { return mType == eProgressType; }
+
+ bool IsRoot() const { return mType == eRootType; }
+ a11y::RootAccessible* AsRoot();
+
+ bool IsSearchbox() const;
+
+ bool IsSelect() const { return HasGenericType(eSelect); }
+
+ bool IsTable() const { return HasGenericType(eTable); }
+ virtual TableAccessible* AsTable() { return nullptr; }
+
+ /**
+ * Note: The eTable* types defined in the ARIA map are used in
+ * nsAccessibilityService::CreateAccessible to determine which ARIAGrid*
+ * classes to use for accessible object creation. However, an invalid table
+ * structure might cause these classes not to be used after all.
+ *
+ * To make sure we're really dealing with a table cell, only check the
+ * generic type defined by the class, not the type defined in the ARIA map.
+ */
+ bool IsTableCell() const { return mGenericTypes & eTableCell; }
+ virtual TableCellAccessible* AsTableCell() { return nullptr; }
+ const TableCellAccessible* AsTableCell() const {
+ return const_cast<Accessible*>(this)->AsTableCell();
+ }
+
+ bool IsTableRow() const { return HasGenericType(eTableRow); }
+
+ bool IsTextField() const {
+ return mType == eHTMLTextFieldType || mType == eHTMLTextPasswordFieldType;
+ }
+
+ bool IsPassword() const { return mType == eHTMLTextPasswordFieldType; }
+
+ bool IsText() const { return mGenericTypes & eText; }
+
+ bool IsTextLeaf() const { return mType == eTextLeafType; }
+ TextLeafAccessible* AsTextLeaf();
+
+ bool IsXULLabel() const { return mType == eXULLabelType; }
+ XULLabelAccessible* AsXULLabel();
+
+ bool IsXULListItem() const { return mType == eXULListItemType; }
+
+ bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
+
+ bool IsXULTooltip() const { return mType == eXULTooltipType; }
+
+ bool IsXULTree() const { return mType == eXULTreeType; }
+ XULTreeAccessible* AsXULTree();
+
+ /**
+ * Return true if the accessible belongs to the given accessible type.
+ */
+ bool HasGenericType(AccGenericType aType) const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // ActionAccessible
+
+ /**
+ * Return the number of actions that can be performed on this accessible.
+ */
+ virtual uint8_t ActionCount() const;
+
+ /**
+ * Return action name at given index.
+ */
+ virtual void ActionNameAt(uint8_t aIndex, nsAString& aName);
+
+ /**
+ * Default to localized action name.
+ */
+ void ActionDescriptionAt(uint8_t aIndex, nsAString& aDescription) {
+ nsAutoString name;
+ ActionNameAt(aIndex, name);
+ TranslateString(name, aDescription);
+ }
+
+ /**
+ * Invoke the accessible action.
+ */
+ virtual bool DoAction(uint8_t aIndex) const;
+
+ /**
+ * Return access key, such as Alt+D.
+ */
+ virtual KeyBinding AccessKey() const;
+
+ /**
+ * Return global keyboard shortcut for default action, such as Ctrl+O for
+ * Open file menuitem.
+ */
+ virtual KeyBinding KeyboardShortcut() const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // HyperLinkAccessible (any embedded object in text can implement HyperLink,
+ // which helps determine where it is located within containing text).
+
+ /**
+ * Return true if the accessible is hyper link accessible.
+ */
+ virtual bool IsLink() const;
+
+ /**
+ * Return the start offset of the link within the parent accessible.
+ */
+ virtual uint32_t StartOffset();
+
+ /**
+ * Return the end offset of the link within the parent accessible.
+ */
+ virtual uint32_t EndOffset();
+
+ /**
+ * Return true if the link is valid (e. g. points to a valid URL).
+ */
+ inline bool IsLinkValid() {
+ MOZ_ASSERT(IsLink(), "IsLinkValid is called on not hyper link!");
+
+ // XXX In order to implement this we would need to follow every link
+ // Perhaps we can get information about invalid links from the cache
+ // In the mean time authors can use role="link" aria-invalid="true"
+ // to force it for links they internally know to be invalid
+ return (0 == (State() & mozilla::a11y::states::INVALID));
+ }
+
+ /**
+ * Return the number of anchors within the link.
+ */
+ virtual uint32_t AnchorCount();
+
+ /**
+ * Returns an anchor accessible at the given index.
+ */
+ virtual Accessible* AnchorAt(uint32_t aAnchorIndex);
+
+ /**
+ * Returns an anchor URI at the given index.
+ */
+ virtual already_AddRefed<nsIURI> AnchorURIAt(uint32_t aAnchorIndex) const;
+
+ /**
+ * Returns a text point for the accessible element.
+ */
+ void ToTextPoint(HyperTextAccessible** aContainer, int32_t* aOffset,
+ bool aIsBefore = true) const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // SelectAccessible
+
+ /**
+ * Return an array of selected items.
+ */
+ virtual void SelectedItems(nsTArray<Accessible*>* aItems);
+
+ /**
+ * Return the number of selected items.
+ */
+ virtual uint32_t SelectedItemCount();
+
+ /**
+ * Return selected item at the given index.
+ */
+ virtual Accessible* GetSelectedItem(uint32_t aIndex);
+
+ /**
+ * Determine if item at the given index is selected.
+ */
+ virtual bool IsItemSelected(uint32_t aIndex);
+
+ /**
+ * Add item at the given index the selection. Return true if success.
+ */
+ virtual bool AddItemToSelection(uint32_t aIndex);
+
+ /**
+ * Remove item at the given index from the selection. Return if success.
+ */
+ virtual bool RemoveItemFromSelection(uint32_t aIndex);
+
+ /**
+ * Select all items. Return true if success.
+ */
+ virtual bool SelectAll();
+
+ /**
+ * Unselect all items. Return true if success.
+ */
+ virtual bool UnselectAll();
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Value (numeric value interface)
+
+ virtual double MaxValue() const;
+ virtual double MinValue() const;
+ virtual double CurValue() const;
+ virtual double Step() const;
+ virtual bool SetCurValue(double aValue);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Widgets
+
+ /**
+ * Return true if accessible is a widget, i.e. control or accessible that
+ * manages its items. Note, being a widget the accessible may be a part of
+ * composite widget.
+ */
+ virtual bool IsWidget() const;
+
+ /**
+ * Return true if the widget is active, i.e. has a focus within it.
+ */
+ virtual bool IsActiveWidget() const;
+
+ /**
+ * Return true if the widget has items and items are operable by user and
+ * can be activated.
+ */
+ virtual bool AreItemsOperable() const;
+
+ /**
+ * Return the current item of the widget, i.e. an item that has or will have
+ * keyboard focus when widget gets active.
+ */
+ virtual Accessible* CurrentItem() const;
+
+ /**
+ * Set the current item of the widget.
+ */
+ virtual void SetCurrentItem(const Accessible* aItem);
+
+ /**
+ * Return container widget this accessible belongs to.
+ */
+ virtual Accessible* ContainerWidget() const;
+
+ /**
+ * Return the localized string for the given key.
+ */
+ static void TranslateString(const nsString& aKey, nsAString& aStringOut);
+
+ /**
+ * Return true if the accessible is defunct.
+ */
+ bool IsDefunct() const;
+
+ /**
+ * Return false if the accessible is no longer in the document.
+ */
+ bool IsInDocument() const { return !(mStateFlags & eIsNotInDocument); }
+
+ /**
+ * Return true if the accessible should be contained by document node map.
+ */
+ bool IsNodeMapEntry() const {
+ return HasOwnContent() && !(mStateFlags & eNotNodeMapEntry);
+ }
+
+ /**
+ * Return true if the accessible's group info needs to be updated.
+ */
+ inline bool HasDirtyGroupInfo() const {
+ return mStateFlags & eGroupInfoDirty;
+ }
+
+ /**
+ * Return true if the accessible has associated DOM content.
+ */
+ bool HasOwnContent() const {
+ return mContent && !(mStateFlags & eSharedNode);
+ }
+
+ /**
+ * Return true if native markup has a numeric value.
+ */
+ bool NativeHasNumericValue() const;
+
+ /**
+ * Return true if ARIA specifies support for a numeric value.
+ */
+ bool ARIAHasNumericValue() const;
+
+ /**
+ * Return true if the accessible has a numeric value.
+ */
+ bool HasNumericValue() const;
+
+ /**
+ * Return true if the accessible state change is processed by handling proper
+ * DOM UI event, if otherwise then false. For example, CheckboxAccessible
+ * created for HTML:input@type="checkbox" will process
+ * nsIDocumentObserver::ContentStateChanged instead of 'CheckboxStateChange'
+ * event.
+ */
+ bool NeedsDOMUIEvent() const { return !(mStateFlags & eIgnoreDOMUIEvent); }
+
+ /**
+ * Get/set repositioned bit indicating that the accessible was moved in
+ * the accessible tree, i.e. the accessible tree structure differs from DOM.
+ */
+ bool IsRelocated() const { return mStateFlags & eRelocated; }
+ void SetRelocated(bool aRelocated) {
+ if (aRelocated)
+ mStateFlags |= eRelocated;
+ else
+ mStateFlags &= ~eRelocated;
+ }
+
+ /**
+ * Return true if the accessible allows accessible children from subtree of
+ * a DOM element of this accessible.
+ */
+ bool KidsFromDOM() const { return !(mStateFlags & eNoKidsFromDOM); }
+
+ /**
+ * Return true if this accessible has a parent whose name depends on this
+ * accessible.
+ */
+ bool HasNameDependentParent() const {
+ return mContextFlags & eHasNameDependentParent;
+ }
+
+ /**
+ * Return true if the element is inside an alert.
+ */
+ bool IsInsideAlert() const { return mContextFlags & eInsideAlert; }
+
+ /**
+ * Return true if there is a pending reorder event for this accessible.
+ */
+ bool ReorderEventTarget() const { return mReorderEventTarget; }
+
+ /**
+ * Return true if there is a pending show event for this accessible.
+ */
+ bool ShowEventTarget() const { return mShowEventTarget; }
+
+ /**
+ * Return true if there is a pending hide event for this accessible.
+ */
+ bool HideEventTarget() const { return mHideEventTarget; }
+
+ /**
+ * Set if there is a pending reorder event for this accessible.
+ */
+ void SetReorderEventTarget(bool aTarget) { mReorderEventTarget = aTarget; }
+
+ /**
+ * Set if this accessible is a show event target.
+ */
+ void SetShowEventTarget(bool aTarget) { mShowEventTarget = aTarget; }
+
+ /**
+ * Set if this accessible is a hide event target.
+ */
+ void SetHideEventTarget(bool aTarget) { mHideEventTarget = aTarget; }
+
+ void Announce(const nsAString& aAnnouncement, uint16_t aPriority);
+
+ /**
+ * Fire a focusable state change event if the previous state
+ * was different.
+ */
+ void MaybeFireFocusableStateChange(bool aPreviouslyFocusable);
+
+ protected:
+ virtual ~Accessible();
+
+ /**
+ * Return the accessible name provided by native markup. It doesn't take
+ * into account ARIA markup used to specify the name.
+ */
+ virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName) const;
+
+ /**
+ * Return the accessible description provided by native markup. It doesn't
+ * take into account ARIA markup used to specify the description.
+ */
+ virtual void NativeDescription(nsString& aDescription);
+
+ /**
+ * Return object attributes provided by native markup. It doesn't take into
+ * account ARIA.
+ */
+ virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Initializing, cache and tree traverse methods
+
+ /**
+ * Destroy the object.
+ */
+ void LastRelease();
+
+ /**
+ * Set accessible parent and index in parent.
+ */
+ void BindToParent(Accessible* aParent, uint32_t aIndexInParent);
+ void UnbindFromParent();
+
+ /**
+ * Return sibling accessible at the given offset.
+ */
+ virtual Accessible* GetSiblingAtOffset(int32_t aOffset,
+ nsresult* aError = nullptr) const;
+
+ /**
+ * Flags used to describe the state of this accessible.
+ */
+ enum StateFlags {
+ eIsDefunct = 1 << 0, // accessible is defunct
+ eIsNotInDocument = 1 << 1, // accessible is not in document
+ eSharedNode = 1 << 2, // accessible shares DOM node from another accessible
+ eNotNodeMapEntry = 1 << 3, // accessible shouldn't be in document node map
+ eHasNumericValue = 1 << 4, // accessible has a numeric value
+ eGroupInfoDirty = 1 << 5, // accessible needs to update group info
+ eKidsMutating = 1 << 6, // subtree is being mutated
+ eIgnoreDOMUIEvent = 1 << 7, // don't process DOM UI events for a11y events
+ eRelocated = 1 << 8, // accessible was moved in tree
+ eNoKidsFromDOM = 1 << 9, // accessible doesn't allow children from DOM
+ eHasTextKids = 1 << 10, // accessible have a text leaf in children
+
+ eLastStateFlag = eHasTextKids
+ };
+
+ /**
+ * Flags used for contextual information about the accessible.
+ */
+ enum ContextFlags {
+ eHasNameDependentParent =
+ 1 << 0, // Parent's name depends on this accessible.
+ eInsideAlert = 1 << 1,
+
+ eLastContextFlag = eInsideAlert
+ };
+
+ protected:
+ //////////////////////////////////////////////////////////////////////////////
+ // Miscellaneous helpers
+
+ /**
+ * Return ARIA role (helper method).
+ */
+ mozilla::a11y::role ARIATransformRole(mozilla::a11y::role aRole) const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Name helpers
+
+ /**
+ * Returns the accessible name specified by ARIA.
+ */
+ void ARIAName(nsString& aName) const;
+
+ /**
+ * Returns the accessible description specified by ARIA.
+ */
+ void ARIADescription(nsString& aDescription) const;
+
+ /**
+ * Returns the accessible name specified for this control using XUL
+ * <label control="id" ...>.
+ */
+ static void NameFromAssociatedXULLabel(DocAccessible* aDocument,
+ nsIContent* aElm, nsString& aName);
+
+ /**
+ * Return the name for XUL element.
+ */
+ static void XULElmName(DocAccessible* aDocument, nsIContent* aElm,
+ nsString& aName);
+
+ // helper method to verify frames
+ static nsresult GetFullKeyName(const nsAString& aModifierName,
+ const nsAString& aKeyName,
+ nsAString& aStringOut);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Action helpers
+
+ /**
+ * Prepares click action that will be invoked in timeout.
+ *
+ * @note DoCommand() prepares an action in timeout because when action
+ * command opens a modal dialog/window, it won't return until the
+ * dialog/window is closed. If executing action command directly in
+ * nsIAccessible::DoAction() method, it will block AT tools (e.g. GOK) that
+ * invoke action of mozilla accessibles direclty (see bug 277888 for
+ * details).
+ *
+ * @param aContent [in, optional] element to click
+ * @param aActionIndex [in, optional] index of accessible action
+ */
+ void DoCommand(nsIContent* aContent = nullptr,
+ uint32_t aActionIndex = 0) const;
+
+ /**
+ * Dispatch click event.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ virtual void DispatchClickEvent(nsIContent* aContent,
+ uint32_t aActionIndex) const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Helpers
+
+ /**
+ * Get the container node for an atomic region, defined by aria-atomic="true"
+ * @return the container node
+ */
+ nsIContent* GetAtomicRegion() const;
+
+ /**
+ * Return numeric value of the given ARIA attribute, NaN if not applicable.
+ *
+ * @param aARIAProperty [in] the ARIA property we're using
+ * @return a numeric value
+ */
+ double AttrNumericValue(nsAtom* aARIAAttr) const;
+
+ /**
+ * Return the action rule based on ARIA enum constants EActionRule
+ * (see ARIAMap.h). Used by ActionCount() and ActionNameAt().
+ */
+ uint32_t GetActionRule() const;
+
+ /**
+ * Return group info.
+ */
+ AccGroupInfo* GetGroupInfo() const;
+
+ // Data Members
+ nsCOMPtr<nsIContent> mContent;
+ RefPtr<DocAccessible> mDoc;
+
+ Accessible* mParent;
+ nsTArray<Accessible*> mChildren;
+ int32_t mIndexInParent;
+
+ static const uint8_t kStateFlagsBits = 11;
+ static const uint8_t kContextFlagsBits = 2;
+ static const uint8_t kTypeBits = 6;
+ static const uint8_t kGenericTypesBits = 16;
+
+ /**
+ * Non-NO_ROLE_MAP_ENTRY_INDEX indicates author-supplied role;
+ * possibly state & value as well
+ */
+ uint8_t mRoleMapEntryIndex;
+
+ /**
+ * Keep in sync with StateFlags, ContextFlags, and AccTypes.
+ */
+ mutable uint32_t mStateFlags : kStateFlagsBits;
+ uint32_t mContextFlags : kContextFlagsBits;
+ uint32_t mType : kTypeBits;
+ uint32_t mGenericTypes : kGenericTypesBits;
+ uint32_t mReorderEventTarget : 1;
+ uint32_t mShowEventTarget : 1;
+ uint32_t mHideEventTarget : 1;
+
+ void StaticAsserts() const;
+
+#ifdef A11Y_LOG
+ friend void logging::Tree(const char* aTitle, const char* aMsgText,
+ Accessible* aRoot,
+ logging::GetTreePrefix aPrefixFunc,
+ void* aGetTreePrefixData);
+#endif
+ friend class DocAccessible;
+ friend class xpcAccessible;
+ friend class TreeMutation;
+
+ UniquePtr<mozilla::a11y::EmbeddedObjCollector> mEmbeddedObjCollector;
+ union {
+ int32_t mIndexOfEmbeddedChild;
+ uint32_t mProxyInterfaces;
+ } mInt;
+
+ friend class EmbeddedObjCollector;
+
+ union {
+ AccGroupInfo* groupInfo;
+ ProxyAccessible* proxy;
+ } mutable mBits;
+ friend class AccGroupInfo;
+
+ private:
+ Accessible() = delete;
+ Accessible(const Accessible&) = delete;
+ Accessible& operator=(const Accessible&) = delete;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(Accessible, NS_ACCESSIBLE_IMPL_IID)
+
+/**
+ * Represent key binding associated with accessible (such as access key and
+ * global keyboard shortcuts).
+ */
+class KeyBinding {
+ public:
+ /**
+ * Modifier mask values.
+ */
+ static const uint32_t kShift = 1;
+ static const uint32_t kControl = 2;
+ static const uint32_t kAlt = 4;
+ static const uint32_t kMeta = 8;
+ static const uint32_t kOS = 16;
+
+ static uint32_t AccelModifier();
+
+ KeyBinding() : mKey(0), mModifierMask(0) {}
+ KeyBinding(uint32_t aKey, uint32_t aModifierMask)
+ : mKey(aKey), mModifierMask(aModifierMask) {}
+
+ inline bool IsEmpty() const { return !mKey; }
+ inline uint32_t Key() const { return mKey; }
+ inline uint32_t ModifierMask() const { return mModifierMask; }
+
+ enum Format { ePlatformFormat, eAtkFormat };
+
+ /**
+ * Return formatted string for this key binding depending on the given format.
+ */
+ inline void ToString(nsAString& aValue,
+ Format aFormat = ePlatformFormat) const {
+ aValue.Truncate();
+ AppendToString(aValue, aFormat);
+ }
+ inline void AppendToString(nsAString& aValue,
+ Format aFormat = ePlatformFormat) const {
+ if (mKey) {
+ if (aFormat == ePlatformFormat)
+ ToPlatformFormat(aValue);
+ else
+ ToAtkFormat(aValue);
+ }
+ }
+
+ private:
+ void ToPlatformFormat(nsAString& aValue) const;
+ void ToAtkFormat(nsAString& aValue) const;
+
+ uint32_t mKey;
+ uint32_t mModifierMask;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif