def turnPage(self, previous=False): try: # Find the slider which indicates the current position. posSlider = self.parent.parent.next.lastChild except AttributeError: raise RuntimeError # We need the raw value, not the percentage. oldPos = posSlider.UIAElement.getCurrentPropertyValueEx(UIAHandler.UIA_RangeValueValuePropertyId, True) KeyboardInputGesture.fromName("pageUp" if previous else "pageDown").send() if posSlider.UIAElement.getCurrentPropertyValueEx(UIAHandler.UIA_RangeValueValuePropertyId, True) == oldPos: # No more pages. raise RuntimeError
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 _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 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 script_AnnounceGestures(self, gesture): if self.commandIndex < 0: ui.message(_("Select a command using up or down arrows")) return commandInfo = self.gestures[self.categories[self.catIndex]][ self.commands[self.commandIndex]] if commandInfo.gestures: try: ui.message(".\n".join([ ": ".join( KeyboardInputGesture.getDisplayTextForIdentifier(g)) for g in commandInfo.gestures ])) except: ui.message("\n".join(commandInfo.gestures)) else: ui.message(_("There is no gesture"))
def finish(self): global toggling, lastGesture, gestureTimer # keep a local var to gestureTimer tempTimer = gestureTimer # while ensure all timers started have finished now while tempTimer and tempTimer.is_alive(): debugLog("Waiting timer thread termination...") tempTimer.join() # update local var to current running timer tempTimer = gestureTimer toggling = False # lastGesture may be None if add-on key was pressed and released if lastGesture: # build whole gesture fixedGesture = '+'.join(["NVDA", lastGesture]) debugLog("Executing %s" % fixedGesture) inputManager.emulateGesture( KeyboardInputGesture.fromName(fixedGesture)) lastGesture = None
def getNewVLCKeysHelp(self): newVLCKeys = self.localeSettings.getVLCKeysToUpdate() if newVLCKeys is None: return "" vlcKeyNames = list(newVLCKeys.keys()) # Translators: message to the user. text = _( "The VLC command keys which will be record in the VLC configuration file are:" ) + "\r\n" for (keyName, msg) in _vlcHotKeyHelp: if keyName not in vlcKeyNames: continue key = self.normalizeKeyToNVDA(newVLCKeys[keyName]) if len(key) in [0, 1]: text = text + "%s %s" % (msg, key) + "\n" else: gesture = KeyboardInputGesture.fromName(key) text = text + "%s %s" % (msg, gesture.displayName) + "\n" return text
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 onExecuteScriptButton(self, evt): def callback(script, gestureOrgestureCls): self._executeScriptWaitingTimer = None wx.CallLater(200, speech.cancelSpeech) wx.CallLater(500, self._executeScript, script, gestureOrgestureCls, self.repeatCount) self.Destroy() self.repeatCount = self.repeatCount + 1 if self._executeScriptWaitingTimer is not None else 0 if self._executeScriptWaitingTimer is not None: self._executeScriptWaitingTimer.Stop() self._executeScriptWaitingTimer = None selectedItems = self.tree.getSelectedItemData() if selectedItems is None: item = None else: # get the leaf of the selection item = next((item for item in reversed(selectedItems) if item is not None), None) if not item: return scriptInfo = item.scriptInfo script = self.getScript(item) if not script: log.error("no script to run: %s, %s, %s" % ( scriptInfo.scriptName, scriptInfo.className, scriptInfo.moduleName)) return try: gestureCls = inputCore._getGestureClsForIdentifier(scriptInfo.gestures[0]) except Exception: gestureCls = KeyboardInputGesture gesture = None if gestureCls == KeyboardInputGesture and len(scriptInfo.gestures): identifier = scriptInfo.gestures[0] key = identifier.split(":", 1)[1] gesture = KeyboardInputGesture.fromName(key) gestureOrGestureCls = gesture if gesture else gestureCls from ..settings import _addonConfigManager delay = _addonConfigManager.getMaximumDelayBetweenSameScript() self._executeScriptWaitingTimer = wx.CallLater(delay, callback, script, gestureOrGestureCls)
def onPaste (self, evt): # Simulates typing the block of text in the edit area. self.Hide() evt.Skip() index=self.listBox.GetFocusedItem() name = self.listBox.GetItemText(index) paste = self.dictBlocks [name] for x in range(len(paste)): if paste[x] == "": time.sleep(0.1) KeyboardInputGesture.fromName("Enter").send() else: api.copyToClip(str(paste[x])) time.sleep(0.1) KeyboardInputGesture.fromName("Control+v").send() KeyboardInputGesture.fromName("Enter").send() time.sleep(0.1)
def emulateKeyPress(self, kbIdentifier: str, blockUntilProcessed=True): """ Emulates a key press using NVDA's input gesture framework. The key press will either result in a script being executed, or the key being sent on to the OS. By default this method will block until any script resulting from this key has been executed, and the NVDA core has again gone back to sleep. @param kbIdentifier: an NVDA keyboard gesture identifier. 0 or more modifier keys followed by a main key, all separated by a plus (+) symbol. E.g. control+shift+downArrow. See vkCodes.py in the NVDA source directory for valid key names. """ gesture = KeyboardInputGesture.fromName(kbIdentifier) inputCore.manager.emulateGesture(gesture) if blockUntilProcessed: # Emulating may have queued a script or events. # Insert our own function into the queue after, and wait for that to be also executed. queueProcessed = set() def _setQueueProcessed(): nonlocal queueProcessed queueProcessed = True queueHandler.queueFunction(queueHandler.eventQueue, _setQueueProcessed) _blockUntilConditionMet( getValue=lambda: queueProcessed, giveUpAfterSeconds=self._minTimeout(5), errorMessage="Timed out waiting for key to be processed", ) # We know that by now the core will have woken up and processed the scripts, events and our own function. # Wait for the core to go to sleep, # Which means there is no more things the core is currently processing. _blockUntilConditionMet( getValue=lambda: watchdog.isCoreAsleep(), giveUpAfterSeconds=self._minTimeout(5), errorMessage="Timed out waiting for core to sleep again", )
def cut(self): KeyboardInputGesture.fromName("control+x").send()
def script_expandLeft(self, gesture): KIGesture.fromName('Shift+LeftArrow').send() KIGesture.fromName('Shift+F6').send()
def script_expandRight(self, gesture): KIGesture.fromName('Shift+RightArrow').send() KIGesture.fromName('Shift+F8').send()
def tab(self): sleep(0.5) KeyboardInputGesture.fromName("tab").send()
def script_changeAndPreview(self, gesture): gesture.send() api.getFocusObject().displayText = '' api.getFocusObject().name == '' KIGesture.fromName('Shift+F6').send()
def script_nvdaDuplicateLine(self, gesture): #Retrieves the line before sending gesture, duplicate line is the same as the current one. line = self.getLambdaObj().getline(self.windowHandle, -1, -1) #duplicate line using keyboard shortcuts KeyboardInputGesture.fromName("home").send() self.skipSelectionReport = 2 #JWEdit bug: fires selection multiple times. KeyboardInputGesture.fromName("shift+end").send() KeyboardInputGesture.fromName("control+c").send() KeyboardInputGesture.fromName("end").send() KeyboardInputGesture.fromName("enter").send() KeyboardInputGesture.fromName("control+v").send() self.say(line)
def script_pageUpByThree(self, gesture): for i in range(3): KIGesture.fromName('upArrow').send()
def script_replaceApplications(self, gesture): # This is necessary because the usage of the applications key deselects all tracks. KIGesture.fromName('shift+f10').send()
def doAction(self): if controlTypes.STATE_FOCUSED not in self.states: return KeyboardInputGesture.fromName("space").send()
def script_close(self, gesture): KeyboardInputGesture.fromName("escape").send()
def script_selectMessages(self, item): Thread(target=speak, args=(None, 0.2), daemon=True).start() KeyboardInputGesture.fromName("applications").send() Thread(target=self.getMenuItems, args=(2, ), daemon=True).start()
def script_markAsRead(self, gesture): Thread(target=speak, args=(None, 0.2), daemon=True).start() KeyboardInputGesture.fromName("applications").send() Thread(target=self.getMenuItems, args=(3, ), daemon=True).start()
def script_contextMenu(self, gesture): KeyboardInputGesture.fromName("applications").send()
def script_pageDownByThree(self, gesture): for i in range(3): KIGesture.fromName('downArrow').send()
NUM_BRAILLE_KEYS = 9 WIN10_2004 = (10, 0, 19041) ItemSpec = namedtuple("ItemSpec", ["label", "default_value", "allowed_values"]) profile = OrderedDict() profile["AUTO_BRL_KEY"] = ItemSpec( label = _("Automatically enable braille keyboard simulation when NVDA starts."), default_value = False, allowed_values = None, ) profile["IME_LANGUAGE_MODE_TOGGLE_KEY"] = ItemSpec( label = _("The key shortcut to toggle IME alphanumeric/native mode:"), default_value = "leftshift" if (6, 0, 0) <= (getWinVer().major, getWinVer().minor, getWinVer().build) < WIN10_2004 else "control+space", allowed_values = OrderedDict([ ("control+space", KeyboardInputGesture.fromName("control+space").displayName), ("leftshift", KeyboardInputGesture.fromName("leftshift").displayName), ("rightshift", KeyboardInputGesture.fromName("rightshift").displayName), ]), ) profile["DEFAULT_NO_ALPHANUMERIC_BRL_KEY"] = ItemSpec( label = _("Disable braille keyboard simulation by default in IME alphanumeric mode."), default_value = False, allowed_values = None, ) profile["BRAILLE_KEYS"] = ItemSpec( label = _("Braille Keys:"), default_value = " FDSJKLA;", allowed_values = lambda bk: len(bk) == len(set(bk)) == NUM_BRAILLE_KEYS and all(ord(k) == windll.user32.MapVirtualKeyExW(VkKeyScanEx(k, getInputHkl())[1], MAPVK_VK_TO_CHAR, getInputHkl()) for k in bk), )
def cut(self): keyName = "control+x" if not isArabicKeyboardLayout() else u"control+ء" KeyboardInputGesture.fromName(keyName).send()
def sendGestures(gestureList): waitKeyUp () for gesture in gestureList: KeyboardInputGesture.fromName(gesture).send() time.sleep(0.1)
def script_reduceRight(self, gesture): KIGesture.fromName('Control+Shift+LeftArrow').send() KIGesture.fromName('Shift+F8').send()
def script_quickMarker(self, gesture): KIGesture.fromName('control+m').send() KIGesture.fromName('enter').send()
def paste(self): sleep(0.1) KeyboardInputGesture.fromName("control+v").send() sleep(0.5) self.obj.setFocus() pt.clean()
def SendKey(keys): KeyboardInputGesture.fromName(keys).send()
def handleConfigProfileSwitch(self): activation = config.conf["sharedComputer"]["numLockActivationChoice"] if activation < 2 and winUser.getKeyState(winUser.VK_NUMLOCK) != activation: KeyboardInputGesture.fromName("numLock").send()
def script_activarMenu(self, gesture): # Prevents the helper was launched when the keyboard is locked by the InputLock addon if inputCore.manager._captureFunc and not inputCore.manager._captureFunc( gesture): return if varGlobal.IS_WinON == True: msg = \ _("""Ya hay una instancia de zUtilidades abierta. No es posible tener dos instancias a la vez.""") varGlobal.mensaje(msg) return self.leerCategoriaDAT() if len(self.categorias) == 0: varGlobal.mensaje(_("No hay categorías")) return varGlobal.IS_WinON = True if self.lanzador == "zl": catTotalTemporal = self.catTotalzl elif self.lanzador == "zn": catTotalTemporal = self.catTotalzn if catTotalTemporal == len(self.categorias): pass else: if self.lanzador == "zl": self.catIndexzl = 0 self.itemIndexzl = -1 elif self.lanzador == "zn": self.catIndexzn = 0 self.itemIndexzn = -1 if len(self.categorias) == 0: varGlobal.mensaje(_("No hay categorías")) varGlobal.IS_WinON = False return if self.toggling: self.script_exit(gesture) self.finish() return for k in ("upArrow", "downArrow", "leftArrow", "rightArrow", "enter", "shift+enter", "control+enter", "numpadEnter", "shift+numpadEnter", "control+numpadEnter", "escape", "backspace", "F1", "F12", "numpad2", "numpad4", "numpad5", "numpad6", "numpad8", "numpadPlus", "numpadMinus", "numpadDelete"): try: script = KeyboardInputGesture.fromName(k).script except KeyError: script = None if script and self != script.__self__: try: script.__self__.removeGestureBinding("kb:" + k) except KeyError: pass else: self.oldGestureBindings["kb:" + k] = script if self.lanzador == "zl": self.bindGestures(self.__zlmenuGestures) elif self.lanzador == "zn": self.bindGestures(self.__znmenuGestures) for c in ascii_uppercase: self.bindGesture("kb:" + c, "skipToCategory") if self.lanzador == "zn": self.bindGesture("kb:F1", "viewNote") self.bindGesture("kb:F2", "copyPP") self.bindGesture("kb:F3", "pastePP") self.toggling = True varGlobal.mensaje(_("Menú activado")) if self.lanzador == "zl": firstTimeTemporal = self.firstTimezl if self.lanzador == "zn": firstTimeTemporal = self.firstTimezn if firstTimeTemporal: self.script_speechHelp(None) if self.lanzador == "zl": self.firstTimezl = False elif self.lanzador == "zn": self.firstTimezn = False self.leerArchivosDAT(0) varGlobal.mensaje(self.categorias[0]) if self.lanzador == "zl": self.catTotalzl = len(self.categorias) elif self.lanzador == "zn": self.catTotalzn = len(self.categorias) else: if self.lanzador == "zl": try: varGlobal.mensaje(self.categorias[self.catIndexzl]) except: varGlobal.mensaje(self.categorias[0]) elif self.lanzador == "zn": try: varGlobal.mensaje(self.categorias[self.catIndexzn]) except: varGlobal.mensaje(self.categorias[0])