def _generateRoleName(self, obj, **args): if _settingsManager.getSetting('onlySpeakDisplayedText'): return [] result = [] acss = self.voice(speech_generator.SYSTEM) role = args.get('role', obj.getRole()) force = args.get('force', False) doNotSpeak = [pyatspi.ROLE_UNKNOWN] if not force: doNotSpeak.extend([pyatspi.ROLE_FORM, pyatspi.ROLE_LABEL, pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_LIST_ITEM, pyatspi.ROLE_PARAGRAPH, pyatspi.ROLE_SECTION, pyatspi.ROLE_TABLE_CELL]) if not (role in doNotSpeak): if role == pyatspi.ROLE_IMAGE: link = self._script.utilities.ancestorWithRole( obj, [pyatspi.ROLE_LINK], [pyatspi.ROLE_DOCUMENT_FRAME]) if link: result.append(rolenames.getSpeechForRoleName(link)) if role == pyatspi.ROLE_HEADING: level = self._script.utilities.headingLevel(obj) if level: # Translators: the %(level)d is in reference to a heading # level in HTML (e.g., For <h3>, the level is 3) # and the %(role)s is in reference to a previously # translated rolename for the heading. # result.append(_("%(role)s level %(level)d") % { 'role': rolenames.getSpeechForRoleName(obj, role), 'level': level}) else: result.append(rolenames.getSpeechForRoleName(obj, role)) else: result.append(rolenames.getSpeechForRoleName(obj, role)) if result: result.extend(acss) if role == pyatspi.ROLE_LINK \ and obj.childCount and obj[0].getRole() == pyatspi.ROLE_IMAGE: # If this is a link with a child which is an image, we # want to indicate that. # acss = self.voice(speech_generator.HYPERLINK) result.append(rolenames.getSpeechForRoleName(obj[0])) result.extend(acss) return result
def bookmarkCurrentWhereAmI(self, inputEvent): """ Report "Where am I" information for this bookmark relative to the current pointer location.""" index = (inputEvent.hw_code, self.getURIKey()) try: path, characterOffset = self._bookmarks[index] obj = self.pathToObj(path) except KeyError: self._script.systemBeep() return [cur_obj, cur_characterOffset] = self._script.getCaretContext() # Are they the same object? if self._script.utilities.isSameObject(cur_obj, obj): # Translators: this announces that the current object is the same # object pointed to by the bookmark. # self._script.presentMessage(_('bookmark is current object')) return # Are their parents the same? elif self._script.utilities.isSameObject(cur_obj.parent, obj.parent): # Translators: this announces that the current object's parent and # the parent of the object pointed to by the bookmark are the same. # self._script.presentMessage( _('bookmark and current object have same parent')) return # Do they share a common ancestor? # bookmark's ancestors bookmark_ancestors = [] p = obj.parent while p: bookmark_ancestors.append(p) p = p.parent # look at current object's ancestors to compare to bookmark's ancestors p = cur_obj.parent while p: if bookmark_ancestors.count(p) > 0: rolename = rolenames.getSpeechForRoleName(p) # Translators: this announces that the bookmark and the current # object share a common ancestor # self._script.presentMessage(_('shared ancestor %s') % rolename) return p = p.parent # Translators: This announces that a comparison between the bookmark # and the current object can not be determined. # self._script.presentMessage(_('comparison unknown'))
def _generateAncestors(self, obj, **args): result = [] priorObj = args.get('priorObj', None) commonAncestor = self._script.utilities.commonAncestor(priorObj, obj) if obj is commonAncestor: return result # Skip items of unknown rolenames, menu bars, labels with # children, and autocompletes. (With autocompletes, we # wind up speaking the text object). Beginning with Firefox # 3.2, list items have names corresponding with their text. # This results in displayedText returning actual text # and the parent list item being spoken when it should not # be. So we'll take list items out of the context. # skipRoles = [pyatspi.ROLE_UNKNOWN, pyatspi.ROLE_MENU_BAR, pyatspi.ROLE_LABEL, pyatspi.ROLE_AUTOCOMPLETE, pyatspi.ROLE_LIST_ITEM] # Stop if we get to a document frame or an internal frame. # stopRoles = [pyatspi.ROLE_DOCUMENT_FRAME, pyatspi.ROLE_INTERNAL_FRAME] # [[[TODO - JD: Right now we're using this method to get the # full context of menu items in whereAmI. It seems to work for # gtk-demo, but here we're getting way too much context. So for # now, add in a check. Later, look for better way.]]] # if args.get('formatType', 'unfocused') == 'basicWhereAmI': stopRoles.append(pyatspi.ROLE_MENU_BAR) # There are some objects we want to include in the context, # but not add their rolenames. # dontSpeakRoles = [pyatspi.ROLE_TABLE_CELL, pyatspi.ROLE_FILLER] parent = obj.parent while parent and (parent.parent != parent): role = parent.getRole() if self._script.utilities.isSameObject(parent, commonAncestor) \ or role in stopRoles: break if role in skipRoles or self._script.utilities.isLayoutOnly(parent): parent = parent.parent continue # If the parent is a menu and its parent is a combo box # we'll speak the object as a combo box. # if role == pyatspi.ROLE_MENU \ and parent.parent.getRole() == pyatspi.ROLE_COMBO_BOX: parent = parent.parent continue # Also skip the parent if its accessible text is a single # EMBEDDED_OBJECT_CHARACTER: displayedText will end up # coming back to the child of an object for the text if # an object's text contains a single EOC. In addition, # beginning with Firefox 3.2, a table cell may derive its # accessible name from focusable objects it contains (e.g. # links, form fields). displayedText will return the # object's name in this case (because of the presence of # the EOC and other characters). This causes us to be # chatty. So if it's a table cell which contains an EOC, # we will also skip the parent. # parentText = self._script.utilities.queryNonEmptyText(parent) if parentText: unicodeText = parentText.getText(0, -1).decode("UTF-8") if self._script.EMBEDDED_OBJECT_CHARACTER in unicodeText \ and (len(unicodeText) == 1 \ or role == pyatspi.ROLE_TABLE_CELL): parent = parent.parent continue # Put in the text and label (if they exist). # text = self._script.utilities.displayedText(parent) label = self._script.utilities.displayedLabel(parent) newResult = [] acss = self.voice(speech_generator.DEFAULT) if text and (text != label) and len(text.strip()) \ and (not text.startswith("chrome://")): newResult.extend(acss) newResult.append(text) if label and len(label.strip()): newResult.extend(acss) newResult.append(label) # Finally add the role if it's not among the roles we don't # wish to speak. # if not _settingsManager.getSetting('onlySpeakDisplayedText'): acss = self.voice(speech_generator.SYSTEM) if not (role in dontSpeakRoles) and len(newResult): roleInfo = rolenames.getSpeechForRoleName(parent) if roleInfo: result.extend(acss) result.append(roleInfo) # If this object is an ARIA widget with STATE_REQUIRED, add # that. (Note that for the most part, the ARIA widget itself # has this state, but in the case of a group of radio buttons, # it is the group which has the state). # result.extend(self._generateRequired(parent, **args)) result.extend(newResult) # [[[TODO - JD: Right now we're using this method to get the # full context of menu items in whereAmI. It seems to work for # gtk-demo, but here we're getting way too much context. So for # now, add in a check. Later, look for better way.]]] # if args.get('formatType', 'unfocused') == 'basicWhereAmI' \ and parent.getRole() == pyatspi.ROLE_COMBO_BOX: break parent = parent.parent result.reverse() return result
def _generateRoleName(self, obj, **args): """Prevents some roles from being spoken.""" result = [] acss = self.voice(speech_generator.SYSTEM) role = args.get('role', obj.getRole()) force = args.get('force', False) # Saying "menu item" for a combo box can confuse users. Therefore, # speak the combo box role instead. Also, only do it if the menu # item is not focused (if the menu item is focused, it means we're # navigating in the combo box) # if not obj.getState().contains(pyatspi.STATE_FOCUSED): comboBox = self._script.utilities.ancestorWithRole( obj, [pyatspi.ROLE_COMBO_BOX], [pyatspi.ROLE_DOCUMENT_FRAME]) if comboBox: return self._generateRoleName(comboBox, **args) if not force: doNotSpeak = [pyatspi.ROLE_FORM, pyatspi.ROLE_LABEL, pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_PARAGRAPH, pyatspi.ROLE_SECTION, pyatspi.ROLE_UNKNOWN] else: # We never ever want to speak 'unknown' # doNotSpeak = [pyatspi.ROLE_UNKNOWN] if not force and self._script.inDocumentContent(obj): doNotSpeak.append(pyatspi.ROLE_TABLE_CELL) if not self._script.isAriaWidget(obj) \ and args.get('formatType', 'unfocused') != 'basicWhereAmI': doNotSpeak.append(pyatspi.ROLE_LIST_ITEM) doNotSpeak.append(pyatspi.ROLE_LIST) if not (role in doNotSpeak): if role == pyatspi.ROLE_IMAGE: link = self._script.utilities.ancestorWithRole( obj, [pyatspi.ROLE_LINK], [pyatspi.ROLE_DOCUMENT_FRAME]) if link: result.append(rolenames.getSpeechForRoleName(link)) if role == pyatspi.ROLE_HEADING: level = self._script.getHeadingLevel(obj) if level: # Translators: the %(level)d is in reference to a heading # level in HTML (e.g., For <h3>, the level is 3) # and the %(role)s is in reference to a previously # translated rolename for the heading. # result.append(_("%(role)s level %(level)d") % { 'role': rolenames.getSpeechForRoleName(obj, role), 'level': level}) else: result.append(rolenames.getSpeechForRoleName(obj, role)) else: result.append(rolenames.getSpeechForRoleName(obj, role)) if result: result.extend(acss) if role == pyatspi.ROLE_LINK \ and obj.childCount and obj[0].getRole() == pyatspi.ROLE_IMAGE: # If this is a link with a child which is an image, we # want to indicate that. # acss = self.voice(speech_generator.HYPERLINK) result.append(rolenames.getSpeechForRoleName(obj[0])) result.extend(acss) return result