Bug 756287 - Introduce PresenterContext in AccessFu. r=davidb

This commit is contained in:
Eitan Isaacson 2012-05-18 11:56:38 -07:00
parent 47f46b181d
commit c53c69acbb
2 changed files with 95 additions and 80 deletions

View File

@ -215,12 +215,10 @@ var AccessFu = {
doc.defaultView, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, 0);
}
let newContext = this.getNewContext(event.oldAccessible,
pivot.position);
let presenterContext = new PresenterContext(pivot.position,
event.oldAccessible);
this.presenters.forEach(
function(p) {
p.pivotChanged(pivot.position, newContext);
});
function(p) { p.pivotChanged(presenterContext); });
break;
}
case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
@ -313,8 +311,13 @@ var AccessFu = {
{
if (this._isBrowserDoc(aEvent.accessible)) {
// The document recieved focus, call tabSelected to present current tab.
let docContext = new PresenterContext(aEvent.accessible, null);
let cursorable = aEvent.accessible.
QueryInterface(Ci.nsIAccessibleCursorable);
let vcContext = new PresenterContext(
(cursorable) ? cursorable.virtualCursor.position : null, null);
this.presenters.forEach(
function(p) { p.tabSelected(aEvent.accessible); });
function(p) { p.tabSelected(docContext, vcContext); });
}
break;
}
@ -383,41 +386,6 @@ var AccessFu = {
return location.protocol != "about:";
},
getNewContext: function getNewContext(aOldObject, aNewObject) {
let newLineage = [];
let oldLineage = [];
let parent = aNewObject;
while ((parent = parent.parent))
newLineage.push(parent);
if (aOldObject) {
parent = aOldObject;
while ((parent = parent.parent))
oldLineage.push(parent);
}
// newLineage.reverse();
// oldLineage.reverse();
let i = 0;
let newContext = [];
while (true) {
let newAncestor = newLineage.pop();
let oldAncestor = oldLineage.pop();
if (newAncestor == undefined)
break;
if (newAncestor != oldAncestor)
newContext.push(newAncestor);
i++;
}
return newContext;
},
// A hash of documents that don't yet have an accessible tree.
_pendingDocuments: {},

View File

@ -14,7 +14,8 @@ Cu.import('resource://gre/modules/Services.jsm');
var EXPORTED_SYMBOLS = ['VisualPresenter',
'AndroidPresenter',
'DummyAndroidPresenter'];
'DummyAndroidPresenter',
'PresenterContext'];
/**
* The interface for all presenter classes. A presenter could be, for example,
@ -36,11 +37,10 @@ Presenter.prototype = {
/**
* The virtual cursor's position changed.
* @param {nsIAccessible} aObject the new position.
* @param {nsIAccessible[]} aNewContext the ancestry of the new position that
* is different from the old virtual cursor position.
* @param {PresenterContext} aContext the context object for the new pivot
* position.
*/
pivotChanged: function pivotChanged(aObject, aNewContext) {},
pivotChanged: function pivotChanged(aContext) {},
/**
* An object's action has been invoked.
@ -78,11 +78,12 @@ Presenter.prototype = {
/**
* The current tab has changed.
* @param {nsIAccessible} aObject the document contained by the tab
* accessible, or null if it is a new tab with no attached
* document yet.
* @param {PresenterContext} aDocContext context object for tab's
* document.
* @param {PresenterContext} aVCContext context object for tab's current
* virtual cursor position.
*/
tabSelected: function tabSelected(aDocObj) {},
tabSelected: function tabSelected(aDocContext, aVCContext) {},
/**
* The viewport has changed, either a scroll, pan, zoom, or
@ -139,34 +140,32 @@ VisualPresenter.prototype = {
this._highlight(this._currentObject);
},
pivotChanged: function VisualPresenter_pivotChanged(aObject, aNewContext) {
this._currentObject = aObject;
pivotChanged: function VisualPresenter_pivotChanged(aContext) {
this._currentObject = aContext.accessible;
if (!aObject) {
if (!aContext.accessible) {
this._hide();
return;
}
try {
aObject.scrollTo(Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
this._highlight(aObject);
aContext.accessible.scrollTo(
Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
this._highlight(aContext.accessible);
} catch (e) {
dump('Error getting bounds: ' + e);
return;
}
},
tabSelected: function VisualPresenter_tabSelected(aDocObj) {
let vcPos = aDocObj ? aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).
virtualCursor.position : null;
this.pivotChanged(vcPos);
tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) {
this.pivotChanged(aVCContext);
},
tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj,
aPageState) {
if (aPageState == 'newdoc')
this.pivotChanged(null);
this._hide();
},
// Internals
@ -234,14 +233,15 @@ AndroidPresenter.prototype = {
ANDROID_VIEW_TEXT_CHANGED: 0x10,
ANDROID_WINDOW_STATE_CHANGED: 0x20,
pivotChanged: function AndroidPresenter_pivotChanged(aObject, aNewContext) {
pivotChanged: function AndroidPresenter_pivotChanged(aContext) {
let output = [];
for (let i in aNewContext)
output.push.apply(output,
UtteranceGenerator.genForObject(aNewContext[i]));
for (let i in aContext.newAncestry)
output.push.apply(
output, UtteranceGenerator.genForObject(aContext.newAncestry[i]));
output.push.apply(output,
UtteranceGenerator.genForObject(aObject, true));
UtteranceGenerator.genForObject(aContext.accessible,
true));
this.sendMessageToJava({
gecko: {
@ -262,21 +262,9 @@ AndroidPresenter.prototype = {
});
},
tabSelected: function AndroidPresenter_tabSelected(aDocObj) {
tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) {
// Send a pivot change message with the full context utterance for this doc.
let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
let context = [];
let parent = vcDoc.virtualCursor.position || aDocObj;
while ((parent = parent.parent)) {
context.push(parent);
if (parent == aDocObj)
break;
}
context.reverse();
this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
this.pivotChanged(aVCContext);
},
tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
@ -342,3 +330,62 @@ DummyAndroidPresenter.prototype = {
dump(JSON.stringify(aMsg, null, 2) + '\n');
}
};
/**
* PresenterContext: An object that generates and caches context information
* for a given accessible and its relationship with another accessible.
*/
function PresenterContext(aAccessible, aOldAccessible) {
this._accessible = aAccessible;
this._oldAccessible = aOldAccessible;
}
PresenterContext.prototype = {
get accessible() {
return this._accessible;
},
get oldAccessible() {
return this._oldAccessible;
},
/*
* This is a list of the accessible's ancestry up to the common ancestor
* of the accessible and the old accessible. It is useful for giving the
* user context as to where they are in the heirarchy.
*/
get newAncestry() {
if (!this._newAncestry) {
let newLineage = [];
let oldLineage = [];
let parent = this._accessible;
while ((parent = parent.parent))
newLineage.push(parent);
if (this._oldAccessible) {
parent = this._oldAccessible;
while ((parent = parent.parent))
oldLineage.push(parent);
}
let i = 0;
this._newAncestry = [];
while (true) {
let newAncestor = newLineage.pop();
let oldAncestor = oldLineage.pop();
if (newAncestor == undefined)
break;
if (newAncestor != oldAncestor)
this._newAncestry.push(newAncestor);
i++;
}
}
return this._newAncestry;
}
};