Bug 1200836 - Land on first atomic object in container traversal. r=yzen

--HG--
rename : accessible/jsat/TraversalRules.jsm => accessible/jsat/Traversal.jsm
This commit is contained in:
Eitan Isaacson 2015-09-02 09:44:30 -07:00
parent 546ec0bfcb
commit af27c436af
8 changed files with 173 additions and 15 deletions

View File

@ -15,7 +15,9 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
'resource://gre/modules/accessibility/TraversalRules.jsm');
'resource://gre/modules/accessibility/Traversal.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TraversalHelper',
'resource://gre/modules/accessibility/Traversal.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
'resource://gre/modules/accessibility/Presentation.jsm');
@ -27,7 +29,6 @@ const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
this.ContentControl = function ContentControl(aContentScope) {
this._contentScope = Cu.getWeakReference(aContentScope);
this._vcCache = new WeakMap();
this._childMessageSenders = new WeakMap();
};
@ -128,7 +129,7 @@ this.ContentControl.prototype = {
return;
}
let moved = vc[action](TraversalRules[aMessage.json.rule]);
let moved = TraversalHelper.move(vc, action, aMessage.json.rule);
if (moved) {
if (origin === 'child') {

View File

@ -18,8 +18,6 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
'resource://gre/modules/accessibility/Presentation.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
'resource://gre/modules/accessibility/TraversalRules.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Events',

View File

@ -4,14 +4,14 @@
/* global PrefCache, Roles, Prefilters, States, Filters, Utils,
TraversalRules, Components, XPCOMUtils */
/* exported TraversalRules */
/* exported TraversalRules, TraversalHelper */
'use strict';
const Ci = Components.interfaces;
const Cu = Components.utils;
this.EXPORTED_SYMBOLS = ['TraversalRules']; // jshint ignore:line
this.EXPORTED_SYMBOLS = ['TraversalRules', 'TraversalHelper']; // jshint ignore:line
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
@ -26,7 +26,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Prefilters', // jshint ignore:line
let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter) {
function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter, aContainerRule) {
this._explicitMatchRoles = new Set(aRoles);
this._matchRoles = aRoles;
if (aRoles.length) {
@ -40,6 +40,7 @@ function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter) {
}
this._matchFunc = aMatchFunc || function() { return Filters.MATCH; };
this.preFilter = aPreFilter || gSimplePreFilter;
this.containerRule = aContainerRule;
}
BaseTraversalRule.prototype = {
@ -221,8 +222,7 @@ this.TraversalRules = { // jshint ignore:line
function Landmark_match(aAccessible) {
return Utils.getLandmarkName(aAccessible) ? Filters.MATCH :
Filters.IGNORE;
}
),
}, null, true),
Entry: new BaseTraversalRule(
[Roles.ENTRY,
@ -276,7 +276,8 @@ this.TraversalRules = { // jshint ignore:line
List: new BaseTraversalRule(
[Roles.LIST,
Roles.DEFINITION_LIST]),
Roles.DEFINITION_LIST],
null, null, true),
PageTab: new BaseTraversalRule(
[Roles.PAGETAB]),
@ -316,3 +317,51 @@ this.TraversalRules = { // jshint ignore:line
return Filters.MATCH;
}
};
this.TraversalHelper = {
_helperPivotCache: null,
get helperPivotCache() {
delete this.helperPivotCache;
this.helperPivotCache = new WeakMap();
return this.helperPivotCache;
},
getHelperPivot: function TraversalHelper_getHelperPivot(aRoot) {
let pivot = this.helperPivotCache.get(aRoot.DOMNode);
if (!pivot) {
pivot = Utils.AccRetrieval.createAccessiblePivot(aRoot);
this.helperPivotCache.set(aRoot.DOMNode, pivot);
}
return pivot;
},
move: function TraversalHelper_move(aVirtualCursor, aMethod, aRule) {
let rule = TraversalRules[aRule];
if (rule.containerRule) {
let moved = false;
let helperPivot = this.getHelperPivot(aVirtualCursor.root);
helperPivot.position = aVirtualCursor.position;
// We continue to step through containers until there is one with an
// atomic child (via 'Simple') on which we could land.
while (!moved) {
if (helperPivot[aMethod](rule)) {
aVirtualCursor.modalRoot = helperPivot.position;
moved = aVirtualCursor.moveFirst(TraversalRules.Simple);
aVirtualCursor.modalRoot = null;
} else {
// If we failed to step to another container, break and return false.
break;
}
}
return moved;
} else {
return aVirtualCursor[aMethod](rule);
}
}
};

