diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index e3cf1106c981..bb31b43e7de6 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -565,8 +565,10 @@ NS_IMETHODIMP nsAccessible::GetState(PRUint32 *aState) else { *aState |= STATE_FOCUSABLE; nsCOMPtr focusedNode; - if (NS_SUCCEEDED(GetFocusedNode(mDOMNode, getter_AddRefs(focusedNode))) && focusedNode == mDOMNode) + if (gLastFocusedNode == mDOMNode || + (NS_SUCCEEDED(GetFocusedNode(mDOMNode, getter_AddRefs(focusedNode))) && focusedNode == mDOMNode)) { *aState |= STATE_FOCUSED; + } } } diff --git a/accessible/src/base/nsRootAccessible.cpp b/accessible/src/base/nsRootAccessible.cpp index cb6c52297d28..788ec1662700 100644 --- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -138,6 +138,28 @@ NS_IMETHODIMP nsRootAccessible::GetRole(PRUint32 *aRole) return NS_OK; } +NS_IMETHODIMP nsRootAccessible::GetState(PRUint32 *aState) +{ + nsresult rv = NS_ERROR_FAILURE; + if (mDOMNode) { + rv = nsDocAccessibleWrap::GetState(aState); + } + if (NS_FAILED(rv)) { + return rv; + } + + NS_ASSERTION(mDocument, "mDocument should not be null unless mDOMNode is"); + if (gLastFocusedNode) { + nsCOMPtr rootAccessibleDoc(do_QueryInterface(mDocument)); + nsCOMPtr focusedDoc; + gLastFocusedNode->GetOwnerDocument(getter_AddRefs(focusedDoc)); + if (rootAccessibleDoc == focusedDoc) { + *aState |= STATE_FOCUSED; + } + } + return NS_OK; +} + void nsRootAccessible::GetChromeEventHandler(nsIDOMEventTarget **aChromeTarget) { @@ -258,8 +280,8 @@ void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *focusAccessible, { if (focusAccessible && focusNode && gLastFocusedNode != focusNode) { nsCOMPtr privateFocusAcc(do_QueryInterface(focusAccessible)); - privateFocusAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS, focusAccessible, nsnull); NS_IF_RELEASE(gLastFocusedNode); + gLastFocusedNode = nsnull; PRUint32 role = ROLE_NOTHING; focusAccessible->GetRole(&role); if (role != ROLE_MENUITEM && role != ROLE_LISTITEM) { @@ -267,6 +289,7 @@ void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *focusAccessible, gLastFocusedNode = focusNode; NS_ADDREF(gLastFocusedNode); } + privateFocusAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS, focusAccessible, nsnull); if (mCaretAccessible) mCaretAccessible->AttachNewSelectionListener(focusNode); } @@ -542,15 +565,18 @@ void nsRootAccessible::GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNo nsCOMPtr domEventTarget; nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget)); nsCOMPtr content(do_QueryInterface(domEventTarget)); - if (content && content->IsContentOfType(nsIContent::eHTML)) { - // Kind of a hack. If we're on an HTML element we want to make sure that it wasn't - // inserted via XBL. In that case we want the "original explicit event target". - // The difference is not 100% clear from the API docs, - // but this combination gets the following important cases correct: + nsIContent *bindingParent; + if (content && content->IsContentOfType(nsIContent::eHTML) && + (bindingParent = content->GetBindingParent()) != nsnull) { + // Use binding parent when the event occurs in + // anonymous HTML content. + // This gets the following important cases correct: // 1. Inserted buttons like OK, Cancel, Help. // 2. XUL menulists and comboboxes. // 3. The focused radio button in a group. - nsevent->GetExplicitOriginalTarget(getter_AddRefs(domEventTarget)); + CallQueryInterface(bindingParent, aTargetNode); + NS_ASSERTION(*aTargetNode, "No target node for binding parent of anonymous event target"); + return; } if (domEventTarget) { CallQueryInterface(domEventTarget, aTargetNode); diff --git a/accessible/src/base/nsRootAccessible.h b/accessible/src/base/nsRootAccessible.h index f04d0c2c62f6..39e536cc23c3 100644 --- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -66,6 +66,7 @@ class nsRootAccessible : public nsDocAccessibleWrap, /* attribute wstring accName; */ NS_IMETHOD GetParent(nsIAccessible * *aParent); NS_IMETHOD GetRole(PRUint32 *aRole); + NS_IMETHOD GetState(PRUint32 *aState); // ----- nsIDOMEventListener -------------------------- NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); diff --git a/accessible/src/xul/nsXULFormControlAccessible.cpp b/accessible/src/xul/nsXULFormControlAccessible.cpp index e91a2337f3bd..4f8035fd622f 100644 --- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -664,7 +664,11 @@ NS_IMETHODIMP nsXULTextFieldAccessible::GetState(PRUint32 *aState) // to get the accessible state from. Doesn't add to cache // because Init() is not called. nsHTMLTextFieldAccessible tempAccessible(inputField, mWeakShell); - return tempAccessible.GetState(aState); + nsresult rv = tempAccessible.GetState(aState); + if (gLastFocusedNode == mDOMNode) { + *aState |= STATE_FOCUSED; + } + return rv; }