Bug 963298 - Add states to Constants and unify states and extended states. r=yzen

This commit is contained in:
Eitan Isaacson 2014-01-27 16:35:13 -08:00
parent 8d72f4cda9
commit 52d44674cc
6 changed files with 125 additions and 103 deletions

View File

@ -3,37 +3,50 @@ const Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
this.EXPORTED_SYMBOLS = ['Roles', 'Events', 'Relations', 'Filters'];
this.EXPORTED_SYMBOLS = ['Roles', 'Events', 'Relations', 'Filters', 'States'];
function ConstantsMap (aObject, aPrefix) {
function ConstantsMap (aObject, aPrefix, aMap = {}, aModifier = null) {
let offset = aPrefix.length;
for (var name in aObject) {
if (name.indexOf(aPrefix) === 0) {
this[name.slice(offset)] = aObject[name];
aMap[name.slice(offset)] = aModifier ?
aModifier(aObject[name]) : aObject[name];
}
}
return aMap;
}
XPCOMUtils.defineLazyGetter(
this, 'Roles',
function() {
return new ConstantsMap(Ci.nsIAccessibleRole, 'ROLE_');
return ConstantsMap(Ci.nsIAccessibleRole, 'ROLE_');
});
XPCOMUtils.defineLazyGetter(
this, 'Events',
function() {
return new ConstantsMap(Ci.nsIAccessibleEvent, 'EVENT_');
return ConstantsMap(Ci.nsIAccessibleEvent, 'EVENT_');
});
XPCOMUtils.defineLazyGetter(
this, 'Relations',
function() {
return new ConstantsMap(Ci.nsIAccessibleRelation, 'RELATION_');
return ConstantsMap(Ci.nsIAccessibleRelation, 'RELATION_');
});
XPCOMUtils.defineLazyGetter(
this, 'Filters',
function() {
return new ConstantsMap(Ci.nsIAccessibleTraversalRule, 'FILTER_');
return ConstantsMap(Ci.nsIAccessibleTraversalRule, 'FILTER_');
});
XPCOMUtils.defineLazyGetter(
this, 'States',
function() {
let statesMap = ConstantsMap(Ci.nsIAccessibleStates, 'STATE_', {},
(val) => { return { base: val, extended: 0 }; });
ConstantsMap(Ci.nsIAccessibleStates, 'EXT_STATE_', statesMap,
(val) => { return { base: 0, extended: val }; });
return statesMap;
});

View File

@ -24,6 +24,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Events',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States',
'resource://gre/modules/accessibility/Constants.jsm');
this.EXPORTED_SYMBOLS = ['EventManager'];
@ -147,13 +149,13 @@ this.EventManager.prototype = {
case Events.STATE_CHANGE:
{
let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
!(event.isExtraState)) {
let state = Utils.getState(event);
if (state.contains(States.CHECKED)) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
event.isEnabled ? 'check' : 'uncheck'));
} else if (event.state == Ci.nsIAccessibleStates.STATE_SELECTED) {
} else if (state.contains(States.SELECTED)) {
this.present(
Presentation.
actionInvoked(aEvent.accessible,
@ -176,10 +178,10 @@ this.EventManager.prototype = {
QueryInterface(Ci.nsIAccessibleCaretMoveEvent).caretOffset;
// Update editing state, both for presenter and other things
let [,extState] = Utils.getStates(acc);
let state = Utils.getState(acc);
let editState = {
editing: !!(extState & Ci.nsIAccessibleStates.EXT_STATE_EDITABLE),
multiline: !!(extState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE),
editing: state.contains(States.EDITABLE),
multiline: state.contains(States.MULTI_LINE),
atStart: caretOffset == 0,
atEnd: caretOffset == characterCount
};

View File

@ -29,6 +29,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm',
'resource://gre/modules/PluralForm.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States',
'resource://gre/modules/accessibility/Constants.jsm');
var gStringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
getService(Ci.nsIStringBundleService).
@ -97,7 +99,7 @@ this.OutputGenerator = {
* context information for a given accessible and its relationship with
* another accessible.
* @return {Array} Two string array. The first string describes the object
* and its states. The second string is the object's name. Whether the
* and its state. The second string is the object's name. Whether the
* object's description or it's role is included is determined by
* {@link roleRuleMap}.
*/
@ -112,11 +114,8 @@ this.OutputGenerator = {
if (aAccessible.childCount == 0)
flags |= INCLUDE_NAME;
let state = {};
let extState = {};
aAccessible.getState(state, extState);
let states = {base: state.value, ext: extState.value};
return func.apply(this, [aAccessible, roleString, states, flags, aContext]);
return func.apply(this, [aAccessible, roleString,
Utils.getState(aAccessible), flags, aContext]);
},
/**
@ -240,7 +239,7 @@ this.OutputGenerator = {
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {},
_getLocalizedStates: function _getLocalizedStates(aStates) {},
_getLocalizedState: function _getLocalizedState(aState) {},
_getPluralFormString: function _getPluralFormString(aString, aCount) {
let str = gStringBundle.GetStringFromName(this._getOutputName(aString));
@ -322,11 +321,11 @@ this.OutputGenerator = {
'definitionlist': INCLUDE_DESC | INCLUDE_NAME},
objectOutputFunctions: {
_generateBaseOutput: function _generateBaseOutput(aAccessible, aRoleStr, aStates, aFlags) {
_generateBaseOutput: function _generateBaseOutput(aAccessible, aRoleStr, aState, aFlags) {
let output = [];
if (aFlags & INCLUDE_DESC) {
let desc = this._getLocalizedStates(aStates);
let desc = this._getLocalizedState(aState);
let roleStr = this._getLocalizedRole(aRoleStr);
if (roleStr) {
this._addType(desc, aAccessible, aRoleStr);
@ -349,7 +348,7 @@ this.OutputGenerator = {
return output;
},
label: function label(aAccessible, aRoleStr, aStates, aFlags, aContext) {
label: function label(aAccessible, aRoleStr, aState, aFlags, aContext) {
if (aContext.isNestedControl ||
aContext.accessible == Utils.getEmbeddedControl(aAccessible)) {
// If we are on a nested control, or a nesting label,
@ -360,20 +359,19 @@ this.OutputGenerator = {
return this.objectOutputFunctions.defaultFunc.apply(this, arguments);
},
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
let rolestr = (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
'textarea' : 'entry';
entry: function entry(aAccessible, aRoleStr, aState, aFlags) {
let rolestr = aState.contains(States.MULTI_LINE) ? 'textarea' : 'entry';
return this.objectOutputFunctions.defaultFunc.apply(
this, [aAccessible, rolestr, aStates, aFlags]);
this, [aAccessible, rolestr, aState, aFlags]);
},
pagetab: function pagetab(aAccessible, aRoleStr, aStates, aFlags) {
pagetab: function pagetab(aAccessible, aRoleStr, aState, aFlags) {
let localizedRole = this._getLocalizedRole(aRoleStr);
let itemno = {};
let itemof = {};
aAccessible.groupPosition({}, itemof, itemno);
let output = [];
let desc = this._getLocalizedStates(aStates);
let desc = this._getLocalizedState(aState);
desc.push(
gStringBundle.formatStringFromName(
'objItemOf', [localizedRole, itemno.value, itemof.value], 3));
@ -385,7 +383,7 @@ this.OutputGenerator = {
return output;
},
table: function table(aAccessible, aRoleStr, aStates, aFlags) {
table: function table(aAccessible, aRoleStr, aState, aFlags) {
let output = [];
let table;
try {
@ -499,11 +497,11 @@ this.UtteranceGenerator = {
__proto__: OutputGenerator.objectOutputFunctions,
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aState, aFlags) {
return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
},
heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
heading: function heading(aAccessible, aRoleStr, aState, aFlags) {
let level = {};
aAccessible.groupPosition(level, {}, {});
let utterance =
@ -515,7 +513,7 @@ this.UtteranceGenerator = {
return utterance;
},
listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {
listitem: function listitem(aAccessible, aRoleStr, aState, aFlags) {
let itemno = {};
let itemof = {};
aAccessible.groupPosition({}, itemof, itemno);
@ -531,26 +529,26 @@ this.UtteranceGenerator = {
return utterance;
},
list: function list(aAccessible, aRoleStr, aStates, aFlags) {
list: function list(aAccessible, aRoleStr, aState, aFlags) {
return this._getListUtterance
(aAccessible, aRoleStr, aFlags, aAccessible.childCount);
},
definitionlist: function definitionlist(aAccessible, aRoleStr, aStates, aFlags) {
definitionlist: function definitionlist(aAccessible, aRoleStr, aState, aFlags) {
return this._getListUtterance
(aAccessible, aRoleStr, aFlags, aAccessible.childCount / 2);
},
application: function application(aAccessible, aRoleStr, aStates, aFlags) {
application: function application(aAccessible, aRoleStr, aState, aFlags) {
// Don't utter location of applications, it gets tiring.
if (aAccessible.name != aAccessible.DOMNode.location)
return this.objectOutputFunctions.defaultFunc.apply(this,
[aAccessible, aRoleStr, aStates, aFlags]);
[aAccessible, aRoleStr, aState, aFlags]);
return [];
},
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
cell: function cell(aAccessible, aRoleStr, aState, aFlags, aContext) {
let utterance = [];
let cell = aContext.getCellInfo(aAccessible);
if (cell) {
@ -612,10 +610,10 @@ this.UtteranceGenerator = {
}
},
_getLocalizedStates: function _getLocalizedStates(aStates) {
_getLocalizedState: function _getLocalizedState(aState) {
let stateUtterances = [];
if (aStates.base & Ci.nsIAccessibleStates.STATE_UNAVAILABLE) {
if (aState.contains(States.UNAVAILABLE)) {
stateUtterances.push(gStringBundle.GetStringFromName('stateUnavailable'));
}
@ -623,31 +621,31 @@ this.UtteranceGenerator = {
// This is because we expose the checked information on the node itself.
// XXX: this means the checked state is always appended to the end, regardless
// of the utterance ordering preference.
if (Utils.AndroidSdkVersion < 16 && aStates.base & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
let stateStr = (aStates.base & Ci.nsIAccessibleStates.STATE_CHECKED) ?
if (Utils.AndroidSdkVersion < 16 && aState.contains(States.CHECKABLE)) {
let statetr = aState.contains(States.CHECKED) ?
'stateChecked' : 'stateNotChecked';
stateUtterances.push(gStringBundle.GetStringFromName(stateStr));
stateUtterances.push(gStringBundle.GetStringFromName(statetr));
}
if (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_EXPANDABLE) {
let stateStr = (aStates.base & Ci.nsIAccessibleStates.STATE_EXPANDED) ?
if (aState.contains(States.EXPANDABLE)) {
let statetr = aState.contains(States.EXPANDED) ?
'stateExpanded' : 'stateCollapsed';
stateUtterances.push(gStringBundle.GetStringFromName(stateStr));
stateUtterances.push(gStringBundle.GetStringFromName(statetr));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_REQUIRED) {
if (aState.contains(States.REQUIRED)) {
stateUtterances.push(gStringBundle.GetStringFromName('stateRequired'));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_TRAVERSED) {
if (aState.contains(States.TRAVERSED)) {
stateUtterances.push(gStringBundle.GetStringFromName('stateTraversed'));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_HASPOPUP) {
if (aState.contains(States.HASPOPUP)) {
stateUtterances.push(gStringBundle.GetStringFromName('stateHasPopup'));
}
if (aStates.base & Ci.nsIAccessibleStates.STATE_SELECTED) {
if (aState.contains(States.SELECTED)) {
stateUtterances.push(gStringBundle.GetStringFromName('stateSelected'));
}
@ -717,11 +715,11 @@ this.BrailleGenerator = {
__proto__: OutputGenerator.objectOutputFunctions,
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aState, aFlags) {
return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
},
listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {
listitem: function listitem(aAccessible, aRoleStr, aState, aFlags) {
let braille = [];
this._addName(braille, aAccessible, aFlags);
@ -730,7 +728,7 @@ this.BrailleGenerator = {
return braille;
},
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
cell: function cell(aAccessible, aRoleStr, aState, aFlags, aContext) {
let braille = [];
let cell = aContext.getCellInfo(aAccessible);
if (cell) {
@ -763,7 +761,7 @@ this.BrailleGenerator = {
return this.objectOutputFunctions.cell.apply(this, arguments);
},
statictext: function statictext(aAccessible, aRoleStr, aStates, aFlags) {
statictext: function statictext(aAccessible, aRoleStr, aState, aFlags) {
// Since we customize the list bullet's output, we add the static
// text from the first node in each listitem, so skip it here.
if (aAccessible.parent.role == Roles.LISTITEM) {
@ -773,10 +771,10 @@ this.BrailleGenerator = {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
_useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aStates, aFlags) {
_useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aState, aFlags) {
let braille = [];
let desc = this._getLocalizedStates(aStates);
let desc = this._getLocalizedState(aState);
braille.push(desc.join(' '));
this._addName(braille, aAccessible, aFlags);
@ -785,15 +783,15 @@ this.BrailleGenerator = {
return braille;
},
checkbutton: function checkbutton(aAccessible, aRoleStr, aStates, aFlags) {
checkbutton: function checkbutton(aAccessible, aRoleStr, aState, aFlags) {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
radiobutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
radiobutton: function radiobutton(aAccessible, aRoleStr, aState, aFlags) {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
togglebutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
togglebutton: function radiobutton(aAccessible, aRoleStr, aState, aFlags) {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
}
},
@ -823,14 +821,14 @@ this.BrailleGenerator = {
}
},
_getLocalizedStates: function _getLocalizedStates(aStates) {
_getLocalizedState: function _getLocalizedState(aState) {
let stateBraille = [];
let getCheckedState = function getCheckedState() {
let resultMarker = [];
let state = aStates.base;
let fill = !!(state & Ci.nsIAccessibleStates.STATE_CHECKED) ||
!!(state & Ci.nsIAccessibleStates.STATE_PRESSED);
let state = aState;
let fill = state.contains(States.CHECKED) ||
state.contains(States.PRESSED);
resultMarker.push('(');
resultMarker.push(fill ? 'x' : ' ');
@ -839,7 +837,7 @@ this.BrailleGenerator = {
return resultMarker.join('');
};
if (aStates.base & Ci.nsIAccessibleStates.STATE_CHECKABLE) {
if (aState.contains(States.CHECKABLE)) {
stateBraille.push(getCheckedState());
}

View File

@ -22,6 +22,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'BrailleGenerator',
'resource://gre/modules/accessibility/OutputGenerator.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States',
'resource://gre/modules/accessibility/Constants.jsm');
this.EXPORTED_SYMBOLS = ['Presentation'];
@ -284,16 +286,14 @@ AndroidPresenter.prototype = {
});
}
} else {
let state = Utils.getStates(aContext.accessible)[0];
let state = Utils.getState(aContext.accessible);
androidEvents.push({eventType: (isExploreByTouch) ?
this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
text: UtteranceGenerator.genForContext(aContext).output,
bounds: aContext.bounds,
clickable: aContext.accessible.actionCount > 0,
checkable: !!(state &
Ci.nsIAccessibleStates.STATE_CHECKABLE),
checked: !!(state &
Ci.nsIAccessibleStates.STATE_CHECKED),
checkable: state.contains(States.CHECKABLE),
checked: state.contains(States.CHECKED),
brailleOutput: brailleOutput});
}
@ -305,10 +305,10 @@ AndroidPresenter.prototype = {
},
actionInvoked: function AndroidPresenter_actionInvoked(aObject, aActionName) {
let state = Utils.getStates(aObject)[0];
let state = Utils.getState(aObject);
// Checkable objects will have a state changed event we will use instead.
if (state & Ci.nsIAccessibleStates.STATE_CHECKABLE)
if (state.contains(States.CHECKABLE))
return null;
return {
@ -316,7 +316,7 @@ AndroidPresenter.prototype = {
details: [{
eventType: this.ANDROID_VIEW_CLICKED,
text: UtteranceGenerator.genForAction(aObject, aActionName),
checked: !!(state & Ci.nsIAccessibleStates.STATE_CHECKED)
checked: state.contains(States.CHECKED)
}]
};
},

View File

@ -17,6 +17,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Filters',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States',
'resource://gre/modules/accessibility/Constants.jsm');
let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
@ -153,10 +155,7 @@ this.TraversalRules = {
function Anchor_match(aAccessible)
{
// We want to ignore links, only focus named anchors.
let state = {};
let extraState = {};
aAccessible.getState(state, extraState);
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
if (Utils.getState(aAccessible).contains(States.LINKED)) {
return Filters.IGNORE;
} else {
return Filters.MATCH;
@ -221,10 +220,7 @@ this.TraversalRules = {
function Link_match(aAccessible)
{
// We want to ignore anchors, only focus real links.
let state = {};
let extraState = {};
aAccessible.getState(state, extraState);
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
if (Utils.getState(aAccessible).contains(States.LINKED)) {
return Filters.MATCH;
} else {
return Filters.IGNORE;

View File

@ -19,6 +19,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Events',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Relations',
'resource://gre/modules/accessibility/Constants.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'States',
'resource://gre/modules/accessibility/Constants.jsm');
this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache', 'SettingCache'];
@ -186,14 +188,36 @@ this.Utils = {
}
},
getStates: function getStates(aAccessible) {
if (!aAccessible)
return [0, 0];
getState: function getState(aAccessibleOrEvent) {
function State(aBase, aExtended) {
this.base = aBase;
this.extended = aExtended;
let state = {};
let extState = {};
aAccessible.getState(state, extState);
return [state.value, extState.value];
this.contains = (other) => {
return !!(this.base & other.base || this.extended & other.extended);
};
this.toString = () => {
let stateStrings = Utils.AccRetrieval.
getStringStates(this.base, this.extended);
let statesArray = new Array(stateStrings.length);
for (let i = 0; i < statesArray.length; i++) {
statesArray[i] = stateStrings.item(i);
}
return '[' + statesArray.join(', ') + ']';
};
}
if (aAccessibleOrEvent instanceof Ci.nsIAccessibleStateChangeEvent) {
return new State(
aAccessibleOrEvent.isExtraState ? 0 : aAccessibleOrEvent.state,
aAccessibleOrEvent.isExtraState ? aAccessibleOrEvent.state : 0);
} else {
let state = {};
let extState = {};
aAccessibleOrEvent.getState(state, extState);
return new State(state.value, extState.value);
}
},
getAttributes: function getAttributes(aAccessible) {
@ -251,11 +275,8 @@ this.Utils = {
}
try {
let extstate = {};
let state = {};
aAccessible.getState(state, extstate);
if (extstate.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT ||
state.value & Ci.nsIAccessibleStates.STATE_INVISIBLE ||
let state = this.getState(aAccessible);
if (state.contains(States.DEFUNCT) || state.contains(States.INVISIBLE) ||
Utils.inHiddenSubtree(aAccessible)) {
return false;
}
@ -409,12 +430,7 @@ this.Logger = {
},
statesToString: function statesToString(aAccessible) {
let [state, extState] = Utils.getStates(aAccessible);
let stringArray = [];
let stateStrings = Utils.AccRetrieval.getStringStates(state, extState);
for (var i=0; i < stateStrings.length; i++)
stringArray.push(stateStrings.item(i));
return stringArray.join(' ');
return Utils.getState(aAccessible).toString();
},
dumpTree: function dumpTree(aLogLevel, aRootAccessible) {
@ -587,8 +603,7 @@ PivotContext.prototype = {
if (this._includeInvisible) {
include = true;
} else {
let [state,] = Utils.getStates(child);
include = !(state & Ci.nsIAccessibleStates.STATE_INVISIBLE);
include = !(Utils.getState(child).contains(States.INVISIBLE));
}
if (include) {
if (aPreorder) {
@ -716,9 +731,7 @@ PivotContext.prototype = {
_isDefunct: function _isDefunct(aAccessible) {
try {
let extstate = {};
aAccessible.getState({}, extstate);
return !!(extstate.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT);
return Utils.getState(aAccessible).contains(States.DEFUNCT);
} catch (x) {
return true;
}