def updateSupportedSettings(self,synth): import ui from scriptHandler import _isScriptRunning #Save name of the current setting to restore ring position after reconstruction prevName=self.settings[self._current].setting.name if self._current is not None and hasattr(self,'settings') else None list = [] for s in synth.supportedSettings: if not s.availableInSynthSettingsRing: continue if prevName==s.name: #restore the last setting self._current=len(list) if isinstance(s,synthDriverHandler.NumericSynthSetting): cls=SynthSetting elif isinstance(s,synthDriverHandler.BooleanSynthSetting): cls=BooleanSynthSetting else: cls=StringSynthSetting list.append(cls(synth,s)) if len(list) == 0: self._current = None self.settings = None else: self.settings = list if not prevName or not self.settings or len(self.settings)<=self._current or prevName!=self.settings[self._current].setting.name: #Previous chosen setting doesn't exists. Set position to default self._current = synth.initialSettingsRingSetting if _isScriptRunning: #User changed some setting from ring and that setting no more exists. We have just reverted to first setting, so report this change to user queueHandler.queueFunction(queueHandler.eventQueue,ui.message,"%s %s" % (self.currentSettingName,self.currentSettingValue))
def event_valueChange(self): pbConf=config.conf["presentation"]["progressBarUpdates"] states=self.states if pbConf["progressBarOutputMode"]=="off" or controlTypes.STATE_INVISIBLE in states or controlTypes.STATE_OFFSCREEN in states: return super(ProgressBar,self).event_valueChange() val=self.value try: percentage = min(max(0.0, float(val.strip("%\0"))), 100.0) except (AttributeError, ValueError): log.debugWarning("Invalid value: %r" % val) return super(ProgressBar, self).event_valueChange() braille.handler.handleUpdate(self) if not pbConf["reportBackgroundProgressBars"] and not self.isInForeground: return try: left,top,width,height=self.location except: left=top=width=height=0 x=left+(width/2) y=top+(height/2) lastBeepProgressValue=self.progressValueCache.get("beep,%d,%d"%(x,y),None) if pbConf["progressBarOutputMode"] in ("beep","both") and (lastBeepProgressValue is None or abs(percentage-lastBeepProgressValue)>=pbConf["beepPercentageInterval"]): tones.beep(pbConf["beepMinHZ"]*2**(percentage/25.0),40) self.progressValueCache["beep,%d,%d"%(x,y)]=percentage lastSpeechProgressValue=self.progressValueCache.get("speech,%d,%d"%(x,y),None) if pbConf["progressBarOutputMode"] in ("speak","both") and (lastSpeechProgressValue is None or abs(percentage-lastSpeechProgressValue)>=pbConf["speechPercentageInterval"]): queueHandler.queueFunction(queueHandler.eventQueue,speech.speakMessage,_("%d percent")%percentage) self.progressValueCache["speech,%d,%d"%(x,y)]=percentage
def nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString): global lastInputLangChangeTime import queueHandler import ui curTime=time.time() if (curTime-lastInputLangChangeTime)<0.2: return 0 lastInputLangChangeTime=curTime #layoutString can sometimes be None, yet a registry entry still exists for a string representation of hkl if not layoutString: layoutString=hex(hkl)[2:].rstrip('L').upper().rjust(8,'0') log.debugWarning("layoutString was None, generated new one from hkl as %s"%layoutString) layoutName=_lookupKeyboardLayoutNameWithHexString(layoutString) if not layoutName and hkl<0xd0000000: #Try using the high word of hkl as the lang ID for a default layout for that language simpleLayoutString=layoutString[0:4].rjust(8,'0') log.debugWarning("trying simple version: %s"%simpleLayoutString) layoutName=_lookupKeyboardLayoutNameWithHexString(simpleLayoutString) if not layoutName: #Try using the low word of hkl as the lang ID for a default layout for that language simpleLayoutString=layoutString[4:].rjust(8,'0') log.debugWarning("trying simple version: %s"%simpleLayoutString) layoutName=_lookupKeyboardLayoutNameWithHexString(simpleLayoutString) if not layoutName: log.debugWarning("Could not find layout name for keyboard layout, reporting as unknown") layoutName=_("unknown layout") queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("layout %s")%layoutName) return 0
def __call__(self): # calling this object with no arguments will work. This way we can use the class as the object to call. queueHandler.queueFunction(queueHandler.eventQueue, tipDialog.create) #This should queue this to open in the future when NVDA is ready. Seems to prevent an issue with the dialog not appearing thince this gets called randomly. lastUse = TipTimeManager(time.time()) config = tipConfig.conf config["internal"]["lastUse"] = lastUse.toNormalizedTime() config.save() lastUse.alert(self) #register callBack again. If we die before the next day, that's fine, but we want to make sure the tip will pop up in one day if need be.
def changeNotify(cls, rootDocHandle, rootID): try: queueHandler.queueFunction( queueHandler.eventQueue, cls.rootIdentifiers[rootDocHandle, rootID]._handleUpdate ) except KeyError: pass
def _monitor(self): try: oldLines = self._getTextLines() except: log.exception("Error getting initial lines") oldLines = [] while self._keepMonitoring: self._event.wait() if not self._keepMonitoring: break if self.STABILIZE_DELAY > 0: # wait for the text to stabilise. time.sleep(self.STABILIZE_DELAY) if not self._keepMonitoring: # Monitoring was stopped while waiting for the text to stabilise. break self._event.clear() try: newLines = self._getTextLines() if config.conf["presentation"]["reportDynamicContentChanges"]: outLines = self._calculateNewText(newLines, oldLines) if len(outLines) == 1 and len(outLines[0]) == 1: # This is only a single character, # which probably means it is just a typed character, # so ignore it. del outLines[0] for line in outLines: queueHandler.queueFunction(queueHandler.eventQueue, self._reportNewText, line) oldLines = newLines except: log.exception("Error getting lines or calculating new text")
def nvdaController_brailleMessage(text): focus=api.getFocusObject() if focus.sleepMode==focus.SLEEP_FULL: return -1 import queueHandler import braille queueHandler.queueFunction(queueHandler.eventQueue,braille.handler.message,text) return 0
def nvdaController_cancelSpeech(): focus=api.getFocusObject() if focus.sleepMode==focus.SLEEP_FULL: return -1 import queueHandler import speech queueHandler.queueFunction(queueHandler.eventQueue,speech.cancelSpeech) return 0
def nvdaController_speakText(text): focus=api.getFocusObject() if focus.sleepMode==focus.SLEEP_FULL: return -1 import queueHandler import speech queueHandler.queueFunction(queueHandler.eventQueue,speech.speakText,text) return 0
def _metadataAnnouncerInternal(status, startup=False): import nvwave, queueHandler, speech if not startup: speech.cancelSpeech() queueHandler.queueFunction(queueHandler.eventQueue, ui.message, status) nvwave.playWaveFile(os.path.join(os.path.dirname(__file__), "SPL_Metadata.wav")) # #51 (18.03/15.14-LTS): close link to metadata announcer thread when finished. global _earlyMetadataAnnouncer _earlyMetadataAnnouncer = None
def _insertCompletion(self, original, completed): self.completionAmbiguous = False insert = completed[len(original):] if not insert: return self.inputCtrl.SetValue(self.inputCtrl.GetValue() + insert) queueHandler.queueFunction(queueHandler.eventQueue, speech.speakText, insert) self.inputCtrl.SetInsertionPointEnd()
def nvdaControllerInternal_inputLangChangeNotify(threadID,hkl,layoutString): global lastInputMethodName, lastInputLanguageName focus=api.getFocusObject() #This callback can be called before NVDa is fully initialized #So also handle focus object being None as well as checking for sleepMode if not focus or focus.sleepMode: return 0 import NVDAObjects.window #Generally we should not allow input lang changes from threads that are not focused. #But threadIDs for console windows are always wrong so don't ignore for those. if not isinstance(focus,NVDAObjects.window.Window) or (threadID!=focus.windowThreadID and focus.windowClassName!="ConsoleWindowClass"): return 0 import sayAllHandler #Never announce changes while in sayAll (#1676) if sayAllHandler.isRunning(): return 0 import queueHandler import ui languageID=hkl&0xffff buf=create_unicode_buffer(1024) res=windll.kernel32.GetLocaleInfoW(languageID,2,buf,1024) # Translators: the label for an unknown language when switching input methods. inputLanguageName=buf.value if res else _("unknown language") layoutStringCodes=[] inputMethodName=None #layoutString can either be a real input method name, a hex string for an input method name in the registry, or an empty string. #If its a real input method name its used as is. #If its a hex string or its empty, then the method name is looked up by trying: #The full hex string, the hkl as a hex string, the low word of the hex string or hkl, the high word of the hex string or hkl. if layoutString: try: int(layoutString,16) layoutStringCodes.append(layoutString) except ValueError: inputMethodName=layoutString if not inputMethodName: layoutStringCodes.insert(0,hex(hkl)[2:].rstrip('L').upper().rjust(8,'0')) for stringCode in list(layoutStringCodes): layoutStringCodes.append(stringCode[4:].rjust(8,'0')) if stringCode[0]<'D': layoutStringCodes.append(stringCode[0:4].rjust(8,'0')) for stringCode in layoutStringCodes: inputMethodName=_lookupKeyboardLayoutNameWithHexString(stringCode) if inputMethodName: break if not inputMethodName: log.debugWarning("Could not find layout name for keyboard layout, reporting as unknown") # Translators: The label for an unknown input method when switching input methods. inputMethodName=_("unknown input method") if ' - ' in inputMethodName: inputMethodName="".join(inputMethodName.split(' - ')[1:]) if inputLanguageName!=lastInputLanguageName: lastInputLanguageName=inputLanguageName # Translators: the message announcing the language and keyboard layout when it changes inputMethodName=_("{language} - {layout}").format(language=inputLanguageName,layout=inputMethodName) if inputMethodName!=lastInputMethodName: lastInputMethodName=inputMethodName queueHandler.queueFunction(queueHandler.eventQueue,ui.message,inputMethodName) return 0
def onOk(self, evt): action=self.actionsList.GetSelection() if action == 0: wx.GetApp().ExitMainLoop() elif action == 1: queueHandler.queueFunction(queueHandler.eventQueue,core.restart) elif action == 2: queueHandler.queueFunction(queueHandler.eventQueue,core.restart,True) self.Destroy()
def onSaveConfigurationCommand(self,evt): if globalVars.appArgs.secure: queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Cannot save configuration - NVDA in secure mode")) return try: config.save() queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Configuration saved")) except: messageBox(_("Could not save configuration - probably read only file system"),_("Error"),wx.OK | wx.ICON_ERROR)
def nvdaControllerInternal_IMEOpenStatusUpdate(opened): if opened: # Translators: a message when the IME open status changes to opened message=_("IME opened") else: # Translators: a message when the IME open status changes to closed message=_("IME closed") import ui queueHandler.queueFunction(queueHandler.eventQueue,ui.message,message) return 0
def _loadBuffer(self): try: self.VBufHandle=NVDAHelper.localLib.VBuf_createBuffer(self.rootNVDAObject.appModule.helperLocalBindingHandle,self.rootDocHandle,self.rootID,unicode(self.backendName)) if not self.VBufHandle: raise RuntimeError("Could not remotely create virtualBuffer") except: log.error("", exc_info=True) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone, success=False) return queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone)
def nvdaControllerInternal_inputCompositionUpdate(compositionString,selectionStart,selectionEnd,isReading): from NVDAObjects.inputComposition import InputComposition if selectionStart==-1: queueHandler.queueFunction(queueHandler.eventQueue,handleInputCompositionEnd,compositionString) return 0 focus=api.getFocusObject() if isinstance(focus,InputComposition): focus.compositionUpdate(compositionString,selectionStart,selectionEnd,isReading) else: queueHandler.queueFunction(queueHandler.eventQueue,handleInputCompositionStart,compositionString,selectionStart,selectionEnd,isReading) return 0
def event_suggestionsOpened(self): super(SearchField, self).event_suggestionsOpened() # Announce number of items found (except in Start search box where the suggestions are selected as user types). # Oddly, Edge's address omnibar returns 0 for suggestion count when there are clearly suggestions (implementation differences). # Because inaccurate count could be announced (when users type, suggestion count changes), thus announce this if position info reporting is enabled. if config.conf["presentation"]["reportObjectPositionInformation"]: if self.UIAElement.cachedAutomationID == "TextBox" or self.UIAElement.cachedAutomationID == "SearchTextBox" and self.appModule.appName != "searchui": # Item count must be the last one spoken. suggestionsCount = self.controllerFor[0].childCount suggestionsMessage = "1 suggestion" if suggestionsCount == 1 else "%s suggestions"%suggestionsCount queueHandler.queueFunction(queueHandler.eventQueue, ui.message, suggestionsMessage)
def queueEvent(eventName,obj,**kwargs): """Queues an NVDA event to be executed. @param eventName: the name of the event type (e.g. 'gainFocus', 'nameChange') @type eventName: string """ global lastQueuedFocusObject queueHandler.queueFunction(queueHandler.eventQueue,_queueEventCallback,eventName,obj,kwargs) if eventName=="gainFocus": lastQueuedFocusObject=obj _pendingEventCountsByName[eventName]=_pendingEventCountsByName.get(eventName,0)+1 _pendingEventCountsByObj[obj]=_pendingEventCountsByObj.get(obj,0)+1 _pendingEventCountsByNameAndObj[(eventName,obj)]=_pendingEventCountsByNameAndObj.get((eventName,obj),0)+1
def onSaveConfigurationCommand(self,evt): if globalVars.appArgs.secure: # Translators: Reported when current configuration cannot be saved while NVDA is running in secure mode such as in Windows login screen. queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Cannot save configuration - NVDA in secure mode")) return try: config.conf.save() # Translators: Reported when current configuration has been saved. queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Configuration saved")) except: # Translators: Message shown when current configuration cannot be saved such as when running NVDA from a CD. messageBox(_("Could not save configuration - probably read only file system"),_("Error"),wx.OK | wx.ICON_ERROR)
def reportSelectedCandidate(candidateObject,allowDuplicate=False,newList=False): if not eventHandler.isPendingEvents("gainFocus") and (allowDuplicate or candidateObject!=api.getFocusObject()): if not isinstance(api.getFocusObject(),BaseCandidateItem): oldCandidateItemsText=None candidateObject.container=api.getFocusObject() eventHandler.queueEvent("foreground",candidateObject) else: oldCandidateItemsText=api.getFocusObject().visibleCandidateItemsText candidateObject.container=api.getFocusObject().container if config.conf["inputComposition"]["autoReportAllCandidates"] and (newList or candidateObject.visibleCandidateItemsText!=oldCandidateItemsText): queueHandler.queueFunction(queueHandler.eventQueue,ui.message,candidateObject.visibleCandidateItemsText) eventHandler.queueEvent("gainFocus",candidateObject)
def _recogOnResult(result): global _activeRecog _activeRecog = None # This might get called from a background thread, so any UI calls must be queued to the main thread. if isinstance(result, Exception): # Translators: Reported when recognition (e.g. OCR) fails. log.error("Recognition failed: %s" % result) queueHandler.queueFunction(queueHandler.eventQueue, ui.message, _("Recognition failed")) return resObj = RecogResultNVDAObject(result=result) # This method queues an event to the main thread. resObj.setFocus()
def disp(Values): if(WFlag == True): # ディスプレイ出力 buff1=create_string_buffer(DirectBM_dic.Ret2(Values),80) buff2=create_string_buffer('',80) try: dll.bmDisplayData(buff1,buff2,DispSize) except: pass try: queueHandler.queueFunction(queueHandler.eventQueue,ui.message,Values) except: pass
def onSaveConfigurationCommand(self,evt): if globalVars.appArgs.secure: queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Cannot save configuration - NVDA in secure mode")) return try: config.save() queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("configuration saved")) except: self.prePopup() d = wx.MessageDialog(self,_("Could not save configuration - probably read only file system"),_("Error"),style=wx.OK | wx.ICON_ERROR) d.ShowModal() d.Destroy() self.postPopup()
def checkAutoAction(self): with self.lock: if not self.isReady: return funcMoveto = None firstCancelSpeech = True for result in self.markerResults: if result.markerQuery.autoAction: controlIdentifier = result.node.controlIdentifier # check only 100 first characters text = result.node.getTreeInterceptorText()[:100] autoActionName = result.markerQuery.autoAction func = getattr(result, "script_%s" % autoActionName) lastText = self.triggeredIdentifiers.get(controlIdentifier) if (lastText is None or text != lastText): self.triggeredIdentifiers[controlIdentifier] = text if autoActionName == "speak": playWebAppSound("errorMessage") elif autoActionName == "moveto": if lastText is None: # only if it's a new identifier if funcMoveto is None: if func.__name__== self.lastAutoMoveto \ and time.time() - self.lastAutoMovetoTime < 4: # no autoMoveto of same rule before 4 seconds continue else: funcMoveto = func func = None if func: if firstCancelSpeech: speech.cancelSpeech() firstCancelSpeech = False try: queueHandler.queueFunction( queueHandler.eventQueue, func, None) except: log.exception( (u'Error in rule "{rule}" while executing' u' autoAction "{autoAction}"').format( rule=result.markerQuery.name, autoAction=autoActionName)) if funcMoveto is not None: if firstCancelSpeech: speech.cancelSpeech() firstCancelSpeech = False self.lastAutoMoveto = funcMoveto.__name__ self.lastAutoMovetoTime = time.time() queueHandler.queueFunction(queueHandler.eventQueue, funcMoveto, None)
def _get_Menus(self, obj): if len( assignedShortcuts ) == 0 and obj.previous and obj.previous.role == controlTypes.ROLE_MENUBAR: menus = obj.previous.children # 9 menus for V2.1.3 and 10(+2) for V2.2.0 # 11 menus for V2.2.2 and presumably 12for V2.3.0 if len(menus) >= 9: signet = dataPath + 'signet.wav' playWaveFile(signet) for menu in menus: queueHandler.queueFunction(queueHandler.eventQueue, self._get_menuItem, menu) return True
def _loadBuffer(self): try: self.VBufHandle = NVDAHelper.localLib.VBuf_createBuffer( self.rootNVDAObject.appModule.helperLocalBindingHandle, self.rootDocHandle, self.rootID, unicode(self.backendName)) if not self.VBufHandle: raise RuntimeError("Could not remotely create virtualBuffer") except: log.error("", exc_info=True) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone, success=False) return queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone)
def sayHelpText(self): def getExplanationText(): textList = [] for o in self.pane.children[1:]: if o.role in [controlTypes.ROLE_STATICTEXT, controlTypes.ROLE_LINK]\ and controlTypes.STATE_INVISIBLE not in o.states: textList.append(o.name) if len(textList): return "\n".join(textList) else: # Translators: message to user that there is no help. return _("No explanation help") text = getExplanationText() queueHandler.queueFunction(queueHandler.eventQueue, ui.message, text)
def triggerNVDAExit(newNVDA: Optional[NewNVDAInstance] = None): """ Used to safely exit NVDA. If a new instance is required to start after exit, queue one by specifying instance information with `newNVDA`. """ import queueHandler global _hasShutdownBeenTriggered with _shuttingDownFlagLock: if not _hasShutdownBeenTriggered: # queue this so that the calling process can exit safely (eg a Popup menu) queueHandler.queueFunction(queueHandler.eventQueue, _doShutdown, newNVDA) _hasShutdownBeenTriggered = True else: log.debugWarning("NVDA exit has already been triggered")
def event_gainFocus(self): printDebug("InAnchoredPlaylist: event_gainFocus: %s, isFocusable: %s, " % (controlTypes.roleLabels[self.role], self.isFocusable)) # noqa:E501 # if it's first event_gainFocus in anchored playlist, # speak anchored playlist name previousFocus = self.appModule.lastFocusedObject if previousFocus is None: previousFocus = self if not hasattr(previousFocus, "inAnchoredPlaylist")\ or not hasattr(previousFocus, "playlistSpoken")\ or not previousFocus.playlistSpoken: queueHandler.queueFunction( queueHandler.eventQueue, speech.speakMessage, VLCAnchoredPlaylist._playlistName) self.playlistSpoken = True queueHandler.queueFunction(queueHandler.eventQueue, self.reportFocus)
def nextLine(self): try: dest = self._readingInfo.copy() moved = dest.move(self._getReadingUnit(), 1) if not moved: if self.allowPageTurns and isinstance(dest.obj, textInfos.DocumentWithPageTurns): try: dest.obj.turnPage() except RuntimeError: pass else: dest = dest.obj.makeTextInfo(textInfos.POSITION_FIRST) else: return dest.collapse() self._setCursor(dest) queueHandler.queueFunction(queueHandler.eventQueue, speech.cancelSpeech) queueHandler.queueFunction(queueHandler.eventQueue, sayCurrentLine) except BaseException: pass
def getMeaning(text, base_url): t = MyThread(text, base_url) t.start() while not t.meaning and not t.error and t.is_alive(): beep(500, 100) time.sleep(0.5) t.join() title = u'المَعَاني message box' useDefaultFullBrowser = config.conf["dictionariesAlmaany"][ "windowType"] == 0 useBrowserWindowOnly = config.conf["dictionariesAlmaany"][ "windowType"] == 1 useNvdaMessageBox = config.conf["dictionariesAlmaany"][ "windowType"] == 2 if t.meaning and useDefaultFullBrowser: openBrowserWindow('default', t.meaning, directive='', default=True) elif t.meaning and useBrowserWindowOnly: if 'Firefox' in browsers and not appIsRunning('firefox.exe'): openBrowserWindow('Firefox', t.meaning, directive=' --kiosk ') elif 'Google Chrome' in browsers and not appIsRunning( 'chrome.exe'): openBrowserWindow('Google Chrome', t.meaning, directive=' -kiosk ') elif 'Internet Explorer' in browsers: openBrowserWindow('Internet Explorer', t.meaning, directive=' -k -private ') elif t.meaning and useNvdaMessageBox: queueHandler.queueFunction(queueHandler.eventQueue, ui.browseableMessage, t.meaning, title=title, isHtml=True) return elif t.error: if t.error == "HTTP Error 410: Gone": # Translators: Message displayed if error happened. msg = _("No meaning found") elif t.error == "<urlopen error [Errno 11001] getaddrinfo failed>": # Translators: Message displayed if error happened. msg = _("Most likely no internet connection") else: msg = t.error errorMessage = "{}( {})".format(_("Sorry, An Error Happened"), msg) queueHandler.queueFunction(queueHandler.eventQueue, ui.message, errorMessage)
def _loadBuffer(self): try: if log.isEnabledFor(log.DEBUG): startTime = time.time() self.VBufHandle=NVDAHelper.localLib.VBuf_createBuffer(self.rootNVDAObject.appModule.helperLocalBindingHandle,self.rootDocHandle,self.rootID,unicode(self.backendName)) if not self.VBufHandle: raise RuntimeError("Could not remotely create virtualBuffer") except: log.error("", exc_info=True) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone, success=False) return if log.isEnabledFor(log.DEBUG): log.debug("Buffer load took %.3f sec, %d chars" % ( time.time() - startTime, NVDAHelper.localLib.VBuf_getTextLength(self.VBufHandle))) queueHandler.queueFunction(queueHandler.eventQueue, self._loadBufferDone)
def internal_mouseEvent(msg,x,y,injected): global mouseMoved, curMousePos, lastMouseEventTime lastMouseEventTime=time.time() if injected: return True if not config.conf['mouse']['enableMouseTracking']: return True try: curMousePos=(x,y) if msg==WM_MOUSEMOVE: mouseMoved=True elif msg in (WM_LBUTTONDOWN,WM_RBUTTONDOWN): queueHandler.queueFunction(queueHandler.eventQueue,speech.cancelSpeech) except: log.error("", exc_info=True) return True
def script_calculatorResult(self, gesture): # To prevent double focus announcement, check where we are. focus = api.getFocusObject() gesture.send() # In redstone, calculator result keeps firing name change, so tell it to do so if and only if enter has been pressed. self._shouldAnnounceResult = True # Hack: only announce display text when an actual calculator button (usually equals button) is pressed. # In redstone, pressing enter does not move focus to equals button. if isinstance(focus, UIA): if focus.UIAElement.cachedAutomationID == "CalculatorResults": queueHandler.queueFunction(queueHandler.eventQueue, focus.reportFocus) else: resultsScreen = api.getForegroundObject().children[1].lastChild if isinstance(resultsScreen, UIA) and resultsScreen.UIAElement.cachedClassName == "LandmarkTarget": # And no, do not allow focus to move. queueHandler.queueFunction(queueHandler.eventQueue, resultsScreen.firstChild.reportFocus)
def script_continuePlayback(self, gesture): printDebug("InMainWindow: script_continuePlayback alt+R VLC Command script") if self.hasNoMedia(): return mainWindow = self.appModule.mainWindow isPlaying = mainWindow.isPlaying() if isPlaying: mainWindow.togglePlayOrPause() mainWindow.mainPanel.pushContinuePlaybackButton() time.sleep(0.2) mainWindow.resetMediaStates(False) mainWindow.sayElapsedTime() queueHandler.queueFunction( queueHandler.eventQueue, mainWindow.togglePlayOrPause) queueHandler.queueFunction( queueHandler.eventQueue, mainWindow.reportMediaStates)
def queueEvent(eventName, obj, **kwargs): """Queues an NVDA event to be executed. @param eventName: the name of the event type (e.g. 'gainFocus', 'nameChange') @type eventName: string """ _trackFocusObject(eventName, obj) with _pendingEventCountsLock: _pendingEventCountsByName[eventName] = _pendingEventCountsByName.get( eventName, 0) + 1 _pendingEventCountsByObj[obj] = _pendingEventCountsByObj.get(obj, 0) + 1 _pendingEventCountsByNameAndObj[( eventName, obj)] = _pendingEventCountsByNameAndObj.get( (eventName, obj), 0) + 1 queueHandler.queueFunction(queueHandler.eventQueue, _queueEventCallback, eventName, obj, kwargs)
def translate(self, text: str, isHtml: bool = False) -> None: """Retrieve the dictionary entry for the given word or phrase and display/announce the result. This method must always be called in a separate thread so as not to block NVDA. @param text: a word or phrase to look up in a dictionary @type text: str @param isHtml: a sign of whether it is necessary to display the result of work in the form of HTML page @type isHtml: bool """ active = config.conf[addonName]['active'] langs = services[active].langs pairs = [(self.source, self.target)] if self.isAutoSwap: if langs.isAvailable(self.target, self.source): pairs.append((self.target, self.source)) for lFrom, lInto in pairs: translator = translateWithCaching(lFrom, lInto, text, hashForCache(active)) if translator.error: translateWithCaching.cache_clear() # reset cache when HTTP errors occur self._cacheInfo = str(translateWithCaching.cache_info()) # - to check the current status of queries cache if translator.plaintext: break else: if not translator.plaintext: # Translators: Notification of missing dictionary entry for current request ui.message(_("No results")) self._messages.clear() return self._lastTranslator = translator setattr(self._lastTranslator, 'id', active) if isHtml: ui.browseableMessage( message=translator.html, title='%s-%s' % (langs[translator.langFrom].name, langs[translator.langTo].name), isHtml=isHtml ) else: self._messages.append('%s - %s' % (langs[translator.langFrom].name, langs[translator.langTo].name)) self._messages.append(translator.plaintext) message = '...'.join(self._messages) self._messages.clear() queueFunction( eventQueue, messageWithLangDetection, {'text': message, 'lang': translator.langTo} ) if self.isCopyToClipboard: api.copyToClip(translator.plaintext, notify=True)
def executeGesture(self, gesture): """Perform the action associated with a gesture. @param gesture: The gesture to execute. @type gesture: L{InputGesture} @raise NoInputGestureAction: If there is no action to perform. """ if watchdog.isAttemptingRecovery: # The core is dead, so don't try to perform an action. # This lets gestures pass through unhindered where possible, # as well as stopping a flood of actions when the core revives. raise NoInputGestureAction script = gesture.script focus = api.getFocusObject() if focus.sleepMode is focus.SLEEP_FULL or ( focus.sleepMode and not getattr(script, 'allowInSleepMode', False)): raise NoInputGestureAction speechEffect = gesture.speechEffectWhenExecuted if speechEffect == gesture.SPEECHEFFECT_CANCEL: queueHandler.queueFunction(queueHandler.eventQueue, speech.cancelSpeech) elif speechEffect in (gesture.SPEECHEFFECT_PAUSE, gesture.SPEECHEFFECT_RESUME): queueHandler.queueFunction( queueHandler.eventQueue, speech.pauseSpeech, speechEffect == gesture.SPEECHEFFECT_PAUSE) if log.isEnabledFor(log.IO) and not gesture.isModifier: log.io("Input: %s" % gesture.logIdentifier) if self.isInputHelpActive: bypass = getattr(script, "bypassInputHelp", False) queueHandler.queueFunction(queueHandler.eventQueue, self._handleInputHelp, gesture, onlyLog=bypass) if not bypass: return if gesture.isModifier: raise NoInputGestureAction if config.conf["keyboard"][ "speakCommandKeys"] and gesture.shouldReportAsCommand: queueHandler.queueFunction(queueHandler.eventQueue, speech.speakMessage, gesture.displayName) gesture.reportExtra() if script: scriptHandler.queueScript(script, gesture) return raise NoInputGestureAction
def sayElapsedTime(self, forced=False): if not self.hasMedia(): return (muteState, level) = self.volumeInfos.getMuteAndLevel() if not muteState and not forced and self.isPlaying(): return mediaInfos = MediaInfos(self) from vlc_addonConfig import _addonConfigManager if not forced and not _addonConfigManager.getAutoElapsedTimeReportOption( ): return elapsedTime = mediaInfos.getElapsedTime() if elapsedTime: # Translators: message to the user to say played duration. msg = _("Played duration %s") if forced else "%s" queueHandler.queueFunction(queueHandler.eventQueue, ui.message, msg % formatTime(elapsedTime))
def resetConfiguration(self): from ..utils import makeAddonWindowTitle if gui.messageBox( # Translators: A message asking the user to confirm reset of configuration. _("The add-on configuration will be reset to factory values and NVDA will be restarted. Would you like to continue ?" ), # noqa:E501 makeAddonWindowTitle(_("Configuration reset")), wx.YES | wx.NO | wx.ICON_WARNING) == wx.NO: return addonConfigFile = os.path.join(globalVars.appArgs.configPath, self._configFileName) os.remove(addonConfigFile) self.addonConfig = self._versionToConfiguration[ self._currentConfigVersion](None) # noqa:E501 self.saveSettings(True) self.deleteNVDAAddonConfiguration() queueHandler.queueFunction(queueHandler.eventQueue, core.restart)
def askForNVDARestart(): if gui.messageBox( # Translators: A message asking the user if they wish to restart NVDA _("Some Changes have been made . " "You must save the configuration and restart NVDA for these changes to take effect. " "Would you like to do it now?"), "%s - %s" % (_addonSummary, NVDAString("Restart NVDA")), wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES: _addonConfigManager.saveSettings(True) queueHandler.queueFunction(queueHandler.eventQueue, core.restart) return gui.messageBox( # Translators: A message to user _("Don't forget to save the configuration for the changes to take effect !" ), "%s - %s" % (_addonSummary, NVDAString("Warning")), wx.OK | wx.ICON_WARNING)
def onSaveConfigurationCommand(self, evt): if globalVars.appArgs.secure: # Translators: Reported when current configuration cannot be saved while NVDA is running in secure mode such as in Windows login screen. queueHandler.queueFunction( queueHandler.eventQueue, ui.message, _("Cannot save configuration - NVDA in secure mode")) return try: config.conf.save() # Translators: Reported when current configuration has been saved. queueHandler.queueFunction(queueHandler.eventQueue, ui.message, _("Configuration saved")) except: # Translators: Message shown when current configuration cannot be saved such as when running NVDA from a CD. messageBox( _("Could not save configuration - probably read only file system" ), _("Error"), wx.OK | wx.ICON_ERROR)
def internal_mouseEvent(msg,x,y,injected): global mouseMoved, curMousePos, lastMouseEventTime lastMouseEventTime=time.time() if injected: return True if not config.conf['mouse']['enableMouseTracking']: return True try: curMousePos=(x,y) if msg==WM_MOUSEMOVE: mouseMoved=True core.requestPump() elif msg in (WM_LBUTTONDOWN,WM_RBUTTONDOWN): queueHandler.queueFunction(queueHandler.eventQueue,speech.cancelSpeech) except: log.error("", exc_info=True) return True
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.local_machine = local_machine.LocalMachine() self.slave_session = None self.master_session = None self.create_menu() self.connecting = False self.url_handler_window = url_handler.URLHandlerWindow( callback=self.verify_connect) url_handler.register_url_handler() self.master_transport = None self.slave_transport = None self.server = None self.hook_thread = None self.sending_keys = False self.key_modified = False self.sd_server = None self.sd_relay = None self.sd_bridge = None try: configuration.get_config() except configobj.ParseError: os.remove( os.path.abspath( os.path.join(globalVars.appArgs.configPath, configuration.CONFIG_FILE_NAME))) queueHandler.queueFunction( queueHandler.eventQueue, wx.CallAfter, wx.MessageBox, _("Your NVDA Remote configuration was corrupted and has been reset." ), _("NVDA Remote Configuration Error"), wx.OK | wx.ICON_EXCLAMATION) cs = configuration.get_config()['controlserver'] if hasattr(shlobj, 'SHGetKnownFolderPath'): self.temp_location = os.path.join( shlobj.SHGetKnownFolderPath(shlobj.FolderId.PROGRAM_DATA), 'temp') else: self.temp_location = os.path.join( shlobj.SHGetFolderPath(0, shlobj.CSIDL_COMMON_APPDATA), 'temp') self.ipc_file = os.path.join(self.temp_location, 'remote.ipc') if globalVars.appArgs.secure: self.handle_secure_desktop() if cs['autoconnect'] and not self.master_session and not self.slave_session: self.perform_autoconnect() self.sd_focused = False
def sayHelpText(self): def getDisplayExplanationButton(): button = None for o in self.pane.firstChild.children: if o.role == controlTypes.ROLE_TOGGLEBUTTON\ and controlTypes.STATE_INVISIBLE not in o.states: button = o break return button def getExplanationText(): focus = api.getFocusObject() button = getDisplayExplanationButton() if button is None: return None oldSpeechMode = speech.speechMode speech.speechMode = speech.speechMode_off stateHasChanged = False if controlTypes.STATE_PRESSED not in button.states: button.doAction() stateHasChanged = True oText = button.next textList = [oText.name] textList.append(oText.value) if stateHasChanged: button.doAction() focus.setFocus() api.processPendingEvents() speech.speechMode = oldSpeechMode speech.cancelSpeech() return "\r\n".join(textList) def getDefaultHelpText(): infos = self.getErrorInformations() (suggestion, suggestionHelpText, suggestionCount) = infos["suggestion"] return suggestionHelpText text = getExplanationText() if text is None: text = getDefaultHelpText() if text is None: text = _("No explanation help") queueHandler.queueFunction(queueHandler.eventQueue, ui.message, text)
def showHelp(helpId: str): """Display the corresponding section of the user guide when either the Help button in an NVDA dialog is pressed or the F1 key is pressed on a recognized control. """ import ui import queueHandler if not helpId: # Translators: Message indicating no context sensitive help is available for the control or dialog. noHelpMessage = _("No help available here.") queueHandler.queueFunction(queueHandler.eventQueue, ui.message, noHelpMessage) return import gui helpFile = gui.getDocFilePath("userGuide.html") if helpFile is None: # Translators: Message shown when trying to display context sensitive help, # indicating that the user guide could not be found. noHelpMessage = _("No user guide found.") log.debugWarning( "No user guide found: possible cause - running from source without building user docs" ) queueHandler.queueFunction(queueHandler.eventQueue, ui.message, noHelpMessage) return log.debug(f"Opening help: helpId = {helpId}, userGuidePath: {helpFile}") nvdaTempDir = os.path.join(tempfile.gettempdir(), "nvda") if not os.path.exists(nvdaTempDir): os.mkdir(nvdaTempDir) contextHelpRedirect = os.path.join(nvdaTempDir, "contextHelp.html") try: # a redirect is necessary because not all browsers support opening a fragment URL from the command line. writeRedirect(helpId, helpFile, contextHelpRedirect) except Exception: log.error("Unable to write context help redirect file.", exc_info=True) return try: os.startfile(f"file://{contextHelpRedirect}") except Exception: log.error("Unable to launch context help.", exc_info=True)
def handleInputConversionModeUpdate(oldFlags,newFlags,lcid): import speech textList=[] if newFlags!=oldFlags and lcid&0xff==0x11: #Japanese msg=JapaneseInputConversionModeMessages.get(newFlags) if msg: textList.append(msg) else: for x in xrange(32): x=2**x msgs=inputConversionModeMessages.get(x) if not msgs: continue newOn=bool(newFlags&x) oldOn=bool(oldFlags&x) if newOn!=oldOn: textList.append(msgs[0] if newOn else msgs[1]) if len(textList)>0: queueHandler.queueFunction(queueHandler.eventQueue,speech.speakMessage," ".join(textList))
def triggerNVDAExit(newNVDA: Optional[NewNVDAInstance] = None) -> bool: """ Used to safely exit NVDA. If a new instance is required to start after exit, queue one by specifying instance information with `newNVDA`. @return: True if this is the first call to trigger the exit, and the shutdown event was queued. """ import queueHandler global _hasShutdownBeenTriggered with _shuttingDownFlagLock: if not _hasShutdownBeenTriggered: # queue this so that the calling process can exit safely (eg a Popup menu) queueHandler.queueFunction(queueHandler.eventQueue, _doShutdown, newNVDA) _hasShutdownBeenTriggered = True log.debug("_doShutdown has been queued") return True else: log.debug("NVDA has already been triggered to exit safely.") return False
def handleInputConversionModeUpdate(oldFlags,newFlags,lcid): import ui textList=[] if newFlags!=oldFlags and lcid&0xff==0x11: #Japanese msg=JapaneseInputConversionModeMessages.get(newFlags) if msg: textList.append(msg) else: for x in xrange(32): x=2**x msgs=inputConversionModeMessages.get(x) if not msgs: continue newOn=bool(newFlags&x) oldOn=bool(oldFlags&x) if newOn!=oldOn: textList.append(msgs[0] if newOn else msgs[1]) if len(textList)>0: queueHandler.queueFunction(queueHandler.eventQueue,ui.message," ".join(textList))
def onOk(self, evt): try: self.Access8MathConfig["settings"]["language"] = list( available_languages_dict.keys())[ self.languageList.GetSelection()] self.Access8MathConfig["settings"][ "item_interval_time"] = self.item_interval_timeChoices[ self.item_interval_timeList.GetSelection()] for k in self.CheckBox_settings.keys(): self.Access8MathConfig["settings"][k] = getattr( self, k + "CheckBox").IsChecked() except: self.Access8MathConfig["settings"]["language"] = "en" self.Access8MathConfig["settings"]["item_interval_time"] = 50 for k in self.CheckBox_settings.keys(): self.Access8MathConfig["settings"][k] = True tones.beep(100, 100) # _config.save() A8M_PM.initialize(self.Access8MathConfig) try: api.setReviewPosition( MathMlTextInfo(globalVars.math_obj, textInfos.POSITION_FIRST), False) except: pass if self.edit_NVDA_gesture != self.Access8MathConfig["settings"][ "edit_NVDA_gesture"]: if gui.messageBox( # Translators: The message displayed _("For the NVDA+gesture configuration to apply, NVDA must be restarted. Do you want to restart NVDA now?" ), # Translators: The title of the dialog _("NVDA+gesture Configuration Change"), wx.OK | wx.CANCEL | wx.ICON_WARNING, self) == wx.OK: queueHandler.queueFunction(queueHandler.eventQueue, core.restart) return super(GeneralSettingsDialog, self).onOk(evt)
def switchToVoiceProfile(self, selector, silent=False): def finish(synthName, synthspeechConfig, msg): # stop previous synth because oneCore voice switch don't work without it setSynth(None) config.conf[SCT_Speech] = synthSpeechConfig.copy() setSynth(synthName) # Reinitialize the tones module to update the audio device if py3: import tones tones.terminate() tones.initialize() else: import tones reload(tones) getSynth().saveSettings() if msg: ui.message(msg) newProfile = self.getVoiceProfile(selector) synthName = None for s, val in getSynthList(): if s == newProfile[KEY_SynthName]: synthName = s break voiceProfileName = newProfile[KEY_VoiceProfileName] if synthName is None: if gui.messageBox( # Translators: the label of a message box dialog. _("Impossible, the synthetizer of voice profile {voiceProfileName} associated to selector {selector} is not available. Do you want to free this selector ?" ).format(selector=selector, voiceProfileName=voiceProfileName), # noqa:E501 # Translators: the title of a message box dialog. _("Synthetizer error"), wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES: core.callLater(200, self.freeSelector, selector) return synthSpeechConfig = deepCopy(config.conf[SCT_Speech]) synthSpeechConfig.update(newProfile[SCT_Speech].copy()) self.setLastSelector(selector) msg = None if silent else _("Selector {selector}: {name}").format( selector=selector, name=voiceProfileName) queueHandler.queueFunction(queueHandler.eventQueue, finish, synthName, synthSpeechConfig, msg)
def nvdaControllerInternal_IMEOpenStatusUpdate(opened): #nvdajp begin if config.conf["keyboard"]["nvdajpImeBeep"]: import tones if opened: tones.beep(880, 20) else: tones.beep(440, 20) return 0 #nvdajp end if opened: # Translators: a message when the IME open status changes to opened message = _("IME opened") else: # Translators: a message when the IME open status changes to closed message = _("IME closed") import ui queueHandler.queueFunction(queueHandler.eventQueue, ui.message, message) return 0
def internal_mouseEvent(msg,x,y,injected): """Event called by winInputHook when it receives a mouse event. """ global mouseMoved, curMousePos, lastMouseEventTime lastMouseEventTime=time.time() if injected and (ignoreInjected or config.conf['mouse']['ignoreInjectedMouseInput']): return True if not config.conf['mouse']['enableMouseTracking']: return True try: curMousePos=(x,y) if msg==WM_MOUSEMOVE: mouseMoved=True core.requestPump() elif msg in (WM_LBUTTONDOWN,WM_RBUTTONDOWN): queueHandler.queueFunction(queueHandler.eventQueue,speech.cancelSpeech) except: log.error("", exc_info=True) return True
def nvdaControllerInternal_inputCompositionUpdate(compositionString, selectionStart, selectionEnd, isReading): from NVDAObjects.inputComposition import InputComposition if selectionStart == -1: queueHandler.queueFunction(queueHandler.eventQueue, handleInputCompositionEnd, compositionString) return 0 focus = api.getFocusObject() if isinstance(focus, InputComposition): focus.compositionUpdate(compositionString, selectionStart, selectionEnd, isReading) else: queueHandler.queueFunction(queueHandler.eventQueue, handleInputCompositionStart, compositionString, selectionStart, selectionEnd, isReading) return 0
def onOk(self, evt): options = [] for (ctrl, optionInfo) in zip(self.options, self.OPTION_LIST): try: value = ctrl.Value except AttributeError: value = ctrl.StringSelection.split(' ')[0] if value: splitFlag = optionInfo[1][-1].split('=') flag = splitFlag[0] if len(splitFlag) == 1: pass elif len(splitFlag) == 2: flag = flag + '={}'.format(value) else: raise ValueError('Unexpected value {}'.format(optionInfo[1][-1])) options.append(flag) queueHandler.queueFunction(queueHandler.eventQueue, restartWithOptions, options) super(RestartWithOptionsDialog, self).onOk(evt)
def __init__(self): super(globalPluginHandler.GlobalPlugin, self).__init__() tipDialog.initialize() conf = tipConfig.conf try: confVal = conf["internal"]["lastUse"] except KeyError: conf["internal"]["lastUse"] = time.time() confVal = conf["internal"]["lastUse"] conf.save() lastUse = TipTimeManager(confVal) if lastUse.hasMoreThanADayPassed(): conf["internal"]["lastUse"] = time.time() conf.save() lastUse = TipTimeManager(conf['internal']['lastUse']) if conf["user"]["level"] != "not sure": queueHandler.queueFunction(queueHandler.eventQueue, tipDialog.create) #This should queue this to open in the future when NVDA is ready. self.purger() #gracefully remove dead timers. lastUse.alert(self) # runs a timer over and over every few minutes, and when the specified action happens, calls -the callback specified.
def nvdaControllerInternal_requestRegistration(uuidString): pid=c_long() windll.rpcrt4.I_RpcBindingInqLocalClientPID(None,byref(pid)) pid=pid.value if not pid: log.error("Could not get process ID for RPC call") return -1; bindingHandle=c_long() bindingHandle.value=localLib.createRemoteBindingHandle(uuidString) if not bindingHandle: log.error("Could not bind to inproc rpc server for pid %d"%pid) return -1 registrationHandle=c_long() res=localLib.nvdaInProcUtils_registerNVDAProcess(bindingHandle,byref(registrationHandle)) if res!=0 or not registrationHandle: log.error("Could not register NVDA with inproc rpc server for pid %d, res %d, registrationHandle %s"%(pid,res,registrationHandle)) windll.rpcrt4.RpcBindingFree(byref(bindingHandle)) return -1 import appModuleHandler queueHandler.queueFunction(queueHandler.eventQueue,appModuleHandler.update,pid,helperLocalBindingHandle=bindingHandle,inprocRegistrationHandle=registrationHandle) return 0