Bug 891967 - Show caret in braille when editing. r=eeejay r=kats

This commit is contained in:
Max Li 2013-07-11 15:55:40 -04:00
parent 3181ff1886
commit 5c31cb6849
5 changed files with 88 additions and 33 deletions

View File

@ -362,6 +362,8 @@ var Output = {
startOffset: 0,
endOffset: 0,
text: '',
selectionStart: 0,
selectionEnd: 0,
init: function init(aOutput) {
if (aOutput && 'output' in aOutput) {
@ -370,11 +372,20 @@ var Output = {
// We need to append a space at the end so that the routing key corresponding
// to the end of the output (i.e. the space) can be hit to move the caret there.
this.text = aOutput.output + ' ';
return this.text;
this.selectionStart = typeof aOutput.selectionStart === 'number' ?
aOutput.selectionStart : this.selectionStart;
this.selectionEnd = typeof aOutput.selectionEnd === 'number' ?
aOutput.selectionEnd : this.selectionEnd;
return { text: this.text,
selectionStart: this.selectionStart,
selectionEnd: this.selectionEnd };
}
return null;
},
update: function update(aText) {
adjustText: function adjustText(aText) {
let newBraille = [];
let braille = {};
@ -384,8 +395,7 @@ var Output = {
newBraille.push(prefix);
}
let newText = aText;
newBraille.push(newText);
newBraille.push(aText);
let suffix = this.text.substring(this.endOffset).trim();
if (suffix) {
@ -393,9 +403,23 @@ var Output = {
newBraille.push(suffix);
}
braille.startOffset = prefix.length;
braille.output = newBraille.join('');
braille.endOffset = braille.output.length - suffix.length;
this.startOffset = braille.startOffset = prefix.length;
this.text = braille.text = newBraille.join('') + ' ';
this.endOffset = braille.endOffset = braille.text.length - suffix.length;
braille.selectionStart = this.selectionStart;
braille.selectionEnd = this.selectionEnd;
return braille;
},
adjustSelection: function adjustSelection(aSelection) {
let braille = {};
braille.startOffset = this.startOffset;
braille.endOffset = this.endOffset;
braille.text = this.text;
this.selectionStart = braille.selectionStart = aSelection.selectionStart + this.startOffset;
this.selectionEnd = braille.selectionEnd = aSelection.selectionEnd + this.startOffset;
return braille;
}
@ -502,6 +526,7 @@ var Output = {
Android: function Android(aDetails, aBrowser) {
const ANDROID_VIEW_TEXT_CHANGED = 0x10;
const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
if (!this._bridge)
this._bridge = Cc['@mozilla.org/android/bridge;1'].getService(Ci.nsIAndroidBridge);
@ -510,14 +535,18 @@ var Output = {
androidEvent.type = 'Accessibility:Event';
if (androidEvent.bounds)
androidEvent.bounds = this._adjustBounds(androidEvent.bounds, aBrowser, true);
if (androidEvent.eventType === ANDROID_VIEW_TEXT_CHANGED) {
androidEvent.brailleText = this.brailleState.update(androidEvent.text);
switch(androidEvent.eventType) {
case ANDROID_VIEW_TEXT_CHANGED:
androidEvent.brailleOutput = this.brailleState.adjustText(androidEvent.text);
break;
case ANDROID_VIEW_TEXT_SELECTION_CHANGED:
androidEvent.brailleOutput = this.brailleState.adjustSelection(androidEvent.brailleOutput);
break;
default:
androidEvent.brailleOutput = this.brailleState.init(androidEvent.brailleOutput);
break;
}
let (output = this.brailleState.init(androidEvent.brailleText)) {
if (typeof output === 'string') {
androidEvent.brailleText = output;
}
};
this._bridge.handleGeckoMessage(JSON.stringify(androidEvent));
}
},

View File

@ -212,6 +212,9 @@ this.EventManager.prototype = {
editState.atStart != this.editState.atStart)
this.sendMsgFunc("AccessFu:Input", editState);
this.present(Presentation.textSelectionChanged(acc.getText(0,-1),
caretOffset, caretOffset, 0, 0, aEvent.isFromUserInput));
this.editState = editState;
break;
}

View File

@ -61,7 +61,7 @@ Presenter.prototype = {
/**
* Text selection has changed. TODO.
*/
textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {},
textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd, aIsFromUser) {},
/**
* Selection has changed. TODO.
@ -234,12 +234,12 @@ AndroidPresenter.prototype = {
let state = Utils.getStates(aContext.accessible)[0];
let brailleText = '';
let brailleOutput = {};
if (Utils.AndroidSdkVersion >= 16) {
if (!this._braillePresenter) {
this._braillePresenter = new BraillePresenter();
}
brailleText = this._braillePresenter.pivotChanged(aContext, aReason).
brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
details;
}
@ -252,7 +252,7 @@ AndroidPresenter.prototype = {
Ci.nsIAccessibleStates.STATE_CHECKABLE),
checked: !!(state &
Ci.nsIAccessibleStates.STATE_CHECKED),
brailleText: brailleText});
brailleOutput: brailleOutput});
return {
@ -310,20 +310,28 @@ AndroidPresenter.prototype = {
textSelectionChanged: function AndroidPresenter_textSelectionChanged(aText, aStart,
aEnd, aOldStart,
aOldEnd) {
aOldEnd, aIsFromUser) {
let androidEvents = [];
if (Utils.AndroidSdkVersion >= 14) {
if (Utils.AndroidSdkVersion >= 14 && !aIsFromUser) {
if (!this._braillePresenter) {
this._braillePresenter = new BraillePresenter();
}
let brailleOutput = this._braillePresenter.textSelectionChanged(aText, aStart, aEnd,
aOldStart, aOldEnd,
aIsFromUser).details;
androidEvents.push({
eventType: this.ANDROID_VIEW_TEXT_SELECTION_CHANGED,
text: [aText],
fromIndex: aStart,
toIndex: aEnd,
itemCount: aText.length
itemCount: aText.length,
brailleOutput: brailleOutput
});
}
if (Utils.AndroidSdkVersion >= 16) {
if (Utils.AndroidSdkVersion >= 16 && aIsFromUser) {
let [from, to] = aOldStart < aStart ? [aOldStart, aStart] : [aStart, aOldStart];
androidEvents.push({
eventType: this.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
@ -454,9 +462,20 @@ BraillePresenter.prototype = {
let brailleOutput = BrailleGenerator.genForContext(aContext);
brailleOutput.output = brailleOutput.output.join(' ');
brailleOutput.selectionStart = 0;
brailleOutput.selectionEnd = 0;
return { type: this.type, details: brailleOutput };
}
},
textSelectionChanged: function BraillePresenter_textSelectionChanged(aText, aStart,
aEnd, aOldStart,
aOldEnd, aIsFromUser) {
return { type: this.type,
details: { selectionStart: aStart,
selectionEnd: aEnd } };
},
};
@ -496,8 +515,11 @@ this.Presentation = {
for each (p in this.presenters)];
},
textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {
return [p.textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd)
textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd,
aOldStart, aOldEnd,
aIsFromUser) {
return [p.textSelectionChanged(aText, aStart, aEnd,
aOldStart, aOldEnd, aIsFromUser)
for each (p in this.presenters)];
},

View File

@ -243,7 +243,7 @@ function moveCaret(aMessage) {
function presentCaretChange(aText, aOldOffset, aNewOffset) {
if (aOldOffset !== aNewOffset) {
let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
aOldOffset, aOldOffset);
aOldOffset, aOldOffset, true);
sendAsyncMessage('AccessFu:Present', msg);
}
}

View File

@ -200,9 +200,10 @@ public class GeckoAccessibility {
sVirtualCursorNode.setBoundsInScreen(screenBounds);
}
final String brailleText = message.optString("brailleText");
if (!brailleText.isEmpty()) {
sendBrailleText(view, brailleText);
final JSONObject braille = message.optJSONObject("brailleOutput");
if (braille != null) {
sendBrailleText(view, braille.optString("text"),
braille.optInt("selectionStart"), braille.optInt("selectionEnd"));
}
ThreadUtils.postToUiThread(new Runnable() {
@ -234,13 +235,13 @@ public class GeckoAccessibility {
}
}
private static void sendBrailleText(final View view, final String text) {
private static void sendBrailleText(final View view, final String text, final int selectionStart, final int selectionEnd) {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(view, VIRTUAL_CURSOR_POSITION);
WriteData data = WriteData.forInfo(info);
data.setText(text);
// Set the focus blink
data.setSelectionStart(0);
data.setSelectionEnd(0);
// Set either the focus blink or the current caret position/selection
data.setSelectionStart(selectionStart);
data.setSelectionEnd(selectionEnd);
sSelfBrailleClient.write(data);
}