Bug 391617 - CAccessibleText::scroll* methods are incorrect, r=aaronlev, a=dsicore

This commit is contained in:
surkov.alexander@gmail.com 2007-09-24 22:48:51 -07:00
parent cb674c33c4
commit adbfa3bec2
10 changed files with 422 additions and 215 deletions

View File

@ -45,7 +45,7 @@ typedef long nsAccessibleTextBoundary;
interface nsIAccessible;
[scriptable, uuid(948419b2-53f6-4a74-bb69-1345faf3e8e8)]
[scriptable, uuid(caa4f543-070e-4705-8428-2e53575c41bb)]
interface nsIAccessibleText : nsISupports
{
const nsAccessibleTextBoundary BOUNDARY_CHAR = 0;
@ -180,15 +180,31 @@ interface nsIAccessibleText : nsISupports
/**
* Makes a specific part of string visible on screen.
*
* @param aStartIndex - 0-based character offset.
* @param aEndIndex - 0-based character offset - the offset of the
* character just past the last character of the
* string.
* @param aScrollType - defines how to scroll (see nsIAccessibleScrollType for
* available constants).
* @param startIndex 0-based character offset
* @param endIndex 0-based character offset - the offset of the
* character just past the last character of the
* string
* @param scrollType defines how to scroll (see nsIAccessibleScrollType for
* available constants)
*/
void scrollSubstringTo(in long aStartIndex, in long aEndIndex,
in unsigned long aScrollType);
void scrollSubstringTo(in long startIndex, in long endIndex,
in unsigned long scrollType);
/**
* Moves the top left of a substring to a specified location.
*
* @param startIndex 0-based character offset
* @param endIndex 0-based character offset - the offset of the
* character just past the last character of
* the string
* @param coordinateType specifies the coordinates origin (for available
* constants refer to nsIAccessibleCoordinateType)
* @param x defines the x coordinate
* @param y defines the y coordinate
*/
void scrollSubstringToPoint(in long startIndex, in long endIndex,
in unsigned long coordinateType,
in long x, in long y);
};
/*

View File

@ -90,8 +90,7 @@ interface nsIAccessibleScrollType : nsISupports
/**
* These constants define which coordinate system a point is located in. Note,
* keep them synchronized with IA2CoordinateType.
* These constants define which coordinate system a point is located in.
*/
[scriptable, uuid(c9fbdf10-619e-436f-bf4b-8566686f1577)]
interface nsIAccessibleCoordinateType : nsISupports

View File

@ -61,7 +61,6 @@
#include "nsPIDOMWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsPresContext.h"
@ -441,71 +440,14 @@ nsAccessNode::ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY)
if (!frame)
return NS_ERROR_FAILURE;
nsPresContext *presContext = frame->PresContext();
switch (aCoordinateType) {
case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
break;
case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
{
nsIntPoint wndCoords = nsAccUtils::GetScreenCoordsForWindow(mDOMNode);
aX += wndCoords.x;
aY += wndCoords.y;
break;
}
case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
{
nsCOMPtr<nsPIAccessNode> parent;
nsCOMPtr<nsIAccessible> accessible;
nsresult rv = QueryInterface(NS_GET_IID(nsIAccessible),
getter_AddRefs(accessible));
if (NS_SUCCEEDED(rv) && accessible) {
nsCOMPtr<nsIAccessible> parentAccessible;
accessible->GetParent(getter_AddRefs(parentAccessible));
parent = do_QueryInterface(parentAccessible);
} else {
nsCOMPtr<nsIAccessNode> parentAccessNode;
GetParentNode(getter_AddRefs(parentAccessNode));
parent = do_QueryInterface(parentAccessNode);
}
NS_ENSURE_STATE(parent);
nsIFrame *parentFrame = parent->GetFrame();
NS_ENSURE_STATE(parentFrame);
nsIntRect parentRect = parentFrame->GetScreenRectExternal();
aX += parentRect.x;
aY += parentRect.y;
break;
}
default:
return NS_ERROR_INVALID_ARG;
}
nsIntPoint coords;
nsresult rv = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType,
this, &coords);
NS_ENSURE_SUCCESS(rv, rv);
nsIFrame *parentFrame = frame;
while (parentFrame = parentFrame->GetParent()) {
nsIScrollableFrame *scrollableFrame = nsnull;
CallQueryInterface(parentFrame, &scrollableFrame);
if (scrollableFrame) {
nsIntRect frameRect = frame->GetScreenRectExternal();
PRInt32 devDeltaX = aX - frameRect.x;
PRInt32 devDeltaY = aY - frameRect.y;
nsPoint deltaPoint;
deltaPoint.x = presContext->DevPixelsToAppUnits(devDeltaX);
deltaPoint.y = presContext->DevPixelsToAppUnits(devDeltaY);
nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
scrollPoint -= deltaPoint;
scrollableFrame->ScrollTo(scrollPoint);
}
}
while (parentFrame = parentFrame->GetParent())
nsAccUtils::ScrollFrameToPoint(parentFrame, frame, coords);
return NS_OK;
}

