Bug 310921. AccessibleObjectFromPoint can give wrong answers with text nodes that have multiple frames. r=mkaply, sr=dbaron

This commit is contained in:
aaronleventhal%moonset.net 2005-10-04 02:33:58 +00:00
Родитель d21fb93bf0
Коммит 8b4f326fce
2 изменённых файлов: 32 добавлений и 34 удалений

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

@ -43,6 +43,7 @@
#include "nsAccessibleWrap.h"
#include "nsGUIEvent.h"
#include "nsILink.h"
#include "nsIFrame.h"
#include "nsINameSpaceManager.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
@ -60,8 +61,12 @@ nsBlockAccessible::nsBlockAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell
NS_IMPL_ISUPPORTS_INHERITED0(nsBlockAccessible, nsAccessible)
/* nsIAccessible accGetAt (in long x, in long y); */
NS_IMETHODIMP nsBlockAccessible::GetChildAtPoint(PRInt32 tx, PRInt32 ty, nsIAccessible **_retval)
NS_IMETHODIMP nsBlockAccessible::GetChildAtPoint(PRInt32 tx, PRInt32 ty,
nsIAccessible **aChildAtPoint)
{
*aChildAtPoint = nsnull;
nsCOMPtr<nsIAccessible> childAtPoint;
// We're going to find the child that contains coordinates (tx,ty)
PRInt32 x,y,w,h;
GetBounds(&x,&y,&w,&h); // Get bounds for this accessible
@ -69,8 +74,6 @@ NS_IMETHODIMP nsBlockAccessible::GetChildAtPoint(PRInt32 tx, PRInt32 ty, nsIAcce
{
// It's within this nsIAccessible, let's drill down
nsCOMPtr<nsIAccessible> child;
nsCOMPtr<nsIAccessible> smallestChild;
PRInt32 smallestArea = -1;
nsCOMPtr<nsIAccessible> next;
GetFirstChild(getter_AddRefs(child));
PRInt32 cx,cy,cw,ch; // Child bounds
@ -78,39 +81,42 @@ NS_IMETHODIMP nsBlockAccessible::GetChildAtPoint(PRInt32 tx, PRInt32 ty, nsIAcce
while(child) {
child->GetBounds(&cx,&cy,&cw,&ch);
// ok if there are multiple frames the contain the point
// and they overlap then pick the smallest. We need to do this
// for text frames.
// if there are multiple accessibles the contain the point
// and they overlap then pick the one with a frame that contans 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]]
if (tx >= cx && tx < cx + cw && ty >= cy && ty < cy + ch)
{
if (smallestArea == -1 || cw*ch < smallestArea) {
smallestArea = cw*ch;
smallestChild = child;
// See whether one of the frames for this accessible
// contains this screen point
if (!childAtPoint) {
// Default in case accessible doesn't have a frame such as
// tree items or combo box dropdown markers
childAtPoint = child;
}
nsCOMPtr<nsPIAccessNode> accessNode(do_QueryInterface(child));
if (accessNode) {
nsIFrame *frame = accessNode->GetFrame();
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->GetNextInFlow();
}
}
}
child->GetNextSibling(getter_AddRefs(next));
child = next;
}
if (smallestChild != nsnull)
{
*_retval = smallestChild;
NS_ADDREF(*_retval);
return NS_OK;
}
*_retval = this;
NS_ADDREF(this);
return NS_OK;
*aChildAtPoint = childAtPoint ? childAtPoint : this;
NS_ADDREF(*aChildAtPoint);
}
*_retval = nsnull;
return NS_OK;
}

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

@ -50,7 +50,6 @@
#include "nsIRenderingContext.h"
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
@ -220,26 +219,19 @@ nsresult nsTextAccessibleWrap::GetCharacterExtents(PRInt32 aStartOffset, PRInt32
PRInt32* aX, PRInt32* aY,
PRInt32* aWidth, PRInt32* aHeight)
{
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsPresContext *presContext = presShell->GetPresContext();
nsPresContext *presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
float t2p = presContext->TwipsToPixels();
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
nsIFrame *frame = GetFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsIViewManager* viewManager = presShell->GetViewManager();
NS_ASSERTION(viewManager, "No view manager for pres shell");
nsCOMPtr<nsIWidget> widget;
viewManager->GetWidget(getter_AddRefs(widget));
nsIWidget *widget = frame->GetWindow();
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
nsIRenderingContext *rendContext;
rendContext = widget->GetRenderingContext();
nsPoint startPoint, endPoint;
nsIFrame *startFrame = GetPointFromOffset(frame, presContext, rendContext,
aStartOffset, PR_TRUE, startPoint);