Bug 756296 - Introduce pivot moveToPoint(). r=davidb

This commit is contained in:
Eitan Isaacson 2012-06-20 14:07:51 -07:00
parent c5138de0ee
commit 43020f808e
4 changed files with 130 additions and 11 deletions

View File

@ -122,6 +122,20 @@ interface nsIAccessiblePivot : nsISupports
*/
boolean movePreviousByText(in TextBoundaryType aBoundary);
/**
* Move pivot to given coordinate in screen pixels.
*
* @param aRule [in] raversal rule to use.
* @param aX [in] screen's x coordinate
* @param aY [in] screen's y coordinate
* @param aIgnoreNoMatch [in] don't unset position if no object was found at
* point.
* @return true on success, false if the pivot has not been moved.
*/
boolean moveToPoint(in nsIAccessibleTraversalRule aRule,
in long aX, in long aY,
in boolean aIgnoreNoMatch);
/**
* Add an observer for pivot changes.
*

View File

@ -305,6 +305,51 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, bool* aResult)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsAccessiblePivot::MoveToPoint(nsIAccessibleTraversalRule* aRule,
PRInt32 aX, PRInt32 aY, bool aIgnoreNoMatch,
bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(aRule);
*aResult = false;
if (mRoot && mRoot->IsDefunct())
return NS_ERROR_NOT_IN_TREE;
RuleCache cache(aRule);
Accessible* match = nsnull;
Accessible* child = mRoot->ChildAtPoint(aX, aY, Accessible::eDeepestChild);
while (child && mRoot != child) {
PRUint16 filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
nsresult rv = cache.ApplyFilter(child, &filtered);
NS_ENSURE_SUCCESS(rv, rv);
// Ignore any matching nodes that were below this one
if (filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE)
match = nsnull;
// Match if no node below this is a match
if ((filtered & nsIAccessibleTraversalRule::FILTER_MATCH) && !match) {
PRInt32 childX, childY, childWidth, childHeight;
child->GetBounds(&childX, &childY, &childWidth, &childHeight);
// Double-check child's bounds since the deepest child may have been out
// of bounds. This assures we don't return a false positive.
if (aX >= childX && aX < childX + childWidth &&
aY >= childY && aY < childY + childHeight)
match = child;
}
child = child->Parent();
}
if (match || !aIgnoreNoMatch)
*aResult = MovePivotInternal(match);
return NS_OK;
}
// Observer functions
NS_IMETHODIMP

View File

@ -86,9 +86,8 @@ function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
}
var position = aDocAcc.virtualCursor.position;
var idMatches = position.DOMNode.id == aIdOrNameOrAcc;
var nameMatches = position.name == aIdOrNameOrAcc;
var idMatches = position && position.DOMNode.id == aIdOrNameOrAcc;
var nameMatches = position && position.name == aIdOrNameOrAcc;
var accMatches = position == aIdOrNameOrAcc;
SimpleTest.ok(idMatches || nameMatches || accMatches, "id or name matches",
@ -170,26 +169,70 @@ function setVCRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets)
* @param aDocAcc [in] document that manages the virtual cursor
* @param aPivotMoveMethod [in] method to test (ie. "moveNext", "moveFirst", etc.)
* @param aRule [in] traversal rule object
* @param aIdOrNameOrAcc [in] id, accessivle or accessible name to expect
* @param aIdOrNameOrAcc [in] id, accessible or accessible name to expect
* virtual cursor to land on after performing move method.
* false if no move is expected.
*/
function setVCPosInvoker(aDocAcc, aPivotMoveMethod, aRule, aIdOrNameOrAcc)
{
var expectMove = (aIdOrNameOrAcc != false);
this.invoke = function virtualCursorChangedInvoker_invoke()
{
VCChangedChecker.
storePreviousPosAndOffset(aDocAcc.virtualCursor);
var moved = aDocAcc.virtualCursor[aPivotMoveMethod](aRule);
SimpleTest.ok((aIdOrNameOrAcc && moved) || (!aIdOrNameOrAcc && !moved),
SimpleTest.ok((expectMove && moved) || (!expectMove && !moved),
"moved pivot");
};
this.getID = function setVCPosInvoker_getID()
{
return "Do " + (aIdOrNameOrAcc ? "" : "no-op ") + aPivotMoveMethod;
return "Do " + (expectMove ? "" : "no-op ") + aPivotMoveMethod;
};
if (aIdOrNameOrAcc) {
if (expectMove) {
this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
} else {
this.eventSeq = [];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc)
];
}
}
/**
* Move the pivot to the position under the point.
*
* @param aDocAcc [in] document that manages the virtual cursor
* @param aX [in] screen x coordinate
* @param aY [in] screen y coordinate
* @param aIgnoreNoMatch [in] don't unset position if no object was found at
* point.
* @param aRule [in] traversal rule object
* @param aIdOrNameOrAcc [in] id, accessible or accessible name to expect
* virtual cursor to land on after performing move method.
* false if no move is expected.
*/
function moveVCCoordInvoker(aDocAcc, aX, aY, aIgnoreNoMatch,
aRule, aIdOrNameOrAcc)
{
var expectMove = (aIdOrNameOrAcc != false);
this.invoke = function virtualCursorChangedInvoker_invoke()
{
VCChangedChecker.
storePreviousPosAndOffset(aDocAcc.virtualCursor);
var moved = aDocAcc.virtualCursor.moveToPoint(aRule, aX, aY,
aIgnoreNoMatch);
SimpleTest.ok((expectMove && moved) || (!expectMove && !moved),
"moved pivot");
};
this.getID = function setVCPosInvoker_getID()
{
return "Do " + (expectMove ? "" : "no-op ") + "moveToPoint " + aIdOrNameOrAcc;
};
if (expectMove) {
this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
} else {
this.eventSeq = [];
@ -220,7 +263,7 @@ function queueTraversalSequence(aQueue, aDocAcc, aRule, aSequence)
}
// No further more matches for given rule, expect no virtual cursor changes.
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, null));
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, false));
for (var i = aSequence.length-2; i >= 0; i--) {
var invoker =
@ -229,18 +272,18 @@ function queueTraversalSequence(aQueue, aDocAcc, aRule, aSequence)
}
// No previous more matches for given rule, expect no virtual cursor changes.
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, null));
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, false));
aQueue.push(new setVCPosInvoker(aDocAcc, "moveLast", aRule,
aSequence[aSequence.length - 1]));
// No further more matches for given rule, expect no virtual cursor changes.
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, null));
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, false));
aQueue.push(new setVCPosInvoker(aDocAcc, "moveFirst", aRule, aSequence[0]));
// No previous more matches for given rule, expect no virtual cursor changes.
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, null));
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, false));
}
/**

View File

@ -15,6 +15,7 @@
<script type="application/javascript" src="../role.js"></script>
<script type="application/javascript" src="../states.js"></script>
<script type="application/javascript" src="../pivot.js"></script>
<script type="application/javascript" src="../layout.js"></script>
<script type="application/javascript">
var gBrowserWnd = null;
@ -76,6 +77,22 @@
gQueue.push(new removeVCRootInvoker(
doc.getElementById('links')));
var [x, y] = getBounds(getAccessible(doc.getElementById('heading-1-1')));
gQueue.push(new moveVCCoordInvoker(docAcc, x + 1, y + 1, true,
HeadersTraversalRule, 'heading-1-1'));
// Already on the point, so we should not get a move event.
gQueue.push(new moveVCCoordInvoker(docAcc, x + 1, y + 1, true,
HeadersTraversalRule, false));
// Attempting a coordinate outside any header, should not move.
gQueue.push(new moveVCCoordInvoker(docAcc, x - 1, y - 1, true,
HeadersTraversalRule, false));
// Attempting a coordinate outside any header, should move to null
gQueue.push(new moveVCCoordInvoker(docAcc, x - 1, y - 1, false,
HeadersTraversalRule, null));
gQueue.invoke();
}