diff --git a/accessible/public/nsIAccessible.idl b/accessible/public/nsIAccessible.idl index 4e8b4de50acf..01750b1d1832 100644 --- a/accessible/public/nsIAccessible.idl +++ b/accessible/public/nsIAccessible.idl @@ -58,7 +58,7 @@ interface nsIAccessibleRelation; * * @status UNDER_REVIEW */ -[scriptable, uuid(004b6882-2df1-49df-bb5f-0fb81a5b1edf)] +[scriptable, uuid(c7520419-87ec-42bc-98cc-04c0bf173530)] interface nsIAccessible : nsISupports { /** @@ -199,9 +199,25 @@ interface nsIAccessible : nsISupports * current accessible will be returned. * If the point is in neither the current accessible or a child, then * null will be returned. + * + * @param x screen's x coordinate + * @param y screen's y coordinate + * @return the deepest accessible child containing the given point */ nsIAccessible getChildAtPoint(in long x, in long y); + /** + * Deepest accessible child which contains the coordinate at (x, y) in screen + * pixels. If the point is in the current accessible but not in a child, the + * current accessible will be returned. If the point is in neither the current + * accessible or a child, then null will be returned. + * + * @param x screen's x coordinate + * @param y screen's y coordinate + * @return the deepest accessible child containing the given point + */ + nsIAccessible getDeepestChildAtPoint(in long x, in long y); + /** * Nth accessible child using zero-based index or last child if index less than zero */ diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index b0d1f628f952..4e2c732c5672 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -1104,10 +1104,10 @@ NS_IMETHODIMP nsAccessible::GetFocusedChild(nsIAccessible **aFocusedChild) return NS_OK; } - /* nsIAccessible getChildAtPoint (in long x, in long y); */ +// nsIAccessible getDeepestChildAtPoint(in long x, in long y) NS_IMETHODIMP -nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, - nsIAccessible **aAccessible) +nsAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible) { NS_ENSURE_ARG_POINTER(aAccessible); *aAccessible = nsnull; @@ -1205,29 +1205,52 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, // Fall through -- the point is in this accessible but not in a child // We are allowed to return |this| as the answer } - else { - nsCOMPtr parent; - while (PR_TRUE) { - accessible->GetParent(getter_AddRefs(parent)); - if (!parent) { - // Reached the top of the hierarchy - // these bounds were inside an accessible that is not a descendant of this one - NS_IF_ADDREF(*aAccessible = fallbackAnswer); - return NS_OK; - } - if (parent == this) { - // We reached |this|, so |accessible| is the - // child we want to return - break; - } - accessible.swap(parent); - } - } NS_IF_ADDREF(*aAccessible = accessible); return NS_OK; } +// nsIAccessible getChildAtPoint(in long x, in long y) +NS_IMETHODIMP +nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible) +{ + nsresult rv = GetDeepestChildAtPoint(aX, aY, aAccessible); + NS_ENSURE_SUCCESS(rv, rv); + + if (!*aAccessible) + return NS_OK; + + nsCOMPtr parent, accessible(*aAccessible); + while (PR_TRUE) { + accessible->GetParent(getter_AddRefs(parent)); + if (!parent) { + NS_ASSERTION(PR_FALSE, + "Obtained accessible isn't a child of this accessible."); + // Reached the top of the hierarchy. These bounds were inside an + // accessible that is not a descendant of this one. + + // If we can't find the point in a child, we will return the fallback + // answer: we return |this| if the point is within it, otherwise nsnull. + PRInt32 x, y, width, height; + GetBounds(&x, &y, &width, &height); + if (aX >= x && aX < x + width && aY >= y && aY < y + height) + NS_ADDREF(*aAccessible = this); + + return NS_OK; + } + + if (parent == this) { + // We reached |this|, so |accessible| is the child we want to return. + NS_ADDREF(*aAccessible = accessible); + return NS_OK; + } + accessible.swap(parent); + } + + return NS_OK; +} + void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame) { /* diff --git a/accessible/src/base/nsOuterDocAccessible.cpp b/accessible/src/base/nsOuterDocAccessible.cpp index bc5571e853b9..c8a96ccb05e7 100644 --- a/accessible/src/base/nsOuterDocAccessible.cpp +++ b/accessible/src/base/nsOuterDocAccessible.cpp @@ -67,6 +67,7 @@ nsOuterDocAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState) return NS_OK; } +// nsIAccessible::getChildAtPoint(in long x, in long y) NS_IMETHODIMP nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible) @@ -85,6 +86,23 @@ nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, return GetFirstChild(aAccessible); // Always return the inner doc unless bounds outside of it } +// nsIAccessible::getDeepestChildAtPoint(in long x, in long y) +NS_IMETHODIMP +nsOuterDocAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible) +{ + // Call getDeepestChildAtPoint on the fist child accessible of the outer + // document accessible if the given point is inside of outer document. + nsCOMPtr childAcc; + nsresult rv = GetChildAtPoint(aX, aY, getter_AddRefs(childAcc)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!childAcc) + return NS_OK; + + return childAcc->GetDeepestChildAtPoint(aX, aY, aAccessible); +} + void nsOuterDocAccessible::CacheChildren() { // An outer doc accessible usually has 1 nsDocAccessible child, diff --git a/accessible/src/base/nsOuterDocAccessible.h b/accessible/src/base/nsOuterDocAccessible.h index 94b431dd49db..c2fb96a76b98 100644 --- a/accessible/src/base/nsOuterDocAccessible.h +++ b/accessible/src/base/nsOuterDocAccessible.h @@ -54,8 +54,12 @@ class nsOuterDocAccessible : public nsAccessibleWrap NS_IMETHOD GetRole(PRUint32 *aRole); NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState); + NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible); + NS_IMETHOD GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible); + void CacheChildren(); nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes); NS_IMETHOD GetNumActions(PRUint8 *aNumActions); diff --git a/accessible/src/mac/mozAccessible.mm b/accessible/src/mac/mozAccessible.mm index 47edc480c823..46020aa7f4e0 100644 --- a/accessible/src/mac/mozAccessible.mm +++ b/accessible/src/mac/mozAccessible.mm @@ -293,22 +293,17 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible) { if (mIsExpired) return nil; - + // Convert from cocoa's coordinate system to gecko's. According to the docs // the point we're given is guaranteed to be bottom-left screen coordinates. nsPoint geckoPoint; ConvertCocoaToGeckoPoint (point, geckoPoint); - // start iterating as deep down as we can on this point, with the current accessible as the root. - // as soon as GetChildAtPoint() returns null, or can't descend further (without getting the same accessible again) - // we stop. - nsCOMPtr deepestFoundChild, newChild(mGeckoAccessible); - do { - deepestFoundChild = newChild; - deepestFoundChild->GetChildAtPoint((PRInt32)geckoPoint.x, (PRInt32)geckoPoint.y, getter_AddRefs(newChild)); - } while (newChild && newChild.get() != deepestFoundChild.get()); + nsCOMPtr deepestFoundChild; + mGeckoAccessible->GetDeepestChildAtPoint((PRInt32)geckoPoint.x, + (PRInt32)geckoPoint.y, + getter_AddRefs(deepestFoundChild)); - // if we found something, return its native accessible. if (deepestFoundChild) { mozAccessible *nativeChild = GetNativeFromGeckoAccessible(deepestFoundChild); diff --git a/accessible/src/xul/nsXULTreeAccessible.cpp b/accessible/src/xul/nsXULTreeAccessible.cpp index 539e964d92d4..51f59cc25cd2 100644 --- a/accessible/src/xul/nsXULTreeAccessible.cpp +++ b/accessible/src/xul/nsXULTreeAccessible.cpp @@ -355,6 +355,15 @@ nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY, return GetCachedTreeitemAccessible(row, column, aAccessible); } +// nsIAccessible::getDeepestChildAtPoint(in long x, in long y) +NS_IMETHODIMP +nsXULTreeAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible) +{ + // Call getChildAtPoint until tree doesn't support complex content. + return GetChildAtPoint(aX, aY, aAccessible); +} + // Ask treeselection to get all selected children NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval) { diff --git a/accessible/src/xul/nsXULTreeAccessible.h b/accessible/src/xul/nsXULTreeAccessible.h index fe6d64130632..23ad8b329d27 100644 --- a/accessible/src/xul/nsXULTreeAccessible.h +++ b/accessible/src/xul/nsXULTreeAccessible.h @@ -71,8 +71,11 @@ public: NS_IMETHOD GetLastChild(nsIAccessible **_retval); NS_IMETHOD GetChildCount(PRInt32 *_retval); NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild); + NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible); + NS_IMETHOD GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY, + nsIAccessible **aAccessible); static void GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject); static nsresult GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32 *aCount);