зеркало из https://github.com/mozilla/pjs.git
Bug 395081. AccessibleObjectFromPoint() returns errors. r=surkov, a=dsicore
This commit is contained in:
Родитель
d2dd5c0ea2
Коммит
d0a61678f0
|
@ -194,6 +194,10 @@ interface nsIAccessible : nsISupports
|
|||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
nsIAccessible getChildAtPoint(in long x, in long y);
|
||||
|
||||
|
|
|
@ -1064,6 +1064,24 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE; // Already shut down
|
||||
}
|
||||
|
||||
// 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
|
||||
nsCOMPtr<nsIAccessible> fallbackAnswer;
|
||||
PRInt32 x, y, width, height;
|
||||
GetBounds(&x, &y, &width, &height);
|
||||
if (aX >= x && aX < x + width &&
|
||||
aY >= y && aY < y + height) {
|
||||
fallbackAnswer = this;
|
||||
}
|
||||
if (MustPrune(this)) { // Do not dig any further
|
||||
NS_IF_ADDREF(*aAccessible = fallbackAnswer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Search an accessible at the given point starting from accessible document
|
||||
// because containing block (see CSS2) for out of flow element (for example,
|
||||
// absolutely positioned element) may be different from its DOM parent and
|
||||
|
@ -1073,9 +1091,7 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
nsCOMPtr<nsIAccessibleDocument> accDocument;
|
||||
nsresult rv = GetAccessibleDocument(getter_AddRefs(accDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!accDocument)
|
||||
return NS_OK;
|
||||
NS_ENSURE_TRUE(accDocument, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsPIAccessNode> accessNodeDocument(do_QueryInterface(accDocument));
|
||||
NS_ASSERTION(accessNodeDocument,
|
||||
|
@ -1092,37 +1108,75 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
|||
|
||||
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
|
||||
nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
|
||||
if (!foundFrame)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> content(foundFrame->GetContent());
|
||||
if (!content)
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (!foundFrame || !(content = foundFrame->GetContent())) {
|
||||
NS_IF_ADDREF(*aAccessible = fallbackAnswer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
accService->GetRelevantContentNodeFor(node, getter_AddRefs(relevantNode));
|
||||
if (!relevantNode)
|
||||
if (!relevantNode) {
|
||||
NS_IF_ADDREF(*aAccessible = fallbackAnswer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accService->GetAccessibleFor(relevantNode, getter_AddRefs(accessible));
|
||||
if (!accessible)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAccessible> parent;
|
||||
accessible->GetParent(getter_AddRefs(parent));
|
||||
|
||||
while (parent && parent != this) {
|
||||
accessible.swap(parent);
|
||||
accessible->GetParent(getter_AddRefs(parent));
|
||||
if (!accessible) {
|
||||
// No accessible for the node with the point, so find the first
|
||||
// accessible in the DOM parent chain
|
||||
accDocument->GetAccessibleInParentChain(relevantNode,
|
||||
getter_AddRefs(accessible));
|
||||
if (!accessible) {
|
||||
NS_IF_ADDREF(*aAccessible = fallbackAnswer);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent)
|
||||
NS_ADDREF(*aAccessible = accessible);
|
||||
if (accessible == this) {
|
||||
// Manually walk through accessible children and see if
|
||||
// the are within this point.
|
||||
// This takes care of cases where layout won't walk into
|
||||
// things for us, such as image map areas and sub documents
|
||||
nsCOMPtr<nsIAccessible> child;
|
||||
while (NextChild(child)) {
|
||||
PRInt32 childX, childY, childWidth, childHeight;
|
||||
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
|
||||
if (aX >= childX && aX < childX + childWidth &&
|
||||
aY >= childY && aY < childY + childHeight &&
|
||||
(State(child) & nsIAccessibleStates::STATE_INVISIBLE) == 0) {
|
||||
// Don't walk into offscreen or invisible items
|
||||
NS_IF_ADDREF(*aAccessible = child);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// Fall through -- the point is in this accessible but not in a child
|
||||
// We are allowed to return |this| as the answer
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIAccessible> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
|
||||
NS_IMETHOD GetChildCount(PRInt32 *_retval);
|
||||
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
|
||||
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
|
||||
{ *aAccessible = this; return NS_OK; } // Don't walk into these
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,6 +86,24 @@ nsOuterDocAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOuterDocAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
if (!mDOMNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRInt32 docX, docY, docWidth, docHeight;
|
||||
GetBounds(&docX, &docY, &docWidth, &docHeight);
|
||||
if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return GetFirstChild(aAccessible); // Always return the inner doc unless bounds outside of it
|
||||
}
|
||||
|
||||
void nsOuterDocAccessible::CacheChildren()
|
||||
{
|
||||
// An outer doc accessible usually has 1 nsDocAccessible child,
|
||||
|
|
|
@ -55,6 +55,8 @@ class nsOuterDocAccessible : public nsAccessibleWrap
|
|||
NS_IMETHOD GetName(nsAString& aName);
|
||||
NS_IMETHOD GetRole(PRUint32 *aRole);
|
||||
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
nsIAccessible **aAccessible);
|
||||
void CacheChildren();
|
||||
};
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ public:
|
|||
NS_IMETHOD GetChildCount(PRInt32 *_retval);
|
||||
NS_IMETHOD GetDescription(nsAString& _retval);
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
|
||||
{ *aAccessible = this; return NS_OK; } // Don't walk into these
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче