def event_appModule_gainFocus(self): inputCore.manager._captureFunc = self._inputCaptor if not config.conf["reviewCursor"]["followFocus"]: # Move the review cursor so others can't access its previous position. self._oldReviewPos = api.getReviewPosition() self._oldReviewObj = self._oldReviewPos.obj api.setNavigatorObject(eventHandler.lastQueuedFocusObject)
def script_sent(self, gesture): global orig fg = api.getForegroundObject() try: handle = windowUtils.findDescendantWindow( fg.windowHandle, className="RichEdit20WPT", controlID=4098) if handle: # found handle w = NVDAObjects.IAccessible.getNVDAObjectFromEvent( handle, winUser.OBJID_CLIENT, 0) if scriptHandler.getLastScriptRepeatCount() == 2: # trible press, copy to clipboard and set focus to original field api.copyToClip(w.value) ui.message(_("Copied to clipboard")) api.setNavigatorObject(w, isFocus=True) orig.setFocus() elif scriptHandler.getLastScriptRepeatCount() == 1: # double press, set focus in field winUser.setForegroundWindow(handle) else: # single press ui.message(" %s %s" % (w.name, w.value)) orig = api.getFocusObject() except LookupError: # for RSS mails try: handle = windowUtils.findDescendantWindow( fg.windowHandle, className="RichEdit20WPT", controlID=4105) if handle: # found handle w = NVDAObjects.IAccessible.getNVDAObjectFromEvent( handle, winUser.OBJID_CLIENT, 0) ui.message(" %s %s" % (w.name, w.value)) except LookupError: tones.beep(440, 20)
def script_startExploration(self, gesture): self.configVars() with measureTime("Toolbars found in"): self.findToolbars() self.initialFilterBars() if self.bars: self.populateBar(self.bars[self.barIndex]) if not self.bars: # Translators: message in applications without toolbars ui.message(_("No toolbar found")) return # a backup of various info, useful later self.startSnap["focus"] = api.getFocusObject() self.startSnap["nav"] = api.getNavigatorObject() self.startSnap["foreground"] = api.getForegroundObject() self.startSnap["pid"] = api.getFocusObject().processID self.startSnap["reviewMode"] = review.getCurrentMode() # declare exploration started self.exploring = True # set object navigation active review.setCurrentMode("object", updateReviewPosition=False) # see script_explore for gesture explanation for direction in ("up", "right", "down", "left"): self.bindGesture("kb:%sArrow" % direction, "explore") self.bindGesture("kb:escape", "finish") self.bindGesture("kb:enter", "objActivate") self.bindGesture("kb:space", "objLeftClick") self.bindGesture("kb:applications", "objRightClick") self.bindGesture("kb:shift+f10", "objRightClick") bar = self.bars[self.barIndex] api.setNavigatorObject(bar) speech.speakObject(bar, reason=REASON_FOCUS)
def event_UIA_elementSelected(self, obj, nextHandler): # #7273: When this is fired on categories, the first emoji from the new category is selected but not announced. # Therefore, move the navigator object to that item if possible. # However, in recent builds, name change event is also fired. # For consistent experience, report the new category first by traversing through controls. # #8189: do not announce candidates list itself (not items), as this is repeated each time candidate items are selected. if obj.UIAElement.cachedAutomationID == "CandidateList": return speech.cancelSpeech() # Sometimes clipboard candidates list gets selected, so ask NvDA to descend one more level. if obj.UIAElement.cachedAutomationID == "TEMPLATE_PART_ClipboardItemsList": obj = obj.firstChild candidate = obj # Sometimes, due to bad tree traversal, something other than the selected item sees this event. parent = obj.parent if obj.UIAElement.cachedClassName == "ListViewItem" and isinstance(parent, UIA) and parent.UIAElement.cachedAutomationID != "TEMPLATE_PART_ClipboardItemsList": # The difference between emoji panel and suggestions list is absence of categories/emoji separation. # Turns out automation ID for the container is different, observed in build 17666 when opening clipboard copy history. candidate = obj.parent.previous if candidate is not None: # Emoji categories list. ui.message(candidate.name) obj = candidate.firstChild if obj is not None: api.setNavigatorObject(obj) obj.reportFocus() braille.handler.message(braille.getBrailleTextForProperties(name=obj.name, role=obj.role, positionInfo=obj.positionInfo)) # Cache selected item. self._recentlySelected = obj.name else: # Translators: presented when there is no emoji when searching for one in Windows 10 Fall Creators Update and later. ui.message(_("No emoji")) nextHandler()
def script_navigatorObject_toFakeRootDialog(self, gesture): if not self.tcNumber: # None or 0 ui.message(_('Test mode is off.')) return obj = self.getFakeRootDialog() api.setNavigatorObject(obj) speech.speakObject(obj)
def readObjectsHelper_generator(obj): lastSentIndex=0 lastReceivedIndex=0 speechGen=generateObjectSubtreeSpeech(obj,itertools.count()) objIndexMap={} keepReading=True while True: # lastReceivedIndex might be None if other speech was interspersed with this say all. # In this case, we want to send more text in case this was the last chunk spoken. if lastReceivedIndex is None or (lastSentIndex-lastReceivedIndex)<=1: if keepReading: try: o,lastSentIndex=speechGen.next() except StopIteration: keepReading=False continue objIndexMap[lastSentIndex]=o receivedIndex=speech.getLastSpeechIndex() if receivedIndex!=lastReceivedIndex and (lastReceivedIndex!=0 or receivedIndex!=None): lastReceivedIndex=receivedIndex lastReceivedObj=objIndexMap.get(lastReceivedIndex) if lastReceivedObj is not None: api.setNavigatorObject(lastReceivedObj) #Clear old objects from the map for i in objIndexMap.keys(): if i<=lastReceivedIndex: del objIndexMap[i] while speech.isPaused: yield yield
def _reportSelectedEntry(self): obj = self._getSelectedEntry() if obj is None: return self._reportFocusEnteredEventForParent(obj) api.setNavigatorObject(obj) obj.reportFocus()
def script_reportStatusLine(self, gesture): #it seems that the status bar is the last child of the forground object #so, get it from there obj = api.getForegroundObject().lastChild found=False if obj and obj.role == controlTypes.ROLE_STATUSBAR: text = api.getStatusBarText(obj) api.setNavigatorObject(obj) found=True else: info=api.getForegroundObject().flatReviewPosition if info: info.expand(textInfos.UNIT_STORY) info.collapse(True) info.expand(textInfos.UNIT_LINE) text=info.text info.collapse() api.setReviewPosition(info) found=True if not found: # Translators: Reported when there is no status line for the current program or window. ui.message(_("No status line found")) return if scriptHandler.getLastScriptRepeatCount()==0: ui.message(text) else: speech.speakSpelling(text)
def event_UIA_elementSelected(self, obj, nextHandler): # #7273: When this is fired on categories, the first emoji from the new category is selected but not announced. # Therefore, move the navigator object to that item if possible. # However, in recent builds, name change event is also fired. # For consistent experience, report the new category first by traversing through controls. speech.cancelSpeech() # And no, if running on build 17040 and if this is typing suggestion, do not announce candidate window changes, as it is duplicate announcement and is anoying. if obj.UIAElement.cachedAutomationID == "IME_Candidate_Window": return candidate = obj if obj.UIAElement.cachedClassName == "ListViewItem": # The difference between emoji panel and suggestions list is absence of categories/emoji separation. # If dealing with keyboard entry suggestions (build 17040 and later), return immediately. candidate = obj.parent.previous if candidate is None: return ui.message(candidate.name) obj = candidate.firstChild if obj is not None: api.setNavigatorObject(obj) obj.reportFocus() braille.handler.message( braille.getBrailleTextForProperties( name=obj.name, role=obj.role, positionInfo=obj.positionInfo)) else: # Translators: presented when there is no emoji when searching for one in Windows 10 Fall Creators Update and later. ui.message(_("No emoji")) nextHandler()
def readObjectsHelper_generator(obj): lastSentIndex=0 lastReceivedIndex=0 speechGen=generateObjectSubtreeSpeech(obj,itertools.count()) objIndexMap={} keepReading=True while True: # lastReceivedIndex might be None if other speech was interspersed with this say all. # In this case, we want to send more text in case this was the last chunk spoken. if lastReceivedIndex is None or (lastSentIndex-lastReceivedIndex)<=1: if keepReading: try: o,lastSentIndex=speechGen.next() except StopIteration: keepReading=False continue objIndexMap[lastSentIndex]=o receivedIndex=speech.getLastSpeechIndex() if receivedIndex!=lastReceivedIndex and (lastReceivedIndex!=0 or receivedIndex!=None): lastReceivedIndex=receivedIndex lastReceivedObj=objIndexMap.get(lastReceivedIndex) if lastReceivedObj is not None: api.setNavigatorObject(lastReceivedObj, isFocus=lastSayAllMode==CURSOR_CARET) #Clear old objects from the map for i in objIndexMap.keys(): if i<=lastReceivedIndex: del objIndexMap[i] while speech.isPaused: yield yield
def event_UIA_elementSelected(self): focusControllerFor = api.getFocusObject().controllerFor if len(focusControllerFor) > 0 and focusControllerFor[ 0].appModule is self.appModule and self.name: speech.cancelSpeech() api.setNavigatorObject(self) self.reportFocus()
def callback(obj, oldspeechMode): api.processPendingEvents() speech.cancelSpeech() speech.speechMode = oldSpeechMode api.setNavigatorObject(obj) api.moveMouseToNVDAObject(obj) speech.speakObject(obj)
def event_gainFocus(self, obj, nextHandler): # Non-English locales does not fire item selected event for looping selector unless navigator is first set to it. if isinstance( obj, UIA ) and obj.UIAElement.cachedClassName == "CustomLoopingSelector": api.setNavigatorObject(obj.simpleFirstChild) nextHandler()
def script_header(self, gesture): obj = self.getHeader() if obj is None: return api.setNavigatorObject(obj) api.moveMouseToNVDAObject(obj) api.setMouseObject(obj) speech.speakObject(obj)
def script_reportChannelMember(self,gesture): gesture.send() obj = api.getFocusObject() if obj.role is controlTypes.ROLE_UNKNOWN: objP = obj.parent if objP is not None and objP.name: api.setNavigatorObject(objP) ui.message(objP.name)
def onDefaultAction(self, event): self.Hide() obj = self.getObjectFromList().obj api.setNavigatorObject(obj) try: scriptHandler.executeScript(globalCommands.commands.script_review_activate, None) except: ui.message(_("Can not do default action for this object"))
def reviewRecentMessage(self, index): count = self._getMessageCount() if index > count: # Translators: This is presented to inform the user that no instant message has been received. ui.message(_("No message yet")) return message = self.getChild(count - index) api.setNavigatorObject(message) self.reportMessage(message.name)
def _moveToColumn(self, obj): if not obj: ui.message(_("edge of table")) return if obj is not self: # Use the focused copy of the row as the parent for all cells to make comparison faster. obj.parent = self api.setNavigatorObject(obj) speech.speakObject(obj, reason=controlTypes.REASON_FOCUS)
def onRightClick(self, event): index = self.list.GetSelection() headerObj = self.headerList[index] self.Destroy() api.setNavigatorObject(headerObj) commands.script_moveMouseToNavigatorObject(None) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTDOWN, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTUP, 0, 0, None, None) ui.message(_("%s header clicked") % headerObj.name)
def _moveToColumn(self, obj): if not obj: ui.message(_("Edge of table")) return if obj is not self: # Use the focused copy of the row as the parent for all cells to make comparison faster. obj.parent = self api.setNavigatorObject(obj) speech.speakObject(obj, reason=controlTypes.REASON_FOCUS)
def onOptionsButton(self, event): self.Hide() self.options.scrollIntoView() api.setNavigatorObject(self.options) try: scriptHandler.executeScript( globalCommands.commands.script_review_activate, None) except: beep(150, 100)
def script_headerOptions(self, gesture): if self.parent.simpleParent.role == controlTypes.ROLE_DIALOG: return obj = self.parent.getChild(1) while obj.name != self.columnHeaderText and obj.role == controlTypes.ROLE_TABLECOLUMNHEADER: obj = obj.next api.setNavigatorObject(obj) speakObject(obj) winUser.setCursorPos(self.location[0] + 2, obj.location[1] + 2) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTDOWN, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTUP, 0, 0, None, None)
def script_headerOptions(self, gesture): if self.parent.simpleParent.role == controlTypes.ROLE_DIALOG: return obj = self.table.simpleFirstChild while obj.name != self.columnHeaderText and obj.role == controlTypes.ROLE_HEADER: obj = obj.next api.setNavigatorObject(obj) winUser.setCursorPos(self.location[0] + 2, obj.location[1] + 2) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTDOWN, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_RIGHTUP, 0, 0, None, None) KeyboardInputGesture.fromName("downArrow").send()
def event_UIA_elementSelected(self): # Build 17600 series introduces Sets, a way to group apps into tabs. # #45: unfortunately, the start page for this (an embedded searchui process inside Edge) says controller for list is empty when in fact it isn't. # Thankfully, it is easy to spot them: if a link is next to results list, then this is the embedded searchui results list. focusControllerFor=api.getFocusObject().controllerFor announceSuggestions = ((len(focusControllerFor)>0 and focusControllerFor[0].appModule is self.appModule and self.name) or self.parent.next is not None) if announceSuggestions: speech.cancelSpeech() api.setNavigatorObject(self) self.reportFocus()
def tbContextMenu(self, obj, func): api.setNavigatorObject(obj) x = obj.location[0] + 2 y = obj.location[1] + 2 winUser.setCursorPos(x, y) if api.getDesktopObject().objectFromPoint(x, y) == obj: scriptHandler.executeScript(func, None) else: # TRANSLATORS: Message shown when the object is not found ui.message(_("Not found"))
def event_gainFocus(self, obj, nextHandler): global intelliSenseLastFocused global lastFocusedIntelliSenseItem if obj.name == "Text Editor" and obj.role == controlTypes.ROLE_EDITABLETEXT: if _isCompletionPopupShowing(): api.setNavigatorObject(lastFocusedIntelliSenseItem) intelliSenseLastFocused = True return intelliSenseLastFocused = False lastFocusedIntelliSenseItem = None nextHandler()
def script_previousWidget(self, gesture): if not self.focusedWidget: KeyboardInputGesture.fromName("shift+tab").send() return self.focusedWidget = self.focusedWidget.simplePrevious if self.focusedWidget: api.setNavigatorObject(self.focusedWidget) speakObject(self.focusedWidget) else: api.setNavigatorObject(self) speakObject(self)
def script_navigatorObject_moveToObjectAtFlatReviewPosition(self,gesture): pos=api.getReviewPosition() try: obj=pos.NVDAObjectAtStart except NotImplementedError: obj=None if obj and obj!=pos.obj: api.setNavigatorObject(obj) speech.speakObject(obj) else: speech.speakMessage(_("No object at flat review position"))
def finish(self, restoreMode=False, restoreObjects=False): self.exploring = False self.clearGestureBindings() self.bindGestures(self.__gestures) # restore initial objects and review mode if restoreMode: review.setCurrentMode(self.startSnap["reviewMode"], updateReviewPosition=False) if restoreObjects: api.setFocusObject(self.startSnap["focus"]) api.setNavigatorObject(self.startSnap["nav"]) speech.speakObject(self.startSnap["focus"], reason=REASON_FOCUS)
def script_reportStatusLine(self,gesture): obj = api.getStatusBar() if not obj: ui.message(_("no status bar found")) return text = api.getStatusBarText(obj) if scriptHandler.getLastScriptRepeatCount()==0: ui.message(text) else: speech.speakSpelling(text) api.setNavigatorObject(obj)
def script_navigatorObject_firstChild(self,gesture): curObject=api.getNavigatorObject() if not isinstance(curObject,NVDAObject): speech.speakMessage(_("no navigator object")) return simpleReviewMode=config.conf["reviewCursor"]["simpleReviewMode"] curObject=curObject.simpleFirstChild if simpleReviewMode else curObject.firstChild if curObject is not None: api.setNavigatorObject(curObject) speech.speakObject(curObject,reason=speech.REASON_QUERY) else: speech.speakMessage(_("No children"))
def event_UIA_elementSelected(self, obj, nextHandler): # Logic for IME candidate items is handled all within its own object # Therefore pass these events straight on. if isinstance(obj, ImeCandidateItem): return nextHandler() # #7273: When this is fired on categories, # the first emoji from the new category is selected but not announced. # Therefore, move the navigator object to that item if possible. # However, in recent builds, name change event is also fired. # For consistent experience, report the new category first by traversing through controls. # #8189: do not announce candidates list itself (not items), # as this is repeated each time candidate items are selected. if obj.UIAAutomationId == "CandidateList": return speech.cancelSpeech() # Sometimes, due to bad tree traversal or wrong item getting selected, # something other than the selected item sees this event. # In build 18262, emoji panel may open to People group and skin tone modifier gets selected. if obj.parent.UIAAutomationId == "SkinTonePanelModifier_ListView": # But this will point to nothing if emoji search results are not people. if obj.parent.next is not None: obj = obj.parent.next else: obj = obj.parent.parent.firstChild candidate = obj if ( obj and obj.UIAElement.cachedClassName == "ListViewItem" and obj.parent and isinstance(obj.parent, UIA) and obj.parent.UIAAutomationId != "TEMPLATE_PART_ClipboardItemsList" ): # The difference between emoji panel and suggestions list is absence of categories/emoji separation. # Turns out automation ID for the container is different, # observed in build 17666 when opening clipboard copy history. candidate = obj.parent.previous if candidate is not None: # Emoji categories list. ui.message(candidate.name) obj = candidate.firstChild if obj is not None: api.setNavigatorObject(obj) obj.reportFocus() braille.handler.message(braille.getPropertiesBraille( name=obj.name, role=obj.role, positionInfo=obj.positionInfo )) # Cache selected item. self._recentlySelected = obj.name else: # Translators: presented when there is no emoji when searching for one # in Windows 10 Fall Creators Update and later. ui.message(_("No emoji")) nextHandler()
def event_UIA_elementSelected(self): # Cancel speech to have speech announce the selection as soon as possible. # This is needed because L{reportFocus} does not cancel speech. # Therefore, if speech wouldn't be cancelled, # selection announcements would queue up when changing selection rapidly. speech.cancelSpeech() api.setNavigatorObject(self, isFocus=True) self.reportFocus() # Display results as flash messages. braille.handler.message(braille.getPropertiesBraille( name=self.name, role=self.role, positionInfo=self.positionInfo, description=self.description ))
def event_gainFocus(self, obj, nextHandler): global intelliSenseLastFocused, lastFocusedIntelliSenseItem if isinstance(obj, UIA) and obj.UIAElement.currentClassName == "WpfTextView" and obj.role == controlTypes.ROLE_EDITABLETEXT: # in many cases, the editor fire focus events when intelliSense menu is opened, which leads to a lengthy announcements after reporting the current intelliSense item #so, allow the focus to return to the editor if that happens, but don't report the focus event, and set the navigator object to be last reported intelliSense item to allow the user to review if self._isCompletionPopupShowing(): api.setNavigatorObject(lastFocusedIntelliSenseItem) return if self._shouldIgnoreFocusEvent(obj): return intelliSenseLastFocused = False lastFocusedIntelliSenseItem = None nextHandler()
def readTrainingText(self): window = api.getForegroundObject() for descendant in window.recursiveDescendants: if not isinstance(descendant, UIA): continue try: automationID = descendant.UIAElement.currentAutomationID except: continue if automationID == "txttrain": api.setNavigatorObject(descendant) speech.speakText(descendant.name) break
def readTrainingText(self): window = api.getForegroundObject() for descendant in window.recursiveDescendants: if not isinstance(descendant, UIA): continue try: automationID = descendant.UIAElement.currentAutomationID except: continue if automationID == "txttrain": api.setNavigatorObject(descendant) ui.message(descendant.name) break
def script_readDocumentation(self, gesture): rootDocumentationWindow = None # If there aren't any suggestion selected, there is no way to find quick documentation if not self.appModule.selectedItem: gesture.send() return # Try to locate the documentation document try: rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous.previous except AttributeError: pass # In XML documents this is different, maybe in other editors too # so we try to locate the root window again if not rootDocumentationWindow or not rootDocumentationWindow.appModule == self.appModule: try: rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous except AttributeError: pass # Check if this object is from the same appModule if rootDocumentationWindow and rootDocumentationWindow.appModule == self.appModule: api.setNavigatorObject(rootDocumentationWindow) documentObj = rootDocumentationWindow while documentObj: if documentObj.firstChild: documentObj = documentObj.firstChild # In some editors the help document is a HTML ones # On XML documents, for example, it is a simple read-only editable text if documentObj.role in (controlTypes.Role.DOCUMENT, controlTypes.Role.EDITABLETEXT): break else: break if documentObj.role == controlTypes.Role.DOCUMENT: api.setNavigatorObject(documentObj) braille.handler.handleReviewMove() sayAll.SayAllHandler.readText(sayAll.CURSOR.REVIEW) elif documentObj.role == controlTypes.Role.EDITABLETEXT: ui.message(documentObj.value) else: # Translators: When the help popup cannot be found for the selected autocompletion item ui.message(_("Cann't find the documentation window."))
def readCheckButton(self): if controlTypes.STATE_PRESSED in self.pointedObj.states: #TRANSLATORS: a button is checked state = _("checked") else: #TRANSLATORS: a button is not checked state = _("not checked") if self.pointedObj.description: ui.message( "%s, %s, %s" % (self.pointedObj.name, state, self.pointedObj.description)) else: ui.message("%s, %s" % (self.pointedObj.name, state)) api.setNavigatorObject(self.pointedObj)
def script_readDocumentation(self, gesture): rootDocumentationWindow = None # If there aren't any suggestion selected, there is no way to find quick documentation if not self.appModule.selectedItem: gesture.send() return # Try to locate the documentation document try: rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous.previous except AttributeError: pass # In XML documents this is different, maybe in other editors too # so we try to locate the root window again if not rootDocumentationWindow or not rootDocumentationWindow.appModule == self.appModule: try: rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous except AttributeError: pass # Check if this object is from the same appModule if rootDocumentationWindow and rootDocumentationWindow.appModule == self.appModule: api.setNavigatorObject(rootDocumentationWindow) documentObj = rootDocumentationWindow while documentObj: if documentObj.firstChild: documentObj = documentObj.firstChild # In some editors the help document is a HTML ones # On XML documents, for example, it is a simple read-only editable text if documentObj.role in (controlTypes.ROLE_DOCUMENT, controlTypes.ROLE_EDITABLETEXT): break else: break if documentObj.role == controlTypes.ROLE_DOCUMENT: api.setNavigatorObject(documentObj) braille.handler.handleReviewMove() sayAllHandler.readText(sayAllHandler.CURSOR_REVIEW) elif documentObj.role == controlTypes.ROLE_EDITABLETEXT: ui.message(documentObj.value) else: # Translators: When the help popup cannot be found for the selected autocompletion item ui.message(_("Cann't find the documentation window."))
def moveTo(self, x, y, new=False, unit=textInfos.UNIT_LINE): obj = api.getDesktopObject().objectFromPoint(x, y) prevObj = None while obj and obj.beTransparentToMouse: prevObj = obj obj = obj.parent if not obj or (obj.presentationType != obj.presType_content and obj.role != controlTypes.ROLE_PARAGRAPH): obj = prevObj if not obj: return hasNewObj = False if obj != self._obj: self._obj = obj hasNewObj = True if self.updateReview: api.setNavigatorObject(obj) else: obj = self._obj pos = None if obj.treeInterceptor: try: pos = obj.treeInterceptor.makeTextInfo(obj) except LookupError: pos = None if pos: obj = obj.treeInterceptor.rootNVDAObject if hasNewObj and self._obj and obj.treeInterceptor is self._obj.treeInterceptor: hasNewObj = False if not pos: try: pos = obj.makeTextInfo(locationHelper.Point(x, y)) except (NotImplementedError, LookupError): pass if pos: pos.expand(unit) if pos and self.updateReview: api.setReviewPosition(pos) speechCanceled = False if hasNewObj: speech.cancelSpeech() speechCanceled = True speech.speakObject(obj) if pos and (new or not self._pos or pos.__class__ != self._pos.__class__ or pos.compareEndPoints(self._pos, "startToStart") != 0 or pos.compareEndPoints(self._pos, "endToEnd") != 0): self._pos = pos if not speechCanceled: speech.cancelSpeech() speech.speakTextInfo(pos, reason=controlTypes.OutputReason.CARET)
def _set_passThrough(self, state): if self._passThrough == state: return self._passThrough = state if state: if config.conf['reviewCursor']['followFocus']: focusObj=api.getFocusObject() if self is focusObj.treeInterceptor: api.setNavigatorObject(focusObj) braille.handler.handleGainFocus(api.getFocusObject()) else: obj=api.getNavigatorObject() if config.conf['reviewCursor']['followCaret'] and self is obj.treeInterceptor: api.setNavigatorObject(self.rootNVDAObject) braille.handler.handleGainFocus(self)
def moveTo(self,x,y,new=False,unit=textInfos.UNIT_LINE): obj=api.getDesktopObject().objectFromPoint(x,y) prevObj=None while obj and obj.beTransparentToMouse: prevObj=obj obj=obj.parent if not obj or (obj.presentationType!=obj.presType_content and obj.role!=controlTypes.ROLE_PARAGRAPH): obj=prevObj if not obj: return hasNewObj=False if obj!=self._obj: self._obj=obj hasNewObj=True if self.updateReview: api.setNavigatorObject(obj) else: obj=self._obj pos=None if obj.treeInterceptor: try: pos=obj.treeInterceptor.makeTextInfo(obj) except LookupError: pos=None if pos: obj=obj.treeInterceptor.rootNVDAObject if hasNewObj and self._obj and obj.treeInterceptor is self._obj.treeInterceptor: hasNewObj=False if not pos: try: pos=obj.makeTextInfo(textInfos.Point(x,y)) except (NotImplementedError,LookupError): pass if pos: pos.expand(unit) if pos and self.updateReview: api.setReviewPosition(pos) speechCanceled=False if hasNewObj: speech.cancelSpeech() speechCanceled=True speech.speakObject(obj) if pos and (new or not self._pos or pos.__class__!=self._pos.__class__ or pos.compareEndPoints(self._pos,"startToStart")!=0 or pos.compareEndPoints(self._pos,"endToEnd")!=0): self._pos=pos if not speechCanceled: speech.cancelSpeech() speech.speakTextInfo(pos,reason=controlTypes.REASON_CARET)
def event_show(self): candidateList=self.simpleFirstChild if not candidateList: return role=candidateList.role if role==controlTypes.ROLE_LIST: item=candidateList.firstChild while item and controlTypes.STATE_SELECTED not in item.states: item=item.next if item: reportSelectedCandidate(item) return elif config.conf["reviewCursor"]["followFocus"]: api.setNavigatorObject(candidateList, isFocus=True) elif role==controlTypes.ROLE_MENUBUTTON: item=candidateList.firstChild.next.next item=MSCandUI21_candidateMenuItem(IAccessibleObject=item.IAccessibleObject,IAccessibleChildID=item.IAccessibleChildID) if item and isinstance(item.candidateNumber,int) and item.name: reportSelectedCandidate(item)
def readObjectsHelper_generator(obj): levelsIndexMap={} updateObj=obj keepReading=True keepUpdating=True indexCount=0 lastSpokenIndex=0 endIndex=0 while keepUpdating: while speech.isPaused: yield continue if keepReading: speech.speakObject(obj,index=indexCount,reason=speech.REASON_SAYALL) up=[] down=[] obj=obj.getNextInFlow(up=up,down=down) if not obj: endIndex=indexCount keepReading=False indexCount+=1 levelsIndexMap[indexCount]=(len(up),len(down)) spokenIndex=speech.getLastSpeechIndex() if spokenIndex is None: spokenIndex=0 for count in range(spokenIndex-lastSpokenIndex): upLen,downLen=levelsIndexMap.get(lastSpokenIndex+count+1,(0,0)) if upLen==0 and downLen==0: tones.beep(880,50) if upLen>0: for count in range(upLen+1): tones.beep(880*(1.25**count),50) time.sleep(0.025) if downLen>0: for count in range(downLen+1): tones.beep(880/(1.25**count),50) time.sleep(0.025) updateObj=updateObj.nextInFlow api.setNavigatorObject(updateObj) if not keepReading and spokenIndex>=endIndex: keepUpdating=False lastSpokenIndex=spokenIndex yield
def _set_passThrough(self, state): if self._passThrough == state: return self._passThrough = state if state: if config.conf['reviewCursor']['followFocus']: focusObj=api.getFocusObject() if self is focusObj.treeInterceptor: if review.getCurrentMode()=='document': # if focus is in this treeInterceptor and review mode is document, turning on passThrough should force object review review.setCurrentMode('object') api.setNavigatorObject(focusObj) braille.handler.handleGainFocus(api.getFocusObject()) else: obj=api.getNavigatorObject() if config.conf['reviewCursor']['followCaret'] and self is obj.treeInterceptor: if review.getCurrentMode()=='object': # if navigator object is in this treeInterceptor and the review mode is object, then turning off passThrough should force document review review.setCurrentMode('document',True) braille.handler.handleGainFocus(self)
def script_moveNavigatorObjectToMouse(self,gesture): ui.message(_("Move navigator object to mouse")) obj=api.getMouseObject() api.setNavigatorObject(obj) speech.speakObject(obj)
def event_UIA_elementSelected(self): speech.cancelSpeech() api.setNavigatorObject(self) self.reportFocus()
def event_UIA_elementSelected(self): speech.cancelSpeech() api.setNavigatorObject(self, isFocus=True) self.reportFocus() super(SuggestionListItem,self).event_UIA_elementSelected()
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop. """ log.debug("Core starting") ctypes.windll.user32.SetProcessDPIAware() import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.initialize() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s"%lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s"%lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %s" % winVersion.winVersionText) log.info("Using Python version %s"%sys.version) log.info("Using comtypes version %s"%comtypes.__version__) import configobj log.info("Using configobj version %s with validate version %s"%(configobj.__version__,configobj.validate.__version__)) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing add-ons system") addonHandler.initialize() if globalVars.appArgs.disableAddons: log.info("Add-ons are disabled. Restart NVDA to enable them.") import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx # wxPython 4 no longer has either of these constants (despite the documentation saying so), some add-ons may rely on # them so we add it back into wx. https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.Centre wx.CENTER_ON_SCREEN = wx.CENTRE_ON_SCREEN = 0x2 log.info("Using wx version %s"%wx.version()) class App(wx.App): def OnAssert(self,file,line,cond,msg): message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg) log.debugWarning(message,codepath="WX Widgets",stack_info=True) app = App(redirect=False) # We support queryEndSession events, but in general don't do anything for them. # However, when running as a Windows Store application, we do want to request to be restarted for updates def onQueryEndSession(evt): if config.isAppX: # Automatically restart NVDA on Windows Store update ctypes.windll.kernel32.RegisterApplicationRestart(None,0) app.Bind(wx.EVT_QUERY_END_SESSION, onQueryEndSession) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import braille log.debug("Initializing braille") braille.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() import audioDucking if audioDucking.isAudioDuckingSupported(): # the GUI mainloop must be running for this to work so delay it wx.CallAfter(audioDucking.initialize) # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. # NVDA uses the main frame to check for and quit another instance of NVDA. # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. # We don't need to do anything else because wx handles WM_QUIT for all windows. import windowUtils class MessageWindow(windowUtils.CustomWindow): className = u"wxWindowClassNR" #Just define these constants here, so we don't have to import win32con WM_POWERBROADCAST = 0x218 WM_DISPLAYCHANGE = 0x7e PBT_APMPOWERSTATUSCHANGE = 0xA UNKNOWN_BATTERY_STATUS = 0xFF AC_ONLINE = 0X1 NO_SYSTEM_BATTERY = 0X80 #States for screen orientation ORIENTATION_NOT_INITIALIZED = 0 ORIENTATION_PORTRAIT = 1 ORIENTATION_LANDSCAPE = 2 def __init__(self, windowName=None): super(MessageWindow, self).__init__(windowName) self.oldBatteryStatus = None self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED self.orientationCoordsCache = (0,0) self.handlePowerStatusChange() def windowProc(self, hwnd, msg, wParam, lParam): post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam) if msg == self.WM_POWERBROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE: self.handlePowerStatusChange() elif msg == self.WM_DISPLAYCHANGE: self.handleScreenOrientationChange(lParam) def handleScreenOrientationChange(self, lParam): import ui import winUser # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx. #The low word is the width and hiword is height. width = winUser.LOWORD(lParam) height = winUser.HIWORD(lParam) self.orientationCoordsCache = (width,height) if width > height: # If the height and width are the same, it's actually a screen flip, and we do want to alert of those! if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented so that it is wider than it is tall. ui.message(_("Landscape" )) self.orientationStateCache = self.ORIENTATION_LANDSCAPE else: if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented in such a way that the height is taller than it is wide. ui.message(_("Portrait")) self.orientationStateCache = self.ORIENTATION_PORTRAIT def handlePowerStatusChange(self): #Mostly taken from script_say_battery_status, but modified. import ui import winKernel sps = winKernel.SYSTEM_POWER_STATUS() if not winKernel.GetSystemPowerStatus(sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS: return if sps.BatteryFlag & self.NO_SYSTEM_BATTERY: return if self.oldBatteryStatus is None: #Just initializing the cache, do not report anything. self.oldBatteryStatus = sps.ACLineStatus return if sps.ACLineStatus == self.oldBatteryStatus: #Sometimes, this double fires. This also fires when the battery level decreases by 3%. return self.oldBatteryStatus = sps.ACLineStatus if sps.ACLineStatus & self.AC_ONLINE: #Translators: Reported when the battery is plugged in, and now is charging. ui.message(_("Charging battery. %d percent") % sps.BatteryLifePercent) else: #Translators: Reported when the battery is no longer plugged in, and now is not charging. ui.message(_("Not charging battery. %d percent") %sps.BatteryLifePercent) messageWindow = MessageWindow(unicode(versionInfo.name)) # initialize wxpython localization support locale = wx.Locale() lang=languageHandler.getLanguage() wxLang=locale.FindLanguageInfo(lang) if not wxLang and '_' in lang: wxLang=locale.FindLanguageInfo(lang.split('_')[0]) if hasattr(sys,'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) # #8064: Wx might know the language, but may not actually contain a translation database for that language. # If we try to initialize this language, wx will show a warning dialog. # Therefore treat this situation like wx not knowing the language at all. if not locale.IsAvailable(wxLang.Language): wxLang=None if wxLang: try: locale.Init(wxLang.Language) except: log.error("Failed to initialize wx locale",exc_info=True) else: log.debugWarning("wx does not support language %s" % lang) import api import winUser import NVDAObjects.window desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install or globalVars.appArgs.installSilent: import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent) elif globalVars.appArgs.portablePath and (globalVars.appArgs.createPortable or globalVars.appArgs.createPortableSilent): import gui.installerGui wx.CallAfter(gui.installerGui.doCreatePortable,portableDirectory=globalVars.appArgs.portablePath, silent=globalVars.appArgs.createPortableSilent,startAfterCreate=not globalVars.appArgs.createPortableSilent) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject # Doing this here is a bit ugly, but we don't want these modules imported # at module level, including wx. log.debug("Initializing core pump") class CorePump(gui.NonReEntrantTimer): "Checks the queues and executes functions." def run(self): global _isPumpPending _isPumpPending = False watchdog.alive() try: if touchHandler.handler: touchHandler.handler.pump() JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.asleep() if _isPumpPending and not _pump.IsRunning(): # #3803: Another pump was requested during this pump execution. # As our pump is not re-entrant, schedule another pump. _pump.Start(PUMP_MAX_DELAY, True) global _pump _pump = CorePump() requestPump() log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck=None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") postNvdaStartup.notify() log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: _terminate(updateCheck) _terminate(watchdog) _terminate(globalPluginHandler, name="global plugin handler") _terminate(gui) config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.exception("Lose focus error") try: speech.cancelSpeech() except: pass import treeInterceptorHandler _terminate(treeInterceptorHandler) _terminate(IAccessibleHandler, name="IAccessible support") _terminate(UIAHandler, name="UIA support") _terminate(winConsoleHandler, name="winConsole support") _terminate(JABHandler, name="Java Access Bridge support") _terminate(appModuleHandler, name="app module handler") _terminate(NVDAHelper) _terminate(touchHandler) _terminate(keyboardHandler, name="keyboard handler") _terminate(mouseHandler) _terminate(inputCore) _terminate(brailleInput) _terminate(braille) _terminate(speech) _terminate(addonHandler) if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass # #5189: Destroy the message window as late as possible # so new instances of NVDA can find this one even if it freezes during exit. messageWindow.destroy() log.debug("core done")
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop. """ log.debug("Core starting") try: # Windows >= Vista ctypes.windll.user32.SetProcessDPIAware() except AttributeError: pass import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.initialize() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s"%lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s"%lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %s" % winVersion.winVersionText) log.info("Using Python version %s"%sys.version) log.info("Using comtypes version %s"%comtypes.__version__) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing add-ons system") addonHandler.initialize() if globalVars.appArgs.disableAddons: log.info("Add-ons are disabled. Restart NVDA to enable them.") import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx log.info("Using wx version %s"%wx.version()) class App(wx.App): def OnAssert(self,file,line,cond,msg): message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg) log.debugWarning(message,codepath="WX Widgets",stack_info=True) app = App(redirect=False) # We do support QueryEndSession events, but we don't want to do anything for them. app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) import braille log.debug("Initializing braille") braille.initialize() log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() import audioDucking if audioDucking.isAudioDuckingSupported(): # the GUI mainloop must be running for this to work so delay it wx.CallAfter(audioDucking.initialize) # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. # NVDA uses the main frame to check for and quit another instance of NVDA. # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. # We don't need to do anything else because wx handles WM_QUIT for all windows. import windowUtils class MessageWindow(windowUtils.CustomWindow): className = u"wxWindowClassNR" messageWindow = MessageWindow(unicode(versionInfo.name)) # initialize wxpython localization support locale = wx.Locale() lang=languageHandler.getLanguage() wxLang=locale.FindLanguageInfo(lang) if not wxLang and '_' in lang: wxLang=locale.FindLanguageInfo(lang.split('_')[0]) if hasattr(sys,'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) if wxLang: try: locale.Init(wxLang.Language) except: log.error("Failed to initialize wx locale",exc_info=True) else: log.debugWarning("wx does not support language %s" % lang) import api import winUser import NVDAObjects.window desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install or globalVars.appArgs.installSilent: import wx import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject # Doing this here is a bit ugly, but we don't want these modules imported # at module level, including wx. log.debug("Initializing core pump") class CorePump(wx.Timer): "Checks the queues and executes functions." def Notify(self): global _isPumpPending _isPumpPending = False watchdog.alive() try: if touchHandler.handler: touchHandler.handler.pump() JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.asleep() if _isPumpPending and not _pump.IsRunning(): # #3803: A pump was requested, but the timer was ignored by a modal loop # because timers aren't re-entrant. # Therefore, schedule another pump. _pump.Start(PUMP_MAX_DELAY, True) global _pump _pump = CorePump() requestPump() log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck=None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: _terminate(updateCheck) _terminate(watchdog) _terminate(globalPluginHandler, name="global plugin handler") _terminate(gui) config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.exception("Lose focus error") try: speech.cancelSpeech() except: pass import treeInterceptorHandler _terminate(treeInterceptorHandler) _terminate(IAccessibleHandler, name="IAccessible support") _terminate(UIAHandler, name="UIA support") _terminate(winConsoleHandler, name="winConsole support") _terminate(JABHandler, name="Java Access Bridge support") _terminate(appModuleHandler, name="app module handler") _terminate(NVDAHelper) _terminate(touchHandler) _terminate(keyboardHandler, name="keyboard handler") _terminate(mouseHandler) _terminate(inputCore) _terminate(brailleInput) _terminate(braille) _terminate(speech) _terminate(addonHandler) if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass # #5189: Destroy the message window as late as possible # so new instances of NVDA can find this one even if it freezes during exit. messageWindow.destroy() log.debug("core done")
def event_UIA_elementSelected(self): focusControllerFor=api.getFocusObject().controllerFor if len(focusControllerFor)>0 and focusControllerFor[0].appModule is self.appModule and self.name: speech.cancelSpeech() api.setNavigatorObject(self) self.reportFocus()
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and installs the core pump timer, which checks the queues and executes functions every 1 ms. Finally, it starts the wx main loop. """ log.debug("Core starting") import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.load() if not globalVars.appArgs.minimal: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s"%lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s"%lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %r" % (sys.getwindowsversion(),)) log.info("Using Python version %s"%sys.version) log.info("Using comtypes version %s"%comtypes.__version__) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing addons system.") addonHandler.initialize() import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx log.info("Using wx version %s"%wx.version()) app = wx.App(redirect=False) # HACK: wx currently raises spurious assertion failures when a timer is stopped but there is already an event in the queue for that timer. # Unfortunately, these assertion exceptions are raised in the middle of other code, which causes problems. # Therefore, disable assertions for now. app.SetAssertMode(wx.PYAPP_ASSERT_SUPPRESS) # We do support QueryEndSession events, but we don't want to do anything for them. app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) import braille log.debug("Initializing braille") braille.initialize() log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() # initialize wxpython localization support locale = wx.Locale() lang=languageHandler.getLanguage() if '_' in lang: wxLang=lang.split('_')[0] else: wxLang=lang if hasattr(sys,'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) try: locale.Init(lang,wxLang) except: pass import api import winUser import NVDAObjects.window desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install: import wx import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject class CorePump(wx.Timer): "Checks the queues and executes functions." def __init__(self,*args,**kwargs): log.debug("Core pump starting") super(CorePump,self).__init__(*args,**kwargs) def Notify(self): try: JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.alive() log.debug("starting core pump") pump = CorePump() pump.Start(1) log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck=None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: log.debug("Terminating updateCheck") updateCheck.terminate() log.debug("Terminating watchdog") watchdog.terminate() log.debug("Terminating global plugin handler") globalPluginHandler.terminate() log.debug("Terminating GUI") gui.terminate() config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.error("Lose focus error",exc_info=True) try: speech.cancelSpeech() except: pass log.debug("Cleaning up running treeInterceptors") try: import treeInterceptorHandler treeInterceptorHandler.terminate() except: log.error("Error cleaning up treeInterceptors",exc_info=True) log.debug("Terminating IAccessible support") try: IAccessibleHandler.terminate() except: log.error("Error terminating IAccessible support",exc_info=True) log.debug("Terminating UIA support") try: UIAHandler.terminate() except: log.error("Error terminating UIA support",exc_info=True) log.debug("Terminating winConsole support") try: winConsoleHandler.terminate() except: log.error("Error terminating winConsole support",exc_info=True) log.debug("Terminating Java Access Bridge support") try: JABHandler.terminate() except: log.error("Error terminating Java Access Bridge support",exc_info=True) log.debug("Terminating app module handler") appModuleHandler.terminate() log.debug("Terminating NVDAHelper") try: NVDAHelper.terminate() except: log.error("Error terminating NVDAHelper",exc_info=True) log.debug("Terminating touchHandler") try: touchHandler.terminate() except: log.error("Error terminating touchHandler") log.debug("Terminating keyboard handler") try: keyboardHandler.terminate() except: log.error("Error terminating keyboard handler") log.debug("Terminating mouse handler") try: mouseHandler.terminate() except: log.error("error terminating mouse handler",exc_info=True) log.debug("Terminating input core") inputCore.terminate() log.debug("Terminating brailleInput") brailleInput.terminate() log.debug("Terminating braille") try: braille.terminate() except: log.error("Error terminating braille",exc_info=True) log.debug("Terminating speech") try: speech.terminate() except: log.error("Error terminating speech",exc_info=True) try: addonHandler.terminate() except: log.error("Error terminating addonHandler",exc_info=True) if not globalVars.appArgs.minimal: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.debug("core done")
# Much of this should eventually be replaced by stuff which gets reset before each test # so the tests are isolated. import config config.initialize() # Initialize languageHandler so that translatable strings work. import languageHandler languageHandler.setLanguage("en") # NVDAObjects need appModuleHandler to be initialized. import appModuleHandler appModuleHandler.initialize() # Anything which notifies of cursor updates requires braille to be initialized. import braille braille.initialize() # For braille unit tests, we need to construct a fake braille display as well as enable the braille handler # Give the display 40 cells braille.handler.displaySize=40 braille.handler.enabled = True # The focus and navigator objects need to be initialized to something. from objectProvider import PlaceholderNVDAObject,NVDAObjectWithRole phObj = PlaceholderNVDAObject() import api api.setFocusObject(phObj) api.setNavigatorObject(phObj) api.setDesktopObject(phObj) # Stub speech functions to make them no-ops. # Eventually, these should keep track of calls so we can make assertions. import speech speech.speak = lambda speechSequence, symbolLevel=None: None speech.speakSpelling = lambda text, locale=None, useCharacterDescriptions=False: None