Bug 302937. Expose onclick actions on leaf text and image nodes. r=parente, sr=jst, a=cbeard

This commit is contained in:
aaronleventhal%moonset.net 2005-08-10 01:51:39 +00:00
Родитель b8ff615ee1
Коммит 3885aca374
8 изменённых файлов: 83 добавлений и 131 удалений

Просмотреть файл

@ -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