def isPresentableTextChangedEventForLocusOfFocus(self, event): if self.isComboBoxNoise(event): msg = "SOFFICE: Event is believed to be combo box noise" debug.println(debug.LEVEL_INFO, msg, True) return False return super().isPresentableTextChangedEventForLocusOfFocus(event)
def textAttributes(self, acc, offset, get_defaults=False): """Get the text attributes run for a given offset in a given accessible Arguments: - acc: An accessible. - offset: Offset in the accessible's text for which to retrieve the attributes. - get_defaults: Get the default attributes as well as the unique ones. Default is True Returns a dictionary of attributes, a start offset where the attributes begin, and an end offset. Returns ({}, 0, 0) if the accessible does not supprt the text attribute. """ rv, start, end = script_utilities.Utilities.\ textAttributes(self, acc, offset, get_defaults) # If there are no text attributes associated with the text at a # given offset, we might get some seriously bogus offsets, in # particular, an extremely large start offset and an extremely # large, but negative end offset. As a result, any text attributes # which are present on the line after the specified offset will # not be indicated by braille.py's getAttributeMask. Therefore, # we'll set the start offset to the character being examined, # and the end offset to the next character. # start = min(start, offset) if end < 0: debug.println(debug.LEVEL_WARNING, "soffice.script.py:getTextAttributes: detected a bogus " + "end offset. Start offset: %s, end offset: %s" % (start, end)) end = offset + 1 return rv, start, end
def getKeyBindings(self): """Defines the key bindings for this script. Setup the default key bindings, then add one in for toggling whether we prefix chat room messages with the name of the chat room. Returns an instance of keybindings.KeyBindings. """ debug.println(self.debugLevel, "gaim.getKeyBindings.") keyBindings = default.Script.getKeyBindings(self) keyBindings.add( keybindings.KeyBinding( "h", 1 << settings.MODIFIER_ORCA, 1 << settings.MODIFIER_ORCA, self.inputEventHandlers["togglePrefixHandler"], ) ) # In gaim/pidgin, we are overriding the default script's bookmark # feature and keybindings to provide chat room message history. # messageKeys = ["1", "2", "3", "4", "5", "6", "7", "8", "9"] for messageKey in messageKeys: keyBindings.add( keybindings.KeyBinding( messageKey, 1 << settings.MODIFIER_ORCA, 1 << settings.MODIFIER_ORCA, self.inputEventHandlers["goToBookmark"], ) ) return keyBindings
def nodeLevel(self, obj): """ Determines the level of at which this object is at by using the object attribute 'level'. To be consistent with the default nodeLevel() this value is 0-based (Gecko return is 1-based) """ if obj is None or obj.getRole() == pyatspi.ROLE_HEADING \ or (obj.parent and obj.parent.getRole() == pyatspi.ROLE_MENU): return -1 try: state = obj.getState() except: return -1 else: if state.contains(pyatspi.STATE_DEFUNCT): # Yelp (or perhaps the work-in-progress a11y patch) # seems to be guilty of this. # #print "nodeLevel - obj is defunct", obj debug.println(debug.LEVEL_WARNING, "nodeLevel - obj is defunct") debug.printStack(debug.LEVEL_WARNING) return -1 try: attrs = obj.getAttributes() except: attrs = None if attrs is None: return -1 for attr in attrs: if attr.startswith("level:"): return int(attr[6:]) - 1 return -1
def isAnInputLine(self, obj): if not obj: return False if obj == self.locateInputLine(obj): return True parent = obj.parent try: role = parent.getRole() except: msg = "SOFFICE: Exception getting role of %s" % parent debug.println(debug.LEVEL_INFO, msg, True) return False if role in [pyatspi.ROLE_EXTENDED, pyatspi.ROLE_PANEL]: if self.spreadSheetCellName(parent): return False parent = parent.parent try: role = parent.getRole() except: msg = "SOFFICE: Exception getting role of %s" % parent debug.println(debug.LEVEL_INFO, msg, True) return False if role == pyatspi.ROLE_TEXT: return True return False
def generateContents(self, contents, **args): if not len(contents): return [] result = [] contents = self._script.utilities.filterContentsForPresentation(contents, False) msg = "WEB: Generating speech contents (length: %i)" % len(contents) debug.println(debug.LEVEL_INFO, msg, True) for i, content in enumerate(contents): obj, start, end, string = content msg = "ITEM %i: %s, start: %i, end: %i, string: '%s'" % (i, obj, start, end, string) debug.println(debug.LEVEL_INFO, msg, True) utterance = self.generateSpeech( obj, startOffset=start, endOffset=end, string=string, index=i, total=len(contents), **args ) if utterance and utterance[0]: result.append(utterance) if not result: if self._script.inSayAll(): string = "" else: string = messages.BLANK result = [string, self.voice(speech_generator.DEFAULT)] return result
def onStateChanged(self, event): """Called whenever an object's state changes. Arguments: - event: the Event """ # If we've received an "object:state-changed:showing" event for the # poorly named gtk-edit toggle button, then just return. We will have # spoken the information for this component with the previously # received "object:state-changed:focused" event. For all other events, # just let the parent class handle it. See bug #371637 for more # details. # if event.type.startswith("object:state-changed:showing"): rolesList = [pyatspi.ROLE_LABEL, \ pyatspi.ROLE_PANEL, \ pyatspi.ROLE_FILLER, \ pyatspi.ROLE_FILLER, \ pyatspi.ROLE_FILLER, \ pyatspi.ROLE_PANEL, \ pyatspi.ROLE_TOOL_BAR, \ pyatspi.ROLE_PANEL, \ pyatspi.ROLE_FRAME, \ pyatspi.ROLE_APPLICATION] if self.utilities.hasMatchingHierarchy(event.source, rolesList): debug.println(self.debugLevel, "nautilus.onStateChanged - " \ + "Location: label.") return default.Script.onStateChanged(self, event)
def _getBrailleRegionsForToggleButton(self, obj): """Get the braille for a radio button. If the button already had focus, then only the state is displayed. Arguments: - obj: the check box Returns a list where the first element is a list of Regions to display and the second element is the Region which should get focus. """ self._debugGenerator("_getBrailleRegionsForRadioButton", obj) text = "" text = self._script.appendString(text, self._script.getDisplayedLabel(obj)) text = self._script.appendString(text, self._script.getDisplayedText(obj)) # First special toggle button is the one in the toolbar and # that it has no name Application should implement an # accessible name in this component, but until this is made We # speech/braille "display more options" when the focus is in # one of these toggle buttons. # roleList = [rolenames.ROLE_TOGGLE_BUTTON, rolenames.ROLE_TOOL_BAR] if self._script.isDesiredFocusedItem(obj, roleList) and not obj.name: text += _("Display more options") # Second special case is each one of the four graphics toggle # buttons in the main window Application should implement an # accessible relationship between the button and the label, # but until this is made we append for each one the button the # label that should be associated and its state (checked or # not) # rolesList = [rolenames.ROLE_TOGGLE_BUTTON,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_PANEL,\ rolenames.ROLE_PANEL] if self._script.isDesiredFocusedItem(obj, rolesList): debug.println(debug.LEVEL_FINEST, "planner.onFocus - main window: " \ + "one of the four graphic toggle buttons.") filler = obj.parent allLabels = self._script.findByRole(filler, rolenames.ROLE_LABEL) text += allLabels[0].name text = self._script.appendString( settings.brailleRadioButtonIndicators[ obj.state.count(atspi.Accessibility.STATE_CHECKED)], text) text = self._script.appendString(text, self._getTextForRole(obj)) regions = [] componentRegion = braille.Component(obj, text) regions.append(componentRegion) return [regions, componentRegion]
def isActivatableEvent(self, event): """Returns True if the given event is one that should cause this script to become the active script. This is only a hint to the focus tracking manager and it is not guaranteed this request will be honored. Note that by the time the focus tracking manager calls this method, it thinks the script should become active. This is an opportunity for the script to say it shouldn't. """ # Let's make sure we have an active window if focus on an icon # changes. Focus can change when we don't have an an active # window when someone deletes a file from a shell and nautilus # happens to be showing the directory where that file exists. # See bug #568696. We'll be specific here so as to avoid # looking at the child states for every single event from # nautilus, which happens to be an event-happy application. # if event and event.type == "focus:" \ and event.source.getRole() == pyatspi.ROLE_ICON: shouldActivate = False for child in self.app: if child.getState().contains(pyatspi.STATE_ACTIVE): shouldActivate = True break else: shouldActivate = True if not shouldActivate: debug.println(debug.LEVEL_FINE, "%s does not want to become active" % self.name) return shouldActivate
def locusOfFocusChanged(self, event, oldFocus, newFocus): """Handles changes of focus of interest to the script.""" # Normally we don't cache the name, because we cannot count on apps and # tookits emitting name-changed events (needed by AT-SPI2 to update the # name so that we don't have stale values). However, if we don't cache # the name, we wind up with dead accessibles in (at least) the search bar # popup. For now, cache the name to get things working and clear the cache # for objects we plan to present. Mind you, clearing the cache on objects # with many descendants can cause AT-SPI2 to become non-responsive so try # to guess what NOT to clear the cache for. http://crbug.com/896706 doNotClearCacheFor = [pyatspi.ROLE_DIALOG, pyatspi.ROLE_FRAME, pyatspi.ROLE_LIST_BOX, pyatspi.ROLE_MENU, pyatspi.ROLE_REDUNDANT_OBJECT, pyatspi.ROLE_TABLE, pyatspi.ROLE_TREE, pyatspi.ROLE_TREE_TABLE, pyatspi.ROLE_UNKNOWN, pyatspi.ROLE_WINDOW] if newFocus.getRole() not in doNotClearCacheFor: msg = "CHROMIUM: CANNOT CACHE NAME HACK: Clearing cache for %s" % newFocus debug.println(debug.LEVEL_INFO, msg, True) newFocus.clearCache() if super().locusOfFocusChanged(event, oldFocus, newFocus): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.locusOfFocusChanged(self, event, oldFocus, newFocus)
def onSelectionChanged(self, event): """Callback for object:selection-changed accessibility events.""" if self.utilities.isComboBoxWithToggleDescendant(event.source): super().onSelectionChanged(event) return isFocused = event.source.getState().contains(pyatspi.STATE_FOCUSED) role = event.source.getRole() if role == pyatspi.ROLE_COMBO_BOX and not isFocused: return if not isFocused and self.utilities.isTypeahead(orca_state.locusOfFocus): msg = "GTK: locusOfFocus believed to be typeahead. Presenting change." debug.println(debug.LEVEL_INFO, msg, True) selectedChildren = self.utilities.selectedChildren(event.source) for child in selectedChildren: if not self.utilities.isLayoutOnly(child): self.presentObject(child) return if role == pyatspi.ROLE_LAYERED_PANE \ and self.utilities.selectedChildCount(event.source) > 1: return super().onSelectionChanged(event)
def validatedTopLevelObject(self, obj): # TODO - JD: We cannot just override topLevelObject() because that will # break flat review access to document content in LO using Gtk+ 3. That # bug seems to be fixed in LO v5.3.0. When that version is released, this # and hopefully other hacks can be removed. window = super().topLevelObject(obj) if not window or window.getIndexInParent() >= 0: return window msg = "SOFFICE: %s's window %s has -1 indexInParent" % (obj, window) debug.println(debug.LEVEL_INFO, msg, True) for child in self._script.app: if self.isSameObject(child, window): window = child break try: index = window.getIndexInParent() except: index = -1 msg = "SOFFICE: Returning %s (index: %i)" % (window, index) debug.println(debug.LEVEL_INFO, msg, True) return window
def onTextInserted(self, event): """Callback for object:text-changed:insert accessibility events.""" if not self.utilities.treatEventAsCommand(event): super().onTextInserted(event) return msg = "TERMINAL: Insertion is believed to be due to terminal command" debug.println(debug.LEVEL_INFO, msg, True) self.updateBraille(event.source) newString = self.utilities.insertedText(event) if len(newString) == 1: self.speakCharacter(newString) else: voice = self.speechGenerator.voice(string=newString) speech.speak(newString, voice) if self.flatReviewContext: return try: text = event.source.queryText() except: pass else: self._saveLastCursorPosition(event.source, text.caretOffset) self.utilities.updateCachedTextSelection(event.source)
def presentKeyboardEvent(self, event): if orca_state.learnModeEnabled or not event.isPrintableKey(): return super().presentKeyboardEvent(event) if event.isPressedKey(): return False self._sayAllIsInterrupted = False self.utilities.clearCachedCommandState() if event.shouldEcho == False or event.isOrcaModified(): return False # We have no reliable way of knowing a password is being entered into # a terminal -- other than the fact that the text typed isn't there. try: text = event.getObject().queryText() offset = text.caretOffset prevChar = text.getText(offset - 1, offset) char = text.getText(offset, offset + 1) except: return False string = event.event_string if string not in [prevChar, "space", char]: return False msg = "TERMINAL: Presenting keyboard event %s" % string debug.println(debug.LEVEL_INFO, msg, True) voice = self.speechGenerator.voice(string=string) speech.speakKeyEvent(event, voice) return True
def isZombie(self, obj): rv = super().isZombie(obj) if rv and self.isLink(obj) and obj.getIndexInParent() == -1: msg = 'INFO: Hacking around bug 759736 for %s' % obj debug.println(debug.LEVEL_INFO, msg, True) return False return rv
def onTextInserted(self, event): """Callback for object:text-changed:insert accessibility events.""" if super().onTextInserted(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onTextInserted(self, event)
def onExpandedChanged(self, event): """Callback for object:state-changed:expanded accessibility events.""" if super().onExpandedChanged(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onExpandedChanged(self, event)
def onActiveDescendantChanged(self, event): """Callback for object:active-descendant-changed accessibility events.""" if super().onActiveDescendantChanged(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onActiveDescendantChanged(self, event)
def onTextSelectionChanged(self, event): """Callback for object:text-selection-changed accessibility events.""" if super().onTextSelectionChanged(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onTextSelectionChanged(self, event)
def onTextSelectionChanged(self, event): """Callback for object:text-selection-changed accessibility events.""" if self.utilities.isComboBoxNoise(event): msg = "SOFFICE: Event is believed to be combo box noise" debug.println(debug.LEVEL_INFO, msg, True) return super().onTextSelectionChanged(event)
def onTextDeleted(self, event): """Callback for object:text-changed:delete accessibility events.""" if self.utilities.treatEventAsNoise(event): msg = "TERMINAL: Deletion is believed to be noise" debug.println(debug.LEVEL_INFO, msg, True) return super().onTextDeleted(event)
def deletedText(self, event): match = re.search("\n~", event.any_data) if not match: return event.any_data adjusted = event.any_data[:match.start()] msg = "TERMINAL: Adjusted deletion: '%s'" % adjusted debug.println(debug.LEVEL_INFO, msg, True) return adjusted
def setupInputEventHandlers(self): debug.println(self.debugLevel, "gnome-mud.setupInputEventHandlers.") default.Script.setupInputEventHandlers(self) self.inputEventHandlers["readPreviousMessageHandler"] = \ input_event.InputEventHandler( Script.readPreviousMessage, _("Read the latest n messages in the incoming messages text \ area."))
def onCheckedChanged(self, event): """Callback for object:state-changed:checked accessibility events.""" if super().onCheckedChanged(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onCheckedChanged(self, event)
def locusOfFocusChanged(self, event, oldFocus, newFocus): """Handles changes of focus of interest to the script.""" if super().locusOfFocusChanged(event, oldFocus, newFocus): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.locusOfFocusChanged(self, event, oldFocus, newFocus)
def onCaretMoved(self, event): """Callback for object:text-caret-moved accessibility events.""" if super().onCaretMoved(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onCaretMoved(self, event)
def onNameChanged(self, event): """Callback for object:property-change:accessible-name events.""" if super().onNameChanged(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onNameChanged(self, event)
def onWindowDeactivated(self, event): """Callback for window:deactivate accessibility events.""" if super().onWindowDeactivated(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onWindowDeactivated(self, event)
def onDocumentReload(self, event): """Callback for document:reload accessibility events.""" if super().onDocumentReload(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onDocumentReload(self, event)
def onMouseButton(self, event): """Callback for mouse:button accessibility events.""" if super().onMouseButton(event): return msg = "GECKO: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg) default.Script.onMouseButton(self, event)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if self._inSayAll: return if self._lastCommandWasStructNav: return if not event.detail1: return if self.utilities.isAnInputLine(event.source): msg = "SOFFICE: Event ignored: spam from inputLine" debug.println(debug.LEVEL_INFO, msg, True) return if event.source.childCount and self.utilities.isAnInputLine( event.source[0]): msg = "SOFFICE: Event ignored: spam from inputLine parent" debug.println(debug.LEVEL_INFO, msg, True) return role = event.source.getRole() if role in [pyatspi.ROLE_TEXT, pyatspi.ROLE_LIST]: comboBox = self.utilities.containingComboBox(event.source) if comboBox: orca.setLocusOfFocus(event, comboBox, True) return parent = event.source.parent if parent and parent.getRole() == pyatspi.ROLE_TOOL_BAR: default.Script.onFocusedChanged(self, event) return # TODO - JD: Verify this is still needed ignoreRoles = [pyatspi.ROLE_FILLER, pyatspi.ROLE_PANEL] if role in ignoreRoles: return # We will present this when the selection changes. if role == pyatspi.ROLE_MENU: return if self.utilities._flowsFromOrToSelection(event.source): return if role == pyatspi.ROLE_PARAGRAPH: obj, offset = self.pointOfReference.get("lastCursorPosition", (None, -1)) start, end, string = self.utilities.getCachedTextSelection(obj) if start != end: return keyString, mods = self.utilities.lastKeyAndModifiers() if keyString in ["Left", "Right"]: orca.setLocusOfFocus(event, event.source, False) return if self.utilities.isSpreadSheetTable( event.source) and orca_state.locusOfFocus: if self.utilities.isDead(orca_state.locusOfFocus): msg = "SOFFICE: Event believed to be post-editing focus claim. Dead locusOfFocus." debug.println(debug.LEVEL_INFO, msg, True) orca.setLocusOfFocus(event, event.source, False) return if orca_state.locusOfFocus.getRole() in [ pyatspi.ROLE_PARAGRAPH, pyatspi.ROLE_TABLE_CELL ]: msg = "SOFFICE: Event believed to be post-editing focus claim based on role." debug.println(debug.LEVEL_INFO, msg, True) orca.setLocusOfFocus(event, event.source, False) return default.Script.onFocusedChanged(self, event)
def onStateChanged(self, event): """Called whenever an object's state changes. Arguments: - event: the Event """ debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # self.printAncestry(event.source) rolesList = [rolenames.ROLE_PUSH_BUTTON, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FRAME, \ rolenames.ROLE_APPLICATION] visible = event.source.state.count( \ atspi.Accessibility.STATE_VISIBLE) # Check to see if we have just had an "object:state-changed:showing" # event for the Stop button. If the name is "Stop", and one of its # states is VISIBLE, that means we have started a search. As the # search progresses, regularly inform the user of this by speaking # "Searching" (assuming the search tool has focus). # # Translators: the "Stop" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. # if self.isDesiredFocusedItem(event.source, rolesList) and \ event.source.name == _("Stop") and visible: debug.println(self.debugLevel, "gnome-search-tool.onNameChanged - " \ + "search started.") self.searching = True # If we don't already have a handle to the table containing the # list of files found, then get it now. # if not self.fileTable: frame = self.getTopLevel(event.source) allTables = self.findByRole(frame, rolenames.ROLE_TABLE) self.fileTable = allTables[0] gobject.idle_add(self._speakSearching) # Check to see if we have just had an "object:state-changed:showing" # event for the Find button. If the name is "Find", and one of its # states is VISIBLE and we are currently searching, that means we # have just stopped a search. Inform the user that the search is # complete and tell them how many files were found. # # Translators: the "Find" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. # if self.isDesiredFocusedItem(event.source, rolesList) and \ event.source.name == _("Find") and visible and self.searching: debug.println(self.debugLevel, "gnome-search-tool.onNameChanged - " \ + "search completed.") self.searching = False speech.speak(_("Search complete.")) sensitive = self.fileTable.state.count( \ atspi.Accessibility.STATE_SENSITIVE) if sensitive: fileCount = self.fileTable.table.nRows noFilesString = ngettext("%d file found", "%d files found", fileCount) % fileCount speech.speak(noFilesString) else: speech.speak(_("No files found.")) # Pass the event onto the parent class to be handled in the default way. # default.Script.onStateChanged(self, event)
def checkKeyboardEventData(self, keyboardEvent): """Processes the given keyboard event. Here is used to: * Fill event_string using the key.id * Set the is_text properly Arguments: - keyboardEvent: an instance of input_event.KeyboardEvent """ # On the AtkKeyEventStruct documentation you can find this # description: # guint keyval; # A guint representing a keysym value corresponding to those # used by GDK # # There are no Clutter way to get a gdk-like keyvalname. # Anyway, cally will fill event_string with the final # representation of a text char. # # In the same way, Clutter provides the keyval without the # modifiers, and GDK yes. We will try to apply it, at least # to compute keyval_name # # More information: # http://library.gnome.org/devel/atk/stable/AtkUtil.html # http://bugzilla.o-hand.com/show_bug.cgi?id=2072 # apply the modifiers to keyboardEvent.id # keyval = keyboardEvent.id try: keymap = Gdk.Keymap.get_default() if keymap: success, entries = keymap.get_entries_for_keyval(keyval) group = entries[0].group modifiers = Gdk.ModifierType(keyboardEvent.modifiers) success, keyval, egroup, level, consumed = \ keymap.translate_keyboard_state (keyboardEvent.hw_code, modifiers, group) except: debug.println(debug.LEVEL_FINE, "Could not compute keyval with modifiers") string = "prev keyval=%d" % keyboardEvent.id string = string + " post keyval=%d" % keyval debug.println(debug.LEVEL_FINE, string) keyboardEvent.id = keyval # if cally doesn't provide a event_string we get that using # Gdk. I know that it will probably called again computing # keyval_name but to simplify code, and not start to add # guess-code here I will maintain that in this way # if (keyboardEvent.event_string == ""): debug.println(debug.LEVEL_FINE, "Computing event_string") try: keyboardEvent.event_string = Gdk.keyval_name(keyboardEvent.id) except: debug.println(debug.LEVEL_FINE, "Could not obtain keyval_name for id: %d" \ % keyboardEvent.id) # at-spi uses event_string to compute is_text, so if it is # NULL we should compute again with the proper # event_string # keyboardEvent.is_text = _computeIsText(keyboardEvent.event_string) return default.Script.checkKeyboardEventData(self, keyboardEvent)
def _getVoiceSettings(self, profile, app=None): voiceSettings = {} if app is not None and app != '': appSpecific = True else: appSpecific = False for voice in ['default', 'uppercase', 'hyperlink', 'system']: if appSpecific == True: voiceGSettings = Settings( schema_id='org.gnome.orca.voice', path='/org/gnome/orca/profile/%s/app/%s/voice/%s/' % (profile, app, voice)) voiceGSettingsFamily = Settings( schema_id='org.gnome.orca.voice.family', path='/org/gnome/orca/profile/%s/app/%s/voice/%s/' % (profile, app, voice)) else: voiceGSettings = Settings( schema_id='org.gnome.orca.voice', path='/org/gnome/orca/profile/%s/voice/%s/' % (profile, voice)) voiceGSettingsFamily = Settings( schema_id='org.gnome.orca.voice.family', path='/org/gnome/orca/profile/%s/voice/%s/' % (profile, voice)) # Used to quickly determine whether a voice's settings have been # set and are different from the defaults voiceEstablished = voiceGSettings.get_boolean('established') voiceSetting = {} voiceSettingFamily = {} if appSpecific == False and self.voiceDefaults.__contains__(voice): voiceSetting = self.voiceDefaults[voice].copy() if voiceEstablished == True: if appSpecific == False and voiceSetting.__contains__( 'established'): voiceSetting.pop('established') for setting in ['average-pitch', 'gain', 'rate']: if voiceGSettings.get_user_value(setting) is not None: gSettingsVal = voiceGSettings.get_double(setting) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting voice setting for voice %s with name %s = %s' % (voice, setting, gSettingsVal)) voiceSetting[setting] = gSettingsVal if voiceGSettingsFamily.get_boolean('family-set') == True: for setting in ['name', 'locale', 'dialect']: gSettingsVal = voiceGSettingsFamily.get_string(setting) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting voice family setting for voice %s with name %s = %s' % (voice, setting, gSettingsVal)) voiceSettingFamily[setting] = gSettingsVal voiceSetting['family'] = voiceSettingFamily # The JSON backend uses acss the same way, not sure why, so will # just duplicate here to be compatible. if voiceSetting != {}: if appSpecific == True: voiceSettings[voice] = voiceSetting else: voiceSettings[voice] = acss.ACSS(voiceSetting) return voiceSettings
def insertedText(self, event): if len(event.any_data) == 1: return event.any_data if self.isAutoTextEvent(event): return event.any_data if self.isClipboardTextChangedEvent(event): return event.any_data try: text = event.source.queryText() except: msg = "ERROR: Exception querying text for %s" % event.source debug.println(debug.LEVEL_INFO, msg, True) return event.any_data start, end = event.detail1, event.detail1 + len(event.any_data) boundary = pyatspi.TEXT_BOUNDARY_LINE_START firstLine = text.getTextAtOffset(start, boundary) msg = "TERMINAL: First line of insertion: '%s' (%i, %i)" % firstLine debug.println(debug.LEVEL_INFO, msg, True) lastLine = text.getTextAtOffset(end - 1, boundary) msg = "TERMINAL: Last line of insertion: '%s' (%i, %i)" % lastLine debug.println(debug.LEVEL_INFO, msg, True) if firstLine == lastLine: msg = "TERMINAL: Not adjusting single-line insertion." debug.println(debug.LEVEL_INFO, msg, True) return event.any_data currentLine = text.getTextAtOffset(text.caretOffset, boundary) msg = "TERMINAL: Current line: '%s' (%i, %i)" % currentLine debug.println(debug.LEVEL_INFO, msg, True) if firstLine != ("", 0, 0): start = firstLine[1] if currentLine not in (("", 0, 0), firstLine, lastLine): lastLine = currentLine if lastLine != ("", 0, 0): end = lastLine[2] if lastLine[0].endswith("\n"): end -= 1 adjusted = text.getText(start, end) if adjusted: msg = "TERMINAL: Adjusted insertion: '%s'" % adjusted debug.println(debug.LEVEL_INFO, msg, True) else: msg = "TERMINAL: Adjustment failed. Returning any_data." debug.println(debug.LEVEL_INFO, msg, True) adjusted = event.any_data return adjusted
def _getGeneralSettings(self, profile, app=None): generalSettings = {} if app is not None and app != '': generalGSettings = Settings( schema_id='org.gnome.orca.general', path='/org/gnome/orca/profile/%s/app/%s/' % (profile, app)) appSpecificGSettings = Settings( schema_id='org.gnome.orca.general.app', path='/org/gnome/orca/profile/%s/app/%s/' % (profile, app)) speechGeneralGSettings = Settings( schema_id='org.gnome.orca.general.speech', path='/org/gnome/orca/profile/%s/app/%s/' % (profile, app)) brailleGeneralGSettings = Settings( schema_id='org.gnome.orca.general.braille', path='/org/gnome/orca/profile/%s/app/%s/' % (profile, app)) soundGeneralGSettings = Settings( schema_id='org.gnome.orca.general.sound', path='/org/gnome/orca/profile/%s/app/%s/' % (profile, app)) appSpecific = True else: generalGSettings = Settings(schema_id='org.gnome.orca.general', path='/org/gnome/orca/profile/%s/' % profile) speechGeneralGSettings = Settings( schema_id='org.gnome.orca.general.speech', path='/org/gnome/orca/profile/%s/' % profile) brailleGeneralGSettings = Settings( schema_id='org.gnome.orca.general.braille', path='/org/gnome/orca/profile/%s/' % profile) soundGeneralGSettings = Settings( schema_id='org.gnome.orca.general.sound', path='/org/gnome/orca/profile/%s/' % profile) appSpecific = False for setting in orcaToGSettingsMapGeneral.keys(): gSetting = orcaToGSettingsMapGeneral.get(setting) gSettingName = gSetting[0] gSettingType = gSetting[1] # GSettings will always return a value, even if the user has not # Set one, but if a setting is not set for an app, we don't want # to set anything, so the global setting is used, which may be # different from the default. if appSpecific == True: if generalGSettings.get_user_value(gSettingName) is not None: gSettingsVal = self._getGSetting(generalGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal else: gSettingsVal = self._getGSetting(generalGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal for setting in orcaToGSettingsMapGeneralSpeech.keys(): gSetting = orcaToGSettingsMapGeneralSpeech.get(setting) gSettingName = gSetting[0] gSettingType = gSetting[1] # GSettings will always return a value, even if the user has not # Set one, but if a setting is not set for an app, we don't want # to set anything, so the global setting is used, which may be # different from the default. if appSpecific == True: if speechGeneralGSettings.get_user_value( gSettingName) is not None: gSettingsVal = self._getGSetting(speechGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal else: gSettingsVal = self._getGSetting(speechGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal for setting in orcaToGSettingsMapGeneralSound.keys(): gSetting = orcaToGSettingsMapGeneralSound.get(setting) gSettingName = gSetting[0] gSettingType = gSetting[1] # GSettings will always return a value, even if the user has not # Set one, but if a setting is not set for an app, we don't want # to set anything, so the global setting is used, which may be # different from the default. if appSpecific == True: if soundGeneralGSettings.get_user_value( gSettingName) is not None: gSettingsVal = self._getGSetting(soundGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal else: gSettingsVal = self._getGSetting(soundGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal for setting in orcaToGSettingsMapGeneralBraille.keys(): gSetting = orcaToGSettingsMapGeneralBraille.get(setting) gSettingName = gSetting[0] gSettingType = gSetting[1] # GSettings will always return a value, even if the user has not # Set one, but if a setting is not set for an app, we don't want # to set anything, so the global setting is used, which may be # different from the default. if appSpecific == True: if brailleGeneralGSettings.get_user_value( gSettingName) is not None: gSettingsVal = self._getGSetting(brailleGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal else: gSettingsVal = self._getGSetting(brailleGeneralGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal if appSpecific == True: for setting in orcaToGSettingsMapGeneralApp.keys(): gSetting = orcaToGSettingsMapGeneralApp.get(setting) gSettingName = gSetting[0] gSettingType = gSetting[1] if appSpecificGSettings.get_user_value( gSettingName) is not None: gSettingsVal = self._getGSetting(appSpecificGSettings, gSettingName, gSettingType) debug.println( debug.LEVEL_FINEST, 'INFO: GSettings backend: Getting %s of type %s = %s' % (gSettingName, gSettingType, gSettingsVal)) generalSettings[setting] = gSettingsVal return generalSettings
def onFocus(self, event): """Called whenever an object gets focus. Overridden in this script because we sometimes get a focus event in addition to caret-moved events when we change from one area in the document to another. We want to minimize the repetition of text along with the unnecessary speaking of object types (e.g. drawing area, text, etc.). Arguments: - event: the Event """ self.currentInputEvent = None # We sometimes get focus events for items that don't -- # or don't yet) have focus. Ignore these. # if (event.source.role == rolenames.ROLE_CHECK_BOX or \ event.source.role == rolenames.ROLE_PUSH_BUTTON or \ event.source.role == rolenames.ROLE_RADIO_BUTTON) and \ not event.source.state.count(atspi.Accessibility.STATE_FOCUSED): return if not event.source.state.count(atspi.Accessibility.STATE_SHOWING): return if not self.findToolbarActive and \ event.source.role == rolenames.ROLE_TEXT: if event.source.parent and \ (event.source.parent.role == rolenames.ROLE_DRAWING_AREA or \ event.source.parent.role == rolenames.ROLE_UNKNOWN): # We're going to get at least one (and likely several) # caret-moved events which will cause this to get spoken, # so skip it for now. # return if event.source.role == rolenames.ROLE_DRAWING_AREA: # A drawing area can claim focus when visually what has focus is # a text object that is a child of the drawing area. When this # occurs, Orca doesn't see the text. Therefore, try to figure out # where we are based on where we were and what key we pressed. # Then set the event.source accordingly before handing things off # to the default script. # debug.println(self.debugLevel, "acroread: Drawing area bug") lastKey = None try: lastKey = orca_state.lastNonModifierKeyEvent.event_string except: pass LOFIndex = orca_state.locusOfFocus.index childIndex = None # [[[TODO: JD - These aren't all of the possibilities. This is # very much a work in progress and of testing.]]] # if lastKey == "Up": childIndex = LOFIndex - 1 elif lastKey == "Down": childIndex = LOFIndex + 1 elif lastKey == "Right" or lastKey == "End": childIndex = LOFIndex elif lastKey == "Left" or lastKey == "Home": childIndex = LOFIndex if (childIndex >= 0): child = event.source.child(childIndex) event.source = child default.Script.onFocus(self, event)