зеркало из https://github.com/mozilla/gecko-dev.git
Bug 757372 - Announce "editing" when in editing mode. Use a11y states and focus to determine it. r=davidb
This commit is contained in:
Родитель
e66c1cc566
Коммит
2e1ebd1ddd
|
@ -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
|
Загрузка…
Ссылка в новой задаче