mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Implement basic accessible relations. r=louie.zhao, sr=jst, a=mkaply
This commit is contained in:
parent
b42edae703
commit
cc014c3df1
@ -188,6 +188,11 @@ interface nsIAccessible : nsISupports
|
||||
*/
|
||||
nsIAccessible getAccessibleBelow();
|
||||
|
||||
/**
|
||||
* Accessible node related to this one
|
||||
*/
|
||||
nsIAccessible getAccessibleRelated(in unsigned long aRelationType);
|
||||
|
||||
void getBounds(out long x,
|
||||
out long y,
|
||||
out long width,
|
||||
@ -301,10 +306,57 @@ interface nsIAccessible : nsISupports
|
||||
const unsigned long EXT_STATE_TRANSIENT = 0x40000000; // Tells accessibility aid "Don't add event listener - this object doesn't generate any". For example, could be used with higher level containers.
|
||||
const unsigned long EXT_STATE_VERTICAL = 0x80000000; // Especially used for sliders and scrollbars
|
||||
|
||||
/**
|
||||
* Relation Types -- most of these come from ATK's atkrelationtype.h
|
||||
* RELATION_NULL:
|
||||
* RELATION_CONTROLLED_BY: Controlled by one or more target objects.
|
||||
* RELATION_CONTROLLER_FOR: Controller for one or more target objects.
|
||||
* RELATION_LABEL_FOR: Label for one or more target objects.
|
||||
* RELATION_LABELLED_BY: Labelled by one or more target objects.
|
||||
* RELATION_MEMBER_OF: Member of a group of one or more target objects.
|
||||
* RELATION_NODE_CHILD_OF: Cell in a treetable which is displayed because a
|
||||
* cell in the same col is expanded & identifies it.
|
||||
* RELATION_FLOWS_TO: Has content that flows logically to another
|
||||
* object in a sequential way, e.g. text flow.
|
||||
* RELATION_FLOWS_FROM: Has content that flows logically from another
|
||||
* object in a sequential way, e.g. text flow.
|
||||
* RELATION_SUBWINDOW_OF: Subwindow attached to a component but otherwise
|
||||
* not connected in the UI hierarchy to that component.
|
||||
* RELATION_EMBEDS: Visually embeds another object's content, i.e.
|
||||
* this object's content flows around another's content.
|
||||
* RELATION_EMBEDDED_BY: Inverse of RELATION_EMBEDS; this object's content
|
||||
* is visually embedded in another object.
|
||||
* RELATION_POPUP_FOR: Popup for another object.
|
||||
* RELATION_PARENT_WINDOW_OF: Parent window of another object.
|
||||
* RELATION_DEFAULT_BUTTON: Part of a form/dialog with a related default button.
|
||||
* RELATION_DESCRIBED_BY: Described by one or more target objects.
|
||||
* RELATION_DESCRIPTION_FOR: Description for one or more target objects.
|
||||
* RELATION_LAST_DEFINED:
|
||||
*/
|
||||
|
||||
const unsigned long RELATION_NUL = 0x00; // ATK_RELATION_NUL
|
||||
const unsigned long RELATION_CONTROLLED_BY = 0x01; // ATK_RELATION_CONTROLLED_BY
|
||||
const unsigned long RELATION_CONTROLLER_FOR = 0x02; // ATK_RELATION_CONTROLLER_FOR
|
||||
const unsigned long RELATION_LABEL_FOR = 0x03; // ATK_RELATION_LABEL_FOR
|
||||
const unsigned long RELATION_LABELLED_BY = 0x04; // ATK_RELATION_LABELLED_BY
|
||||
const unsigned long RELATION_MEMBER_OF = 0x05; // ATK_RELATION_MEMBER_OF
|
||||
const unsigned long RELATION_NODE_CHILD_OF = 0x06; // ATK_RELATION_NODE_CHILD_OF
|
||||
const unsigned long RELATION_FLOWS_TO = 0x07; // ATK_RELATION_FLOWS_TO
|
||||
const unsigned long RELATION_FLOWS_FROM = 0x08; // ATK_RELATION_FLOWS_FROM
|
||||
const unsigned long RELATION_SUBWINDOW_OF = 0x09; // ATK_RELATION_SUBWINDOW_OF
|
||||
const unsigned long RELATION_EMBEDS = 0x0a; // ATK_RELATION_EMBEDS
|
||||
const unsigned long RELATION_EMBEDDED_BY = 0x0b; // ATK_RELATION_EMBEDDED_BY
|
||||
const unsigned long RELATION_POPUP_FOR = 0x0c; // ATK_RELATION_POPUP_FOR
|
||||
const unsigned long RELATION_PARENT_WINDOW_OF = 0x0d; // ATK_RELATION_PARENT_WINDOW_OF
|
||||
const unsigned long RELATION_DEFAULT_BUTTON = 0x4000; // MSAA only, no ATK relation
|
||||
const unsigned long RELATION_DESCRIBED_BY = 0x4001; // MSAA only, no ATK relation
|
||||
const unsigned long RELATION_DESCRIPTION_FOR = 0x4002; // MSAA only, no ATK relation
|
||||
|
||||
%{C++
|
||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||
|
||||
enum { RELATION_LAST_DEFINED = 14U };
|
||||
|
||||
/**
|
||||
* The following nsIAccessible roles are translated to ATK_ROLE_UNKNOWN
|
||||
*
|
||||
@ -545,6 +597,25 @@ interface nsIAccessible : nsISupports
|
||||
// When in doubt map them to ROLE_NOTHING so that the role string is exposed
|
||||
enum { ROLE_ICON = ROLE_NOTHING };
|
||||
enum { ROLE_PASSWORD_TEXT = ROLE_TEXT };
|
||||
|
||||
// MSAA relationship extensions to accNavigate
|
||||
enum { NAVRELATION_CONTROLLED_BY = 0x1000 };
|
||||
enum { NAVRELATION_CONTROLLER_FOR = 0x1001 };
|
||||
enum { NAVRELATION_LABEL_FOR = 0x1002 };
|
||||
enum { NAVRELATION_LABELLED_BY = 0x1003 };
|
||||
enum { NAVRELATION_MEMBER_OF = 0x1004 };
|
||||
enum { NAVRELATION_NODE_CHILD_OF = 0x1005 };
|
||||
enum { NAVRELATION_FLOWS_TO = 0x1006 };
|
||||
enum { NAVRELATION_FLOWS_FROM = 0x1007 };
|
||||
enum { NAVRELATION_SUBWINDOW_OF = 0x1008 };
|
||||
enum { NAVRELATION_EMBEDS = 0x1009 };
|
||||
enum { NAVRELATION_EMBEDDED_BY = 0x100a };
|
||||
enum { NAVRELATION_POPUP_FOR = 0x100b };
|
||||
enum { NAVRELATION_PARENT_WINDOW_OF = 0x100c };
|
||||
enum { NAVRELATION_DEFAULT_BUTTON = 0x100d };
|
||||
enum { NAVRELATION_DESCRIBED_BY = 0x100e };
|
||||
enum { NAVRELATION_DESCRIPTION_FOR = 0x100f };
|
||||
|
||||
#endif
|
||||
%}
|
||||
};
|
||||
|
@ -107,10 +107,10 @@ static gint getChildCountCB(AtkObject *aAtkObj);
|
||||
static AtkObject* refChildCB(AtkObject *aAtkObj, gint aChildIndex);
|
||||
static gint getIndexInParentCB(AtkObject *aAtkObj);
|
||||
static AtkStateSet* refStateSetCB(AtkObject *aAtkObj);
|
||||
static AtkRelationSet* refRelationSetCB(AtkObject *aAtkObj);
|
||||
|
||||
/* the missing atkobject virtual functions */
|
||||
/*
|
||||
static AtkRelationSet* refRelationSetCB(AtkObject *aAtkObj);
|
||||
static AtkLayer getLayerCB(AtkObject *aAtkObj);
|
||||
static gint getMdiZorderCB(AtkObject *aAtkObj);
|
||||
static void SetNameCB(AtkObject *aAtkObj,
|
||||
@ -455,7 +455,6 @@ The following nsIAccessible states aren't translated, just ignored.
|
||||
STATE_READONLY: The object is designated read-only.
|
||||
STATE_HOTTRACKED: Means its appearance has changed to indicate mouse
|
||||
over it.
|
||||
STATE_DEFAULT: Represents the default button in a window.
|
||||
STATE_FLOATING: Not supported yet.
|
||||
STATE_MARQUEED: Indicate scrolling or moving text or graphics.
|
||||
STATE_ANIMATED:
|
||||
@ -535,6 +534,11 @@ nsAccessibleWrap::TranslateStates(PRUint32 aState, PRUint32 aExtState, void *aAt
|
||||
if (aState & nsIAccessible::STATE_INVALID)
|
||||
atk_state_set_add_state (state_set, ATK_STATE_INVALID);
|
||||
|
||||
#ifdef MAI_HAS_ATK_STATE_DEFAULT
|
||||
if (aState & nsIAccessible::STATE_DEFAULT)
|
||||
atk_state_set_add_state (state_set, ATK_STATE_DEFAULT);
|
||||
#endif
|
||||
|
||||
#ifdef MAI_HAS_ATK_STATE_REQUIRED
|
||||
if (aState & nsIAccessible::STATE_REQUIRED)
|
||||
atk_state_set_add_state (state_set, ATK_STATE_REQUIRED);
|
||||
@ -595,6 +599,7 @@ classInitCB(AtkObjectClass *aClass)
|
||||
aClass->get_index_in_parent = getIndexInParentCB;
|
||||
aClass->get_role = getRoleCB;
|
||||
aClass->ref_state_set = refStateSetCB;
|
||||
aClass->ref_relation_set = refRelationSetCB;
|
||||
|
||||
aClass->initialize = initializeCB;
|
||||
|
||||
@ -898,6 +903,38 @@ refStateSetCB(AtkObject *aAtkObj)
|
||||
return state_set;
|
||||
}
|
||||
|
||||
AtkRelationSet *
|
||||
refRelationSetCB(AtkObject *aAtkObj)
|
||||
{
|
||||
AtkRelationSet *relation_set = nsnull;
|
||||
relation_set = ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
|
||||
|
||||
NS_ENSURE_SUCCESS(CheckMaiAtkObject(aAtkObj), relation_set);
|
||||
nsAccessibleWrap *accWrap =
|
||||
NS_REINTERPRET_CAST(MaiAtkObject*, aAtkObj)->accWrap;
|
||||
|
||||
AtkObject *accessible_array[1];
|
||||
AtkRelation* relation;
|
||||
|
||||
PRUint32 relationType[2] = {nsIAccessible::RELATION_LABELLED_BY,
|
||||
nsIAccessible::RELATION_LABEL_FOR};
|
||||
|
||||
for (PRUint32 i = 0; i <= 1; i++) {
|
||||
if (!atk_relation_set_contains(relation_set, NS_STATIC_CAST(AtkRelationType, relationType[i]))) {
|
||||
nsIAccessible* accRelated;
|
||||
nsresult rv = accWrap->GetAccessibleRelated(relationType[i], &accRelated);
|
||||
if (NS_SUCCEEDED(rv) && accRelated) {
|
||||
accessible_array[0] = NS_STATIC_CAST(nsAccessibleWrap*, accRelated)->GetAtkObject();
|
||||
relation = atk_relation_new(accessible_array, 1,
|
||||
NS_STATIC_CAST(AtkRelationType, relationType[i]));
|
||||
atk_relation_set_add(relation_set, relation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return relation_set;
|
||||
}
|
||||
|
||||
// Check if aAtkObj is a valid MaiAtkObject
|
||||
nsresult
|
||||
CheckMaiAtkObject(AtkObject *aAtkObj)
|
||||
|
@ -69,6 +69,7 @@ ACCESSIBILITY_ATOM(area, "area")
|
||||
ACCESSIBILITY_ATOM(blockquote, "blockquote")
|
||||
ACCESSIBILITY_ATOM(br, "br")
|
||||
ACCESSIBILITY_ATOM(body, "body")
|
||||
ACCESSIBILITY_ATOM(description, "description") // XUL
|
||||
ACCESSIBILITY_ATOM(form, "form")
|
||||
ACCESSIBILITY_ATOM(h1, "h1")
|
||||
ACCESSIBILITY_ATOM(h2, "h2")
|
||||
@ -88,7 +89,7 @@ ACCESSIBILITY_ATOM(select, "select")
|
||||
ACCESSIBILITY_ATOM(tbody, "tbody")
|
||||
ACCESSIBILITY_ATOM(tfoot, "tfoot")
|
||||
ACCESSIBILITY_ATOM(thead, "thead")
|
||||
ACCESSIBILITY_ATOM(toolbaritem, "toolbaritem")
|
||||
ACCESSIBILITY_ATOM(toolbaritem, "toolbaritem") // XUL
|
||||
ACCESSIBILITY_ATOM(ul, "ul")
|
||||
|
||||
// DHTML accessibility relationship attributes
|
||||
|
@ -67,7 +67,6 @@
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMHTMLBRElement.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
@ -77,8 +76,13 @@
|
||||
#include "nsIDOMXULButtonElement.h"
|
||||
#include "nsIDOMXULCheckboxElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentXBL.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDOMXULLabelElement.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
@ -86,7 +90,6 @@
|
||||
#include "nsAccessibleTreeWalker.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
|
||||
@ -197,10 +200,7 @@ NS_IMETHODIMP nsAccessible::GetKeyboardShortcut(nsAString& _retval)
|
||||
elt->GetAttribute(NS_LITERAL_STRING("accesskey"), accesskey);
|
||||
if (accesskey.IsEmpty()) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(elt);
|
||||
nsIContent *labelContent =
|
||||
content->IsContentOfType(nsIContent::eXUL) ? GetXULLabelContent(content) :
|
||||
GetHTMLLabelContent(content);
|
||||
|
||||
nsIContent *labelContent = GetLabelContent(content);
|
||||
if (labelContent) {
|
||||
labelContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::accesskey, accesskey);
|
||||
}
|
||||
@ -1209,10 +1209,17 @@ nsresult nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* nsAccessible::GetXULLabelContent(nsIContent *aForNode)
|
||||
nsIContent *nsAccessible::GetLabelContent(nsIContent *aForNode)
|
||||
{
|
||||
return aForNode->IsContentOfType(nsIContent::eXUL) ? GetXULLabelContent(aForNode) :
|
||||
GetHTMLLabelContent(aForNode);
|
||||
}
|
||||
|
||||
nsIContent* nsAccessible::GetXULLabelContent(nsIContent *aForNode, nsIAtom *aLabelType)
|
||||
{
|
||||
nsAutoString controlID;
|
||||
nsIContent *labelContent = GetLabelForId(aForNode, nsnull, &controlID);
|
||||
nsIContent *labelContent = GetContentPointingTo(&controlID, aForNode, nsnull,
|
||||
kNameSpaceID_None, aLabelType);
|
||||
if (labelContent) {
|
||||
return labelContent;
|
||||
}
|
||||
@ -1232,12 +1239,14 @@ nsIContent* nsAccessible::GetXULLabelContent(nsIContent *aForNode)
|
||||
}
|
||||
}
|
||||
|
||||
// Look for child label of control
|
||||
// Look for label in subtrees of nearby ancestors
|
||||
static const PRUint32 kAncestorLevelsToSearch = 3;
|
||||
PRUint32 count = 0;
|
||||
while (!labelContent && ++count <= kAncestorLevelsToSearch &&
|
||||
(aForNode = aForNode->GetParent()) != nsnull) {
|
||||
labelContent = GetLabelForId(aForNode, nsAccessibilityAtoms::control, &controlID);
|
||||
labelContent = GetContentPointingTo(&controlID, aForNode,
|
||||
nsAccessibilityAtoms::control,
|
||||
kNameSpaceID_None, aLabelType);
|
||||
}
|
||||
|
||||
return labelContent;
|
||||
@ -1264,7 +1273,7 @@ nsIContent* nsAccessible::GetHTMLLabelContent(nsIContent *aForNode)
|
||||
if (forId.IsEmpty()) {
|
||||
break;
|
||||
}
|
||||
return GetLabelForId(walkUpContent, nsAccessibilityAtoms::_for, &forId);
|
||||
return GetContentPointingTo(&forId, walkUpContent, nsAccessibilityAtoms::_for);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1303,28 +1312,33 @@ nsresult nsAccessible::GetTextFromRelationID(nsIAtom *aIDAttrib, nsString &aName
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Pass in forAttrib == nsnull if any <label> will do
|
||||
nsIContent *nsAccessible::GetLabelForId(nsIContent *aLookContent,
|
||||
nsIAtom *forAttrib,
|
||||
const nsAString *aId)
|
||||
// Pass in aForAttrib == nsnull if any <label> will do
|
||||
nsIContent *nsAccessible::GetContentPointingTo(const nsAString *aId,
|
||||
nsIContent *aLookContent,
|
||||
nsIAtom *aForAttrib,
|
||||
PRUint32 aForAttribNameSpace,
|
||||
nsIAtom *aTagType)
|
||||
{
|
||||
if (aLookContent->Tag() == nsAccessibilityAtoms::label) {
|
||||
if (forAttrib) {
|
||||
if (!aTagType || aLookContent->Tag() == aTagType) {
|
||||
if (aForAttrib) {
|
||||
nsAutoString labelIsFor;
|
||||
aLookContent->GetAttr(kNameSpaceID_None, forAttrib, labelIsFor);
|
||||
aLookContent->GetAttr(aForAttribNameSpace, aForAttrib, labelIsFor);
|
||||
if (labelIsFor.Equals(*aId)) {
|
||||
return aLookContent;
|
||||
}
|
||||
}
|
||||
if (aTagType) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively search descendents for labels
|
||||
PRUint32 count = 0;
|
||||
nsIContent *child;
|
||||
|
||||
while ((child = aLookContent->GetChildAt(count++)) != nsnull) {
|
||||
nsIContent *labelContent = GetLabelForId(child, forAttrib, aId);
|
||||
nsIContent *labelContent = GetContentPointingTo(aId, child, aForAttrib,
|
||||
aForAttribNameSpace, aTagType);
|
||||
if (labelContent) {
|
||||
return labelContent;
|
||||
}
|
||||
@ -1794,6 +1808,176 @@ NS_IMETHODIMP nsAccessible::GetAccessibleBelow(nsIAccessible **_retval)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* nsIAccessible getAccessibleRelated(); */
|
||||
NS_IMETHODIMP nsAccessible::GetAccessibleRelated(PRUint32 aRelationType, nsIAccessible **aRelated)
|
||||
{
|
||||
*aRelated = nsnull;
|
||||
|
||||
// Relationships are defined on the same content node
|
||||
// that the role would be defined on
|
||||
nsIContent *content = GetRoleContent(mDOMNode);
|
||||
if (!content) {
|
||||
return NS_ERROR_FAILURE; // Node already shut down
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relatedNode;
|
||||
nsAutoString relatedID;
|
||||
|
||||
// Search for the related DOM node according to the specified "relation type"
|
||||
switch (aRelationType)
|
||||
{
|
||||
case RELATION_LABEL_FOR:
|
||||
{
|
||||
if (content->Tag() == nsAccessibilityAtoms::label) {
|
||||
nsIAtom *relatedIDAttr = content->IsContentOfType(nsIContent::eHTML) ?
|
||||
nsAccessibilityAtoms::_for : nsAccessibilityAtoms::control;
|
||||
content->GetAttr(kNameSpaceID_None, relatedIDAttr, relatedID);
|
||||
if (relatedID.IsEmpty()) {
|
||||
// Check first child for form control
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RELATION_LABELLED_BY:
|
||||
{
|
||||
relatedNode = do_QueryInterface(GetLabelContent(content));
|
||||
break;
|
||||
}
|
||||
case RELATION_DESCRIBED_BY:
|
||||
{
|
||||
content->GetAttr(kNameSpaceID_StatesWAI_Unofficial,
|
||||
nsAccessibilityAtoms::describedby, relatedID);
|
||||
if (relatedID.IsEmpty()) {
|
||||
nsIContent *description =
|
||||
GetXULLabelContent(content, nsAccessibilityAtoms::description);
|
||||
relatedNode = do_QueryInterface(description);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RELATION_DESCRIPTION_FOR:
|
||||
{
|
||||
nsAutoString controlID;
|
||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::id, controlID);
|
||||
if (!controlID.IsEmpty()) {
|
||||
// Something might be pointing to us
|
||||
PRUint32 count = 0;
|
||||
nsIContent *start = content;
|
||||
static const PRUint32 kAncestorLevelsToSearch = 3;
|
||||
while (!relatedNode && ++count <= kAncestorLevelsToSearch &&
|
||||
(start = start->GetParent()) != nsnull) {
|
||||
nsIContent *description = GetContentPointingTo(&controlID, start,
|
||||
nsAccessibilityAtoms::describedby,
|
||||
kNameSpaceID_StatesWAI_Unofficial,
|
||||
nsnull);
|
||||
relatedNode = do_QueryInterface(description);
|
||||
}
|
||||
}
|
||||
|
||||
nsIContent *description =
|
||||
GetXULLabelContent(content, nsAccessibilityAtoms::description);
|
||||
if (!relatedNode && content->Tag() == nsAccessibilityAtoms::description &&
|
||||
content->IsContentOfType(nsIContent::eXUL)) {
|
||||
// This affectively adds an optional control attribute to xul:description,
|
||||
// which only affects accessibility, by allowing the description to be
|
||||
// tied to a control.
|
||||
content->GetAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::control, relatedID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RELATION_DEFAULT_BUTTON:
|
||||
{
|
||||
if (content->IsContentOfType(nsIContent::eHTML)) {
|
||||
nsCOMPtr<nsIForm> form;
|
||||
while ((form = do_QueryInterface(content)) == nsnull &&
|
||||
(content = content->GetParent()) != nsnull) /* nothing */ ;
|
||||
|
||||
if (form) {
|
||||
// We have a <form> element, so iterate through and try to find a submit button
|
||||
nsCOMPtr<nsISimpleEnumerator> formControls;
|
||||
form->GetControlEnumerator(getter_AddRefs(formControls));
|
||||
nsCOMPtr<nsISupports> controlSupports;
|
||||
PRBool hasMoreElements;
|
||||
while (NS_SUCCEEDED(formControls->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsresult rv = formControls->GetNext(getter_AddRefs(controlSupports));
|
||||
nsCOMPtr<nsIFormControl> control = do_QueryInterface(controlSupports);
|
||||
if (control) {
|
||||
PRInt32 type = control->GetType();
|
||||
if (type == NS_FORM_INPUT_SUBMIT || type == NS_FORM_BUTTON_SUBMIT ||
|
||||
type == NS_FORM_INPUT_IMAGE) {
|
||||
relatedNode = do_QueryInterface(control);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// In XUL, use first <button default="true" .../> in the document
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(content->GetDocument());
|
||||
nsCOMPtr<nsIDOMXULButtonElement> buttonEl;
|
||||
if (xulDoc) {
|
||||
nsCOMPtr<nsIDOMNodeList> possibleDefaultButtons;
|
||||
xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
|
||||
NS_LITERAL_STRING("true"),
|
||||
getter_AddRefs(possibleDefaultButtons));
|
||||
if (possibleDefaultButtons) {
|
||||
PRUint32 length;
|
||||
possibleDefaultButtons->GetLength(&length);
|
||||
nsCOMPtr<nsIDOMNode> possibleButton;
|
||||
// Check for button in list of default="true" elements
|
||||
for (PRUint32 count = 0; count < length && !buttonEl; count ++) {
|
||||
possibleDefaultButtons->Item(count, getter_AddRefs(possibleButton));
|
||||
buttonEl = do_QueryInterface(possibleButton);
|
||||
}
|
||||
}
|
||||
if (!buttonEl) { // Check for anonymous accept button in <dialog>
|
||||
nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(xulDoc));
|
||||
if (xblDoc) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(xulDoc);
|
||||
NS_ASSERTION(domDoc, "No DOM document");
|
||||
nsCOMPtr<nsIDOMElement> rootEl;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(rootEl));
|
||||
if (rootEl) {
|
||||
nsCOMPtr<nsIDOMElement> possibleButtonEl;
|
||||
xblDoc->GetAnonymousElementByAttribute(rootEl,
|
||||
NS_LITERAL_STRING("default"),
|
||||
NS_LITERAL_STRING("true"),
|
||||
getter_AddRefs(possibleButtonEl));
|
||||
buttonEl = do_QueryInterface(possibleButtonEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
relatedNode = do_QueryInterface(buttonEl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (!relatedID.IsEmpty()) {
|
||||
// In some cases we need to get the relatedNode from an ID-style attribute
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mDOMNode->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDOMElement> relatedEl;
|
||||
domDoc->GetElementById(relatedID, getter_AddRefs(relatedEl));
|
||||
relatedNode = do_QueryInterface(relatedEl);
|
||||
}
|
||||
|
||||
// Return the corresponding accessible if the related DOM node is found
|
||||
if (relatedNode) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
||||
return accService->GetAccessibleInWeakShell(relatedNode, mWeakShell, aRelated);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* void addSelection (); */
|
||||
NS_IMETHODIMP nsAccessible::AddSelection()
|
||||
{
|
||||
|
@ -40,10 +40,12 @@
|
||||
#define _nsAccessible_H_
|
||||
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsPIAccessible.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsString.h"
|
||||
|
||||
struct nsRect;
|
||||
@ -142,12 +144,18 @@ protected:
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
PRBool IsPartiallyVisible(PRBool *aIsOffscreen);
|
||||
nsresult GetTextFromRelationID(nsIAtom *aIDAttrib, nsString &aName);
|
||||
static nsIContent *GetLabelForId(nsIContent *aLookContent,
|
||||
|
||||
static nsIContent *GetContentPointingTo(const nsAString *aId,
|
||||
nsIContent *aLookContent,
|
||||
nsIAtom *forAttrib,
|
||||
const nsAString *aId);
|
||||
static nsIContent *GetXULLabelContent(nsIContent *aForNode);
|
||||
PRUint32 aForAttribNamespace = kNameSpaceID_None,
|
||||
nsIAtom *aTagType = nsAccessibilityAtoms::label);
|
||||
static nsIContent *GetXULLabelContent(nsIContent *aForNode,
|
||||
nsIAtom *aLabelType = nsAccessibilityAtoms::label);
|
||||
static nsIContent *GetHTMLLabelContent(nsIContent *aForNode);
|
||||
static nsIContent *GetLabelContent(nsIContent *aForNode);
|
||||
static nsIContent *GetRoleContent(nsIDOMNode *aDOMNode);
|
||||
|
||||
nsresult GetHTMLName(nsAString& _retval, PRBool aCanAggregateSubtree = PR_TRUE);
|
||||
nsresult GetXULName(nsAString& aName, PRBool aCanAggregateSubtree = PR_TRUE);
|
||||
// For accessibles that are not lists of choices, the name of the subtree should be the
|
||||
|
@ -698,6 +698,7 @@ STDMETHODIMP nsAccessibleWrap::accNavigate(
|
||||
return E_FAIL;
|
||||
|
||||
VariantInit(pvarEndUpAt);
|
||||
PRUint32 xpRelation = 0;
|
||||
|
||||
switch(navDir) {
|
||||
case NAVDIR_DOWN:
|
||||
@ -724,6 +725,33 @@ STDMETHODIMP nsAccessibleWrap::accNavigate(
|
||||
case NAVDIR_UP:
|
||||
xpAccessibleStart->GetAccessibleAbove(getter_AddRefs(xpAccessibleResult));
|
||||
break;
|
||||
// MSAA relationship extensions to accNavigate
|
||||
case NAVRELATION_CONTROLLED_BY: xpRelation = RELATION_CONTROLLED_BY; break;
|
||||
case NAVRELATION_CONTROLLER_FOR: xpRelation = RELATION_CONTROLLER_FOR; break;
|
||||
case NAVRELATION_LABEL_FOR: xpRelation = RELATION_LABEL_FOR; break;
|
||||
case NAVRELATION_LABELLED_BY: xpRelation = RELATION_LABELLED_BY; break;
|
||||
case NAVRELATION_MEMBER_OF: xpRelation = RELATION_MEMBER_OF; break;
|
||||
case NAVRELATION_NODE_CHILD_OF: xpRelation = RELATION_NODE_CHILD_OF; break;
|
||||
case NAVRELATION_FLOWS_TO: xpRelation = RELATION_FLOWS_TO; break;
|
||||
case NAVRELATION_FLOWS_FROM: xpRelation = RELATION_FLOWS_FROM; break;
|
||||
case NAVRELATION_SUBWINDOW_OF: xpRelation = RELATION_SUBWINDOW_OF; break;
|
||||
case NAVRELATION_EMBEDS: xpRelation = RELATION_EMBEDS; break;
|
||||
case NAVRELATION_EMBEDDED_BY: xpRelation = RELATION_EMBEDDED_BY; break;
|
||||
case NAVRELATION_POPUP_FOR: xpRelation = RELATION_POPUP_FOR; break;
|
||||
case NAVRELATION_PARENT_WINDOW_OF: xpRelation = RELATION_PARENT_WINDOW_OF; break;
|
||||
case NAVRELATION_DEFAULT_BUTTON: xpRelation = RELATION_DEFAULT_BUTTON; break;
|
||||
case NAVRELATION_DESCRIBED_BY: xpRelation = RELATION_DESCRIBED_BY; break;
|
||||
case NAVRELATION_DESCRIPTION_FOR: xpRelation = RELATION_DESCRIPTION_FOR; break;
|
||||
}
|
||||
|
||||
pvarEndUpAt->vt = VT_EMPTY;
|
||||
|
||||
if (xpRelation) {
|
||||
nsresult rv = GetAccessibleRelated(xpRelation,
|
||||
getter_AddRefs(xpAccessibleResult));
|
||||
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
if (xpAccessibleResult) {
|
||||
@ -731,7 +759,6 @@ STDMETHODIMP nsAccessibleWrap::accNavigate(
|
||||
pvarEndUpAt->vt = VT_DISPATCH;
|
||||
return NS_OK;
|
||||
}
|
||||
pvarEndUpAt->vt = VT_EMPTY;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -50,14 +50,16 @@ nsTextAccessibleWrap(aDomNode, aShell)
|
||||
}
|
||||
|
||||
/* wstring getName (); */
|
||||
NS_IMETHODIMP nsXULTextAccessible::GetName(nsAString& _retval)
|
||||
NS_IMETHODIMP nsXULTextAccessible::GetName(nsAString& aName)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXULDescriptionElement> descriptionElement(do_QueryInterface(mDOMNode));
|
||||
if (descriptionElement) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
return AppendFlatStringFromSubtree(content, &_retval);
|
||||
if (!content) {
|
||||
return NS_ERROR_FAILURE; // Node shut down
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
if (content->Tag() == nsAccessibilityAtoms::label) {
|
||||
return content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
|
||||
}
|
||||
return nsTextAccessibleWrap::GetName(aName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULTextAccessible::GetState(PRUint32 *_retval)
|
||||
|
Loading…
Reference in New Issue
Block a user