зеркало из https://github.com/mozilla/gecko-dev.git
Bug 388927 - getChildAtPoint fails for scrolled content, r=evan.yan, roc, sr=roc, a=dsicore
This commit is contained in:
Родитель
c881ad990f
Коммит
00631daa97
|
@ -1082,70 +1082,73 @@ NS_IMETHODIMP nsAccessible::GetFocusedChild(nsIAccessible **aFocusedChild)
|
|||
}
|
||||
|
||||
/* nsIAccessible getChildAtPoint (in long x, in long y); */
|
||||
NS_IMETHODIMP nsAccessible::GetChildAtPoint(PRInt32 tx, PRInt32 ty, nsIAccessible **aAccessible)
|
||||
NS_IMETHODIMP
|
||||
nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessible> child;
|
||||
GetFirstChild(getter_AddRefs(child));
|
||||
// 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
|
||||
// therefore accessible for containing block may be different from accessible
|
||||
// for DOM parent but GetFrameForPoint() should be called for containing block
|
||||
// to get an out of flow element.
|
||||
nsCOMPtr<nsIAccessibleDocument> accDocument;
|
||||
nsresult rv = GetAccessibleDocument(getter_AddRefs(accDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 x, y, w, h;
|
||||
PRUint32 state;
|
||||
|
||||
nsCOMPtr<nsIAccessible> childAtPoint;
|
||||
while (child) {
|
||||
child->GetBounds(&x, &y, &w, &h);
|
||||
if (tx >= x && tx < x + w && ty >= y && ty < y + h) {
|
||||
nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(child));
|
||||
if (accessNode) {
|
||||
nsIFrame *frame = accessNode->GetFrame();
|
||||
if (!frame) {
|
||||
state = State(child);
|
||||
// In some cases accessibles don't have a frame; examples are
|
||||
// tree items or combo box dropdown markers. For these cases
|
||||
// just ensure that the returned accessible is visible.
|
||||
if ((state & (nsIAccessibleStates::STATE_OFFSCREEN |
|
||||
nsIAccessibleStates::STATE_INVISIBLE)) == 0) {
|
||||
// Don't walk into offscreen or invisible items
|
||||
NS_IF_ADDREF(*aAccessible = child);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If there are multiple accessibles the contain the point
|
||||
// and they overlap then pick the one with a frame that contains the point
|
||||
// For example, A point that's in block #2 is also in block #1, but we want to return #2:
|
||||
// [[block #1 is long wrapped text that continues to
|
||||
// another line]] [[here is a shorter block #2]]
|
||||
while (frame) {
|
||||
if (frame->GetScreenRectExternal().Contains(tx, ty)) {
|
||||
childAtPoint = child;
|
||||
break; // Definitely in this accessible, since one of its frame matches the point
|
||||
}
|
||||
frame = frame->GetNextContinuation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIAccessible> next;
|
||||
child->GetNextSibling(getter_AddRefs(next));
|
||||
child = next;
|
||||
}
|
||||
|
||||
if (childAtPoint) {
|
||||
NS_ADDREF(*aAccessible = childAtPoint);
|
||||
if (!accDocument)
|
||||
return NS_OK;
|
||||
}
|
||||
GetState(&state, nsnull);
|
||||
GetBounds(&x, &y, &w, &h);
|
||||
if ((state & (nsIAccessibleStates::STATE_OFFSCREEN |
|
||||
nsIAccessibleStates::STATE_INVISIBLE)) == 0 &&
|
||||
tx >= x && tx < x + w && ty >= y && ty < y + h) {
|
||||
*aAccessible = this;
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
nsCOMPtr<nsPIAccessNode> accessNodeDocument(do_QueryInterface(accDocument));
|
||||
NS_ASSERTION(accessNodeDocument,
|
||||
"nsIAccessibleDocument doesn't implement nsPIAccessNode");
|
||||
|
||||
nsIFrame *frame = accessNodeDocument->GetFrame();
|
||||
NS_ENSURE_STATE(frame);
|
||||
|
||||
nsPresContext *presContext = frame->PresContext();
|
||||
|
||||
nsIntRect screenRect = frame->GetScreenRectExternal();
|
||||
nsPoint offset(presContext->DevPixelsToAppUnits(aX - screenRect.x),
|
||||
presContext->DevPixelsToAppUnits(aY - screenRect.y));
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
|
||||
nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
|
||||
if (!foundFrame)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> content(foundFrame->GetContent());
|
||||
if (!content)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
|
||||
nsCOMPtr<nsIAccessibilityService> accService = GetAccService();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> relevantNode;
|
||||
accService->GetRelevantContentNodeFor(node, getter_AddRefs(relevantNode));
|
||||
if (!relevantNode)
|
||||
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));
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (parent)
|
||||
NS_ADDREF(*aAccessible = accessible);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
|
||||
|
|
|
@ -319,6 +319,42 @@ NS_IMETHODIMP nsXULTreeAccessible::GetFocusedChild(nsIAccessible **aFocusedChild
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIAccessible::getChildAtPoint(in long x, in long y)
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
nsIFrame *frame = GetFrame();
|
||||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsPresContext *presContext = frame->PresContext();
|
||||
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
|
||||
|
||||
nsIFrame *rootFrame = presShell->GetRootFrame();
|
||||
NS_ENSURE_STATE(rootFrame);
|
||||
|
||||
nsIntRect rootRect = rootFrame->GetScreenRectExternal();
|
||||
|
||||
PRInt32 clientX = presContext->AppUnitsToIntCSSPixels(
|
||||
presContext->DevPixelsToAppUnits(aX - rootRect.x));
|
||||
PRInt32 clientY = presContext->AppUnitsToIntCSSPixels(
|
||||
presContext->DevPixelsToAppUnits(aY - rootRect.y));
|
||||
|
||||
PRInt32 row = -1;
|
||||
nsCOMPtr<nsITreeColumn> column;
|
||||
nsCAutoString childEltUnused;
|
||||
mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
|
||||
childEltUnused);
|
||||
|
||||
// If we failed to find tree cell for the given point then it might be
|
||||
// tree columns.
|
||||
if (row == -1 || !column)
|
||||
return nsXULSelectableAccessible::GetChildAtPoint(aX, aY, aAccessible);
|
||||
|
||||
return GetCachedTreeitemAccessible(row, column, aAccessible);
|
||||
}
|
||||
|
||||
// Ask treeselection to get all selected children
|
||||
NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsIArray **_retval)
|
||||
{
|
||||
|
|
|
@ -72,6 +72,8 @@ 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);
|
||||
|
||||
static void GetTreeBoxObject(nsIDOMNode* aDOMNode, nsITreeBoxObject** aBoxObject);
|
||||
static nsresult GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32 *aCount);
|
||||
|
|
|
@ -607,6 +607,14 @@ public:
|
|||
*/
|
||||
virtual nsresult ReconstructFrames() = 0;
|
||||
|
||||
/**
|
||||
* Given aFrame, the root frame of a stacking context, find its descendant
|
||||
* frame under the point aPt that receives a mouse event at that location,
|
||||
* or nsnull if there is no such frame.
|
||||
* @param aPt the point, relative to the frame origin
|
||||
*/
|
||||
virtual nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt) = 0;
|
||||
|
||||
/**
|
||||
* See if reflow verification is enabled. To enable reflow verification add
|
||||
* "verifyreflow:1" to your NSPR_LOG_MODULES environment variable
|
||||
|
|
|
@ -873,7 +873,9 @@ public:
|
|||
virtual nsresult ReconstructFrames(void);
|
||||
virtual void Freeze();
|
||||
virtual void Thaw();
|
||||
|
||||
|
||||
virtual nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt);
|
||||
|
||||
NS_IMETHOD RenderDocument(const nsRect& aRect, PRBool aUntrusted,
|
||||
PRBool aIgnoreViewportScrolling,
|
||||
nscolor aBackgroundColor,
|
||||
|
@ -2970,6 +2972,12 @@ PresShell::GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const
|
|||
return *aResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
PresShell::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt)
|
||||
{
|
||||
return nsLayoutUtils::GetFrameForPoint(aFrame, aPt);
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче