diff --git a/accessible/src/jsat/VirtualCursorController.jsm b/accessible/src/jsat/VirtualCursorController.jsm index 3462c86aff62..d61f9d66492b 100644 --- a/accessible/src/jsat/VirtualCursorController.jsm +++ b/accessible/src/jsat/VirtualCursorController.jsm @@ -114,38 +114,67 @@ var VirtualCursorController = { SimpleTraversalRule: { getMatchRoles: function(aRules) { - aRules.value = []; - return 0; + aRules.value = this._matchRoles; + return this._matchRoles.length; }, preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT | Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE, match: function(aAccessible) { - if (aAccessible.childCount) - // Non-leafs do not interest us. - return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE; - - // XXX: Find a better solution for ROLE_STATICTEXT. - // It allows to filter list bullets but the same time it - // filters CSS generated content too as unwanted side effect. - let ignoreRoles = [Ci.nsIAccessibleRole.ROLE_WHITESPACE, - Ci.nsIAccessibleRole.ROLE_STATICTEXT]; - - if (ignoreRoles.indexOf(aAccessible.role) < 0) { - let name = aAccessible.name; - if (name && name.trim()) - return Ci.nsIAccessibleTraversalRule.FILTER_MATCH; - } - - let state = {}; - aAccessible.getState(state, {}); - if (state.value & Ci.nsIAccessibleStates.STATE_FOCUSABLE) + switch (aAccessible.role) { + case Ci.nsIAccessibleRole.ROLE_COMBOBOX: + // We don't want to ignore the subtree because this is often + // where the list box hangs out. return Ci.nsIAccessibleTraversalRule.FILTER_MATCH; - - return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE; + case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF: + { + // Nameless text leaves are boring, skip them. + let name = aAccessible.name; + if (name && name.trim()) + return Ci.nsIAccessibleTraversalRule.FILTER_MATCH; + else + return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE; + } + case Ci.nsIAccessibleRole.ROLE_LINK: + // If the link has children we should land on them instead. + // Image map links don't have children so we need to match those. + if (aAccessible.childCount == 0) + return Ci.nsIAccessibleTraversalRule.FILTER_MATCH; + else + return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE; + default: + // Ignore the subtree, if there is one. So that we don't land on + // the same content that was already presented by its parent. + return Ci.nsIAccessibleTraversalRule.FILTER_MATCH | + Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE; + } }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]) + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule]), + + _matchRoles: [ + Ci.nsIAccessibleRole.ROLE_MENUITEM, + Ci.nsIAccessibleRole.ROLE_LINK, + Ci.nsIAccessibleRole.ROLE_PAGETAB, + Ci.nsIAccessibleRole.ROLE_GRAPHIC, + // XXX: Find a better solution for ROLE_STATICTEXT. + // It allows to filter list bullets but at the same time it + // filters CSS generated content too as an unwanted side effect. + // Ci.nsIAccessibleRole.ROLE_STATICTEXT, + Ci.nsIAccessibleRole.ROLE_TEXT_LEAF, + Ci.nsIAccessibleRole.ROLE_PUSHBUTTON, + Ci.nsIAccessibleRole.ROLE_CHECKBUTTON, + Ci.nsIAccessibleRole.ROLE_RADIOBUTTON, + Ci.nsIAccessibleRole.ROLE_COMBOBOX, + Ci.nsIAccessibleRole.ROLE_PROGRESSBAR, + Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN, + Ci.nsIAccessibleRole.ROLE_BUTTONMENU, + Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM, + Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT, + Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM, + Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON, + Ci.nsIAccessibleRole.ROLE_ENTRY + ] } };