View File

@ -10,8 +10,6 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
'resource://gre/modules/accessibility/Presentation.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
'resource://gre/modules/accessibility/TraversalRules.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',

View File

@ -13,7 +13,7 @@ EXTRA_JS_MODULES.accessibility += [
'OutputGenerator.jsm',
'PointerAdapter.jsm',
'Presentation.jsm',
'TraversalRules.jsm',
'Traversal.jsm',
'Utils.jsm'
]

View File

@ -24,3 +24,4 @@ skip-if = buildapp == 'mulet'
[test_tables.html]
[test_pointer_relay.html]
[test_traversal.html]
[test_traversal_helper.html]

View File

@ -21,7 +21,7 @@
<script type="application/javascript" src="../layout.js"></script>
<script type="application/javascript">
Components.utils.import("resource://gre/modules/accessibility/TraversalRules.jsm");
Components.utils.import("resource://gre/modules/accessibility/Traversal.jsm");
var gBrowserWnd = null;
var gQueue = null;

View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu TraversalRules</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
</script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.js"></script>
<script type="application/javascript" src="../events.js"></script>
<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">
Components.utils.import("resource://gre/modules/accessibility/Traversal.jsm");
var vc;
function accessibleIs(aAccessible, aExpected, aMessage) {
if (!aAccessible && aAccessible == aExpected) {
ok(true, "Accessible is null. " + aMessage);
} else {
ok(aAccessible.DOMNode.id == aExpected || aAccessible.name == aExpected,
"expected '" + aExpected + "', got " + prettyName(vc.position) +
". " + aMessage);
}
}
function walkSequence(aMethod, aRule, aExpectedSequence) {
for (var expected of aExpectedSequence) {
ok(TraversalHelper.move(vc, aMethod, aRule),
"successfully did " + aMethod + " with " + aRule);
accessibleIs(vc.position, expected, "landed on correct accessible");
}
}
function testTraversalHelper(aRule, aExpectedSequence) {
vc.position = null;
walkSequence('moveNext', aRule, aExpectedSequence);
ok(!TraversalHelper.move(vc, 'moveNext', aRule), "reached end");
TraversalHelper.move(vc, 'moveLast', 'Simple');
walkSequence('movePrevious', aRule,
Array.from(aExpectedSequence).reverse());
ok(!TraversalHelper.move(vc, 'movePrevious', aRule), "reached start");
vc.position = null;
ok(TraversalHelper.move(vc, 'moveFirst', aRule), "moveFirst");
accessibleIs(vc.position, aExpectedSequence[0],
"moveFirst to correct accessible");
ok(TraversalHelper.move(vc, 'moveLast', aRule), "moveLast");
accessibleIs(vc.position, aExpectedSequence[aExpectedSequence.length - 1],
"moveLast to correct accessible");
}
function doTest()
{
var doc = currentTabDocument();
var docAcc = getAccessible(doc, [nsIAccessibleDocument]);
vc = docAcc.virtualCursor;
testTraversalHelper('Landmark',
['heading-1', 'heading-2', 'statusbar-1']);
testTraversalHelper('List',
['Programming Language', 'listitem-2-1', 'listitem-3-1']);
vc.position = null;
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function () {
/* We open a new browser because we need to test with a top-level content
document. */
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_traversal.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for AccessFu TraversalRules"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=xxx">Mozilla Bug xxx</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>