View File

@ -40,6 +40,7 @@
#include "nsIAccessibleTypes.h"
#include "nsPIAccessible.h"
#include "nsPIAccessNode.h"
#include "nsAccessibleEventData.h"
#include "nsAccessNode.h"
@ -57,6 +58,7 @@
#include "nsIEventListenerManager.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIScrollableFrame.h"
#include "nsIEventStateManager.h"
#include "nsISelection2.h"
#include "nsISelectionController.h"
@ -286,6 +288,19 @@ nsAccUtils::ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex,
nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRUint32 aScrollType)
{
PRInt16 vPercent, hPercent;
ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent);
return ScrollSubstringTo(aFrame, aStartNode, aStartIndex, aEndNode, aEndIndex,
vPercent, hPercent);
}
nsresult
nsAccUtils::ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex,
nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRInt16 aVPercent, PRInt16 aHPercent)
{
if (!aFrame || !aStartNode || !aEndNode)
return NS_ERROR_FAILURE;
@ -311,10 +326,8 @@ nsAccUtils::ScrollSubstringTo(nsIFrame *aFrame,
selection->RemoveAllRanges();
selection->AddRange(scrollToRange);
PRInt16 vPercent, hPercent;
ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent);
selection->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION,
PR_TRUE, vPercent, hPercent);
PR_TRUE, aVPercent, aHPercent);
selection->CollapseToStart();
}
@ -322,6 +335,32 @@ nsAccUtils::ScrollSubstringTo(nsIFrame *aFrame,
return NS_OK;
}
void
nsAccUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
nsIFrame *aFrame,
const nsIntPoint& aPoint)
{
nsIScrollableFrame *scrollableFrame = nsnull;
CallQueryInterface(aScrollableFrame, &scrollableFrame);
if (!scrollableFrame)
return;
nsPresContext *presContext = aFrame->PresContext();
nsIntRect frameRect = aFrame->GetScreenRectExternal();
PRInt32 devDeltaX = aPoint.x - frameRect.x;
PRInt32 devDeltaY = aPoint.y - frameRect.y;
nsPoint deltaPoint;
deltaPoint.x = presContext->DevPixelsToAppUnits(devDeltaX);
deltaPoint.y = presContext->DevPixelsToAppUnits(devDeltaY);
nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
scrollPoint -= deltaPoint;
scrollableFrame->ScrollTo(scrollPoint);
}
void
nsAccUtils::ConvertScrollTypeToPercents(PRUint32 aScrollType,
PRInt16 *aVPercent,
@ -359,6 +398,67 @@ nsAccUtils::ConvertScrollTypeToPercents(PRUint32 aScrollType,
}
}
nsresult
nsAccUtils::ConvertToScreenCoords(PRInt32 aX, PRInt32 aY,
PRUint32 aCoordinateType,
nsIAccessNode *aAccessNode,
nsIntPoint *aCoords)
{
NS_ENSURE_ARG_POINTER(aCoords);
aCoords->MoveTo(aX, aY);
switch (aCoordinateType) {
case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
break;
case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
{
NS_ENSURE_ARG(aAccessNode);
nsCOMPtr<nsIDOMNode> DOMNode;
aAccessNode->GetDOMNode(getter_AddRefs(DOMNode));
NS_ENSURE_STATE(DOMNode);
nsIntPoint wndCoords = nsAccUtils::GetScreenCoordsForWindow(DOMNode);
*aCoords += wndCoords;
break;
}
case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
{
NS_ENSURE_ARG(aAccessNode);
nsCOMPtr<nsPIAccessNode> parent;
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(aAccessNode));
if (accessible) {
nsCOMPtr<nsIAccessible> parentAccessible;
accessible->GetParent(getter_AddRefs(parentAccessible));
parent = do_QueryInterface(parentAccessible);
} else {
nsCOMPtr<nsIAccessNode> parentAccessNode;
aAccessNode->GetParentNode(getter_AddRefs(parentAccessNode));
parent = do_QueryInterface(parentAccessNode);
}
NS_ENSURE_STATE(parent);
nsIFrame *parentFrame = parent->GetFrame();
NS_ENSURE_STATE(parentFrame);
nsIntRect parentRect = parentFrame->GetScreenRectExternal();
aCoords->x += parentRect.x;
aCoords->y += parentRect.y;
break;
}
default:
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
nsIntPoint
nsAccUtils::GetScreenCoordsForWindow(nsIDOMNode *aNode)
{

View File

@ -41,6 +41,7 @@
#include "nsAccessibilityAtoms.h"
#include "nsIAccessible.h"
#include "nsIAccessNode.h"
#include "nsARIAMap.h"
#include "nsIDOMNode.h"
@ -162,6 +163,33 @@ public:
nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRUint32 aScrollType);
/** Helper method to scroll range into view, used for implementation of
* nsIAccessibleText::scrollSubstringTo[Point]().
*
* @param aFrame the frame for accessible the range belongs to.
* @param aStartNode start node of a range
* @param aStartOffset an offset inside the start node
* @param aEndNode end node of a range
* @param aEndOffset an offset inside the end node
* @param aVPercent how to align vertically, specified in percents
* @param aHPercent how to align horizontally, specified in percents
*/
static nsresult ScrollSubstringTo(nsIFrame *aFrame,
nsIDOMNode *aStartNode, PRInt32 aStartIndex,
nsIDOMNode *aEndNode, PRInt32 aEndIndex,
PRInt16 aVPercent, PRInt16 aHPercent);
/**
* Scrolls the given frame to the point, used for implememntation of
* nsIAccessNode::scrollToPoint and nsIAccessibleText::scrollSubstringToPoint.
*
* @param aScrollableFrame the scrollable frame
* @param aFrame the frame to scroll
* @param aPoint the point scroll to
*/
static void ScrollFrameToPoint(nsIFrame *aScrollableFrame,
nsIFrame *aFrame, const nsIntPoint& aPoint);
/**
* Converts scroll type constant defined in nsIAccessibleScrollType to
* vertical and horizontal percents.
@ -170,6 +198,22 @@ public:
PRInt16 *aVPercent,
PRInt16 *aHPercent);
/**
* Converts the given coordinates to coordinates relative screen.
*
* @param aX [in] the given x coord
* @param aY [in] the given y coord
* @param aCoordinateType [in] specifies coordinates origin (refer to
* nsIAccessibleCoordinateType)
* @param aAccessNode [in] the accessible if coordinates are given
* relative it.
* @param aCoords [out] converted coordinates
*/
static nsresult ConvertToScreenCoords(PRInt32 aX, PRInt32 aY,
PRUint32 aCoordinateType,
nsIAccessNode *aAccessNode,
nsIntPoint *aCoords);
/**
* Returns coordinates relative screen for the top level window.
*

View File

@ -61,6 +61,7 @@ REQUIRES = composer \
necko \
string \
thebes \
view \
webshell \
widget \
xpcom \

View File

@ -56,6 +56,7 @@
#include "nsIEditor.h"
#include "nsIFontMetrics.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPlaintextEditor.h"
#include "nsISelection2.h"
@ -665,6 +666,59 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
return NS_OK;
}
nsresult
nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
PRInt32 aEndHTOffset,
nsIDOMNode **aStartNode,
PRInt32 *aStartOffset,
nsIDOMNode **aEndNode,
PRInt32 *aEndOffset)
{
NS_ENSURE_ARG_POINTER(aStartNode);
*aStartNode = nsnull;
NS_ENSURE_ARG_POINTER(aStartOffset);
*aStartOffset = -1;
NS_ENSURE_ARG_POINTER(aEndNode);
*aEndNode = nsnull;
NS_ENSURE_ARG_POINTER(aEndOffset);
*aEndOffset = -1;
nsCOMPtr<nsIAccessible> startAcc, endAcc;
PRInt32 startOffset = aStartHTOffset, endOffset = aEndHTOffset;
nsIFrame *startFrame = nsnull, *endFrame = nsnull;
startFrame = GetPosAndText(startOffset, endOffset, nsnull, &endFrame, nsnull,
getter_AddRefs(startAcc), getter_AddRefs(endAcc));
if (!startAcc || !endAcc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> startNode, endNode;
nsresult rv = GetDOMPointByFrameOffset(startFrame, startOffset, startAcc,
getter_AddRefs(startNode),
&startOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (aStartHTOffset != aEndHTOffset) {
rv = GetDOMPointByFrameOffset(endFrame, endOffset, endAcc,
getter_AddRefs(endNode), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else {
endNode = startNode;
endOffset = startOffset;
}
NS_ADDREF(*aStartNode = startNode);
*aStartOffset = startOffset;
NS_ADDREF(*aEndNode = endNode);
*aEndOffset = endOffset;
return NS_OK;
}
PRInt32
nsHyperTextAccessible::GetRelativeOffset(nsIPresShell *aPresShell,
nsIFrame *aFromFrame,
@ -1572,13 +1626,17 @@ NS_IMETHODIMP nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum, P
/*
* Changes the start and end offset of the specified selection.
*/
NS_IMETHODIMP nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum, PRInt32 aStartOffset, PRInt32 aEndOffset)
NS_IMETHODIMP
nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum,
PRInt32 aStartOffset,
PRInt32 aEndOffset)
{
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 isOnlyCaret = (aStartOffset == aEndOffset); // Caret is a collapsed selection
// Caret is a collapsed selection
PRBool isOnlyCaret = (aStartOffset == aEndOffset);
PRInt32 rangeCount;
domSel->GetRangeCount(&rangeCount);
@ -1595,78 +1653,20 @@ NS_IMETHODIMP nsHyperTextAccessible::SetSelectionBounds(PRInt32 aSelectionNum, P
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
}
nsIFrame *endFrame;
nsCOMPtr<nsIAccessible> startAcc, endAcc;
nsIFrame *startFrame = GetPosAndText(aStartOffset, aEndOffset, nsnull, &endFrame, nsnull,
getter_AddRefs(startAcc), getter_AddRefs(endAcc));
PRInt32 startOffset, endOffset;
nsCOMPtr<nsIDOMNode> startNode, endNode;
nsCOMPtr<nsIPresShell> shell = GetPresShell();
rv = HypertextOffsetsToDOMRange(aStartOffset, aEndOffset,
getter_AddRefs(startNode), &startOffset,
getter_AddRefs(endNode), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (!startFrame) { // past the end of the hyper text
nsCOMPtr<nsIAccessNode> startAccessNode = do_QueryInterface(startAcc);
NS_ENSURE_TRUE(startAccessNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> node;
startAccessNode->GetDOMNode(getter_AddRefs(node));
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
rv = range->SetStartAfter(node);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsIContent *startParentContent = startFrame->GetContent();
PRInt32 startOffset;
if (startFrame->GetType() != nsAccessibilityAtoms::textFrame) {
nsIContent *newParent = startParentContent->GetParent();
startOffset = newParent->IndexOf(startParentContent);
startParentContent = newParent;
}
else {
// We have a rendered offset into the text frame, and it needs to be
// a content offset for us to set the caret
nsIFrame *startPrimaryFrame =
shell->GetPrimaryFrameFor(startFrame->GetContent());
rv = RenderedToContentOffset(startPrimaryFrame, aStartOffset, &startOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIDOMNode> startParentNode(do_QueryInterface(startParentContent));
NS_ENSURE_TRUE(startParentNode, NS_ERROR_FAILURE);
rv = range->SetStart(startParentNode, startOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = range->SetStart(startNode, startOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (isOnlyCaret) {
rv = range->Collapse(PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (!endFrame) { // past the end of the hyper text
nsCOMPtr<nsIAccessNode> endAccessNode = do_QueryInterface(endAcc);
NS_ENSURE_TRUE(endAccessNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> node;
endAccessNode->GetDOMNode(getter_AddRefs(node));
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
rv = range->SetEndAfter(node);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsIContent *endParentContent = endFrame->GetContent();
PRInt32 endOffset;
if (endFrame->GetType() != nsAccessibilityAtoms::textFrame) {
nsIContent *newParent = endParentContent->GetParent();
endOffset = newParent->IndexOf(endParentContent);
endParentContent = newParent;
}
else {
// We have a rendered offset into the text frame, and it needs to be
// a content offset for us to set the caret
nsIFrame *endPrimaryFrame =
shell->GetPrimaryFrameFor(endFrame->GetContent());
rv = RenderedToContentOffset(endPrimaryFrame, aEndOffset, &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIDOMNode> endParentNode(do_QueryInterface(endParentContent));
NS_ENSURE_TRUE(endParentNode, NS_ERROR_FAILURE);
rv = range->SetEnd(endParentNode, endOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = isOnlyCaret ? range->Collapse(PR_TRUE) :
range->SetEnd(endNode, endOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (aSelectionNum == rangeCount) { // Add successfully created new range
return domSel->AddRange(range);
@ -1708,56 +1708,96 @@ NS_IMETHODIMP nsHyperTextAccessible::RemoveSelection(PRInt32 aSelectionNum)
return domSel->RemoveRange(range);
}
// void nsIAccessibleText::
// scrollSubstringTo(in long startIndex, in long endIndex,
// in unsigned long scrollType);
NS_IMETHODIMP
nsHyperTextAccessible::ScrollSubstringTo(PRInt32 aStartIndex, PRInt32 aEndIndex,
PRUint32 aScrollType)
{
PRInt32 startOffset = aStartIndex, endOffset = aEndIndex;
nsIFrame *startFrame = nsnull, *endFrame = nsnull;
nsCOMPtr<nsIAccessible> startAcc, endAcc;
PRInt32 startOffset, endOffset;
nsCOMPtr<nsIDOMNode> startNode, endNode;
startFrame = GetPosAndText(startOffset, endOffset,
nsnull, &endFrame, nsnull,
getter_AddRefs(startAcc), getter_AddRefs(endAcc));
if (!startFrame || !endFrame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> startNode;
nsCOMPtr<nsIContent> startContent(startFrame->GetContent());
if (startFrame->GetType() == nsAccessibilityAtoms::textFrame) {
nsresult rv = RenderedToContentOffset(startFrame, startOffset,
&startOffset);
NS_ENSURE_SUCCESS(rv, rv);
startNode = do_QueryInterface(startContent);
} else {
nsCOMPtr<nsIContent> startParent(startContent->GetParent());
NS_ENSURE_STATE(startParent);
startOffset = startParent->IndexOf(startContent);
startNode = do_QueryInterface(startParent);
}
NS_ENSURE_STATE(startNode);
nsCOMPtr<nsIDOMNode> endNode;
nsCOMPtr<nsIContent> endContent(endFrame->GetContent());
if (endFrame->GetType() == nsAccessibilityAtoms::textFrame) {
nsresult rv = RenderedToContentOffset(endFrame, endOffset,
&endOffset);
NS_ENSURE_SUCCESS(rv, rv);
endNode = do_QueryInterface(endContent);
} else {
nsCOMPtr<nsIContent> endParent(endContent->GetParent());
NS_ENSURE_STATE(endParent);
endOffset = endParent->IndexOf(endContent);
endNode = do_QueryInterface(endParent);
}
NS_ENSURE_STATE(endNode);
nsresult rv = HypertextOffsetsToDOMRange(aStartIndex, aEndIndex,
getter_AddRefs(startNode),
&startOffset,
getter_AddRefs(endNode),
&endOffset);
NS_ENSURE_SUCCESS(rv, rv);
return nsAccUtils::ScrollSubstringTo(GetFrame(), startNode, startOffset,
endNode, endOffset, aScrollType);
}
// void nsIAccessibleText::
// scrollSubstringToPoint(in long startIndex, in long endIndex,
// in unsigned long coordinateType,
// in long x, in long y);
NS_IMETHODIMP
nsHyperTextAccessible::ScrollSubstringToPoint(PRInt32 aStartIndex,
PRInt32 aEndIndex,
PRUint32 aCoordinateType,
PRInt32 aX, PRInt32 aY)
{
nsIFrame *frame = GetFrame();
if (!frame)
return NS_ERROR_FAILURE;
nsIntPoint coords;
nsresult rv = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType,
this, &coords);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 startOffset, endOffset;
nsCOMPtr<nsIDOMNode> startNode, endNode;
rv = HypertextOffsetsToDOMRange(aStartIndex, aEndIndex,
getter_AddRefs(startNode), &startOffset,
getter_AddRefs(endNode), &endOffset);
NS_ENSURE_SUCCESS(rv, rv);
nsPresContext *presContext = frame->PresContext();
PRBool initialScrolled = PR_FALSE;
nsIFrame *parentFrame = frame;
while (parentFrame = parentFrame->GetParent()) {
nsIScrollableFrame *scrollableFrame = nsnull;
CallQueryInterface(parentFrame, &scrollableFrame);
if (scrollableFrame) {
if (!initialScrolled) {
// Scroll substring to the given point. Turn the point into percents
// relative scrollable area to use nsAccUtils::ScrollSubstringTo.
nsIntRect frameRect = parentFrame->GetScreenRectExternal();
PRInt32 devOffsetX = coords.x - frameRect.x;
PRInt32 devOffsetY = coords.y - frameRect.y;
nsPoint offsetPoint(presContext->DevPixelsToAppUnits(devOffsetX),
presContext->DevPixelsToAppUnits(devOffsetY));
nsSize size(parentFrame->GetSize());
PRInt16 hPercent = offsetPoint.x * 100 / size.width;
PRInt16 vPercent = offsetPoint.y * 100 / size.height;
rv = nsAccUtils::ScrollSubstringTo(GetFrame(), startNode, startOffset,
endNode, endOffset,
vPercent, hPercent);
NS_ENSURE_SUCCESS(rv, rv);
initialScrolled = PR_TRUE;
} else {
// Substring was scrolled to the given point already inside its closest
// scrollable area. If there are nested scrollable areas then make
// sure we scroll lower areas to the given point inside currently
// traversed scrollable area.
nsAccUtils::ScrollFrameToPoint(parentFrame, frame, coords);
}
}
frame = parentFrame;
}
return NS_OK;
}
nsresult nsHyperTextAccessible::ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
PRUint32 *aRenderedOffset)
{
@ -1803,4 +1843,58 @@ nsresult nsHyperTextAccessible::RenderedToContentOffset(nsIFrame *aFrame, PRUint
return NS_OK;
}
nsresult
nsHyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame *aFrame,
PRInt32 aOffset,
nsIAccessible *aAccessible,
nsIDOMNode **aNode,
PRInt32 *aNodeOffset)
{
NS_ENSURE_ARG(aAccessible);
nsCOMPtr<nsIDOMNode> node;
if (!aFrame) {
// If the given frame is null then set offset after the DOM node of the
// given accessible.
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
nsCOMPtr<nsIDOMNode> DOMNode;
accessNode->GetDOMNode(getter_AddRefs(DOMNode));
nsCOMPtr<nsIContent> content(do_QueryInterface(DOMNode));
NS_ENSURE_STATE(content);
nsCOMPtr<nsIContent> parent(content->GetParent());
NS_ENSURE_STATE(parent);
*aNodeOffset = parent->IndexOf(content) + 1;
node = do_QueryInterface(parent);
} else if (aFrame->GetType() == nsAccessibilityAtoms::textFrame) {
nsCOMPtr<nsIContent> content(aFrame->GetContent());
NS_ENSURE_STATE(content);
nsCOMPtr<nsIPresShell> shell(GetPresShell());
NS_ENSURE_STATE(shell);
nsIFrame *primaryFrame = shell->GetPrimaryFrameFor(content);
nsresult rv = RenderedToContentOffset(primaryFrame, aOffset, aNodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
node = do_QueryInterface(content);
} else {
nsCOMPtr<nsIContent> content(aFrame->GetContent());
NS_ENSURE_STATE(content);
nsCOMPtr<nsIContent> parent(content->GetParent());
NS_ENSURE_STATE(parent);
*aNodeOffset = parent->IndexOf(content);
node = do_QueryInterface(parent);
}
NS_IF_ADDREF(*aNode = node);
return NS_OK;
}

View File

@ -123,6 +123,23 @@ public:
nsIAccessible **aFinalAccessible = nsnull,
PRBool aIsEndOffset = PR_FALSE);
/**
* Turn a start and end hypertext offsets into DOM range.
*
* @param aStartHTOffset [in] the given start hypertext offset
* @param aEndHTOffset [in] the given end hypertext offset
* @param aStartNode [out] start node of the range
* @param aStartOffset [out] start offset of the range
* @param aEndNode [out] end node of the range
* @param aEndOffset [out] end offset of the range
*/
nsresult HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
PRInt32 aEndHTOffset,
nsIDOMNode **aStartNode,
PRInt32 *aStartOffset,
nsIDOMNode **aEndNode,
PRInt32 *aEndOffset);
protected:
/*
* This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
@ -203,6 +220,11 @@ protected:
nsISelection **aDomSel = nsnull,
nsCOMArray<nsIDOMRange>* aRanges = nsnull);
nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
// Helpers
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
nsIAccessible *aAccessible,
nsIDOMNode **aNode, PRInt32 *aNodeOffset);
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,

View File

@ -370,34 +370,18 @@ CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
STDMETHODIMP
CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
enum IA2CoordinateType aCoordinateType,
enum IA2CoordinateType aCoordType,
long aX, long aY)
{
GET_NSIACCESSIBLETEXT
nsCOMPtr<nsIAccessible> accessible;
PRInt32 startOffset = 0, endOffset = 0;
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
// XXX: aEndIndex isn't used.
textAcc->GetAttributeRange(aStartIndex, &startOffset, &endOffset,
getter_AddRefs(accessible));
if (!accessible)
return E_FAIL;
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(accessible));
if (!winAccessNode)
return E_FAIL;
void **instancePtr = 0;
winAccessNode->QueryNativeInterface(IID_IAccessible2, instancePtr);
if (!instancePtr)
return E_FAIL;
IAccessible2 *pAccessible2 = static_cast<IAccessible2*>(*instancePtr);
HRESULT hr = pAccessible2->scrollToPoint(aCoordinateType, aX, aY);
pAccessible2->Release();
return hr;
nsresult rv = textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
geckoCoordType, aX, aY);
return NS_FAILED(rv) ? E_FAIL : S_OK;
}
STDMETHODIMP

View File

@ -1189,10 +1189,15 @@ nsAccessibleWrap::scrollTo(enum IA2ScrollType aScrollType)
}
STDMETHODIMP
nsAccessibleWrap::scrollToPoint(enum IA2CoordinateType coordinateType,
long x, long y)
nsAccessibleWrap::scrollToPoint(enum IA2CoordinateType aCoordType,
long aX, long aY)
{
return E_NOTIMPL;
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
return NS_SUCCEEDED(ScrollToPoint(geckoCoordType, aX, aY)) ?
S_OK : E_FAIL;
}
STDMETHODIMP