def script_nextPageTab (self,gesture): if api.getFocusObject().windowText == u'DropboxTrayIcon' or api.getFocusObject().windowClassName == u'#32768' or api.getForegroundObject().name != _("Dropbox Preferences"): gesture.send() return tabPage = api.getForegroundObject().simpleFirstChild tabPageHandle = tabPage.windowHandle changePageTab(tabPageHandle,"next") objToFocus = tabPage.simpleNext while objToFocus.isFocusable == False or objToFocus.role == controlTypes.ROLE_GROUPING: objToFocus = objToFocus.simpleNext objToFocus.setFocus()
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 updateFocusLocation(sender=None): global focusRect if locationAvailable(sender): newRect = location2rect(sender.location) elif locationAvailable(api.getFocusObject()): newRect = location2rect(api.getFocusObject().location) else: return newRect = limitRectInDesktop(newRect) if not rectEquals(newRect, focusRect): focusRect = newRect setMarkPositions(focusMarkRectList, focusRect, FOCUS_THICKNESS, FOCUS_PADDING) for i in xrange(4): moveAndShowWindow(focusHwndList[i], focusMarkRectList[i])
def updateNavigatorLocation(): global navigatorRect nav = api.getNavigatorObject() if locationAvailable(nav): newRect = location2rect(nav.location) elif locationAvailable(api.getFocusObject()): newRect = location2rect(api.getFocusObject().location) else: return newRect = limitRectInDesktop(newRect) if not rectEquals(newRect, navigatorRect): navigatorRect = newRect setMarkPositions(navigatorMarkRectList, navigatorRect, NAVIGATOR_THICKNESS, NAVIGATOR_PADDING) for i in xrange(4): moveAndShowWindow(navigatorHwndList[i], navigatorMarkRectList[i])
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 event_gainFocus(self,obj,nextHandler): nextHandler() #Force focus to move to something sane when landing on an outlook express message window if obj.windowClassName=="ATH_Note" and obj.event_objectID==winUser.OBJID_CLIENT and obj.IAccessibleChildID==0: api.processPendingEvents() if obj==api.getFocusObject() and controlTypes.STATE_FOCUSED in obj.states: return KeyboardInputGesture.fromName("shift+tab").send()
def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID): if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. return if eventID==UIA_MenuOpenedEventId and eventHandler.isPendingEvents("gainFocus"): # We don't need the menuOpened event if focus has been fired, # as focus should be more correct. return NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return if not self.isNativeUIAElement(sender): return window=self.getNearestWindowHandle(sender) if window and not eventHandler.shouldAcceptEvent(NVDAEventName,windowHandle=window): return import NVDAObjects.UIA obj=NVDAObjects.UIA.UIA(UIAElement=sender) if ( not obj or (NVDAEventName=="gainFocus" and not obj.shouldAllowUIAFocusEvent) or (NVDAEventName=="liveRegionChange" and not obj._shouldAllowUIALiveRegionChangeEvent) ): return focus=api.getFocusObject() if obj==focus: obj=focus eventHandler.queueEvent(NVDAEventName,obj)
def find(self, text): """Find a window with the supplied text in its title. If the text isn't found in any title, search the text of consoles.""" consoles = set() text = text.lower() for c in api.getDesktopObject().children: name = c.name if name is None: continue if text in name.lower(): focus(c.windowHandle) return elif c.windowClassName == u'ConsoleWindowClass': consoles.add(c) #We didn't find the search text in the title, start searching consoles current_console = winConsoleHandler.consoleObject # If our current console is the one with the text in it, presumably we want another one, and if one isn't found, we'll refocus anyway if current_console is not None: consoles.remove(current_console) for console in consoles: #We assume this can't fail console_text = get_console_text(console) if text in console_text.lower(): focus(console.windowHandle) return else: #No consoles found if current_console: winConsoleHandler.connectConsole(current_console) if current_console == api.getFocusObject(): current_console.startMonitoring() #Keep echoing if we didn't switch tones.beep(300, 150)
def recognizeNavigatorObject(recognizer): """User interface function to recognize content in the navigator object. This should be called from a script or in response to a GUI action. @param recognizer: The content recognizer to use. @type recognizer: L{contentRecog.ContentRecognizer} """ global _activeRecog if isinstance(api.getFocusObject(), RecogResultNVDAObject): # Translators: Reported when content recognition (e.g. OCR) is attempted, # but the user is already reading a content recognition result. ui.message(_("Already in a content recognition result")) return nav = api.getNavigatorObject() # Translators: Reported when content recognition (e.g. OCR) is attempted, # but the content is not visible. notVisibleMsg = _("Content is not visible") try: left, top, width, height = nav.location except TypeError: log.debugWarning("Object returned location %r" % nav.location) ui.message(notVisibleMsg) return try: imgInfo = RecogImageInfo.createFromRecognizer(left, top, width, height, recognizer) except ValueError: ui.message(notVisibleMsg) return if _activeRecog: _activeRecog.cancel() # Translators: Reporting when content recognition (e.g. OCR) begins. ui.message(_("Recognizing")) sb = screenBitmap.ScreenBitmap(imgInfo.recogWidth, imgInfo.recogHeight) pixels = sb.captureImage(left, top, width, height) _activeRecog = recognizer recognizer.recognize(pixels, imgInfo, _recogOnResult)
def flushCurrentEntry(): global currentEntry, autoFlushTimer if autoFlushTimer is not None: autoFlushTimer.Stop() autoFlushTimer = None start, text = currentEntry text = text.replace("\r\n", "\n") text = text.replace("\r", "\n") while True: i = text.find("\n") if i == -1: break if i > 0: speech.speakText(text[:i]) if text[i:i + 2] == "\n\n": # Translators: The text which is spoken when a new paragraph is added. speech.speakText(_("new paragraph")) text = text[i + 2:] else: # Translators: The message spoken when a new line is entered. speech.speakText(_("new line")) text = text[i + 1:] if text != "": speech.speakText(text) braille.handler.handleCaretMove(api.getFocusObject()) currentEntry = None requestWSRShowHideEvents()
def IUIAutomationPropertyChangedEventHandler_HandlePropertyChangedEvent(self,sender,propertyId,newValue): # #3867: For now manually force this VARIANT type to empty to get around a nasty double free in comtypes/ctypes. # We also don't use the value in this callback. newValue.vt=VT_EMPTY if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. return NVDAEventName=UIAPropertyIdsToNVDAEventNames.get(propertyId,None) if not NVDAEventName: return if not self.isNativeUIAElement(sender): return try: window=sender.cachedNativeWindowHandle except COMError: window=None if window and not eventHandler.shouldAcceptEvent(NVDAEventName,windowHandle=window): return import NVDAObjects.UIA obj=NVDAObjects.UIA.UIA(UIAElement=sender) if not obj: return focus=api.getFocusObject() if obj==focus: obj=focus eventHandler.queueEvent(NVDAEventName,obj)
def doPreGainFocus(obj,sleepMode=False): oldForeground=api.getForegroundObject() oldFocus=api.getFocusObject() oldTreeInterceptor=oldFocus.treeInterceptor if oldFocus else None api.setFocusObject(obj) if globalVars.focusDifferenceLevel<=1: newForeground=api.getDesktopObject().objectInForeground() if not newForeground: log.debugWarning("Can not get real foreground, resorting to focus ancestors") ancestors=api.getFocusAncestors() if len(ancestors)>1: newForeground=ancestors[1] else: newForeground=obj api.setForegroundObject(newForeground) executeEvent('foreground',newForeground) if sleepMode: return True #Fire focus entered events for all new ancestors of the focus if this is a gainFocus event for parent in globalVars.focusAncestors[globalVars.focusDifferenceLevel:]: executeEvent("focusEntered",parent) if obj.treeInterceptor is not oldTreeInterceptor: if hasattr(oldTreeInterceptor,"event_treeInterceptor_loseFocus"): oldTreeInterceptor.event_treeInterceptor_loseFocus() if obj.treeInterceptor and obj.treeInterceptor.isReady and hasattr(obj.treeInterceptor,"event_treeInterceptor_gainFocus"): obj.treeInterceptor.event_treeInterceptor_gainFocus() return True
def script_readMessage(self, gesture): focus=api.getFocusObject() messageContainer = self.getMessageContainer(focus) if messageContainer is None: self.speak("Message container not found!") else: self.speak(self.getMessage(messageContainer,gesture))
def nvdaControllerInternal_drawFocusRectNotify(hwnd, left, top, right, bottom): import eventHandler from NVDAObjects.window import Window focus=api.getFocusObject() if isinstance(focus,Window) and hwnd==focus.windowHandle: eventHandler.queueEvent("displayModel_drawFocusRectNotify",focus,rect=(left,top,right,bottom)) return 0;
def handleInputCompositionStart(compositionString,selectionStart,selectionEnd,isReading): import speech from NVDAObjects.inputComposition import InputComposition from NVDAObjects.behaviors import CandidateItem focus=api.getFocusObject() if focus.parent and isinstance(focus.parent,InputComposition): #Candidates infront of existing composition string announce=not config.conf["inputComposition"]["announceSelectedCandidate"] focus.parent.compositionUpdate(compositionString,selectionStart,selectionEnd,isReading,announce=announce) return 0 #IME keeps updating input composition while the candidate list is open #Therefore ignore new composition updates if candidate selections are configured for speaking. if config.conf["inputComposition"]["announceSelectedCandidate"] and isinstance(focus,CandidateItem): return 0 if not isinstance(focus,InputComposition): parent=api.getDesktopObject().objectWithFocus() # #5640: Although we want to use the most correct focus (I.e. OS, not NVDA), if they are the same, we definitely want to use the original instance, so that state such as auto selection is maintained. if parent==focus: parent=focus curInputComposition=InputComposition(parent=parent) oldSpeechMode=speech.speechMode speech.speechMode=speech.speechMode_off eventHandler.executeEvent("gainFocus",curInputComposition) focus=curInputComposition speech.speechMode=oldSpeechMode focus.compositionUpdate(compositionString,selectionStart,selectionEnd,isReading)
def handleInputCandidateListUpdate(candidatesString,selectionIndex,inputMethod): candidateStrings=candidatesString.split('\n') import speech from NVDAObjects.inputComposition import InputComposition, CandidateList, CandidateItem focus=api.getFocusObject() if not (0<=selectionIndex<len(candidateStrings)): if isinstance(focus,CandidateItem): oldSpeechMode=speech.speechMode speech.speechMode=speech.speechMode_off eventHandler.executeEvent("gainFocus",focus.parent) speech.speechMode=oldSpeechMode return oldCandidateItemsText=None if isinstance(focus,CandidateItem): oldCandidateItemsText=focus.visibleCandidateItemsText parent=focus.parent wasCandidate=True else: parent=focus wasCandidate=False item=CandidateItem(parent=parent,candidateStrings=candidateStrings,candidateIndex=selectionIndex,inputMethod=inputMethod) if wasCandidate and focus.windowHandle==item.windowHandle and focus.candidateIndex==item.candidateIndex and focus.name==item.name: return if config.conf["inputComposition"]["autoReportAllCandidates"] and item.visibleCandidateItemsText!=oldCandidateItemsText: import ui ui.message(item.visibleCandidateItemsText) eventHandler.executeEvent("gainFocus",item)
def script_moveToParent(self, gesture): # Make sure we're in a editable control focus = api.getFocusObject() if focus.role != controlTypes.ROLE_EDITABLETEXT: ui.message("Not in an edit control.") return # Get the current indentation level textInfo = focus.makeTextInfo(textInfos.POSITION_CARET) textInfo.expand(textInfos.UNIT_LINE) indentationLevel = len(textInfo.text) - len(textInfo.text.strip()) onEmptyLine = len(textInfo.text) == 1 #1 because an empty line will have the \n character # Scan each line until we hit the start of the indentation block, the start of the edit area, or find a line with less indentation level found = False while textInfo.move(textInfos.UNIT_LINE, -2) == -2: textInfo.expand(textInfos.UNIT_LINE) newIndentation = len(textInfo.text) - len(textInfo.text.strip()) # Skip over empty lines if we didn't start on one. if not onEmptyLine and len(textInfo.text) == 1: continue if newIndentation < indentationLevel: # Found it found = True textInfo.updateCaret() speech.speakTextInfo(textInfo, unit=textInfos.UNIT_LINE) break # If we didn't find it, tell the user if not found: ui.message("No parent of indentation block")
def script_saveBookmark(self, gesture): obj = api.getFocusObject() appName=appModuleHandler.getAppNameFromProcessID(obj.processID,True) if appName == "MicrosoftEdgeCP.exe": gesture.send() return treeInterceptor=obj.treeInterceptor if isinstance(treeInterceptor, BrowseModeDocumentTreeInterceptor) and not treeInterceptor.passThrough: obj=treeInterceptor else: gesture.send() return bookmark = obj.makeTextInfo(textInfos.POSITION_CARET).bookmark bookmarks = getSavedBookmarks() noteTitle = obj.makeTextInfo(textInfos.POSITION_SELECTION).text[:100].encode("utf-8") if bookmark.startOffset in bookmarks: noteBody = bookmarks[bookmark.startOffset].body else: noteBody = "" bookmarks[bookmark.startOffset] = Note(noteTitle, noteBody) fileName = getFileBookmarks() try: pickle.dump(bookmarks, file(fileName, "wb")) ui.message( # Translators: message presented when a position is saved as a bookmark. _("Saved position at character %d") % bookmark.startOffset) except Exception as e: log.debugWarning("Error saving bookmark", exc_info=True) ui.message( # Translators: message presented when a bookmark cannot be saved. _("Cannot save bookmark")) raise e
def processFakeFocusWinEvent(eventID, window, objectID, childID): """Process a fake focus win event. @postcondition: The focus will be found and an event generated for it if appropriate. """ # A suitable event for faking the focus has been received with no focus event, so we probably need to find the focus and fake it. # However, it is possible that the focus event has simply been delayed, so wait a bit and only do it if the focus hasn't changed yet. core.callLater(50, _fakeFocus, api.getFocusObject())
def script_reportFormatting(self,gesture): formatConfig={ "detectFormatAfterCursor":False, "reportFontName":True,"reportFontSize":True,"reportFontAttributes":True,"reportColor":True, "reportStyle":True,"reportAlignment":True,"reportSpellingErrors":True, "reportPage":False,"reportLineNumber":False,"reportTables":False, "reportLinks":False,"reportHeadings":False,"reportLists":False, "reportBlockQuotes":False, } o=api.getFocusObject() v=o.treeInterceptor if v and not v.passThrough: o=v try: info=o.makeTextInfo(textInfos.POSITION_CARET) except (NotImplementedError, RuntimeError): info=o.makeTextInfo(textInfos.POSITION_FIRST) info.expand(textInfos.UNIT_CHARACTER) formatField=textInfos.FormatField() for field in info.getTextWithFields(formatConfig): if isinstance(field,textInfos.FieldCommand) and isinstance(field.field,textInfos.FormatField): formatField.update(field.field) text=speech.getFormatFieldSpeech(formatField,formatConfig=formatConfig) if formatField else None if not text: ui.message(_("No formatting information")) return ui.message(text)
def handleSelectionChange(self): """Pushes focus to the newly selected object.""" obj=self.selection if not obj: obj=DocumentWindow(windowHandle=self.windowHandle) if obj and obj!=api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): eventHandler.queueEvent("gainFocus",obj)
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 wasInSayAll=False if gesture.isModifier: if not self.lastModifierWasInSayAll: wasInSayAll=self.lastModifierWasInSayAll=sayAllHandler.isRunning() elif self.lastModifierWasInSayAll: wasInSayAll=True self.lastModifierWasInSayAll=False else: wasInSayAll=sayAllHandler.isRunning() if wasInSayAll: gesture.wasInSayAll=True 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._captureFunc: try: if self._captureFunc(gesture) is False: return except: log.error("Error in capture function, disabling", exc_info=True) self._captureFunc = None 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 event_caret(self): if self is api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): braille.handler.handleCaretMove(self) if config.conf["reviewCursor"]["followCaret"] and api.getNavigatorObject() is self: try: api.setReviewPosition(self.makeTextInfo(textInfos.POSITION_CARET)) except (NotImplementedError, RuntimeError): pass
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 _fakeFocus(oldFocus): if oldFocus is not api.getFocusObject(): # The focus has changed - no need to fake it. return focus = api.getDesktopObject().objectWithFocus() if not focus: return processFocusNVDAEvent(focus)
def event_valueChange(self): focus = api.getFocusObject() if controlTypes.STATE_FOCUSED not in self.states or focus.role != controlTypes.ROLE_COMBOBOX: # This combo box is not focused. return super(V6ComboBox, self).event_valueChange() # This combo box is focused. However, the value change is not fired on the real focus object. # Therefore, redirect this event to the real focus object. focus.event_valueChange()
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 script_specificFind(self,gesture): obj=api.getFocusObject() if not controlTypes.STATE_MULTILINE in obj.states: treeInterceptor=obj.treeInterceptor if not (isinstance(treeInterceptor, BrowseModeDocumentTreeInterceptor) and not treeInterceptor.passThrough): gesture.send() return self.popupSpecificSearchDialog()
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 _get_shouldAllowIAccessibleFocusEvent(self): # hack: When turning pages to a new section, Kindle fires focus on the new section in the table of contents treeview. # We must ignore this focus event as it is a hinderance to a screen reader user while reading the book. focus = api.getFocusObject() if isinstance(focus, BookPageView) and focus.hasFocus: # The book area reports that it still has the focus, so this event is bogus. return False return super(PageTurnFocusIgnorer,self).shouldAllowIAccessibleFocusEvent
def _loadBufferDone(self, success=True): self._loadProgressCallLater.Stop() del self._loadProgressCallLater self.isLoading = False if not success: self.passThrough=True return textLength = NVDAHelper.localLib.VBuf_getTextLength(self.VBufHandle) if textLength == 0: log.debugWarning("Empty buffer. Waiting for documentLoadComplete event instead") # Empty buffer. # May be due to focus event too early in Chromium 100 documents # We may get a later chance to see content with a documentLoadComplete event return if self._hadFirstGainFocus: # If this buffer has already had focus once while loaded, this is a refresh. # Translators: Reported when a page reloads (example: after refreshing a webpage). ui.message(_("Refreshed")) if api.getFocusObject().treeInterceptor == self: self.event_treeInterceptor_gainFocus()
def verify(oldSpeechMode): api.processPendingEvents() speech.cancelSpeech() speech.speechMode = oldSpeechMode focus = api.getFocusObject() from .ww_spellingChecker import SpellingChecker sc = SpellingChecker(focus, self.WinwordVersion) if not sc.inSpellingChecker(): return if focus.role == controlTypes.ROLE_PANE: # focus on the pane not not on an object of the pane # Translators: message to ask user to hit tab key. queueHandler.queueFunction( queueHandler.eventQueue, speech.speakMessage, _("Hit tab to move focus in the spelling checker pane")) else: sc.sayErrorAndSuggestion(title=True, spell=False) queueHandler.queueFunction(queueHandler.eventQueue, speech.speakObject, focus, controlTypes.REASON_FOCUS)
def script_saveToMemory(self, gesture): focus = api.getFocusObject() textInfo = None if focus.windowClassName in ["AkelEditW"] or focus.role in [ controlTypes.ROLE_EDITABLETEXT ]: textInfo = focus.makeTextInfo(textInfos.POSITION_SELECTION) elif focus.treeInterceptor is not None: textInfo = focus.treeInterceptor.makeTextInfo( textInfos.POSITION_SELECTION) if textInfo is not None: text = textInfo.text if len(text) > 0: keyCode = gesture.vkCode # Get which number the user pressed. # The number will be in the range 48 to 57 inclusive, and we will use it to hash the data in the dictionary. self.memory[keyCode] = text # Translators: This message is displayed when text is saved on a memory slot. ui.message(_("Saved")) else: ui.message(nvdaTranslation("No selection"))
def _get_focusRedirect(self): if self.role == controlTypes.ROLE_UNKNOWN: # The control is inaccessible, try several times to find the CellEdit UIA element with focus and use that instead. for count in range(10): if count >= 1: api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return time.sleep(0.05) e = UIAHandler.handler.lastFocusedUIAElement if e and e.cachedAutomationID == "CellEdit": obj = UIA(UIAElement=e) oldFocus = api.getFocusObject() if isinstance(oldFocus, ExcelCell): # Set the edit control's parent as the cell that previously had focus. I.e. the cell being edited. # otherwise a whole bunch of UIA focus ancestors for the edit control will be reported. obj.parent = oldFocus # Cache this for as long as this object exists. self.focusRedirect = obj return obj
def getSelectedText(): """ Retrieves, then returns the currently selected text. @returns: The text currently selected. @rtype: str """ obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if hasattr(treeInterceptor, 'TextInfo') and not treeInterceptor.passThrough: obj = treeInterceptor try: info = obj.makeTextInfo(textInfos.POSITION_SELECTION) except (RuntimeError, NotImplementedError): info = None if not info or info.isCollapsed: return None else: return info.text
def script_reportToEndOfLine(self, gesture): obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if hasattr(treeInterceptor, 'TextInfo') and not treeInterceptor.passThrough: obj = treeInterceptor try: info = obj.makeTextInfo(textInfos.POSITION_CARET) info2 = info.copy() except (NotImplementedError, RuntimeError): info = obj.makeTextInfo(textInfos.POSITION_FIRST) info2 = info.copy() info.expand(textInfos.UNIT_LINE) info.setEndPoint(info2, "startToStart") if scriptHandler.getLastScriptRepeatCount() == 0: speech.speakTextInfo(info, unit=textInfos.UNIT_LINE, reason=controlTypes.REASON_CARET) else: speech.speakSpelling(info.text)
def processDestroyWinEvent(window, objectID, childID): """Process a destroy win event. This removes the object associated with the event parameters from L{liveNVDAObjectTable} if such an object exists. """ try: del liveNVDAObjectTable[(window, objectID, childID)] except KeyError: pass # Specific support for input method MSAA candidate lists. # When their window is destroyed we must correct focus to its parent - which could be a composition string # so can't use generic focus correction. (#2695) focus = api.getFocusObject() from NVDAObjects.IAccessible.mscandui import BaseCandidateItem if (objectID == 0 and childID == 0 and isinstance(focus, BaseCandidateItem) and window == focus.windowHandle and not eventHandler.isPendingEvents("gainFocus")): obj = focus.container if obj: eventHandler.queueEvent("gainFocus", obj)
def script_moveToTempBookmark(self, gesture): obj = api.getFocusObject() appName=appModuleHandler.getAppNameFromProcessID(obj.processID,True) if appName == "MicrosoftEdgeCP.exe": gesture.send() return treeInterceptor=obj.treeInterceptor if isinstance(treeInterceptor, BrowseModeDocumentTreeInterceptor) and not treeInterceptor.passThrough: obj=treeInterceptor else: gesture.send() return fileName = getFileTempBookmark() try: with codecs.open(fileName, "r", "utf-8") as f: tempBookmark = int(f.read()) moveToBookmark(tempBookmark) except: # Translators: Message presented when a temporary bookmark can't be found. ui.message("Temporary bookmark not found")
def terminateIfNecessary(self, lastGesture): """Tries to establish whether we are still exploring toolbars.""" # a bit too extended, maybe, but more secure curFocus = api.getFocusObject() curNav = api.getNavigatorObject() curForeground = api.getForegroundObject() curPid = curFocus.processID nvdaPid = os.getpid() if ( # navigator is out of toolbars (curNav not in self.bars and curNav not in self.barItems) or # focus is changed (curFocus != self.startSnap["focus"]) or # foreground window is changed (curForeground != self.startSnap["foreground"]) or # process is changed, or is NVDA (log viewer, console...) (curPid != self.startSnap["pid"] or curPid == nvdaPid) or # user invoked menu start (lastGesture.mainKeyName in ("leftWindows", "rightWindows"))): self.finish(restoreMode=True)
def script_saveToMemory(self, gesture): """When pressed, this key saves the selected text to this position on the NVDA memory.""" focus = api.getFocusObject() textInfo = None if focus.windowClassName in ["AkelEditW"] or focus.role in [ controlTypes.ROLE_EDITABLETEXT ]: textInfo = focus.makeTextInfo(textInfos.POSITION_SELECTION) elif focus.treeInterceptor is not None: textInfo = focus.treeInterceptor.makeTextInfo( textInfos.POSITION_SELECTION) if textInfo is not None: text = textInfo.text if len(text) > 0: keyCode = gesture.vkCode # Get which number the user pressed. # The number will be in the range 48 to 57 inclusive, and we will use it to hash the data in the dictionary. self.memory[keyCode] = text ui.message("Saved") else: ui.message("No selection")
def examine_focus(self): focus = api.getFocusObject() if not focus: return cc_none log.debug("Examining focus object: %r" % focus) # Check for an explorer/file browser window. # Todo: Is this an accurate method? if focus.windowClassName == "DirectUIHWND": return cc_file # Check for a list item. if focus.role == ROLE_LISTITEM: return cc_list # If we're looking at text... if focus.role == ROLE_EDITABLETEXT or focus.role == ROLE_DOCUMENT: log.debug("Found text control") # Retrieve the states in case we're read-only. states = focus.states for state in states: if state == STATE_READONLY: return cc_read_only_text # Otherwise, we're just an ordinary text field. log.debug("Field seems to be editable.") return cc_text # Comboboxes. if focus.role == ROLE_COMBOBOX: log.debug("Found combo box.") # Again, we need to evaluate states to make sure we're editable. states = focus.states for state in states: if state == STATE_EDITABLE: return cc_text # Otherwise, chances are we can't copy this. log.debug("Combo box content seems to be read-only.") return cc_none # Todo: Other control types we need to check? log.debug("Control type would not suggest clipboard operations.") return cc_none
def script_virtualWindowReview(self, gesture): # Find the first focus ancestor that have any display text, according to the display model # This must be the root application window, or something close to that. # In case of universal apps, traverse child elements. text = None obj = api.getFocusObject() # Because it may take a while to iterate through elements, play abeep to alert users of this fact and the fact it's a UWP screen. if obj.windowClassName.startswith("Windows.UI.Core"): import tones tones.beep(400, 300) text = "\n".join(obtainUWPWindowText()) tones.beep(400, 50) else: root = None for ancestor in api.getFocusAncestors(): if ancestor.appModule and ancestor.displayText: root = ancestor break if root: info = root.makeTextInfo(textInfos.POSITION_FIRST) # sys.maxint is gone in Python 3 as integer bit width can grow arbitrarily. # Use the static value (0x7fffffff or (2^31)-1) directly. info.move(textInfos.UNIT_LINE, 0x7fffffff, endPoint="end") text = info.clipboardText.replace("\0", " ") if obj.windowClassName == u'ConsoleWindowClass': info = obj.makeTextInfo(textInfos.POSITION_FIRST) info.expand(textInfos.UNIT_STORY) text = info.clipboardText.rstrip() if text: name = api.getForegroundObject().name if name in (None, ""): # Translators: The title of the virtual review window when the foreground window has no name, commonly seen when all windows are minimized. name = _("No title") # Translators: Title of the window shown for reading text on screen via a window. ui.browseableMessage( text, title=_("Virtual review: {screenName}").format( screenName=name)) else: # Translator: Message shown when no text can be virtualized. ui.message(_("No text to display"))
def checkUpdate(localGestureCounter, attempt, originalTimestamp, gesture=None, spokenAnyway=False): global gestureCounter, storedText if gestureCounter != localGestureCounter: return try: focus = api.getFocusObject() textInfo = focus.makeTextInfo(textInfos.POSITION_CARET) textInfo.expand(textInfos.UNIT_LINE) text = textInfo.text except Exception as e: log.warning( f"Error retrieving text during dynamic keystroke handling: {e}") return if attempt == 0: storedText = text else: if text != storedText: if spokenAnyway: speech.cancelSpeech() speech.speakTextInfo(textInfo, unit=textInfos.UNIT_LINE) return elapsed = time.time() - originalTimestamp if not spokenAnyway and elapsed > speakAnywayAfter: speech.speakTextInfo(textInfo, unit=textInfos.UNIT_LINE) spokenAnyway = True if elapsed < 1.0: sleepTime = 25 # ms elif elapsed < 10: sleepTime = 1000 # ms else: sleepTime = 5000 core.callLater(sleepTime, checkUpdate, localGestureCounter, attempt + 1, originalTimestamp, spokenAnyway=spokenAnyway)
def script_selectNextBookmark(self, gesture): obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if hasattr(treeInterceptor, 'TextInfo') and not treeInterceptor.passThrough: obj = treeInterceptor else: gesture.send() return bookmarks = getSavedBookmarks() positions = list(bookmarks.keys()) if len(positions) == 0: ui.message( # Translators: message presented when trying to select a bookmark, but none is found. _("No bookmarks found")) return start = obj.makeTextInfo(textInfos.POSITION_ALL) try: end = obj.makeTextInfo(textInfos.POSITION_CARET) except (NotImplementedError, RuntimeError): ui.message( # Translators: message presented when cannot find any bookmarks. _("Cannot find any bookmarks")) return start.setEndPoint(end, "endToStart") count = len(start.text) positions.sort() for pos in positions: if pos > count: end.move(textInfos.UNIT_CHARACTER, pos - count) obj.selection = end if not willSayAllResume(gesture): end.move(textInfos.UNIT_LINE, 1, endPoint="end") speech.speakTextInfo(end, reason=controlTypes.REASON_CARET) ui.message( # Translators: message presented when a bookmark is selected. _("Position: character %d") % pos) return ui.message( # Translators: message presented when the next bookmark is not found. _("Next bookmark not found"))
def recognizeNavigatorObject(recognizer, filterNonGraphic=True): """User interface function to recognize content in the navigator object. This should be called from a script or in response to a GUI action. @param recognizer: The content recognizer to use. @type recognizer: L{contentRecog.ContentRecognizer} """ global _activeRecog if isinstance(api.getFocusObject(), RecogResultNVDAObject): # Translators: Reported when content recognition (e.g. OCR) is attempted, # but the user is already reading a content recognition result. ui.message(_("Already in a content recognition result")) return nav = api.getNavigatorObject() if filterNonGraphic and not recognizer.validateObject(nav): return # Translators: Reported when content recognition (e.g. OCR) is attempted, # but the content is not visible. notVisibleMsg = _("Content is not visible") try: left, top, width, height = nav.location except TypeError: log.debugWarning("Object returned location %r" % nav.location) ui.message(notVisibleMsg) return if not recognizer.validateBounds(nav.location): return try: imgInfo = RecogImageInfo.createFromRecognizer(left, top, width, height, recognizer) except ValueError: ui.message(notVisibleMsg) return if _activeRecog: _activeRecog.cancel() # Translators: Reporting when content recognition (e.g. OCR) begins. ui.message(_("Recognizing")) sb = screenBitmap.ScreenBitmap(imgInfo.recogWidth, imgInfo.recogHeight) pixels = sb.captureImage(left, top, width, height) _activeRecog = recognizer recognizer.recognize(pixels, imgInfo, _recogOnResult)
def sendChars(self, chars: str): """Sends the provided unicode characters to the system. @param chars: The characters to send to the system. """ inputs = [] for ch in chars: for direction in (0,winUser.KEYEVENTF_KEYUP): input = winUser.Input() input.type = winUser.INPUT_KEYBOARD input.ii.ki = winUser.KeyBdInput() input.ii.ki.wScan = ord(ch) input.ii.ki.dwFlags = winUser.KEYEVENTF_UNICODE|direction inputs.append(input) winUser.SendInput(inputs) focusObj = api.getFocusObject() if keyboardHandler.shouldUseToUnicodeEx(focusObj): # #10569: When we use ToUnicodeEx to detect typed characters, # emulated keypresses aren't detected. # Send TypedCharacter events manually. for ch in chars: focusObj.event_typedCharacter(ch=ch)
def move(self, increment, errorMessages, unbounded=False, op=operator.eq): """Moves to another line in current document. This function will call one of its implementations dependingon whether the focus is in an editable text or in a browser. @paramincrement: Direction to move, should be either 1 or -1. @param errorMessages: Error message to speak if the desired line cannot be found. @param unbounded: When in an indented text file whether to allow to jump to another indentation block. For example, in a python source code, when set to True, it will be able to jump from the body of one function to another. When set to false, it will be constrained within the current indentation block, suchas a function. @param op: Operator that is applied to the indentation level of lines being searched. This operator should returntrue only on the desired string. For example, when looking for a string of the same indent, this should be operator.eq. When searching for a string with greater indent, this should be set to operator.gt, and so on. """ focus = api.getFocusObject() if focus.role == controlTypes.ROLE_EDITABLETEXT: self.moveInEditable(increment, errorMessages[0], unbounded, op) elif (len(errorMessages) >= 2) and hasattr(focus, "treeInterceptor") and hasattr(focus.treeInterceptor, "makeTextInfo"): self.moveInBrowser(increment, errorMessages[1], op) else: errorMsg = _("Cannot move here") ui.message(errorMsg)
def sayActivePane(): oFocus = api.getFocusObject() hFocus = oFocus.windowHandle #If ((( isstatusbartoolbar ( hFocus) || intaskpanedialog () ) || inribbons () ) || isvirtualribbonactive () ) || dialogactive (): #Return storyType = oFocus._WinwordSelectionObject.StoryType sPaneName = getPaneName(storyType) if storyType: oActiveWindow = oFocus._WinwordWindowObject.Application.ActiveWindow oActivePane = oActiveWindow.ActivePane try: oFrameset = oActivePane.Frameset except: oFrameset = None if oFrameset: ui.message( _("Frame {name} document pane {index}").format( name=oFrameset.FrameName, index=str(oActivePane.index))) elif sPaneName != "": ui.message(sPaneName)
def script_getInfo(self, gesture): text = "" obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if isinstance(treeInterceptor, treeInterceptorHandler.DocumentTreeInterceptor): obj = treeInterceptor try: info = obj.makeTextInfo(textInfos.POSITION_SELECTION) except (RuntimeError, NotImplementedError): info = None if not info or info.isCollapsed: #No text selected, try grabbing word under review cursor info = api.getReviewPosition().copy() try: info.expand(textInfos.UNIT_WORD) except AttributeError: #Nothing more we can do #translators: message spoken when no text is selected or focused ui.message(_("select or focus something first")) return self.get_info(info.text.strip())
def checkTreeInterceptor(self, eventName): obj = api.getFocusObject() if not obj or not hasattr( obj, "treeInterceptor") or obj.treeInterceptor is None: return ti = obj.treeInterceptor if not ti.isReady: return if ti != self.lastTreeInterceptor: self.lastTreeInterceptor = ti log.info("new treeInterceptor") self.lastSize = 0 try: info = ti.makeTextInfo(textInfos.POSITION_LAST) size = info._endOffset if size != self.lastSize: self.lastSize = size log.info(u"taille : %d" % size) except Exception, e: pass
def nvdaControllerInternal_inputCompositionUpdate(compositionString, selectionStart, selectionEnd, isReading): from NVDAObjects.inputComposition import InputComposition from NVDAObjects.IAccessible.mscandui import ModernCandidateUICandidateItem if selectionStart == -1: queueHandler.queueFunction(queueHandler.eventQueue, handleInputCompositionEnd, compositionString) return 0 focus = api.getFocusObject() if isinstance(focus, InputComposition): focus.compositionUpdate(compositionString, selectionStart, selectionEnd, isReading) # Eliminate InputCompositionStart events from Microsoft Pinyin to avoid reading composition string instead of candidates elif not isinstance(focus, ModernCandidateUICandidateItem): queueHandler.queueFunction(queueHandler.eventQueue, handleInputCompositionStart, compositionString, selectionStart, selectionEnd, isReading) return 0
def script_nextEltRotor(self, gesture): if rotorItem == ROTOR_DEF: return self.sendComb('rightarrow', gesture) elif rotorItem in [ROTOR_MOVE, ROTOR_SELECT]: return self.sendComb(self.getCurrentSelectionRange(False), gesture) elif rotorItem == ROTOR_OBJ: self.sendComb('nvda+shift+rightarrow', gesture) self.showBrailleObj() elif rotorItem == ROTOR_REVIEW: scriptHandler.executeScript( globalCommands.commands.script_braille_scrollForward, gesture) elif rotorItem == ROTOR_TABLES: self.sendComb('control+alt+rightarrow', gesture) elif rotorItem == ROTOR_ERR: obj = api.getFocusObject() if obj.treeInterceptor is not None: obj.treeInterceptor.script_nextError(gesture) else: ui.message(_('Not supported here or browse mode not enabled')) else: return ui.message(_('Not implemented yet'))
def prePopup(self): """Prepare for a popup. This should be called before any dialog or menu which should pop up for the user. L{postPopup} should be called after the dialog or menu has been shown. @postcondition: A dialog or menu may be shown. """ nvdaPid = os.getpid() focus = api.getFocusObject() # Do not set prevFocus if the focus is on a control rendered by NVDA itself, such as the NVDA menu. # This allows to refer to the control that had focus before opening the menu while still using NVDA # on its own controls. The L{nvdaPid} check can be bypassed by setting the optional attribute # L{isPrevFocusOnNvdaPopup} to L{True} when a NVDA dialog offers customizable bound gestures, # eg. the NVDA Python Console. if focus.processID != nvdaPid or getattr( focus, "isPrevFocusOnNvdaPopup", False): self.prevFocus = focus self.prevFocusAncestors = api.getFocusAncestors() if winUser.getWindowThreadProcessID( winUser.getForegroundWindow())[0] != nvdaPid: # This process is not the foreground process, so bring it to the foreground. self.Raise()
def _prepare(): obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if hasattr(treeInterceptor, 'TextInfo') and not treeInterceptor.passThrough: obj = treeInterceptor try: total = obj.makeTextInfo(textInfos.POSITION_ALL) except (NotImplementedError, RuntimeError): raise RuntimeError("Invalid object") try: current = obj.makeTextInfo(textInfos.POSITION_CARET) except (NotImplementedError, RuntimeError): # Translators: Announced when there is no caret in the currently focused control. message(_("Caret not found")) raise RuntimeError("Cannot work with object with no caret") if total.text == '': # Translators: Reported when the field with caret is empty message(_("No text")) raise RuntimeError("Cannot work with empty field") return current, total
def script_goToStationsList(self, gesture): if not self.inMainWindow(): gesture.send() return obj = findWindowNVDAObject("stationsList") focus = api.getFocusObject() if obj == focus: ui.message(_("You are in stations list window")) return if obj is None or not winUser.isWindowVisible(obj.windowHandle): # try to display stations list by pressing expand button clickButton("expandButton") time.sleep(1.0) obj = findWindowNVDAObject("stationsList") if obj is None or not winUser.isWindowVisible(obj.windowHandle): # impossible to display list ui.message(_("Stations list not found")) return # now set focus obj.setFocus() eventHandler.queueEvent("gainFocus", obj)
def reportHeaderFieldN(self, nField, gesture): if api.getFocusObject().windowClassName in ['DayViewWnd', 'WeekViewWnd']: #Calendar view: Alt+digit is used command to set up number of days in the view gesture.send() return nRepeat = getLastScriptRepeatCount() if nRepeat == 0: try: self.olItemWindow = OutlookItemWindow() except NotInMessageWindowError: self.olItemWindow = None if self.olItemWindow is None: # Translators: When trying to use Alt+Number shortcut but not in message. ui.message(_("Not in a message window")) return try: obj, name = self.olItemWindow.getHeaderFieldObject(nField) except HeaderFieldNotFoundeError: self.errorBeep() return self.reportObject(obj, nRepeat)
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 script_saveBookmark(self, gesture): obj = api.getFocusObject() treeInterceptor = obj.treeInterceptor if hasattr(treeInterceptor, 'TextInfo') and not treeInterceptor.passThrough: obj = treeInterceptor else: gesture.send() return start = obj.makeTextInfo(textInfos.POSITION_ALL) try: end = obj.makeTextInfo(textInfos.POSITION_CARET) except (NotImplementedError, RuntimeError): ui.message( # Translators: message presented when a bookmark cannot be saved. _("Bookmark cannot be saved")) return start.setEndPoint(end, "endToStart") count = len(start.text) bookmarks = getSavedBookmarks() noteTitle = obj.makeTextInfo( textInfos.POSITION_SELECTION).text[:100].encode("mbcs") positions = list(bookmarks.keys()) if count in positions: noteBody = bookmarks[count].body else: noteBody = "" bookmarks[count] = Note(noteTitle, noteBody) fileName = getFileBookmarks() try: pickle.dump(bookmarks, file(fileName, "wb")) ui.message( # Translators: message presented when a position is saved as a bookmark. _("Saved position at character %d") % count) except Exception as e: log.debugWarning("Error saving bookmark", exc_info=True) ui.message( # Translators: message presented when a bookmark cannot be saved. _("Cannot save bookmark")) raise e
def moveInTree(self, increment, errorMessage, unbounded=False, op=operator.eq, speakOnly=False, moveCount=1): obj = api.getFocusObject() level = self.getLevel(obj) found = False levels = [] while True: if increment > 0: obj = obj.next else: obj = obj.previous newLevel = self.getLevel(obj) if newLevel is None: break if op(newLevel, level): found = True level = newLevel result = obj moveCount -= 1 if moveCount == 0: break elif newLevel < level: # Not found in this subtree if not unbounded: break levels.append(newLevel) if found: self.beeper.fancyCrackle(levels, volume=getConfig("crackleVolume")) if not speakOnly: result.setFocus() else: speech.speakObject(result) else: self.endOfDocument(errorMessage)
def reloadAppModules(): """Reloads running appModules. especially, it clears the cache of running appModules and deletes them from sys.modules. Each appModule will then be reloaded immediately. """ global appModules state = [] for mod in runningTable.itervalues(): state.append({key: getattr(mod, key) for key in ("processID", # #2892: We must save nvdaHelperRemote handles, as we can't reinitialize without a foreground/focus event. # Also, if there is an active context handle such as a loaded buffer, # nvdaHelperRemote can't reinit until that handle dies. "helperLocalBindingHandle", "_inprocRegistrationHandle", # #5380: We must save config profile triggers so they can be cleaned up correctly. # Otherwise, they'll remain active forever. "_configProfileTrigger", ) if hasattr(mod, key)}) # #2892: Don't disconnect from nvdaHelperRemote during termination. mod._helperPreventDisconnect = True terminate() del appModules mods=[k for k,v in sys.modules.iteritems() if k.startswith("appModules") and v is not None] for mod in mods: del sys.modules[mod] import appModules initialize() for entry in state: pid = entry.pop("processID") mod = getAppModuleFromProcessID(pid) mod.__dict__.update(entry) # The appModule property for existing NVDAObjects will now be None, since their AppModule died. # Force focus, navigator, etc. objects to re-fetch, # since NVDA depends on the appModule property for these. for obj in itertools.chain((api.getFocusObject(), api.getNavigatorObject()), api.getFocusAncestors()): try: del obj._appModuleRef except AttributeError: continue # Fetch and cache right away; the process could die any time. obj.appModule