def panBrailleRight(self, inputEvent=None, panAmount=0): """In document content, we want to use the panning keys to browse the entire document. """ if self.flatReviewContext \ or not self.isBrailleEndShowing() \ or self.utilities.isSpreadSheetCell(orca_state.locusOfFocus) \ or not self.utilities.isTextArea(orca_state.locusOfFocus): return default.Script.panBrailleRight(self, inputEvent, panAmount) text = orca_state.locusOfFocus.queryText() string, startOffset, endOffset = text.getTextAtOffset( text.caretOffset, pyatspi.TEXT_BOUNDARY_LINE_START) if endOffset < text.characterCount: text.setCaretOffset(endOffset) return True obj = self.utilities.findNextObject(orca_state.locusOfFocus) try: text = obj.queryText() except: pass else: orca.setLocusOfFocus(None, obj, notifyScript=False) text.setCaretOffset(0) return True return default.Script.panBrailleRight(self, inputEvent, panAmount)
def onChildrenChanged(self, event): """Callback for object:children-changed accessibility events.""" if self.utilities.isSpreadSheetCell(event.any_data): orca.setLocusOfFocus(event, event.any_data) return if self.utilities.isLastCell(event.any_data): activeRow = self.pointOfReference.get('lastRow', -1) activeCol = self.pointOfReference.get('lastColumn', -1) if activeRow < 0 or activeCol < 0: return if self.utilities.isDead(orca_state.locusOfFocus): orca.setLocusOfFocus(event, event.source, False) self.utilities.handleUndoTextEvent(event) rowCount, colCount = self.utilities.rowAndColumnCount(event.source) if activeRow == rowCount: full = messages.TABLE_ROW_DELETED_FROM_END brief = messages.TABLE_ROW_DELETED else: full = messages.TABLE_ROW_INSERTED_AT_END brief = messages.TABLE_ROW_INSERTED self.presentMessage(full, brief) return default.Script.onChildrenChanged(self, event)
def __sayAllProgressCallback(self, context, progressType): if progressType == speechserver.SayAllContext.PROGRESS: return obj = context.obj orca.setLocusOfFocus(None, obj, notifyScript=False) offset = context.currentOffset text = obj.queryText() if progressType == speechserver.SayAllContext.INTERRUPTED: text.setCaretOffset(offset) return # SayAllContext.COMPLETED doesn't necessarily mean done with SayAll; # just done with the current object. If we're still in SayAll, we do # not want to set the caret (and hence set focus) in a link we just # passed by. try: hypertext = obj.queryHypertext() except NotImplementedError: pass else: linkCount = hypertext.getNLinks() links = [hypertext.getLink(x) for x in range(linkCount)] if filter(lambda l: l.startIndex <= offset <= l.endIndex, links): return text.setCaretOffset(offset)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return self._lastAutoComplete = "" obj = event.source if not self.inDocumentContent(obj): default.Script.onFocusedChanged(self, event) return if self.isEditableMessage(obj): self.textArea = obj default.Script.onFocusedChanged(self, event) return role = obj.getRole() if role != pyatspi.ROLE_DOCUMENT_FRAME: Gecko.Script.onFocusedChanged(self, event) return contextObj, contextOffset = self.getCaretContext() if contextObj: return orca.setLocusOfFocus(event, obj, notifyScript=False)
def onCaretMoved(self, event): """Called whenever the caret moves. Arguments: - event: the Event """ if self._inSayAll: return self._lastCaretContext = event.source, event.detail1 lastKey, mods = self.utilities.lastKeyAndModifiers() if lastKey in ['Tab', 'ISO_Left_Tab']: return if lastKey == 'Down' \ and orca_state.locusOfFocus == event.source.parent \ and event.source.getIndexInParent() == 0 \ and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_LINK: self.updateBraille(event.source) return orca.setLocusOfFocus(event, event.source, False) default.Script.onCaretMoved(self, event)
def onFocus(self, event): """Callback for focus: accessibility events.""" # NOTE: This event type is deprecated and Orca should no longer use it. # This callback remains just to handle bugs in applications and toolkits # that fail to reliably emit object:state-changed:focused events. if self.utilities.isLayoutOnly(event.source): return if self.utilities.isTypeahead(orca_state.locusOfFocus) \ and "Table" in pyatspi.listInterfaces(event.source) \ and not event.source.getState().contains(pyatspi.STATE_FOCUSED): return ancestor = pyatspi.findAncestor(orca_state.locusOfFocus, lambda x: x == event.source) if not ancestor: orca.setLocusOfFocus(event, event.source) return if ancestor and "Table" in pyatspi.listInterfaces(ancestor): return isMenu = lambda x: x and x.getRole() == pyatspi.ROLE_MENU if isMenu(ancestor) and not pyatspi.findAncestor(ancestor, isMenu): return orca.setLocusOfFocus(event, event.source)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return obj = event.source role = obj.getRole() # Accessibility support for menus in Java is badly broken: Missing # events, missing states, bogus events from other objects, etc. # Therefore if we get an event, however broken, for menus or their # their items that suggests they are selected, we'll just cross our # fingers and hope that's true. menuRoles = [pyatspi.ROLE_MENU, pyatspi.ROLE_MENU_BAR, pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_CHECK_MENU_ITEM, pyatspi.ROLE_RADIO_MENU_ITEM, pyatspi.ROLE_POPUP_MENU] if role in menuRoles or obj.parent.getRole() in menuRoles: orca.setLocusOfFocus(event, obj) return try: focusRole = orca_state.locusOfFocus.getRole() except: focusRole = None if focusRole in menuRoles and role == pyatspi.ROLE_ROOT_PANE: return default.Script.onFocusedChanged(self, event)
def onSelectedChanged(self, event): """Callback for object:state-changed:selected accessibility events.""" try: state = event.source.getState() role = event.source.getRole() except: return # Some buttons, like the Wikipedia button, claim to be selected but # lack STATE_SELECTED. The other buttons, such as in the Dash and # event switcher, seem to have the right state. Since the ones with # the wrong state seem to be things we don't want to present anyway # we'll stop doing so and hope we are right. if event.detail1: if role == pyatspi.ROLE_PANEL: try: event.source.clearCache() except: pass if state.contains(pyatspi.STATE_SELECTED): orca.setLocusOfFocus(event, event.source) return clutter.Script.onSelectedChanged(self, event)
def onChildrenChanged(self, event): """Callback for object:children-changed accessibility events.""" if self.utilities.isSpreadSheetCell(event.any_data): orca.setLocusOfFocus(event, event.any_data) return if self.utilities.isLastCell(event.any_data): activeRow = self.pointOfReference.get('lastRow', -1) activeCol = self.pointOfReference.get('lastColumn', -1) if activeRow < 0 or activeCol < 0: return self.utilities.handleUndoTextEvent(event) rowCount, colCount = self.utilities.rowAndColumnCount(event.source) if activeRow == rowCount: full = messages.TABLE_ROW_DELETED_FROM_END brief = messages.TABLE_ROW_DELETED else: full = messages.TABLE_ROW_INSERTED_AT_END brief = messages.TABLE_ROW_INSERTED self.presentMessage(full, brief) return default.Script.onChildrenChanged(self, event)
def onSelectionChanged(self, event): """Called when an object's selection changes. Arguments: - event: the Event """ # Avoid doing this with objects that manage their descendants # because they'll issue a descendant changed event. (Note: This # equality check is intentional; utilities.isSameObject() is # especially thorough with trees and tables, which is not # performant. # if event.source == self.lastDescendantChangedSource: return # We treat selected children as the locus of focus. When the # selection changes in a list we want to update the locus of # focus. If there is no selection, we default the locus of # focus to the containing object. # if (event.source.getRole() in [pyatspi.ROLE_LIST, pyatspi.ROLE_PAGE_TAB_LIST, pyatspi.ROLE_TREE]) \ and event.source.getState().contains(pyatspi.STATE_FOCUSED): newFocus = event.source if event.source.childCount: selection = event.source.querySelection() if selection.nSelectedChildren > 0: newFocus = selection.getSelectedChild(0) orca.setLocusOfFocus(event, newFocus) else: default.Script.onSelectionChanged(self, event)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" if not self.utilities.canBeActiveWindow(event.source): return # If this is a frame for a popup menu, we don't want to treat # it like a proper window:activate event because it's not as # far as the end-user experience is concerned. activeItem = self.utilities.popupMenuForFrame(event.source) if activeItem: selected = self.utilities.selectedChildren(activeItem) if len(selected) == 1: activeItem = selected[0] msg = "CHROMIUM: Setting locusOfFocus to %s" % activeItem orca_state.activeWindow = event.source orca.setLocusOfFocus(event, activeItem) debug.println(debug.LEVEL_INFO, msg, True) return if super().onWindowActivated(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onWindowActivated(self, event) # Right now we don't get accessibility events for alerts which are # already showing at the time of window activation. If that changes, # we should store presented alerts so we don't double-present them. for child in event.source: if child.getRole() == pyatspi.ROLE_ALERT: self.presentObject(child)
def onNameChanged(self, event): """Callback for object:property-change:accessible-name events.""" if not self.spellcheck.isActive(): gtk.Script.onNameChanged(self, event) return name = event.source.name if name == self.spellcheck.getMisspelledWord(): self.spellcheck.presentErrorDetails() return parent = event.source.parent if parent != self.spellcheck.getSuggestionsList() \ or not parent.getState().contains(pyatspi.STATE_FOCUSED): return entry = self.spellcheck.getChangeToEntry() if name != self.utilities.displayedText(entry): return # If we're here, the locusOfFocus was in the selection list when # that list got destroyed and repopulated. Focus is still there. orca.setLocusOfFocus(event, event.source, False) self.updateBraille(orca_state.locusOfFocus)
def onFocus(self, event): """Called whenever an object gets focus. Arguments: - event: the Event """ # This seems to be the most reliable way to identify that the # active chatroom was changed via keyboard from within the entry. # In this case, speak and flash braille the new room name. # if orca_state.locusOfFocus and event.source \ and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_ENTRY \ and event.source.getRole() == pyatspi.ROLE_ENTRY \ and orca_state.locusOfFocus != event.source: room1 = self.chat.getChatRoomName(orca_state.locusOfFocus) room2 = self.chat.getChatRoomName(event.source) if room1 != room2: speech.speak(room2) flashTime = _settingsManager.getSetting('brailleFlashTime') self.displayBrailleMessage(room2, flashTime) orca.setLocusOfFocus(event, event.source) return if self.inDocumentContent(event.source): Gecko.Script.onFocus(self, event) else: default.Script.onFocus(self, event)
def onSelectedChanged(self, event): """Callback for object:state-changed:selected accessibility events.""" if event.source.getRole() == pyatspi.ROLE_PAGE_TAB and event.detail1: oldName = event.source.name event.source.clearCache() newName = event.source.name if oldName != newName: msg = "CHROMIUM: NO NAME CHANGE HACK: (name should be: '%s')" % newName debug.println(debug.LEVEL_INFO, msg, True) # Other apps and toolkits implement the selection interface, which is # what we use to present active-descendanty selection changes, leaving # state-changed:selected for notifications related to toggling the # selected state of the currently-focused item (e.g. pressing ctrl+space # in a file explorer). While handling active-descendanty changes here is # not technically a HACK, once Chromium implements the selection interface, # we should remove this code and defer to Orca's default handling. if event.detail1 and not self.utilities.isLayoutOnly(event.source) \ and not "Selection" in pyatspi.listInterfaces(event.source.parent) \ and self.utilities.canBeActiveWindow(self.utilities.topLevelObject(event.source)): msg = "CHROMIUM: NO SELECTION IFACE HACK: Setting %s to locusOfFocus" % event.source debug.println(debug.LEVEL_INFO, msg, True) orca.setLocusOfFocus(event, event.source) return if super().onSelectedChanged(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onSelectedChanged(self, event)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return self._lastAutoComplete = "" self.pointOfReference['lastAutoComplete'] = None obj = event.source if self.spellcheck.isAutoFocusEvent(event): orca.setLocusOfFocus(event, event.source, False) self.updateBraille(orca_state.locusOfFocus) if self.spellcheck.isSuggestionsItem(event.source) \ and self.spellcheck.isSuggestionsItem(orca_state.locusOfFocus): orca.setLocusOfFocus(event, event.source, False) self.updateBraille(orca_state.locusOfFocus) self.spellcheck.presentSuggestionListItem() return if not self.utilities.inDocumentContent(obj): default.Script.onFocusedChanged(self, event) return if self.isEditableMessage(obj): default.Script.onFocusedChanged(self, event) return Gecko.Script.onFocusedChanged(self, event)
def onCaretMoved(self, event): """Called whenever the caret moves. Arguments: - event: the Event """ if self.isStructuralNavigationCommand(): return if event.detail1 == -1: return if self.utilities.isCellBeingEdited(event.source): orca.setLocusOfFocus(event, event.source.parent) # The lists and combo boxes in the Formatting toolbar emit # object:active-descendant-changed events which cause us # to set the locusOfFocus to the list item. If the user then # arrows within the text portion, we will not present it due # to the event not being from the locusOfFocus. A similar # issue is present in the Target entry of the Hyperlink dialog # for OOo 3.2. # if event.source.getRole() == pyatspi.ROLE_TEXT \ and self.utilities.ancestorWithRole( event.source, [pyatspi.ROLE_TOOL_BAR, pyatspi.ROLE_DIALOG], [pyatspi.ROLE_FRAME]): orca.setLocusOfFocus(event, event.source, False) default.Script.onCaretMoved(self, event)
def onActiveDescendantChanged(self, event): """Called when an object who manages its own descendants detects a change in one of its children. Overridden here because the table on the left-hand side lacks STATE_FOCUSED which causes the default script to reject this event. Arguments: - event: the Event """ child = event.any_data if child: orca.setLocusOfFocus(event, child) else: orca.setLocusOfFocus(event, event.source) # We'll tuck away the activeDescendant information for future # reference since the AT-SPI gives us little help in finding # this. # if orca_state.locusOfFocus \ and (orca_state.locusOfFocus != event.source): self.pointOfReference['activeDescendantInfo'] = \ [orca_state.locusOfFocus.parent, orca_state.locusOfFocus.getIndexInParent()]
def onFocus(self, event): """Callback for focus: accessibility events.""" # NOTE: This event type is deprecated and Orca should no longer use it. # This callback remains just to handle bugs in applications and toolkits # that fail to reliably emit object:state-changed:focused events. if self.utilities.eventIsCanvasNoise(event): return if self.utilities.isLayoutOnly(event.source): return if self.utilities.isTypeahead(orca_state.locusOfFocus) \ and "Table" in pyatspi.listInterfaces(event.source) \ and not event.source.getState().contains(pyatspi.STATE_FOCUSED): return ancestor = pyatspi.findAncestor(orca_state.locusOfFocus, lambda x: x == event.source) if not ancestor: orca.setLocusOfFocus(event, event.source) return if ancestor and "Table" in pyatspi.listInterfaces(ancestor): return isMenu = lambda x: x and x.getRole() == pyatspi.ROLE_MENU if isMenu(ancestor) and not pyatspi.findAncestor(ancestor, isMenu): return orca.setLocusOfFocus(event, event.source)
def onFocus(self, event): """Called whenever an object gets focus. Arguments: - event: the Event """ obj = event.source role = obj.getRole() if role == pyatspi.ROLE_LIST_ITEM and obj.childCount: return textRoles = [pyatspi.ROLE_HEADING, pyatspi.ROLE_PANEL, pyatspi.ROLE_PARAGRAPH, pyatspi.ROLE_SECTION] if role in textRoles: return if role == pyatspi.ROLE_LINK and obj.childCount: try: text = obj.queryText() except NotImplementedError: orca.setLocusOfFocus(event, obj[0]) default.Script.onFocus(self, event)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" if not self.utilities.canBeActiveWindow(event.source): return # If this is a frame for a popup menu, we don't want to treat # it like a proper window:activate event because it's not as # far as the end-user experience is concerned. activeItem = self.utilities.popupMenuForFrame(event.source) if activeItem: selected = self.utilities.selectedChildren(activeItem) if len(selected) == 1: activeItem = selected[0] msg = "CHROMIUM: Setting locusOfFocus to %s" % activeItem orca_state.activeWindow = event.source orca.setLocusOfFocus(event, activeItem) debug.println(debug.LEVEL_INFO, msg, True) return if super().onWindowActivated(event): return msg = "CHROMIUM: Passing along event to default script" debug.println(debug.LEVEL_INFO, msg, True) default.Script.onWindowActivated(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 default.Script.onFocusedChanged(self, event)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" gtk.Script.onWindowActivated(self, event) obj, offset = self.utilities.getCaretContext() if obj: orca.setLocusOfFocus(None, obj)
def onCaretMoved(self, event): """Callback for object:text-caret-moved accessibility events.""" obj = event.source if obj.getState().contains(pyatspi.STATE_FOCUSED): orca.setLocusOfFocus(event, event.source, False) gtk.Script.onCaretMoved(self, event)
def onCaretMoved(self, event): """Called whenever the caret moves. Arguments: - event: the Event """ # Much of the Gecko code is designed to handle Gecko's broken # caret navigation. This is not needed in -- and can sometimes # interfere with our presentation of -- a simple message being # composed by the user. Surely we can count on Thunderbird to # handle navigation in that case. # if self.isEditableMessage(event.source) \ or self.isNonHTMLEntry(event.source): self.setCaretContext(event.source, event.detail1) return default.Script.onCaretMoved(self, event) # Page_Up/Page_Down are not used by Orca. However, users report # using these keys in Thunderbird without success. The default # script is sometimes rejecting the resulting caret-moved events # based on the locusOfFocus other times Gecko is because of the # caret context. # lastKey, mods = self.utilities.lastKeyAndModifiers() updatePosition = lastKey in ["Page_Up", "Page_Down"] # Unlike the unpredictable wild, wild web, odds are good that a # caret-moved event in a message composition window is valid. But # depending upon the locusOfFocus at the time this event is issued # the default Gecko toolkit script might not do the right thing. # if not updatePosition and event.detail1 >= 0: updatePosition = \ event.source.getState().contains(pyatspi.STATE_EDITABLE) if updatePosition: orca.setLocusOfFocus(event, event.source, notifyScript=False) self.setCaretContext(event.source, event.detail1) # The Gecko script, should it be about to pass along this # event to the default script, will set the locusOfFocus to # the object returned by findFirstCaretContext(). If that # object is not the same as the event source or the event # source's parent, the default script will reject the event. # As a result, if the user presses Page_Up or Page_Down and # just so happens to land on an object whose sole contents # is an image, we'll say nothing. Ultimately this should # probably be handled elsewhere, but this close to the next # major (2.24) release, I (JD) am not risking it. :-) # [obj, offset] = \ self.findFirstCaretContext(event.source, event.detail1) if obj.getRole() == pyatspi.ROLE_IMAGE: return default.Script.onCaretMoved(self, event) return Gecko.Script.onCaretMoved(self, event)
def locusOfFocusChanged(self, event, oldFocus, newFocus): """Handles changes of focus of interest to the script.""" if self.utilities.isToggleDescendantOfComboBox(newFocus): isComboBox = lambda x: x and x.getRole() == pyatspi.ROLE_COMBO_BOX newFocus = pyatspi.findAncestor(newFocus, isComboBox) or newFocus orca.setLocusOfFocus(event, newFocus, False) super().locusOfFocusChanged(event, oldFocus, newFocus)
def onSelectionChanged(self, event): """Callback for object:selection-changed accessibility events.""" if not self.utilities.isComboBoxSelectionChange(event): super().onSelectionChanged(event) return selectedChildren = self.utilities.selectedChildren(event.source) if len(selectedChildren) == 1: orca.setLocusOfFocus(event, selectedChildren[0], True)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" Gecko.Script.onWindowActivated(self, event) if not self.spellcheck.isCheckWindow(event.source): return self.spellcheck.presentErrorDetails() orca.setLocusOfFocus(None, self.spellcheck.getChangeToEntry(), False) self.updateBraille(orca_state.locusOfFocus)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" gtk.Script.onWindowActivated(self, event) if not self.spellcheck.isCheckWindow(event.source): return self.spellcheck.presentErrorDetails() orca.setLocusOfFocus(None, self.spellcheck.getChangeToEntry(), False) self.updateBraille(orca_state.locusOfFocus)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if self._inSayAll: return if self.isStructuralNavigationCommand(): 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 parent = event.source.parent if parent and parent.getRole() == pyatspi.ROLE_TOOL_BAR: default.Script.onFocusedChanged(self, event) return role = event.source.getRole() 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 # We should present this in response to active-descendant-changed events if event.source.getState().contains(pyatspi.STATE_MANAGES_DESCENDANTS): if role != pyatspi.ROLE_LIST: return default.Script.onFocusedChanged(self, event)
def onWindowActivated(self, event): """Callback for window:activate accessibility events.""" super().onWindowActivated(event) if not self.spellcheck.isCheckWindow(event.source): return if event.source[0].getRole() == pyatspi.ROLE_DIALOG: orca.setLocusOfFocus(event, event.source[0], False) self.spellcheck.presentErrorDetails()
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return # HACK: Although we get object:state-changed:focused events, the # object emitting them might not claim state focusable or state # focused. For now, assume that we won't get bogus focus claims. orca.setLocusOfFocus(event, event.source) return
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if self._inSayAll: return if self.isStructuralNavigationCommand(): return if not event.detail1: return if event.source.getRoleName() == 'text frame': return parent = event.source.parent if parent and parent.getRoleName() == 'text frame': return if parent and parent.getRole() == pyatspi.ROLE_TOOL_BAR: default.Script.onFocusedChanged(self, event) return role = event.source.getRole() 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)) textSelections = self.pointOfReference.get('textSelections', {}) start, end = textSelections.get(hash(obj), (0, 0)) if start != end: return keyString, mods = self.utilities.lastKeyAndModifiers() if keyString in ["Left", "Right"]: orca.setLocusOfFocus(event, event.source, False) return # We should present this in response to active-descendant-changed events if event.source.getState().contains(pyatspi.STATE_MANAGES_DESCENDANTS): if role != pyatspi.ROLE_LIST: return default.Script.onFocusedChanged(self, event)
def onSelectedChanged(self, event): """Callback for object:state-changed:selected accessibility events.""" if self.utilities.isEntryCompletionPopupItem(event.source): if event.detail1: orca.setLocusOfFocus(event, event.source) return if orca_state.locusOfFocus == event.source: orca.setLocusOfFocus(event, None) return super().onSelectedChanged(event)
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return if event.source.parent == self.spellcheck.getSuggestionsList(): orca.setLocusOfFocus(event, event.source, False) self.updateBraille(orca_state.locusOfFocus) self.spellcheck.presentSuggestionListItem() return gtk.Script.onFocusedChanged(self, event)
def onWindowActivated(self, event): # Sets the context to the top level window first, so we can # get information about it the window we just moved to. # orca.setLocusOfFocus(event, event.source) # Now we find the focused object and set the locus of focus to it. # obj = self.findFocusedObject(self.app) if obj: orca.setLocusOfFocus(event, obj) else: default.Script.onWindowActivated(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 if event.source != orca_state.locusOfFocus \ and event.source.getState().contains(pyatspi.STATE_FOCUSED): orca.setLocusOfFocus(event, event.source, False) super().onTextSelectionChanged(event)
def onFocus(self, event): """Callback for focus: accessibility events.""" # NOTE: This event type is deprecated and Orca should no longer use it. # This callback remains just to handle bugs in applications and toolkits # during the remainder of the unstable (3.11) development cycle. if self.utilities.isSameObject(orca_state.locusOfFocus, event.source): return role = event.source.getRole() # This seems to be something we inherit from Gtk+ if role in [pyatspi.ROLE_TEXT, pyatspi.ROLE_PASSWORD_TEXT]: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_PUSH_BUTTON: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_COMBO_BOX: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_PANEL and event.source.name: orca.setLocusOfFocus(event, event.source) return
def onActiveChanged(self, event): """Callback for object:state-changed:active accessibility events.""" if self.findCommandRun: self.findCommandRun = False self.find() return if not event.detail1: return role = event.source.getRole() if role in [pyatspi.ROLE_DIALOG, pyatspi.ROLE_ALERT]: orca.setLocusOfFocus(event, event.source)
def onFocus(self, event): """Callback for focus: accessibility events.""" if self.utilities.isWebKitGtk(event.source): return # This is some mystery child of the 'Messages' panel which fails to show # up in the hierarchy or emit object:state-changed:focused events. if event.source.getRole() == pyatspi.ROLE_LAYERED_PANE: obj = self.utilities.realActiveDescendant(event.source) orca.setLocusOfFocus(event, obj) return gtk.Script.onFocus(self, event)
def onFocus(self, event): """Callback for focus: accessibility events.""" # NOTE: This event type is deprecated and Orca should no longer use it. # This callback remains just to handle bugs in applications and toolkits # during the remainder of the unstable (3.11) development cycle. role = event.source.getRole() # This seems to be something we inherit from Gtk+ if role in [pyatspi.ROLE_TEXT, pyatspi.ROLE_PASSWORD_TEXT]: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_PUSH_BUTTON: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_COMBO_BOX: orca.setLocusOfFocus(event, event.source) return # Ditto. if role == pyatspi.ROLE_PANEL and event.source.name: orca.setLocusOfFocus(event, event.source) return
def onActiveDescendantChanged(self, event): """Callback for object:active-descendant-changed accessibility events.""" if not event.any_data: return if self.utilities.isComposeAutocomplete(event.source): if event.any_data.getState().contains(pyatspi.STATE_SELECTED): orca.setLocusOfFocus(event, event.any_data) else: orca.setLocusOfFocus(event, event.source) return super().onActiveDescendantChanged(event)
def onFocus(self, event): """Callback for focus: accessibility events.""" # We should get proper state-changed events for these. if self.utilities.inDocumentContent(event.source): return if self.utilities.isLayoutOnly(event.source): return # NOTE: This event type is deprecated and Orca should no longer use it. # This callback remains just to handle bugs in applications and toolkits # in which object:state-changed:focused events are missing. And in the # case of Gecko dialogs, that seems to happen a lot. orca.setLocusOfFocus(event, event.source)
def onCaretMoved(self, event): """Caret movement in Gecko is somewhat unreliable and unpredictable, but we need to handle it. When we detect caret movement, we make sure we update our own notion of the caret position: our caretContext is an [obj, characterOffset] that points to our current item and character (if applicable) of interest. If our current item doesn't implement the accessible text specialization, the characterOffset value is meaningless (and typically -1).""" if self.utilities.inDocumentContent(event.source): orca.setLocusOfFocus(event, event.source) Gecko.Script.onCaretMoved(self, event) else: default.Script.onCaretMoved(self, event)
def locusOfFocusChanged(self, event, oldFocus, newFocus): """Handles changes of focus of interest to the script.""" if self.utilities.isToggleDescendantOfComboBox(newFocus): isComboBox = lambda x: x and x.getRole() == pyatspi.ROLE_COMBO_BOX newFocus = pyatspi.findAncestor(newFocus, isComboBox) or newFocus orca.setLocusOfFocus(event, newFocus, False) elif self.utilities.isInOpenMenuBarMenu(newFocus): window = self.utilities.topLevelObject(newFocus) windowChanged = window and orca_state.activeWindow != window if windowChanged: orca_state.activeWindow = window self.windowActivateTime = time.time() super().locusOfFocusChanged(event, oldFocus, newFocus)
def onActiveDescendantChanged(self, event): """Callback for object:active-descendant-changed accessibility events.""" role = event.source.getRole() try: focusedRole = orca_state.locusOfFocus.getRole() except: pass else: # This is very likely typeahead search and not a real focus change. tableRoles = [pyatspi.ROLE_TABLE, pyatspi.ROLE_TREE_TABLE] if focusedRole == pyatspi.ROLE_TEXT and role in tableRoles: orca.setLocusOfFocus(event, event.source, False) default.Script.onActiveDescendantChanged(self, event)
def onBusyChanged(self, event): """Callback for object:state-changed:busy accessibility events.""" obj = event.source if obj.getRole() == pyatspi.ROLE_DOCUMENT_FRAME and not event.detail1: try: role = orca_state.locusOfFocus.getRole() except: pass else: if role in [pyatspi.ROLE_FRAME, pyatspi.ROLE_PAGE_TAB]: orca.setLocusOfFocus(event, event.source, False) if self.utilities.inDocumentContent(): self.speakMessage(obj.name) self._presentMessage(obj)