def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03): """ Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued. @param bookmark: a bookmark representing the position of the caret before it was instructed to move @type bookmark: bookmark @param retryInterval: the interval of time in seconds this method should wait before checking the caret each time. @type retryInterval: float @param timeout: the over all amount of time in seconds the method should wait before giving up completely. @type timeout: float @return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event. @rtype: tuple """ elapsed = 0 newInfo=None while elapsed < timeout: if isScriptWaiting(): return (False,None) api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return (True,None) #The caret may stop working as the focus jumps, we want to stay in the while loop though try: newInfo = self.makeTextInfo(textInfos.POSITION_CARET) newBookmark = newInfo.bookmark except (RuntimeError,NotImplementedError): newInfo=None else: if newBookmark!=bookmark: return (True,newInfo) time.sleep(retryInterval) elapsed += retryInterval return (False,newInfo)
def script_down(self, gesture): gesture.send() if isStarting(): sayMessage(announce[3]) return if isRecording(): return if checkSelection() or checkPart(): speech.speechMode = speech.speechMode_off api.processPendingEvents() speech.speechMode = oldSpeechMode if checkSelection(): if not isReading(): sActual = actualDuration() if not sActual: sActual = announce[1] if sActual == totalTime(): sActual = u'{0} {1}'.format(sActual, announce[2]) sayMessage(announce[6] + ' : ' + sActual + ' ' + actualDurationPercentage()) else: if not isReading(): sActual = actualDuration() if not sActual: sayMessage(u'{0}, {1}'.format(announce[0], announce[1])) return if sActual == totalTime(): sActual = u'{0} {1}'.format(sActual, announce[2]) # Translators: Message to indicate the elapsed time. sayMessage(u'{0}, {1} {2} {3}'.format( announce[0], _('Elapsed time: '), sActual, actualDurationPercentage()))
def callback(obj, oldspeechMode): api.processPendingEvents() speech.cancelSpeech() speech.speechMode = oldSpeechMode api.setNavigatorObject(obj) api.moveMouseToNVDAObject(obj) speech.speakObject(obj)
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03): """ Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued. @param bookmark: a bookmark representing the position of the caret before it was instructed to move @type bookmark: bookmark @param retryInterval: the interval of time in seconds this method should wait before checking the caret each time. @type retryInterval: float @param timeout: the over all amount of time in seconds the method should wait before giving up completely. @type timeout: float @return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event. @rtype: tuple """ elapsed = 0 newInfo = None while elapsed < timeout: if isScriptWaiting(): return (False, None) api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return (True, None) #The caret may stop working as the focus jumps, we want to stay in the while loop though try: newInfo = self.makeTextInfo(textInfos.POSITION_CARET) newBookmark = newInfo.bookmark except (RuntimeError, NotImplementedError): newInfo = None else: if newBookmark != bookmark: return (True, newInfo) time.sleep(retryInterval) elapsed += retryInterval return (False, newInfo)
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 script_down(self, gesture): gesture.send() if isStarting(): sayMessage(announce[3]) return if isRecording(): return if checkSelection() or checkPart(): self.appModule.runValueChange = False api.processPendingEvents() if not isReading(): if checkSelection(): actual = actualDuration() if not actual: actual = announce[1] if actual == totalTime(): actual = '{0} {1}'.format(actual, announce[2]) sayMessage(announce[6] + ' : ' + actual + ' ' + actualDurationPercentage()) else: actual = actualDuration() if not actual: sayMessage('{0}, {1}'.format(announce[0], announce[1])) return if actual == totalTime(): actual = '{0} {1}'.format(actual, announce[2]) # Translators: Message to indicate the elapsed time. sayMessage('{0}, {1} {2} {3}'.format( announce[0], _('Elapsed time: '), actual, actualDurationPercentage())) self.appModule.runValueChange = True
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 script_activate(self,gesture): self.doAction() api.processPendingEvents() oldItem=item=self while item and isinstance(item.candidateNumber,int): oldItem=item item=item.previous if oldItem and isinstance(oldItem.candidateNumber,int) and oldItem.name: reportSelectedCandidate(oldItem,allowDuplicate=True,newList=True)
def script_repeatToggle(self, gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if self.appModule.getRepeat(): onOff = _("on") else: onOff = _("off") ui.message(onOff)
def script_activate(self, gesture): try: self.doAction() if self.windowControlID == ctrlIdsDic["favButton"]: eventHandler.queueEvent("gainFocus", self) time.sleep(0.1) api.processPendingEvents() KeyboardInputGesture.fromName("downArrow").send() except Exception: gesture.send()
def script_clickFavButton(self, gesture): if not self.inMainWindow(): gesture.send() return clickButton("favButton") obj = api.getFocusObject() eventHandler.queueEvent("gainFocus", obj) time.sleep(0.1) api.processPendingEvents() KeyboardInputGesture.fromName("downArrow").send()
def script_activate(self, gesture): self.doAction() api.processPendingEvents() oldItem = item = self while item and isinstance(item.candidateNumber, int): oldItem = item item = item.previous if oldItem and isinstance(oldItem.candidateNumber, int) and oldItem.name: reportSelectedCandidate(oldItem, allowDuplicate=True, newList=True)
def clickButtonWithoutMoving(window): oldSpeechMode = getSpeechMode() setSpeechMode_off() currentObj = api.getFocusObject() name = clickButton(window) currentObj.setFocus() eventHandler.queueEvent("gainFocus", currentObj) time.sleep(0.1) api.processPendingEvents() setSpeechMode(oldSpeechMode) return name
def script_repeatToggle(self, gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getRepeat(): # Translators: the user has pressed the repeat track toggle in winamp, repeat is now on. onOff = pgettext("repeat", "on") else: # Translators: the user has pressed the repeat track toggle in winamp, repeat is now off. onOff = pgettext("repeat", "off") speech.speakMessage(onOff)
def script_shuffleToggle(self, gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getShuffle(): # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now on. onOff = pgettext("shuffle", "on") else: # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now off. onOff = pgettext("shuffle", "off") speech.speakMessage(onOff)
def showManager(context): api.processPendingEvents() webModule = context["webModule"] markerManager = webModule.markerManager if not markerManager.isReady: ui.message(u"Marqueurs non disponibles") return focusObject = context["focusObject"] context["rule"] = markerManager.getCurrentResult(focusObject=focusObject) from ..gui import rulesManager rulesManager.show(context)
def delete(self): index = self.entriesList.GetFocusedItem() item = self.collection[index] self.collectionObject.delete(item) self.refreshList(index) if len(self.collection) == 0: return self.entriesList.SetFocus() time.sleep(0.1) api.processPendingEvents() obj = api.getFocusObject() queueEvent("gainFocus", obj)
def script_repeatToggle(self, gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getRepeat(): # Translators: the user has pressed the repeat track toggle in winamp, repeat is now on. onOff = pgettext("repeat", "on") else: # Translators: the user has pressed the repeat track toggle in winamp, repeat is now off. onOff = pgettext("repeat", "off") ui.message(onOff)
def setFocus(self): oldFocus = self._getPhysicalFocus() super(Mozilla, self).setFocus() # Although all versions of Firefox block inSetFocus or in accFocus until the physical focus has moved, # Firefox 57 and above return before they fire a focus winEvent communicating the focus change to ATs. # Therefore, If the call to setFocus did change the physical focus, # Wait for a focus event to be queued to NVDA before returning. newFocus = self._getPhysicalFocus() if newFocus and newFocus != oldFocus: while not eventHandler.isPendingEvents("gainFocus"): api.processPendingEvents(processEventQueue=False)
def script_shuffleToggle(self, gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() if getShuffle(): # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now on. onOff = pgettext("shuffle", "on") else: # Translators: the user has pressed the shuffle tracks toggle in winamp, shuffle is now off. onOff = pgettext("shuffle", "off") ui.message(onOff)
def setFocus(self): oldFocus=self._getPhysicalFocus() super(Mozilla,self).setFocus() # Although all versions of Firefox block inSetFocus or in accFocus until the physical focus has moved, # Firefox 57 and above return before they fire a focus winEvent communicating the focus change to ATs. # Therefore, If the call to setFocus did change the physical focus, # Wait for a focus event to be queued to NVDA before returning. newFocus=self._getPhysicalFocus() if newFocus and newFocus!=oldFocus: while not eventHandler.isPendingEvents("gainFocus"): api.processPendingEvents(processEventQueue=False)
def clickButton(window): obj = findWindowNVDAObject(window) if obj is None: return None oldSpeechMode = getSpeechMode() setSpeechMode_off() obj.IAccessibleObject.accDoDefaultAction(0) eventHandler.queueEvent("gainFocus", obj) time.sleep(0.1) api.processPendingEvents() setSpeechMode(oldSpeechMode) return obj.name
def _registerCOMWithFocusJuggle(self): import wx import gui # Translators: A title for a dialog shown while Microsoft PowerPoint initializes d=wx.Dialog(None,title=_("Waiting for Powerpoint...")) gui.mainFrame.prePopup() d.Show() self.hasTriedPpAppSwitch=True #Make sure NVDA detects and reports focus on the waiting dialog api.processPendingEvents() comtypes.client.PumpEvents(1) d.Destroy() gui.mainFrame.postPopup()
def script_changePage(self,gesture): try: del self.__dict__['visibleCandidateItemsText'] except KeyError: pass gesture.send() api.processPendingEvents() oldItem=item=self while item and isinstance(item.candidateNumber,int): oldItem=item item=item.previous if oldItem and isinstance(oldItem.candidateNumber,int) and oldItem.name: reportSelectedCandidate(oldItem,allowDuplicate=True,newList=True)
def event_gainFocus(self,obj,nextHandler): nextHandler() #Force focus to move to something sane when landing on a plain text message window if obj.windowClassName=="ME_DocHost" and obj.windowControlID==1000 and obj.role==controlTypes.ROLE_PANE: firstChild=obj.firstChild if firstChild: firstChild=obj.firstChild if firstChild: firstChild.setFocus() return 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 event_caret(self): global selOffsetsAtLastCaretEvent #Fetching formatting and calculating word offsets needs to move the caret, so try to ignore these events selOffsets=self.makeTextInfo(textInfos.POSITION_SELECTION).bookmark if selOffsets==selOffsetsAtLastCaretEvent: return selOffsetsAtLastCaretEvent=selOffsets #Make sure that this object *really* has the focus before bothering to speak any possible selection change api.processPendingEvents() if self is not api.getFocusObject() or eventHandler.isPendingEvents('gainFocus'): return if eventHandler.isPendingEvents('valueChange',self): self.hasContentChangedSinceLastSelection=True super(Edit,self).event_caret()
def __init__(self, parent, focus, rangeType): self.rangeType = rangeType self.dialogClass = GrammaticalErrorsDialog self.noElement = _("No gramatical error") wordApp = focus._WinwordWindowObject.Application if not wordApp.Options.CheckGrammarAsYouType: self.collection = None ui.message(_("Not available, Check grammar as you type is not activated")) time.sleep(3.0) api.processPendingEvents() time.sleep(0.2) queueEvent("gainFocus", api.getFocusObject()) return super(GrammaticalErrors, self).__init__(parent, focus)
def script_changePage(self, gesture): try: del self.__dict__['visibleCandidateItemsText'] except KeyError: pass gesture.send() api.processPendingEvents() oldItem = item = self while item and isinstance(item.candidateNumber, int): oldItem = item item = item.previous if oldItem and isinstance(oldItem.candidateNumber, int) and oldItem.name: reportSelectedCandidate(oldItem, allowDuplicate=True, newList=True)
def _registerCOMWithFocusJuggle(self): import wx import gui # Translators: The title for the dialog shown while Microsoft Outlook initializes. d=wx.Dialog(None,title=_("Waiting for Outlook...")) d.Center(wx.BOTH | wx.CENTER_ON_SCREEN) gui.mainFrame.prePopup() d.Show() self._hasTriedoutlookAppSwitch=True #Make sure NVDA detects and reports focus on the waiting dialog api.processPendingEvents() comtypes.client.PumpEvents(1) d.Destroy() gui.mainFrame.postPopup()
def _registerCOMWithFocusJuggle(self): import wx import gui # Translators: The title for the dialog shown while Microsoft Outlook initializes. d = wx.Dialog(None, title=_("Waiting for Outlook...")) d.Center(wx.BOTH | wx.CENTER_ON_SCREEN) gui.mainFrame.prePopup() d.Show() self._hasTriedoutlookAppSwitch = True #Make sure NVDA detects and reports focus on the waiting dialog api.processPendingEvents() comtypes.client.PumpEvents(1) d.Destroy() gui.mainFrame.postPopup()
def changeVolumeLevel(self, targetLevel, mode): if speakers is not None: for attempt in range(2): processPendingEvents() level = int(speakers.GetMasterVolumeLevelScalar()*100+0.5) log.info("Level speakers at Startup: {} Percent".format(level)) if level < targetLevel or (mode == 1 and level > targetLevel): speakers.SetMasterVolumeLevelScalar(targetLevel/100.0,None) muteState = speakers.GetMute() log.info("speakers at Startup: {}".format(("Unmuted","Muted")[muteState])) if muteState: speakers.SetMute(0, None) log.info("speakers after correction: {} Percent, {}".format( int(speakers.GetMasterVolumeLevelScalar()*100+0.5), ("Unmuted","Muted")[speakers.GetMute()]))
def _paste_safe(self, text, obj=None, label=False): try: temp = api.getClipData() except: temp = '' api.copyToClip(text) if label == True: KIGesture.fromName('p').send() KIGesture.fromName('control+alt+v').send() else: KIGesture.fromName('control+v').send() api.processPendingEvents() if obj: obj.reportFocus() api.copyToClip(temp)
def script_caret_changeSelection(self,gesture): try: oldInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: gesture.send() return gesture.send() if isScriptWaiting() or eventHandler.isPendingEvents("gainFocus"): return api.processPendingEvents(processEventQueue=False) try: newInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: return speech.speakSelectionChange(oldInfo,newInfo)
def script_doAction(self, gesture): # code written by Javi Dominguez and adapted to this add-on printDebug("script_doAction") obj = api.getNavigatorObject() mainWindow = self.appModule.mainWindow anchoredPlaylist = mainWindow.mainPanel.anchoredPlaylist oldAnchoredPlaylistState = anchoredPlaylist.isVisible() controlPanel = mainWindow.mainPanel.controlPanel if obj not in controlPanel.controls[1:]: gesture.send() return description = obj.description if obj.role not in [controlTypes.ROLE_BUTTON, controlTypes.ROLE_GRAPHIC]: obj.doAction() msg = [] for state in obj.states: msg.append(controlTypes.stateLabels[state]) desc = api.getMouseObject().description if obj.role == controlTypes.ROLE_CHECKBOX and\ controlTypes.STATE_CHECKED not in obj.states: msg.append(_("unchecked")) if desc: msg.append(api.getMouseObject().description) elif desc and description == desc: msg.append(desc) if len(msg): text = ", ".join(msg) ui.message(text) else: api.moveMouseToNVDAObject(obj) x, y = winUser.getCursorPos() o = api.getDesktopObject().objectFromPoint(x, y) if o.description == obj.description: controlPanel.clickButton(obj) api.processPendingEvents() api.moveMouseToNVDAObject(obj) o = api.getDesktopObject().objectFromPoint(x, y) if description != o.description: ui.message(api.getMouseObject().description) else: pass newAnchoredPlaylistState = anchoredPlaylist.isVisible() if not oldAnchoredPlaylistState and newAnchoredPlaylistState: obj = anchoredPlaylist.NVDAObject mouseClick(obj) return # put focus on new dialog if there is one (like adjustments and effects) self.focusDialog()
def turnPage(self,previous=False): try: self.IAccessibleActionObject.doAction(1 if previous else 0) except COMError: raise RuntimeError("no more pages") startTime=curTime=time.time() while (curTime-startTime)<0.5: api.processPendingEvents(processEventQueue=False) # should only check for pending pageChange for this object specifically, but object equality seems to fail sometimes? if eventHandler.isPendingEvents("pageChange"): self.invalidateCache() break time.sleep(0.05) curTime=time.time() else: raise RuntimeError("no more pages")
def script_activate(self, gesture): if self.node.nodeManager is None: return if not self.markerQuery.markerManager.isReady: log.info(u"not ready") return treeInterceptor = self.node.nodeManager.treeInterceptor if self.markerQuery.sayName: speech.speakMessage(self.markerQuery.label) self.node.activate() time.sleep(0.1) api.processPendingEvents() if not treeInterceptor: return treeInterceptor.passThrough = self.markerQuery.formMode browseMode.reportPassThrough.last = treeInterceptor.passThrough
def script_caret_changeSelection(self,gesture): try: oldInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: gesture.send() return gesture.send() if isScriptWaiting() or eventHandler.isPendingEvents("gainFocus"): return api.processPendingEvents(processEventQueue=False) try: newInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: return speech.speakSelectionChange(oldInfo,newInfo) braille.handler.handleCaretMove(self)
def script_f7KeyStroke(self, gesture): 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.isInSpellingChecker(): return if focus.role == controlTypes.ROLE_PANE: # focus on the pane not not on an object of the pane queueHandler.queueFunction( queueHandler.eventQueue, speech.speakMessage, # Translators: message to ask user to hit tab key. _("Hit tab to move focus in the spelling checker pane")) else: sc.sayErrorAndSuggestion(title=True, spell=False, focusOnSuggestion=True) queueHandler.queueFunction(queueHandler.eventQueue, speech.speakObject, focus, controlTypes.REASON_FOCUS) stopScriptTimer() if not self.isSupportedVersion(): gesture.send() return focus = api.getFocusObject() from .ww_spellingChecker import SpellingChecker sc = SpellingChecker(focus, self.WinwordVersion) if not sc.isInSpellingChecker(): # moving to spelling checker oldSpeechMode = speech.speechMode speech.speechMode = speech.speechMode_off gesture.send() core.callLater(500, verify, oldSpeechMode) return # moving to document selection winwordWindowObject = self.WinwordWindowObject selection = winwordWindowObject.Selection selection.Characters(1).GoTo() time.sleep(0.1) api.processPendingEvents() speech.cancelSpeech() speech.speakObject(api.getFocusObject(), controlTypes.REASON_FOCUS)
def clickPlayPauseButton(self): oIA = self.getPlayPauseButton() if oIA is None: return name = oIA.accName(0) left, top, width, height = oIA.accLocation(0) leftClick(left + int(width / 2), top + int(height / 2)) # verify if it is done if oIA.accName(0) == name: return # no, so try other thing oldSpeechMode = getSpeechMode() setSpeechMode_off() keyboardHandler.KeyboardInputGesture.fromName("space").send() time.sleep(0.1) api.processPendingEvents() setSpeechMode(oldSpeechMode)
def _registerCOMWithFocusJuggle(self): import wx import gui # Translators: The title for the dialog shown while Microsoft Outlook initializes. d=wx.Dialog(None,title=_("Waiting for Outlook...")) d.CentreOnScreen() gui.mainFrame.prePopup() d.Show() self._hasTriedoutlookAppSwitch=True #Make sure NVDA detects and reports focus on the waiting dialog api.processPendingEvents() try: comtypes.client.PumpEvents(1) except WindowsError: log.debugWarning("Error while pumping com events", exc_info=True) d.Destroy() gui.mainFrame.postPopup()
def _expandToLine(self, textRange): #Try to calculate the line range by finding screen coordinates and using moveToPoint parent = textRange.parentElement() if not parent.isMultiline: #fastest solution for single line edits (<input type="text">) textRange.expand("textEdit") return parentRect = parent.getBoundingClientRect() #This can be simplified when comtypes is fixed lineTop = comtypes.client.dynamic._Dispatch( textRange._comobj).offsetTop lineLeft = parentRect.left + parent.clientLeft #editable documents have a different right most boundary to <textarea> elements. if self.obj.HTMLNode.document.body.isContentEditable: lineRight = parentRect.right else: lineRight = parentRect.left + parent.clientWidth tempRange = textRange.duplicate() try: tempRange.moveToPoint(lineLeft, lineTop) textRange.setEndPoint("startToStart", tempRange) tempRange.moveToPoint(lineRight, lineTop) textRange.setEndPoint("endToStart", tempRange) return except COMError: pass #MoveToPoint fails on Some (possibly floated) textArea elements. #Instead use the physical selection, by moving it with key presses, to work out the line. #This approach is somewhat slower, and less accurate. with self.obj.suspendCaretEvents(): selObj = parent.document.selection oldSelRange = selObj.createRange().duplicate() # #1566: Calling textRange.select() sometimes throws focus onto the document, # so create a new range from the selection and move the selection using that. selObj.createRange().moveToBookmark(textRange.getBookmark()) KeyboardInputGesture.fromName("home").send() api.processPendingEvents(False) newSelStartMark = selObj.createRange().getBookmark() KeyboardInputGesture.fromName("end").send() api.processPendingEvents(False) newSelEndMark = selObj.createRange().getBookmark() tempRange.moveToBookmark(newSelStartMark) textRange.setEndPoint("startToStart", tempRange) tempRange.moveToBookmark(newSelEndMark) textRange.setEndPoint("endToStart", tempRange) oldSelRange.select()
def _expandToLine(self,textRange): #Try to calculate the line range by finding screen coordinates and using moveToPoint parent=textRange.parentElement() if not parent.isMultiline: #fastest solution for single line edits (<input type="text">) textRange.expand("textEdit") return parentRect=parent.getBoundingClientRect() #This can be simplified when comtypes is fixed lineTop=comtypes.client.dynamic._Dispatch(textRange._comobj).offsetTop lineLeft=parentRect.left+parent.clientLeft #editable documents have a different right most boundary to <textarea> elements. if self.obj.HTMLNode.document.body.isContentEditable: lineRight=parentRect.right else: lineRight=parentRect.left+parent.clientWidth tempRange=textRange.duplicate() try: tempRange.moveToPoint(lineLeft,lineTop) textRange.setEndPoint("startToStart",tempRange) tempRange.moveToPoint(lineRight,lineTop) textRange.setEndPoint("endToStart",tempRange) return except COMError: pass #MoveToPoint fails on Some (possibly floated) textArea elements. #Instead use the physical selection, by moving it with key presses, to work out the line. #This approach is somewhat slower, and less accurate. with self.obj.suspendCaretEvents(): selObj=parent.document.selection oldSelRange=selObj.createRange().duplicate() # #1566: Calling textRange.select() sometimes throws focus onto the document, # so create a new range from the selection and move the selection using that. selObj.createRange().moveToBookmark(textRange.getBookmark()) KeyboardInputGesture.fromName("home").send() api.processPendingEvents(False) newSelStartMark=selObj.createRange().getBookmark() KeyboardInputGesture.fromName("end").send() api.processPendingEvents(False) newSelEndMark=selObj.createRange().getBookmark() tempRange.moveToBookmark(newSelStartMark) textRange.setEndPoint("startToStart",tempRange) tempRange.moveToBookmark(newSelEndMark) textRange.setEndPoint("endToStart",tempRange) oldSelRange.select()
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03): elapsed = 0 while elapsed < timeout: if isScriptWaiting(): return False api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return True #The caret may stop working as the focus jumps, we want to stay in the while loop though try: newBookmark = self.makeTextInfo(textInfos.POSITION_CARET).bookmark except (RuntimeError,NotImplementedError): pass else: if newBookmark!=bookmark: return True time.sleep(retryInterval) elapsed += retryInterval return False
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 xrange(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 script_openDropdown(self,gesture): gesture.send() d=None curTime=startTime=time.time() while (curTime-startTime)<=0.25: if scriptHandler.isScriptWaiting(): # Prevent lag if keys are pressed rapidly return if eventHandler.isPendingEvents('gainFocus'): return d=self._getDropdown() if d: break api.processPendingEvents(processEventQueue=False) time.sleep(0.025) curTime=time.time() if not d: log.debugWarning("Failed to get dropDown, giving up") return d.parent=self eventHandler.queueEvent("gainFocus",d)
def event_gainFocus(self): if not self.ppObjectModel and not self.appModule.hasTriedPpAppSwitch: #We failed to get the powerpoint object model, and we havn't yet tried fixing this by switching apps back and forth #As Powerpoint may have just been opened, it can take up to 10 seconds for the object model to be ready. #However, switching away to another application and back again forces the object model to be registered. #This call of ppObjectModel will be None, but the next event_gainFocus should work import wx import gui # Translators: A title for a dialog shown while Microsoft PowerPoint initializes d=wx.Dialog(None,title=_("Waiting for Powerpoint...")) gui.mainFrame.prePopup() d.Show() self.appModule.hasTriedPpAppSwitch=True #Make sure NVDA detects and reports focus on the waiting dialog api.processPendingEvents() comtypes.client.PumpEvents(1) d.Destroy() gui.mainFrame.postPopup() #Focus would have now landed back on this window causing a new event_gainFocus, nothing more to do here. return super(PaneClassDC,self).event_gainFocus()
def script_changeSelection(self,gesture): oldSelection=self._getSelection() gesture.send() import eventHandler import time import api newSelection=None curTime=startTime=time.time() while (curTime-startTime)<=0.15: if scriptHandler.isScriptWaiting(): # Prevent lag if keys are pressed rapidly return if eventHandler.isPendingEvents('gainFocus'): return newSelection=self._getSelection() if newSelection and newSelection!=oldSelection: break api.processPendingEvents(processEventQueue=False) time.sleep(0.015) curTime=time.time() if newSelection: eventHandler.executeEvent('gainFocus',newSelection)
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None, origWord=None): """ Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued. @param bookmark: a bookmark representing the position of the caret before it was instructed to move @type bookmark: bookmark @param retryInterval: the interval of time in seconds this method should wait before checking the caret each time. @type retryInterval: float @param timeout: the over all amount of time in seconds the method should wait before giving up completely, C{None} to use the value from the configuration. @type timeout: float @param origWord: The word at the caret before the movement command, C{None} if the word at the caret should not be used to detect movement. This is intended for use with the delete key. @return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event. @rtype: tuple """ if timeout is None: timeoutMs = config.conf["editableText"]["caretMoveTimeoutMs"] else: # This function's arguments are in seconds, but we want ms. timeoutMs = timeout * 1000 # time.sleep accepts seconds, so retryInterval is in seconds. # Convert to integer ms to avoid floating point precision errors when adding to elapsed. retryMs = int(retryInterval * 1000) elapsed = 0 newInfo=None while True: if isScriptWaiting(): return (False,None) api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): log.debug("Focus event. Elapsed: %d ms" % elapsed) return (True,None) # If the focus changes after this point, fetching the caret may fail, # but we still want to stay in this loop. try: newInfo = self.makeTextInfo(textInfos.POSITION_CARET) except (RuntimeError,NotImplementedError): newInfo = None # Caret events are unreliable in some controls. # Try to detect with bookmarks. newBookmark = None if newInfo: try: newBookmark = newInfo.bookmark except (RuntimeError,NotImplementedError): pass if newBookmark and newBookmark!=bookmark: log.debug("Caret move detected using bookmarks. Elapsed: %d ms" % elapsed) return (True, newInfo) if origWord is not None and newInfo and elapsed >= self._hasCaretMoved_minWordTimeoutMs: # When pressing delete, bookmarks might not be enough to detect caret movement. # Therefore try detecting if the word under the caret has changed, such as when pressing delete. # some editors such as Mozilla Gecko can have text and units that get out of sync with eachother while a character is being deleted. # Therefore, only check if the word has changed after a particular amount of time has elapsed, allowing the text and units to settle down. wordInfo = newInfo.copy() wordInfo.expand(textInfos.UNIT_WORD) word = wordInfo.text if word != origWord: log.debug("Word at caret changed. Elapsed: %d ms" % elapsed) return (True, newInfo) if elapsed >= timeoutMs: break time.sleep(retryInterval) elapsed += retryMs log.debug("Caret didn't move before timeout. Elapsed: %d ms" % elapsed) return (False,newInfo)
def reportSelectionChange(self, oldTextInfo): api.processPendingEvents(processEventQueue=False) newInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) speech.speakSelectionChange(oldTextInfo,newInfo) braille.handler.handleCaretMove(self)
def script_changeItem(self,gesture): gesture.send() if not isScriptWaiting(): api.processPendingEvents() speech.speakObject(self,reason=controlTypes.REASON_FOCUS) braille.handler.handleGainFocus(self)