Bug 757372 - Announce "editing" when in editing mode. Use a11y states and focus to determine it. r=davidb

This commit is contained in:
Eitan Isaacson 2012-07-10 16:10:15 -07:00
Родитель e66c1cc566
Коммит 2e1ebd1ddd
6 изменённых файлов: 89 добавлений и 38 удалений

Просмотреть файл

@ -365,6 +365,21 @@ var AccessFu = {
if (acc.role != Ci.nsIAccessibleRole.ROLE_DOCUMENT &&
doc.role != Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW)
VirtualCursorController.moveCursorToObject(acc);
let [,extState] = Utils.getStates(acc);
let editableState = extState &
(Ci.nsIAccessibleStates.EXT_STATE_EDITABLE |
Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE);
if (editableState != VirtualCursorController.editableState) {
if (!VirtualCursorController.editableState)
this.presenters.forEach(
function(p) {
p.editingModeChanged(true);
}
);
}
VirtualCursorController.editableState = editableState;
break;
}
default:

Просмотреть файл

@ -91,7 +91,12 @@ Presenter.prototype = {
* The viewport has changed, either a scroll, pan, zoom, or
* landscape/portrait toggle.
*/
viewportChanged: function viewportChanged() {}
viewportChanged: function viewportChanged() {},
/**
* We have entered or left text editing mode.
*/
editingModeChanged: function editingModeChanged(aIsEditing) {}
};
/**
@ -303,22 +308,8 @@ AndroidPresenter.prototype = {
tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
aPageState) {
let stateUtterance = UtteranceGenerator.
genForTabStateChange(aDocObj, aPageState);
if (!stateUtterance.length)
return;
this.sendMessageToJava({
gecko: {
type: 'Accessibility:Event',
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
text: stateUtterance,
addedCount: stateUtterance.join(' ').length,
removedCount: 0,
fromIndex: 0
}
});
this._appAnnounce(
UtteranceGenerator.genForTabStateChange(aDocObj, aPageState));
},
textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart,
@ -364,6 +355,26 @@ AndroidPresenter.prototype = {
});
},
editingModeChanged: function AndroidPresenter_editingModeChanged(aIsEditing) {
this._appAnnounce(UtteranceGenerator.genForEditingMode(aIsEditing));
},
_appAnnounce: function _appAnnounce(aUtterance) {
if (!aUtterance.length)
return;
this.sendMessageToJava({
gecko: {
type: 'Accessibility:Event',
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
text: aUtterance,
addedCount: aUtterance.join(' ').length,
removedCount: 0,
fromIndex: 0
}
});
},
sendMessageToJava: function AndroidPresenter_sendMessageTojava(aMessage) {
return Cc['@mozilla.org/android/bridge;1'].
getService(Ci.nsIAndroidBridge).

Просмотреть файл

@ -59,6 +59,16 @@ var Utils = {
default:
return null;
}
},
getStates: function getStates(aAccessible) {
if (!aAccessible)
return [0, 0];
let state = {};
let extState = {};
aAccessible.getState(state, extState);
return [state.value, extState.value];
}
};

Просмотреть файл

@ -123,6 +123,16 @@ var UtteranceGenerator = {
}
},
/**
* Generates an utterance for announcing entering and leaving editing mode.
* @param {aIsEditing} boolean true if we are in editing mode
* @return {Array} The mode utterance
*/
genForEditingMode: function genForEditingMode(aIsEditing) {
return [gStringBundle.GetStringFromName(
aIsEditing ? 'editingMode' : 'navigationMode')];
},
verbosityRoleMap: {
'menubar': INCLUDE_DESC,
'scrollbar': INCLUDE_DESC,

Просмотреть файл

@ -404,11 +404,8 @@ var TraversalRules = {
};
var VirtualCursorController = {
NOT_EDITABLE: 0,
SINGLE_LINE_EDITABLE: 1,
MULTI_LINE_EDITABLE: 2,
exploreByTouch: false,
editableState: 0,
attach: function attach(aWindow) {
this.chromeWin = aWindow;
@ -463,7 +460,7 @@ var VirtualCursorController = {
// an alphanumeric key was pressed, handle it separately.
// If it was pressed with either alt or ctrl, just pass through.
// If it was pressed with meta, pass the key on without the meta.
if (this._isEditableText(target) ||
if (this.editableState ||
aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
return;
@ -477,13 +474,29 @@ var VirtualCursorController = {
this[methodName](document, false, rule);
break;
case aEvent.DOM_VK_END:
if (this.editableState) {
if (target.selectionEnd != target.textLength)
// Don't move forward if caret is not at end of entry.
// XXX: Fix for rtl
return;
else
target.blur();
}
this.moveForward(document, true);
break;
case aEvent.DOM_VK_HOME:
if (this.editableState) {
if (target.selectionEnd != 0)
// Don't move backward if caret is not at start of entry.
// XXX: Fix for rtl
return;
else
target.blur();
}
this.moveBackward(document, true);
break;
case aEvent.DOM_VK_RIGHT:
if (this._isEditableText(target)) {
if (this.editableState) {
if (target.selectionEnd != target.textLength)
// Don't move forward if caret is not at end of entry.
// XXX: Fix for rtl
@ -494,7 +507,7 @@ var VirtualCursorController = {
this.moveForward(document, aEvent.shiftKey);
break;
case aEvent.DOM_VK_LEFT:
if (this._isEditableText(target)) {
if (this.editableState) {
if (target.selectionEnd != 0)
// Don't move backward if caret is not at start of entry.
// XXX: Fix for rtl
@ -505,7 +518,7 @@ var VirtualCursorController = {
this.moveBackward(document, aEvent.shiftKey);
break;
case aEvent.DOM_VK_UP:
if (this._isEditableText(target) == this.MULTI_LINE_EDITABLE) {
if (this.editableState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) {
if (target.selectionEnd != 0)
// Don't blur content if caret is not at start of text area.
return;
@ -521,7 +534,7 @@ var VirtualCursorController = {
break;
case aEvent.DOM_VK_RETURN:
case aEvent.DOM_VK_ENTER:
if (this._isEditableText(target))
if (this.editableState)
return;
this.activateCurrent(document);
break;
@ -538,18 +551,6 @@ var VirtualCursorController = {
aX, aY, true);
},
_isEditableText: function _isEditableText(aElement) {
// XXX: Support contentEditable and design mode
if (aElement instanceof Ci.nsIDOMHTMLInputElement &&
aElement.mozIsTextField(false))
return this.SINGLE_LINE_EDITABLE;
if (aElement instanceof Ci.nsIDOMHTMLTextAreaElement)
return this.MULTI_LINE_EDITABLE;
return this.NOT_EDITABLE;
},
moveForward: function moveForward(aDocument, aLast, aRule) {
let virtualCursor = this.getVirtualCursor(aDocument);
if (aLast) {

Просмотреть файл

@ -107,3 +107,7 @@ stateCollapsed = collapsed
stateUnavailable = unavailable
stateRequired = required
stateTraversed = visited
# App modes
editingMode = editing
navigationMode = navigating