зеркало из https://github.com/mozilla/gecko-dev.git
Bug 302937. Expose onclick actions on leaf text and image nodes. r=parente, sr=jst, a=cbeard
This commit is contained in:
Родитель
b8ff615ee1
Коммит
3885aca374
|
@ -507,6 +507,9 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsISupports *aFrame,
|
|||
else if (tag == nsAccessibilityAtoms::a) {
|
||||
*aAccessible = new nsHTMLLinkAccessible(aNode, aWeakShell, NS_STATIC_CAST(nsIFrame*, aFrame));
|
||||
}
|
||||
else if (content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
|
||||
*aAccessible = new nsLinkableAccessible(aNode, aWeakShell);
|
||||
}
|
||||
else if (tag == nsAccessibilityAtoms::li) {
|
||||
// Normally this is created by the list item frame which knows about the bullet frame
|
||||
// However, in this case the list item must have been styled using display: foo
|
||||
|
@ -529,7 +532,6 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsISupports *aFrame,
|
|||
tag == nsAccessibilityAtoms::tbody ||
|
||||
tag == nsAccessibilityAtoms::tfoot ||
|
||||
tag == nsAccessibilityAtoms::thead ||
|
||||
content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick) ||
|
||||
#else
|
||||
else if (
|
||||
#endif
|
||||
|
|
|
@ -1913,53 +1913,18 @@ NS_IMETHODIMP nsAccessible::GetRole(PRUint32 *aRole)
|
|||
/* PRUint8 getAccNumActions (); */
|
||||
NS_IMETHODIMP nsAccessible::GetNumActions(PRUint8 *aNumActions)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
if (content && content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
|
||||
*aNumActions = 1;
|
||||
} else {
|
||||
*aNumActions = 0;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* DOMString getAccActionName (in PRUint8 index); */
|
||||
NS_IMETHODIMP nsAccessible::GetActionName(PRUint8 index, nsAString& aName)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
if (content && content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
|
||||
// Action 0 (default action): Click on element
|
||||
if (index == eAction_Click) {
|
||||
nsAccessible::GetTranslatedString(NS_LITERAL_STRING("click"), aName);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* void doAction (in PRUint8 index); */
|
||||
NS_IMETHODIMP nsAccessible::DoAction(PRUint8 index)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
if (content && content->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
|
||||
// Action 0 (default action): Click on element
|
||||
if (index == eAction_Click) {
|
||||
nsCOMPtr<nsPresContext> presContext(GetPresContext());
|
||||
if (presContext && content) {
|
||||
nsMouseEvent linkClickEvent(PR_TRUE, NS_MOUSE_LEFT_CLICK, nsnull,
|
||||
nsMouseEvent::eReal);
|
||||
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
content->HandleDOMEvent(presContext,
|
||||
&linkClickEvent,
|
||||
nsnull,
|
||||
NS_EVENT_FLAG_INIT,
|
||||
&eventStatus);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
|
|
@ -154,18 +154,20 @@ NS_IMETHODIMP nsLeafAccessible::GetChildCount(PRInt32 *_retval)
|
|||
|
||||
nsLinkableAccessible::nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
|
||||
nsAccessibleWrap(aNode, aShell),
|
||||
mLinkContent(nsnull),
|
||||
mIsALinkCached(PR_FALSE),
|
||||
mIsLinkVisited(PR_FALSE)
|
||||
mActionContent(nsnull),
|
||||
mIsLink(PR_FALSE),
|
||||
mIsLinkVisited(PR_FALSE),
|
||||
mIsOnclick(PR_FALSE)
|
||||
{
|
||||
CacheActionContent();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessible)
|
||||
|
||||
NS_IMETHODIMP nsLinkableAccessible::TakeFocus()
|
||||
{
|
||||
if (IsALink()) {
|
||||
mLinkContent->SetFocus(nsCOMPtr<nsPresContext>(GetPresContext()));
|
||||
if (mActionContent && mActionContent->IsFocusable()) {
|
||||
mActionContent->SetFocus(nsCOMPtr<nsPresContext>(GetPresContext()));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -175,13 +177,10 @@ NS_IMETHODIMP nsLinkableAccessible::TakeFocus()
|
|||
NS_IMETHODIMP nsLinkableAccessible::GetState(PRUint32 *aState)
|
||||
{
|
||||
nsAccessible::GetState(aState);
|
||||
if (IsALink()) {
|
||||
if (mIsLink) {
|
||||
*aState |= STATE_LINKED;
|
||||
if (mIsLinkVisited)
|
||||
*aState |= STATE_TRAVERSED;
|
||||
}
|
||||
|
||||
if (IsALink()) {
|
||||
// Make sure we also include all the states of the parent link, such as focusable, focused, etc.
|
||||
PRUint32 role;
|
||||
GetRole(&role);
|
||||
|
@ -194,9 +193,9 @@ NS_IMETHODIMP nsLinkableAccessible::GetState(PRUint32 *aState)
|
|||
*aState |= orState;
|
||||
}
|
||||
}
|
||||
if (!mLinkContent->IsFocusable()) {
|
||||
*aState &= ~STATE_FOCUSABLE; // Links must have href or tabindex
|
||||
}
|
||||
if (mActionContent && !mActionContent->IsFocusable()) {
|
||||
*aState &= ~STATE_FOCUSABLE; // Links must have href or tabindex
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
|
||||
|
@ -213,8 +212,8 @@ NS_IMETHODIMP nsLinkableAccessible::GetState(PRUint32 *aState)
|
|||
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetValue(nsAString& _retval)
|
||||
{
|
||||
if (IsALink()) {
|
||||
nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mLinkContent));
|
||||
if (mIsLink) {
|
||||
nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mActionContent));
|
||||
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
|
||||
if (linkNode && presShell)
|
||||
return presShell->GetLinkLocation(linkNode, _retval);
|
||||
|
@ -224,20 +223,23 @@ NS_IMETHODIMP nsLinkableAccessible::GetValue(nsAString& _retval)
|
|||
|
||||
|
||||
/* PRUint8 getAccNumActions (); */
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetNumActions(PRUint8 *_retval)
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
|
||||
{
|
||||
*_retval = eSingle_Action;
|
||||
*aNumActions = mActionContent ? 1 : 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* wstring getAccActionName (in PRUint8 index); */
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetActionName(PRUint8 index, nsAString& _retval)
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetActionName(PRUint8 index, nsAString& aActionName)
|
||||
{
|
||||
// Action 0 (default action): Jump to link
|
||||
aActionName.Truncate();
|
||||
if (index == eAction_Jump) {
|
||||
if (IsALink()) {
|
||||
nsAccessible::GetTranslatedString(NS_LITERAL_STRING("jump"), _retval);
|
||||
return NS_OK;
|
||||
if (mIsLink) {
|
||||
return nsAccessible::GetTranslatedString(NS_LITERAL_STRING("jump"), aActionName);
|
||||
}
|
||||
else if (mIsOnclick) {
|
||||
return nsAccessible::GetTranslatedString(NS_LITERAL_STRING("click"), aActionName);
|
||||
}
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -249,15 +251,15 @@ NS_IMETHODIMP nsLinkableAccessible::DoAction(PRUint8 index)
|
|||
{
|
||||
// Action 0 (default action): Jump to link
|
||||
if (index == eAction_Jump) {
|
||||
if (IsALink()) {
|
||||
if (mActionContent) {
|
||||
nsCOMPtr<nsPresContext> presContext(GetPresContext());
|
||||
if (presContext) {
|
||||
nsMouseEvent linkClickEvent(PR_TRUE, NS_MOUSE_LEFT_CLICK, nsnull,
|
||||
nsMouseEvent clickEvent(PR_TRUE, NS_MOUSE_LEFT_CLICK, nsnull,
|
||||
nsMouseEvent::eReal);
|
||||
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
mLinkContent->HandleDOMEvent(presContext,
|
||||
&linkClickEvent,
|
||||
mActionContent->HandleDOMEvent(presContext,
|
||||
&clickEvent,
|
||||
nsnull,
|
||||
NS_EVENT_FLAG_INIT,
|
||||
&eventStatus);
|
||||
|
@ -268,31 +270,27 @@ NS_IMETHODIMP nsLinkableAccessible::DoAction(PRUint8 index)
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetKeyboardShortcut(nsAString& _retval)
|
||||
NS_IMETHODIMP nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
|
||||
{
|
||||
if (IsALink()) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mLinkContent));
|
||||
if (linkNode && mDOMNode != linkNode) {
|
||||
nsCOMPtr<nsIAccessible> linkAccessible;
|
||||
if (mActionContent) {
|
||||
nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
|
||||
if (actionNode && mDOMNode != actionNode) {
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
rv = accService->GetAccessibleInWeakShell(linkNode, mWeakShell,
|
||||
getter_AddRefs(linkAccessible));
|
||||
if (NS_SUCCEEDED(rv) && linkAccessible)
|
||||
return linkAccessible->GetKeyboardShortcut(_retval);
|
||||
else
|
||||
return rv;
|
||||
accService->GetAccessibleInWeakShell(actionNode, mWeakShell,
|
||||
getter_AddRefs(accessible));
|
||||
if (accessible) {
|
||||
accessible->GetKeyboardShortcut(aKeyboardShortcut);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return nsAccessible::GetKeyboardShortcut(_retval);;
|
||||
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
|
||||
}
|
||||
|
||||
PRBool nsLinkableAccessible::IsALink()
|
||||
void nsLinkableAccessible::CacheActionContent()
|
||||
{
|
||||
if (mIsALinkCached) // Cached answer?
|
||||
return mLinkContent? PR_TRUE: PR_FALSE;
|
||||
|
||||
for (nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
|
||||
walkUpContent;
|
||||
walkUpContent = walkUpContent->GetParent()) {
|
||||
|
@ -306,23 +304,24 @@ PRBool nsLinkableAccessible::IsALink()
|
|||
nsCOMPtr<nsIURI> uri;
|
||||
link->GetHrefURI(getter_AddRefs(uri));
|
||||
if (uri) {
|
||||
mLinkContent = walkUpContent;
|
||||
mIsALinkCached = PR_TRUE;
|
||||
mActionContent = walkUpContent;
|
||||
nsLinkState linkState;
|
||||
link->GetLinkState(linkState);
|
||||
if (linkState == eLinkState_Visited)
|
||||
mIsLinkVisited = PR_TRUE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (walkUpContent->HasAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::onclick)) {
|
||||
mActionContent = walkUpContent;
|
||||
mIsOnclick = PR_TRUE;
|
||||
}
|
||||
}
|
||||
mIsALinkCached = PR_TRUE; // Cached that there is no link
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLinkableAccessible::Shutdown()
|
||||
{
|
||||
mLinkContent = nsnull;
|
||||
mActionContent = nsnull;
|
||||
return nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,10 +94,11 @@ public:
|
|||
NS_IMETHOD Shutdown();
|
||||
|
||||
protected:
|
||||
virtual PRBool IsALink();
|
||||
nsCOMPtr<nsIContent> mLinkContent;
|
||||
PRPackedBool mIsALinkCached; // -1 = unknown, 0 = not a link, 1 = is a link
|
||||
virtual void CacheActionContent();
|
||||
nsCOMPtr<nsIContent> mActionContent;
|
||||
PRPackedBool mIsLink;
|
||||
PRPackedBool mIsLinkVisited;
|
||||
PRPackedBool mIsOnclick;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -752,12 +752,16 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
|||
|
||||
if (aNameSpaceID == kNameSpaceID_XHTML2_Unofficial) {
|
||||
if (aAttribute == nsAccessibilityAtoms::role) {
|
||||
nsCOMPtr<nsIContent> changedContent(do_QueryInterface(targetNode));
|
||||
InvalidateCacheSubtree(changedContent, nsIAccessibleEvent::EVENT_REORDER);
|
||||
InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_REORDER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsAccessibilityAtoms::href || aAttribute == nsAccessibilityAtoms::onclick) {
|
||||
InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_REORDER);
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint32 eventType = 0;
|
||||
if (aAttribute == nsAccessibilityAtoms::selected) {
|
||||
// DHTML or XUL selection
|
||||
|
@ -790,8 +794,7 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
|||
}
|
||||
else if (aNameSpaceID == kNameSpaceID_WAIProperties) {
|
||||
// DHTML accessibility attributes
|
||||
nsCOMPtr<nsIContent> changedContent(do_QueryInterface(targetNode));
|
||||
if (!changedContent->HasAttr(kNameSpaceID_XHTML2_Unofficial,
|
||||
if (!aContent->HasAttr(kNameSpaceID_XHTML2_Unofficial,
|
||||
nsAccessibilityAtoms::role)) {
|
||||
// We don't care about DHTML state changes unless there is
|
||||
// a DHTML role set for the element
|
||||
|
@ -814,12 +817,11 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
|||
// This affects whether the accessible supports nsIAccessibleSelectable.
|
||||
// COM says we cannot change what interfaces are supported on-the-fly,
|
||||
// so invalidate this object. A new one will be created on demand.
|
||||
nsCOMPtr<nsIContent> changedContent(do_QueryInterface(targetNode));
|
||||
if (changedContent->HasAttr(kNameSpaceID_XHTML2_Unofficial,
|
||||
if (aContent->HasAttr(kNameSpaceID_XHTML2_Unofficial,
|
||||
nsAccessibilityAtoms::role)) {
|
||||
// The multiselect and other waistate attributes only take affect
|
||||
// when XHTML2:role is present
|
||||
InvalidateCacheSubtree(changedContent, nsIAccessibleEvent::EVENT_REORDER);
|
||||
InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_REORDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,12 +49,12 @@ nsLinkableAccessible(aDomNode, aShell), mFrame(aFrame)
|
|||
}
|
||||
|
||||
/* wstring getName (); */
|
||||
NS_IMETHODIMP nsHTMLLinkAccessible::GetName(nsAString& _retval)
|
||||
NS_IMETHODIMP nsHTMLLinkAccessible::GetName(nsAString& aName)
|
||||
{
|
||||
if (!IsALink()) // Also initializes private data members
|
||||
if (!mActionContent)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return AppendFlatStringFromSubtree(mLinkContent,&_retval);
|
||||
return AppendFlatStringFromSubtree(mActionContent, &aName);
|
||||
}
|
||||
|
||||
/* unsigned long getRole (); */
|
||||
|
|
|
@ -116,25 +116,15 @@ nsXULTextAccessible(aDomNode, aShell)
|
|||
|
||||
NS_IMETHODIMP nsXULLinkAccessible::GetValue(nsAString& aValue)
|
||||
{
|
||||
if (IsALink()) {
|
||||
return mLinkContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
|
||||
if (mIsLink) {
|
||||
return mActionContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
|
||||
}
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULLinkAccessible::GetState(PRUint32 *aState)
|
||||
{
|
||||
// must set focusable state manually because parent class logic can't detect it without ILink
|
||||
nsresult rv = nsLinkableAccessible::GetState(aState);
|
||||
if (NS_SUCCEEDED(rv) && IsALink()) {
|
||||
*aState |= STATE_FOCUSABLE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULLinkAccessible::GetRole(PRUint32 *aRole)
|
||||
{
|
||||
if (IsALink()) {
|
||||
if (mIsLink) {
|
||||
*aRole = ROLE_LINK;
|
||||
} else {
|
||||
// default to calling the link a button; might have javascript
|
||||
|
@ -144,28 +134,22 @@ NS_IMETHODIMP nsXULLinkAccessible::GetRole(PRUint32 *aRole)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool nsXULLinkAccessible::IsALink()
|
||||
void nsXULLinkAccessible::CacheActionContent()
|
||||
{
|
||||
// use the cached answer if it exists
|
||||
if (mIsALinkCached) {
|
||||
return mLinkContent ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
// indicate the test result is cached
|
||||
mIsALinkCached = PR_TRUE;
|
||||
|
||||
// not a link if no content
|
||||
nsCOMPtr<nsIContent> mTempContent = do_QueryInterface(mDOMNode);
|
||||
if (!mTempContent) {
|
||||
return PR_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// not a link if there is no href attribute or not on a <link> tag
|
||||
if (!mTempContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::href) &&
|
||||
mTempContent->Tag() != nsAccessibilityAtoms::link) {
|
||||
return PR_FALSE;
|
||||
if (mTempContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::href) ||
|
||||
mTempContent->Tag() == nsAccessibilityAtoms::link) {
|
||||
mIsLink = PR_TRUE;
|
||||
mActionContent = mTempContent;
|
||||
}
|
||||
else if (mTempContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::onclick)) {
|
||||
mIsOnclick = PR_TRUE;
|
||||
mActionContent = mTempContent;
|
||||
}
|
||||
// it's a link, but can't detect traversed yet (no ILink interface)
|
||||
mLinkContent = mTempContent;
|
||||
mIsLinkVisited = PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -69,12 +69,11 @@ class nsXULLinkAccessible : public nsXULTextAccessible
|
|||
|
||||
public:
|
||||
nsXULLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
|
||||
NS_IMETHOD GetState(PRUint32 *_retval);
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetValue(nsAString& _retval);
|
||||
|
||||
protected:
|
||||
PRBool IsALink();
|
||||
void CacheActionContent();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче