From d53e34ef994c9da6485d0acfd97712da43b08138 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 18 May 2012 11:56:38 -0700 Subject: [PATCH] Bug 756287 - Introduce PresenterContext in AccessFu. r=davidb --- accessible/src/jsat/AccessFu.jsm | 50 +++--------- accessible/src/jsat/Presenters.jsm | 125 ++++++++++++++++++++--------- 2 files changed, 95 insertions(+), 80 deletions(-) diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index fa4f7f0d7e6..b34c920549e 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -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: {}, diff --git a/accessible/src/jsat/Presenters.jsm b/accessible/src/jsat/Presenters.jsm index 5ff5e8f453f..4f613355c50 100644 --- a/accessible/src/jsat/Presenters.jsm +++ b/accessible/src/jsat/Presenters.jsm @@ -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; + } +};