def _doConfigUpgrade(profile, fromVersion): toVersion = fromVersion+1 upgradeStepName = "upgradeConfigFrom_{0}_to_{1}".format(fromVersion, toVersion) upgradeStepFunc = getattr(profileUpgradeSteps, upgradeStepName) log.debug("Upgrading from schema version {0} to {1}".format(fromVersion, toVersion)) upgradeStepFunc(profile) profile[SCHEMA_VERSION_KEY] = toVersion
def update(obj, force=False): # Don't create treeInterceptors for objects for which NVDA should sleep. if obj.sleepMode: return None #If this object already has a treeInterceptor, just return that and don't bother trying to create one ti=obj.treeInterceptor if not ti: if not obj.shouldCreateTreeInterceptor and not force: return None try: newClass=obj.treeInterceptorClass except NotImplementedError: return None if not force and ( not config.conf['virtualBuffers']['enableOnPageLoad'] or getattr(obj.appModule, "disableBrowseModeByDefault", False) ): # Import late to avoid circular import. from browseMode import BrowseModeTreeInterceptor # Disabling enableOnPageLoad should only affect browse mode tree interceptors. if issubclass(newClass, BrowseModeTreeInterceptor): return None ti=newClass(obj) if not ti.isAlive: return None runningTable.add(ti) log.debug("Adding new treeInterceptor to runningTable: %s"%ti) if ti.shouldPrepare: ti.prepare() return ti
def _onReceive(self, data): if self.isBulk: # data contains the entire packet. stream = StringIO(data) firstByte=data[0] stream.seek(1) else: firstByte = data # data only contained the first byte. Read the rest from the device. stream = self._dev if firstByte=="\x1c": # A device is identifying itself deviceId=stream.read(2) # When a device identifies itself, the packets ends with 0x1f assert stream.read(1) == "\x1f" self._handleIdentification(deviceId) elif firstByte=="\xfa": # Command packets are ten bytes long packet=firstByte+stream.read(9) assert packet[2] == "\x01" # Fixed value checksum=packet[8] assert packet[9] == "\xfb" # Command End assert(chr(sum(ord(c) for c in packet[0:8]+packet[9])&0xff)==checksum) self._handlePacket(packet) else: log.debug("Unknown first byte received: 0x%x"%ord(firstByte)) return
def handleData(self, data): if data >= HEDO_CR_BEGIN and data <= HEDO_CR_END: # Routing key is pressed try: inputCore.manager.executeGesture(InputGestureRouting(data - HEDO_CR_BEGIN)) except inputCore.NoInputGestureAction: log.debug("No Action for routing command") pass elif data >= (HEDO_CR_BEGIN + HEDO_RELEASE_OFFSET) and data <= (HEDO_CR_END + HEDO_RELEASE_OFFSET): # Routing key is released return elif data in HEDO_KEYMAP: # A key is pressed # log.debug("Key " + HEDO_KEYMAP[data] + " pressed") self._keysDown.add(HEDO_KEYMAP[data]) self._ignoreKeyReleases = False elif data > HEDO_RELEASE_OFFSET and (data - HEDO_RELEASE_OFFSET) in HEDO_KEYMAP: # A key is released # log.debug("Key " + str(self._keysDown) + " released") if self._ignoreKeyReleases == False: keys = "+".join(self._keysDown) self._ignoreKeyReleases = True self._keysDown = set() try: inputCore.manager.executeGesture(InputGestureKeys(keys)) except inputCore.NoInputGestureAction: log.debug("No Action for keys {keys}".format(keys=keys)) pass
def _sendIdentificationRequests(self, match): log.debug("Considering sending identification requests for device %s"%str(match)) if match.type==bdDetect.KEY_CUSTOM: # USB Bulk map=[modelTuple for modelTuple in modelMap if modelTuple[1].usbId==match.id] elif "bluetoothName" in match.deviceInfo: # Bluetooth map=[modelTuple for modelTuple in modelMap if modelTuple[1].bluetoothPrefix and match.id.startswith(modelTuple[1].bluetoothPrefix)] else: # The only serial device we support which is not bluetooth, is a Sync Braille self._model = SyncBraille() log.debug("Use %s as model without sending an additional identification request"%self._model.name) return if not map: log.debugWarning("The provided device match to send identification requests didn't yield any results") map = modelMap if len(map)==1: modelCls = map[0][1] numCells = self.numCells or modelCls.numCells if numCells: # There is only one model matching the criteria, and we have the proper number of cells. # There's no point in sending an identification request at all, just use this model log.debug("Use %s as model without sending an additional identification request"%modelCls.name) self._model = modelCls() self.numCells = numCells return self._model = None for id, cls in map: log.debug("Sending request for id %r"%id) self._dev.write("\x1c{id}\x1f".format(id=id)) self._dev.waitForRead(self.timeout) if self._model: log.debug("%s model has been set"%self._model.name) break
def addToPackagePath(self, package): """ Adds this L{Addon} extensions to the specific package path if those exist. This allows the addon to "run" / be available because the package is able to search its path, looking for particular modules. This is used by the following: - `globalPlugins` - `appModules` - `synthDrivers` - `brailleDisplayDrivers` @param package: the python module representing the package. @type package: python module. """ # #3090: Ensure that we don't add disabled / blocked add-ons to package path. # By returning here the addon does not "run"/ become active / registered. if self.isDisabled or self.isBlocked: return extension_path = os.path.join(self.path, package.__name__) if not os.path.isdir(extension_path): # This addon does not have extension points for this package return # Python 2.x doesn't properly handle unicode import paths, so convert them before adding. converted_path = self._getPathForInclusionInPackage(package) package.__path__.insert(0, converted_path) self._extendedPackages.add(package) log.debug("Addon %s added to %s package path", self.manifest['name'], package.__name__)
def completeRemove(self,runUninstallTask=True): if runUninstallTask: try: # #2715: The add-on must be added to _availableAddons here so that # translations can be used in installTasks module. _availableAddons[self.path] = self self.runInstallTask("onUninstall") except: log.error("task 'onUninstall' on addon '%s' failed"%self.name,exc_info=True) finally: del _availableAddons[self.path] tempPath=tempfile.mktemp(suffix=DELETEDIR_SUFFIX,dir=os.path.dirname(self.path)) try: os.rename(self.path,tempPath) except (WindowsError,IOError): raise RuntimeError("Cannot rename add-on path for deletion") shutil.rmtree(tempPath,ignore_errors=True) if os.path.exists(tempPath): log.error("Error removing addon directory %s, deferring until next NVDA restart"%self.path) # clean up the addons state. If an addon with the same name is installed, it should not be automatically # disabled / blocked. log.debug("removing addon {} from _disabledAddons/_blockedAddons".format(self.name)) _disabledAddons.discard(self.name) _blockedAddons.discard(self.name) saveState()
def cancel(self): # Set a flag to tell the callback not to push more audio. self._wasCancelled = True log.debug("Cancelling") # There might be more text pending. Throw it away. self._queuedSpeech = [] self._player.stop()
def killTreeInterceptor(treeInterceptorObject): try: runningTable.remove(treeInterceptorObject) except KeyError: return treeInterceptorObject.terminate() log.debug("Killed treeInterceptor: %s" % treeInterceptorObject)
def loadSettings(self, onlyChanged=False): # Method override due to specific logic needed when changing a voice. c=config.conf[self._configSection][self.name] if self.isSupported("voice"): voice=c.get("voice",None) if not onlyChanged or self.voice!=voice: try: changeVoice(self,voice) except: log.warning("Invalid voice: %s" % voice) # Update the configuration with the correct voice. c["voice"]=self.voice # We need to call changeVoice here so that required initialisation can be performed. changeVoice(self,self.voice) elif not onlyChanged: changeVoice(self,None) for s in self.supportedSettings: if s.id == "voice" or c[s.id] is None: continue val=c[s.id] if onlyChanged and getattr(self,s.id)==val: continue setattr(self,s.id, val) log.debug( ( "Loaded changed settings for SynthDriver {}" if onlyChanged else "Loaded settings for SynthDriver {}" ).format(self.name))
def _onReceive(self, data): """Event handler when data from the display is received Formats a packet of four bytes in a packet type and three arguments. If the packet is known to have a payload, this is also fetched and the checksum is verified. The constructed packet is handed off to L{_handlePacket}. """ if self.isUsb: data = BytesIO(data) packetType = data.read(1) else: packetType = data data = self._dev arg1 = data.read(1) arg2 = data.read(1) arg3 = data.read(1) log.debug("Got packet of type %r with args: %r %r %r", packetType, arg1, arg2, arg3) # Info and extended key responses are the only packets with payload and checksum if packetType in (FS_PKT_INFO, FS_PKT_EXT_KEY): length = ord(arg1) payload = data.read(length) checksum = ord(data.read(1)) calculatedChecksum = BrailleDisplayDriver._calculateChecksum(packetType + arg1 + arg2 + arg3 + payload) assert calculatedChecksum == checksum, "Checksum mismatch, expected %s but got %s" % (checksum, payload[-1]) else: payload = FS_DATA_EMPTY self._handlePacket(packetType, arg1, arg2, arg3, payload)
def getAudioSelectionParsed(self): # Get marker positions and selection duration. # Return the list of substrings to be handled by individual scripts. audioSelectionParsed = self.getAudioSelection().split() if globalVars.appArgs.debugLogging: log.debug("GWV: parsed status bar length: %s"%len(audioSelectionParsed)) return audioSelectionParsed
def getWindowScalingFactor(window): """Gets the logical scaling factor used for the given window handle. This is based off the Dpi reported by windows for the given window handle / divided by the "base" DPI level of 96. Typically this is a result of using the scaling percentage in the windows display settings. 100% is typically 96 DPI, 150% is typically 144 DPI. @param window: a native Windows window handle (hWnd) @returns the logical scaling factor. EG. 1.0 if the window DPI level is 96, 1.5 if the window DPI level is 144""" user32 = ctypes.windll.user32 try: winDpi = user32.GetDpiForWindow(window) except: log.debug("GetDpiForWindow failed, using GetDeviceCaps instead") dc = user32.GetDC(window) winDpi = ctypes.windll.gdi32.GetDeviceCaps(dc, LOGPIXELSX) ret = user32.ReleaseDC(window, dc) if ret != 1: log.error("Unable to release the device context.") # For GetDpiForWindow: an invalid hwnd value will result in a return value of 0. # There is little information about what GetDeviceCaps does in the case of a failure for LOGPIXELSX, however, # a value of zero is certainly an error. if winDpi <= 0: log.debugWarning("Failed to get the DPI for the window, assuming a " "DPI of {} and using a scaling of 1.0. The hWnd value " "used was: {}".format(DEFAULT_DPI_LEVEL, window)) return 1.0 return winDpi / DEFAULT_DPI_LEVEL
def _getColumnContent(self, column): children = UIA._get_children(self) try: return children[column - 1].firstChild.name except Exception as e: log.debug(e) return ""
def _handleResponse(self, command, arg): if command == BAUM_CELL_COUNT: self.numCells = ord(arg) elif command == BAUM_DEVICE_ID: self._deviceID = arg elif command in KEY_NAMES: arg = sum(ord(byte) << offset * 8 for offset, byte in enumerate(arg)) if arg < self._keysDown.get(command, 0): # Release. if not self._ignoreKeyReleases: # The first key released executes the key combination. try: inputCore.manager.executeGesture(InputGesture(self._keysDown)) except inputCore.NoInputGestureAction: pass # Any further releases are just the rest of the keys in the combination being released, # so they should be ignored. self._ignoreKeyReleases = True else: # Press. # This begins a new key combination. self._ignoreKeyReleases = False self._keysDown[command] = arg elif command == BAUM_POWERDOWN: log.debug("Power down") elif command in (BAUM_COMMUNICATION_CHANNEL, BAUM_SERIAL_NUMBER): pass else: log.debugWarning("Unknown command {command!r}, arg {arg!r}".format(command=command, arg=arg))
def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() self._serial = None self._buffer = "" if port == "auto": portsToTry = itertools.chain(self._getUSBPorts(), self._getBluetoothPorts()) elif port == "usb": portsToTry = self._getUSBPorts() elif port == "bluetooth": portsToTry = self._getBluetoothPorts() else: portsToTry = (port,) found = False for port in portsToTry: log.debug("Checking port %s for a BrailleNote", port) try: self._serial = serial.Serial(port, baudrate=BAUD_RATE, timeout=TIMEOUT, writeTimeout=TIMEOUT, parity=serial.PARITY_NONE) except serial.SerialException: continue # Check for cell information if self._describe(): log.debug("BrailleNote found on %s with %d cells", port, self.numCells) found = True break else: self._serial.close() if not found: raise RuntimeError("Can't find a braillenote device (port = %s)" % port) # start reading keys self._readTimer = wx.PyTimer(self._readKeys) self._readTimer.Start(READ_INTERVAL)
def initialize(): global state, _stateFilename, autoChecker _stateFilename = os.path.join(globalVars.appArgs.configPath, "updateCheckState.pickle") try: state = cPickle.load(file(_stateFilename, "r")) except: log.debugWarning("Couldn't retrieve update state", exc_info=True) # Defaults. state = { "lastCheck": 0, "dontRemindVersion": None, } _setStateToNone(state) # check the pending version against the current version # and make sure that pendingUpdateFile and pendingUpdateVersion are part of the state dictionary. if "pendingUpdateVersion" not in state or state["pendingUpdateVersion"] == versionInfo.version: _setStateToNone(state) # remove all update files except the one that is currently pending (if any) try: for fileName in os.listdir(storeUpdatesDir): f=os.path.join(storeUpdatesDir, fileName) if f != state["pendingUpdateFile"]: os.remove(f) log.debug("Update file %s removed"%f) except OSError: log.warning("Unable to remove old update file %s"%f, exc_info=True) if not globalVars.appArgs.launcher and (config.conf["update"]["autoCheck"] or (config.conf["update"]["startupNotification"] and isPendingUpdate())): autoChecker = AutoUpdateChecker()
def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() self._serial = None if port == "auto": portsToTry = itertools.chain(self._getUSBPorts(), self._getBluetoothPorts()) elif port == "usb": portsToTry = self._getUSBPorts() elif port == "bluetooth": portsToTry = self._getBluetoothPorts() else: portsToTry = (port,) for port in portsToTry: log.debug("Checking port %s for a BrailleNote", port) try: self._serial = hwIo.Serial(port, baudrate=BAUD_RATE, timeout=TIMEOUT, writeTimeout=TIMEOUT, parity=serial.PARITY_NONE, onReceive=self._onReceive) except EnvironmentError: continue # Check for cell information if self._describe(): log.debug("BrailleNote found on %s with %d cells", port, self.numCells) break else: self._serial.close() else: raise RuntimeError("Can't find a braillenote device (port = %s)" % port)
def script_showSelectionOptions(self, gesture): fakeSel = self.selection if fakeSel.isCollapsed: # Double click to access the toolbar; e.g. for annotations. try: p = fakeSel.pointAtStart except NotImplementedError: log.debugWarning("Couldn't get point to click") return log.debug("Double clicking") winUser.setCursorPos(p.x, p.y) winUser.mouse_event(winUser.MOUSEEVENTF_LEFTDOWN, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_LEFTDOWN, 0, 0, None, None) winUser.mouse_event(winUser.MOUSEEVENTF_LEFTUP, 0, 0, None, None) return # The user makes a selection using browse mode virtual selection. # Update the selection in Kindle. # This will cause the options to appear. fakeSel.innerTextInfo.updateSelection() # The selection might have been adjusted to meet word boundaries, # so retrieve and report the selection from Kindle. # we can't just use self.makeTextInfo, as that will use our fake selection. realSel = self.rootNVDAObject.makeTextInfo(textInfos.POSITION_SELECTION) # Translators: Announces selected text. %s is replaced with the text. speech.speakSelectionMessage(_("selected %s"), realSel.text) # Remove our virtual selection and move the caret to the active end. fakeSel.innerTextInfo = realSel fakeSel.collapse(end=not self._lastSelectionMovedStart) self.selection = fakeSel
def onContinue(self, evt): try: self.saveState() except: log.debug("unable to save state", exc_info=True) finally: self.EndModal(wx.OK)
def FaultTolerantFile(name): '''Used to write out files in a more fault tolerant way. A temporary file is used, and replaces the file `name' when the context manager scope ends and the the context manager __exit__ is called. This means writing out the complete file can be performed with less concern of corrupting the original file if the process is interrupted by windows shutting down. `name` must be unicode. Usage: with FaultTolerantFile("myFile.txt") as f: f.write("This is a test") This creates a temporary file, and the writes actually happen on this temp file. At the end of the `with` block, when `f` goes out of context the temporary file is closed and, this temporary file replaces "myFile.txt" ''' if not isinstance(name, text_type): raise TypeError("name must be an unicode string") dirpath, filename = os.path.split(name) with NamedTemporaryFile(dir=dirpath, prefix=filename, suffix='.tmp', delete=False) as f: log.debug(f.name) yield f f.flush() os.fsync(f) f.close() moveFileResult = ctypes.windll.kernel32.MoveFileExW(f.name, name, MOVEFILE_REPLACE_EXISTING) if moveFileResult == 0: raise ctypes.WinError()
def loadSettings(self, onlyChanged=False): """ Loads settings for this driver from the configuration. This method assumes that the instance has attributes o/properties corresponding with the name of every setting in L{supportedSettings}. @param onlyChanged: When loading settings, only apply those for which the value in the configuration differs from the current value. @type onlyChanged: bool """ conf=config.conf[self._configSection][self.name] for setting in self.supportedSettings: if not setting.useConfig or conf.get(setting.id) is None: continue val=conf[setting.id] if onlyChanged and getattr(self,setting.id) == val: continue try: setattr(self,setting.id, val) except UnsupportedConfigParameterError: log.debugWarning("Unsupported setting %s; ignoring"%setting.name, exc_info=True) continue if self.supportedSettings: log.debug( ( "Loaded changed settings for {} {}" if onlyChanged else "Loaded settings for {} {}" ).format(self.__class__.__name__, self.name))
def event_typedCharacter(self, obj, nextHandler, ch): if lastKeyDownTime is None or (time.time() - lastKeyDownTime) >= 0.5 and ch != "": if obj.windowClassName != "ConsoleWindowClass": log.debug("typedCharacter %r %r" % (obj.windowClassName, ch)) textInserted(obj.windowHandle, -1, ch) return nextHandler()
def _get_placeholder(self): """If it exists for this object get the value of the placeholder text. For example this might be the aria-placeholder text for a field in a web page. @return: the placeholder text else None @rtype: String or None """ log.debug("Potential unimplemented child class: %r" %self) return None
def registerGeneratorObject(generatorObj): global generators, lastGeneratorObjID if not isinstance(generatorObj, types.GeneratorType): raise TypeError("Arg 2 must be a generator object, not %s" % type(generatorObj)) lastGeneratorObjID += 1 log.debug("Adding generator %d" % lastGeneratorObjID) generators[lastGeneratorObjID] = generatorObj return lastGeneratorObjID
def _closeComPort(self): if self._readTimer is not None: self._readTimer.Stop() self._readTimer = None if self._serial is not None: log.debug("Closing port %s", self._serial.port) self._serial.close() self._serial = None
def close(self): if _isDebug(): log.debug("Closing") self._onReceive = None if hasattr(self, "_file") and self._file is not INVALID_HANDLE_VALUE: ctypes.windll.kernel32.CancelIoEx(self._file, byref(self._readOl)) if hasattr(self, "_writeFile") and self._writeFile not in (self._file, INVALID_HANDLE_VALUE): ctypes.windll.kernel32.CancelIoEx(self._writeFile, byref(self._readOl))
def _terminate(module, name=None): if name is None: name = module.__name__ log.debug("Terminating %s" % name) try: module.terminate() except: log.exception("Error terminating %s" % name)
def evaluateUpdatePendingUpdateMenuItemCommand(self): try: self.sysTrayIcon.menu.Remove(self.sysTrayIcon.installPendingUpdateMenuItem) except: log.debug("Error while removing pending update menu item", exc_info=True) pass if not globalVars.appArgs.secure and updateCheck and updateCheck.isPendingUpdate(): self.sysTrayIcon.menu.Insert(self.sysTrayIcon.installPendingUpdateMenuItemPos,self.sysTrayIcon.installPendingUpdateMenuItem)
def getAudioSelection(self): # Call the info getter twice to obtain audio selection (relies on display text). global multiInstance audioSelection = self.getStatusInfo(0, 2) if multiInstance > 1: audioSelection = self.getStatusInfo(0, 2) if globalVars.appArgs.debugLogging: log.debug("GWV: status bar length: %s"%len(audioSelection)) return audioSelection
def __init__(self, *args, **kwargs): super(GlobalPlugin, self).__init__(*args, **kwargs) log.debug("constructor") self.injectProcessing()
def processForegroundWinEvent(window, objectID, childID): """checks to see if the foreground win event is not the same as the existing focus or any of its parents, then converts the win event to an NVDA event (instantiating an NVDA Object) and then checks the NVDAObject against the existing focus object. If all is ok it queues the foreground event to NVDA and returns True. @param window: a win event's window handle @type window: integer @param objectID: a win event's object ID @type objectID: integer @param childID: a win event's child ID @type childID: integer @returns: True if the foreground was processed, False otherwise. @rtype: boolean """ if isMSAADebugLoggingEnabled(): log.debug( f"Processing foreground winEvent: {getWinEventLogInfo(window, objectID, childID)}" ) # Ignore foreground events on windows that aren't the current foreground window if window != winUser.getForegroundWindow(): if isMSAADebugLoggingEnabled(): log.debug( f"Dropping foreground winEvent as it does not match GetForegroundWindow. " f"WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) return False # If there is a pending gainFocus, it will handle the foreground object. oldFocus = eventHandler.lastQueuedFocusObject # If this foreground win event's window is an ancestor of the existing focus's window, then ignore it if ( isinstance(oldFocus, NVDAObjects.window.Window) and winUser.isDescendantWindow(window, oldFocus.windowHandle) ): if isMSAADebugLoggingEnabled(): log.debug( f"Dropping foreground winEvent as focus is already on a descendant. " f"WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) return False # If the existing focus has the same win event params as these, then ignore this event if ( isinstance(oldFocus, NVDAObjects.IAccessible.IAccessible) and window == oldFocus.event_windowHandle and objectID == oldFocus.event_objectID and childID == oldFocus.event_childID ): if isMSAADebugLoggingEnabled(): log.debug( f"Dropping foreground winEvent as it is duplicate to existing focus. " f"WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) return False # Notify appModuleHandler of this new foreground window appModuleHandler.update(winUser.getWindowThreadProcessID(window)[0]) # If Java access bridge is running, and this is a java window, then pass it to java and forget about it if JABHandler.isRunning and JABHandler.isJavaWindow(window): JABHandler.event_enterJavaWindow(window) if isMSAADebugLoggingEnabled(): log.debug( f"Redirecting foreground winEvent to Java window. " f"WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) return True # Convert the win event to an NVDA event NVDAEvent = winEventToNVDAEvent(winUser.EVENT_SYSTEM_FOREGROUND, window, objectID, childID, useCache=False) if not NVDAEvent: if isMSAADebugLoggingEnabled(): log.debug( f"Could not convert foreground winEvent to an NVDA event. " f"WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) return False eventHandler.queueEvent(*NVDAEvent) return True
def _onReceive(self, data: bytes): byte1, stream, data = self._prepFirstByteStreamAndData(data) if byte1 == ACK: frame = ord(stream.read(1)) self._handleAck(frame) elif byte1 == STX: length = bytesToInt( stream.read(2)) - 2 # length includes the length itself packet: bytes = stream.read(length) if self.isHid and not stream.read(1) == ETX: # Incomplete packet self._hidInputbuffer = data return packetType: bytes = packet[0:1] packetSubType: bytes = packet[1:2] packetData: bytes = packet[2:] if length > 2 else b"" if packetType == EB_SYSTEM: self._handleSystemPacket(packetSubType, packetData) elif packetType == EB_MODE: if packetSubType == EB_MODE_DRIVER: log.debug( "Braille display switched to driver mode, updating display..." ) braille.handler.update() elif packetSubType == EB_MODE_INTERNAL: log.debug("Braille display switched to internal mode") elif packetType == EB_KEY: self._handleKeyPacket(packetSubType, packetData) elif packetType == EB_IRIS_TEST and packetSubType == EB_IRIS_TEST_sub: # Ping command sent by Iris every two seconds, send it back on the main thread. # This means that, if the main thread is frozen, Iris will be notified of this. log.debug("Received ping from Iris braille display") wx.CallAfter(self._sendPacket, packetType, packetSubType, packetData) elif packetType == EB_VISU: log.debug("Ignoring visualisation packet") elif packetType == EB_ENCRYPTION_KEY: log.debug("Ignoring encryption key packet") else: log.debug("Ignoring packet: type %r, subtype %r, data %r" % (packetType, packetSubType, packetData))
def handleData(self, data): if data >= HEDO_MOBIL_CR_BEGIN and data <= HEDO_MOBIL_CR_END: # Routing key is pressed try: inputCore.manager.executeGesture( InputGestureRouting(data - HEDO_MOBIL_CR_BEGIN)) except inputCore.NoInputGestureAction: log.debug("No Action for routing index " + index) pass return # On every keypress or keyrelease information about all keys is sent # There are three groups of keys thus three bytes will be sent on # each keypress or release # The 4 MSB of each byte mark the group # Bytes of the form 0x0? include information for B1 to B3 # Bytes of the form 0x1? include information for B4 to B6 # Bytes of the form 0x2? include information for K1 to K3 # The 4 LSB mark the pressed buttons in the group # Are all buttons of one group released, the 4 LSB are zero if data & 0xF0 == 0x00: # B1..B3 if data & 0x01: self._keysDown.add("B1") if data & 0x02: self._keysDown.add("B2") if data & 0x04: self._keysDown.add("B3") if data == 0x00: self._released_keys.add("B1") elif data & 0xF0 == 0x10: # B4..B6 if data & 0x01: self._keysDown.add("B4") if data & 0x02: self._keysDown.add("B5") if data & 0x04: self._keysDown.add("B6") if data == 0x10: self._released_keys.add("B4") elif data & 0xF0 == 0x20: # K1..K3 if data & 0x01: self._keysDown.add("K1") if data & 0x02: self._keysDown.add("K2") if data & 0x04: self._keysDown.add("K3") if data == 0x20: self._released_keys.add("K1") if "B1" in self._released_keys and "B4" in self._released_keys and "K1" in self._released_keys: # all keys are released keys = "+".join(self._keysDown) self._keysDown = set() self._released_keys = set() try: inputCore.manager.executeGesture(InputGestureKeys(keys)) except inputCore.NoInputGestureAction: log.debug("No Action for keys " + keys) pass
def __init__(self, locale): """ @param locale: The characterDescriptions.dic file will be found by using this locale. @type locale: string """ self._entries = {} fileName = os.path.join('locale', locale, 'characterDescriptions.dic') if not os.path.isfile(fileName): raise LookupError(fileName) f = codecs.open(fileName, "r", "utf_8_sig", errors="replace") for line in f: if line.isspace() or line.startswith('#'): continue line = line.rstrip('\r\n') temp = line.split("\t") if len(temp) > 1: key = temp.pop(0) self._entries[key] = temp else: log.warning("can't parse line '%s'" % line) log.debug("Loaded %d entries." % len(self._entries)) f.close() # nvdajp charaters.dic self._readings = {} fileName = os.path.join('locale', locale, 'characters.dic') if os.path.isfile(fileName): f = codecs.open(fileName, "r", "utf_8_sig", errors="replace") for line in f: if line.isspace() or line.startswith('#'): continue line = line.rstrip('\r\n') temp = line.split("\t") if len(temp) > 1: key = temp.pop(0) code = temp.pop(0) rd = temp.pop(0) if rd.startswith('[') and rd.endswith(']'): self._readings[key] = rd[1:-1] self._entries[key] = temp else: log.warning("can't parse line '%s'" % line) log.debug("Loaded %d readings." % len(self._readings)) f.close() # nvdajp charaters.dic end # nvdajp users chardesc fileName = os.path.join(globalVars.appArgs.configPath, "characterDescriptions-%s.dic" % locale) if os.path.isfile(fileName): log.debug("Loading users characterDescriptions-%s.dic" % locale) f = codecs.open(fileName, "r", "utf_8_sig", errors="replace") for line in f: if line.isspace() or line.startswith('#'): continue line = line.rstrip('\r\n') temp = line.split("\t") if len(temp) > 1: key = temp.pop(0) self._entries[key] = temp else: log.warning("can't parse line '%s'" % line) log.debug("Loaded users characterDescriptions.") f.close() # nvdajp users chardesc end # nvdajp users characters fileName = os.path.join(globalVars.appArgs.configPath, "characters-%s.dic" % locale) if os.path.isfile(fileName): f = codecs.open(fileName, "r", "utf_8_sig", errors="replace") for line in f: if line.isspace() or line.startswith('#'): continue line = line.rstrip('\r\n') temp = line.split("\t") if len(temp) > 1: key = temp.pop(0) code = temp.pop(0) rd = temp.pop(0) if rd.startswith('[') and rd.endswith(']'): self._readings[key] = rd[1:-1] self._entries[key] = temp else: log.warning("can't parse line '%s'" % line) log.debug("Loaded users characters.") f.close()
def winEventToNVDAEvent(eventID, window, objectID, childID, useCache=True): """Tries to convert a win event ID to an NVDA event name, and instanciate or fetch an NVDAObject for the win event parameters. @param eventID: the win event ID (type) @type eventID: integer @param window: the win event's window handle @type window: integer @param objectID: the win event's object ID @type objectID: integer @param childID: the win event's childID @type childID: the win event's childID @param useCache: C{True} to use the L{liveNVDAObjectTable} cache when retrieving an NVDAObject, C{False} if the cache should not be used. @type useCache: boolean @returns: the NVDA event name and the NVDAObject the event is for @rtype: tuple of string and L{NVDAObjects.IAccessible.IAccessible} """ if isMSAADebugLoggingEnabled(): log.debug( f"Creating NVDA event from winEvent: {getWinEventLogInfo(window, objectID, childID, eventID)}, " f"use cache {useCache}" ) NVDAEventName = internalWinEventHandler.winEventIDsToNVDAEventNames.get(eventID, None) if not NVDAEventName: log.debugWarning(f"No NVDA event name for {getWinEventName(eventID)}") return None if isMSAADebugLoggingEnabled(): log.debug(f"winEvent mapped to NVDA event: {NVDAEventName}") # Ignore any events with invalid window handles if not window or not winUser.isWindow(window): if isMSAADebugLoggingEnabled(): log.debug( f"Invalid window. Dropping winEvent {getWinEventLogInfo(window, objectID, childID, eventID)}" ) return None # Make sure this window does not have a ghost window if possible if NVDAObjects.window.GhostWindowFromHungWindow and NVDAObjects.window.GhostWindowFromHungWindow(window): if isMSAADebugLoggingEnabled(): log.debug( f"Ghosted hung window. Dropping winEvent {getWinEventLogInfo(window, objectID, childID, eventID)}" ) return None # We do not support MSAA object proxied from native UIA if UIAHandler.handler and UIAHandler.handler.isUIAWindow(window): if isMSAADebugLoggingEnabled(): log.debug( f"Native UIA window. Dropping winEvent {getWinEventLogInfo(window, objectID, childID, eventID)}" ) return None obj = None if useCache: # See if we already know an object by this win event info obj = liveNVDAObjectTable.get((window, objectID, childID), None) if isMSAADebugLoggingEnabled() and obj: log.debug( f"Fetched existing NVDAObject {obj} from liveNVDAObjectTable" f" for winEvent {getWinEventLogInfo(window, objectID, childID)}" ) # If we don't yet have the object, then actually instanciate it. if not obj: obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent(window, objectID, childID) # At this point if we don't have an object then we can't do any more if not obj: if isMSAADebugLoggingEnabled(): log.debug( "Could not instantiate an NVDAObject for winEvent: " f"{getWinEventLogInfo(window, objectID, childID, eventID)}" ) return None # SDM MSAA objects sometimes don't contain enough information to be useful Sometimes there is a real # window that does, so try to get the SDMChild property on the NVDAObject, and if successull use that as # obj instead. if 'bosa_sdm' in obj.windowClassName: SDMChild = getattr(obj, 'SDMChild', None) if SDMChild: obj = SDMChild if isMSAADebugLoggingEnabled(): log.debug( f"Successfully created NVDA event {NVDAEventName} for {obj} " f"from winEvent {getWinEventLogInfo(window, objectID, childID, eventID)}" ) return (NVDAEventName, obj)
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop. """ log.debug("Core starting") ctypes.windll.user32.SetProcessDPIAware() import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.initialize() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s"%lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s"%lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %s" % winVersion.winVersionText) log.info("Using Python version %s"%sys.version) log.info("Using comtypes version %s"%comtypes.__version__) import configobj log.info("Using configobj version %s with validate version %s"%(configobj.__version__,configobj.validate.__version__)) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing add-ons system") addonHandler.initialize() if globalVars.appArgs.disableAddons: log.info("Add-ons are disabled. Restart NVDA to enable them.") import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx # wxPython 4 no longer has either of these constants (despite the documentation saying so), some add-ons may rely on # them so we add it back into wx. https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.Centre wx.CENTER_ON_SCREEN = wx.CENTRE_ON_SCREEN = 0x2 log.info("Using wx version %s"%wx.version()) class App(wx.App): def OnAssert(self,file,line,cond,msg): message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg) log.debugWarning(message,codepath="WX Widgets",stack_info=True) app = App(redirect=False) # We support queryEndSession events, but in general don't do anything for them. # However, when running as a Windows Store application, we do want to request to be restarted for updates def onQueryEndSession(evt): if config.isAppX: # Automatically restart NVDA on Windows Store update ctypes.windll.kernel32.RegisterApplicationRestart(None,0) app.Bind(wx.EVT_QUERY_END_SESSION, onQueryEndSession) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import braille log.debug("Initializing braille") braille.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() import audioDucking if audioDucking.isAudioDuckingSupported(): # the GUI mainloop must be running for this to work so delay it wx.CallAfter(audioDucking.initialize) # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. # NVDA uses the main frame to check for and quit another instance of NVDA. # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. # We don't need to do anything else because wx handles WM_QUIT for all windows. import windowUtils class MessageWindow(windowUtils.CustomWindow): className = u"wxWindowClassNR" #Just define these constants here, so we don't have to import win32con WM_POWERBROADCAST = 0x218 WM_DISPLAYCHANGE = 0x7e PBT_APMPOWERSTATUSCHANGE = 0xA UNKNOWN_BATTERY_STATUS = 0xFF AC_ONLINE = 0X1 NO_SYSTEM_BATTERY = 0X80 #States for screen orientation ORIENTATION_NOT_INITIALIZED = 0 ORIENTATION_PORTRAIT = 1 ORIENTATION_LANDSCAPE = 2 def __init__(self, windowName=None): super(MessageWindow, self).__init__(windowName) self.oldBatteryStatus = None self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED self.orientationCoordsCache = (0,0) self.handlePowerStatusChange() def windowProc(self, hwnd, msg, wParam, lParam): post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam) if msg == self.WM_POWERBROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE: self.handlePowerStatusChange() elif msg == self.WM_DISPLAYCHANGE: self.handleScreenOrientationChange(lParam) def handleScreenOrientationChange(self, lParam): import ui import winUser # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx. #The low word is the width and hiword is height. width = winUser.LOWORD(lParam) height = winUser.HIWORD(lParam) self.orientationCoordsCache = (width,height) if width > height: # If the height and width are the same, it's actually a screen flip, and we do want to alert of those! if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented so that it is wider than it is tall. ui.message(_("Landscape" )) self.orientationStateCache = self.ORIENTATION_LANDSCAPE else: if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height): return #Translators: The screen is oriented in such a way that the height is taller than it is wide. ui.message(_("Portrait")) self.orientationStateCache = self.ORIENTATION_PORTRAIT def handlePowerStatusChange(self): #Mostly taken from script_say_battery_status, but modified. import ui import winKernel sps = winKernel.SYSTEM_POWER_STATUS() if not winKernel.GetSystemPowerStatus(sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS: return if sps.BatteryFlag & self.NO_SYSTEM_BATTERY: return if self.oldBatteryStatus is None: #Just initializing the cache, do not report anything. self.oldBatteryStatus = sps.ACLineStatus return if sps.ACLineStatus == self.oldBatteryStatus: #Sometimes, this double fires. This also fires when the battery level decreases by 3%. return self.oldBatteryStatus = sps.ACLineStatus if sps.ACLineStatus & self.AC_ONLINE: #Translators: Reported when the battery is plugged in, and now is charging. ui.message(_("Charging battery. %d percent") % sps.BatteryLifePercent) else: #Translators: Reported when the battery is no longer plugged in, and now is not charging. ui.message(_("Not charging battery. %d percent") %sps.BatteryLifePercent) messageWindow = MessageWindow(unicode(versionInfo.name)) # initialize wxpython localization support locale = wx.Locale() lang=languageHandler.getLanguage() wxLang=locale.FindLanguageInfo(lang) if not wxLang and '_' in lang: wxLang=locale.FindLanguageInfo(lang.split('_')[0]) if hasattr(sys,'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) # #8064: Wx might know the language, but may not actually contain a translation database for that language. # If we try to initialize this language, wx will show a warning dialog. # Therefore treat this situation like wx not knowing the language at all. if not locale.IsAvailable(wxLang.Language): wxLang=None if wxLang: try: locale.Init(wxLang.Language) except: log.error("Failed to initialize wx locale",exc_info=True) else: log.debugWarning("wx does not support language %s" % lang) import api import winUser import NVDAObjects.window desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install or globalVars.appArgs.installSilent: import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent) elif globalVars.appArgs.portablePath and (globalVars.appArgs.createPortable or globalVars.appArgs.createPortableSilent): import gui.installerGui wx.CallAfter(gui.installerGui.doCreatePortable,portableDirectory=globalVars.appArgs.portablePath, silent=globalVars.appArgs.createPortableSilent,startAfterCreate=not globalVars.appArgs.createPortableSilent) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject # Doing this here is a bit ugly, but we don't want these modules imported # at module level, including wx. log.debug("Initializing core pump") class CorePump(gui.NonReEntrantTimer): "Checks the queues and executes functions." def run(self): global _isPumpPending _isPumpPending = False watchdog.alive() try: if touchHandler.handler: touchHandler.handler.pump() JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.asleep() if _isPumpPending and not _pump.IsRunning(): # #3803: Another pump was requested during this pump execution. # As our pump is not re-entrant, schedule another pump. _pump.Start(PUMP_MAX_DELAY, True) global _pump _pump = CorePump() requestPump() log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck=None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") postNvdaStartup.notify() log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: _terminate(updateCheck) _terminate(watchdog) _terminate(globalPluginHandler, name="global plugin handler") _terminate(gui) config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.exception("Lose focus error") try: speech.cancelSpeech() except: pass import treeInterceptorHandler _terminate(treeInterceptorHandler) _terminate(IAccessibleHandler, name="IAccessible support") _terminate(UIAHandler, name="UIA support") _terminate(winConsoleHandler, name="winConsole support") _terminate(JABHandler, name="Java Access Bridge support") _terminate(appModuleHandler, name="app module handler") _terminate(NVDAHelper) _terminate(touchHandler) _terminate(keyboardHandler, name="keyboard handler") _terminate(mouseHandler) _terminate(inputCore) _terminate(brailleInput) _terminate(braille) _terminate(speech) _terminate(addonHandler) if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav",async=False) except: pass # #5189: Destroy the message window as late as possible # so new instances of NVDA can find this one even if it freezes during exit. messageWindow.destroy() log.debug("core done")
def terminate(self): log.debug("Terminating the systemTestSpy") self._testSpy.stop()
def onLaterButton(self, evt): log.debug("Usage stats gathering question has been deferred") # evt.Skip() is called since wx.ID_CANCEL is used as the ID for the Ask Later button, # wx automatically ends the modal itself. evt.Skip()
def __init__(self, port: typing.Union[None, str, DeviceMatch]): super().__init__() self.numCells = 0 self.numBtns = 0 self.numRoutingKeys = 0 self.handle = None self._hidBuffer = b"" self._command: typing.Optional[bytes] = None self._argsLen: typing.Optional[int] = None log.debug(f"Seika Notetaker braille driver: ({port!r})") dev: typing.Optional[typing.Union[hwIo.Hid, hwIo.Serial]] = None for match in self._getTryPorts(port): self.isHid = match.type == bdDetect.KEY_HID self.isSerial = match.type == bdDetect.KEY_SERIAL try: if self.isHid: log.info(f"Trying Seika notetaker on USB-HID") self._dev = dev = hwIo.Hid( path=match. port, # for a Hid match type 'port' is actually 'path'. onReceive=self._onReceiveHID) dev.setFeature( SEIKA_HID_FEATURES) # baud rate, stop bit usw dev.setFeature(SEIKA_CMD_ON) # device on elif self.isSerial: log.info( f"Trying Seika notetaker on Bluetooth (serial) port:{match.port}" ) self._dev = dev = hwIo.Serial( port=match.port, onReceive=self._onReceiveSerial, baudrate=BAUD, parity=serial.PARITY_NONE, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE, ) # Note: SEIKA_CMD_ON not sent as per USB-HID, testing from users hasn't indicated any problems. # The exact purpose of SEIKA_CMD_ON isn't known/documented here. else: log.debug(f"Port type not handled: {match.type}") continue except EnvironmentError: log.debugWarning("", exc_info=True) continue if self._getDeviceInfo(dev): break elif dev: dev.close() dev = None if not dev: RuntimeError("No MINI-SEIKA display found") elif self.numCells == 0: dev.close() dev = None raise RuntimeError("No MINI-SEIKA display found, no response") else: log.info(f"Seika notetaker," f" Cells {self.numCells}" f" Buttons {self.numBtns}")
# This file may be used under the terms of the GNU General Public License, version 2 or later. # For more details see: https://www.gnu.org/licenses/gpl-2.0.html """This file provides spy and robot library behaviour for NVDA system tests. It is copied into the (system test specific) NVDA profile directory. It becomes the '__init__.py' file as part of a package. This allows us to share utility methods between the global plugin and the nvdaRobotLib library. """ import globalPluginHandler import threading from .systemTestUtils import _blockUntilConditionMet from logHandler import log from time import clock as _timer import sys import os log.debug("before pathmod: {}".format(sys.path)) # Get the path to the top of the package TOP_DIR = os.path.abspath(os.path.dirname(__file__)) # imports that require libraries not distributed with an install of NVDA sys.path.append(os.path.join(TOP_DIR, "libs")) log.debug("after pathmod: {}".format(sys.path)) from robotremoteserver import RobotRemoteServer whitespaceMinusSlashN = '\t\x0b\x0c\r ' class SystemTestSpy(object): SPEECH_HAS_FINISHED_SECONDS = 0.5 def __init__(self): self._nvdaSpeech = [
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 timeoutMs *= self._caretMovementTimeoutMultiplier # 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 else: # Caret events are unreliable in some controls. # Only use them if we consider them safe to rely on for a particular control, # and only if they arrive within C{_useEvents_maxTimeoutMs} mili seconds # after causing the event to occur. if (elapsed <= self._useEvents_maxTimeoutMs and self.caretMovementDetectionUsesEvents and (eventHandler.isPendingEvents("caret") or eventHandler.isPendingEvents("textChange"))): log.debug( "Caret move detected using event. Elapsed: %d ms" % elapsed) return (True, newInfo) # 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 listHidDevices(onlyAvailable=True): """List HID devices on the system. @param onlyAvailable: Only return devices that are currently available. @type onlyAvailable: bool @return: Generates dicts including keys such as hardwareID, usbID (in the form "VID_xxxx&PID_xxxx") and devicePath. @rtype: generator of dict """ global _hidGuid if not _hidGuid: _hidGuid = GUID() ctypes.windll.hid.HidD_GetHidGuid(ctypes.byref(_hidGuid)) flags = DIGCF_DEVICEINTERFACE if onlyAvailable: flags |= DIGCF_PRESENT buf = ctypes.create_unicode_buffer(1024) g_hdi = SetupDiGetClassDevs(_hidGuid, None, NULL, flags) try: for dwIndex in xrange(256): did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces(g_hdi, None, _hidGuid, dwIndex, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dwNeeded), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_W(ctypes.Structure): _fields_ = ( ('cbSize', DWORD), ('DevicePath', WCHAR * (dwNeeded.value - ctypes.sizeof(DWORD))), ) def __str__(self): return "DevicePath:%s" % (self.DevicePath, ) idd = SP_DEVICE_INTERFACE_DETAIL_DATA_W() idd.cbSize = SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_W devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dwNeeded, None, ctypes.byref(devinfo)): raise ctypes.WinError() # hardware ID if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() else: hwId = buf.value info = _getHidInfo(hwId, idd.DevicePath) if _isDebug(): log.debug("%r" % info) yield info finally: SetupDiDestroyDeviceInfoList(g_hdi) if _isDebug(): log.debug("Finished listing HID devices")
def onDefaultDictionaryCommand(self, evt): # linting is complaining about from .settingsDialogs import * names # too risky to change it all, so we will specify what we want on a method based aproach log.debug("chamasticocact") dic = dictHelper.getDictionary("default") guiHelper.showEnhancedDictionaryDialog(dic)
def main(): """NVDA's core main loop. This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop. """ log.debug("Core starting") try: # Windows >= Vista ctypes.windll.user32.SetProcessDPIAware() except AttributeError: pass import config if not globalVars.appArgs.configPath: globalVars.appArgs.configPath = config.getUserDefaultConfigPath( useInstalledPathIfExists=globalVars.appArgs.launcher) #Initialize the config path (make sure it exists) config.initConfigPath() log.info("Config dir: %s" % os.path.abspath(globalVars.appArgs.configPath)) log.debug("loading config") import config config.initialize() if not globalVars.appArgs.minimal and config.conf["general"][ "playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\start.wav") except: pass logHandler.setLogLevelFromConfig() logHandler.setPlayErrorSoundFromConfig() try: lang = config.conf["general"]["language"] import languageHandler log.debug("setting language to %s" % lang) languageHandler.setLanguage(lang) except: log.warning("Could not set language to %s" % lang) import versionInfo log.info("NVDA version %s" % versionInfo.version) log.info("Using Windows version %s" % winVersion.winVersionText) log.info("Using Python version %s" % sys.version) log.info("Using comtypes version %s" % comtypes.__version__) # Set a reasonable timeout for any socket connections NVDA makes. import socket socket.setdefaulttimeout(10) log.debug("Initializing add-ons system") addonHandler.initialize() if globalVars.appArgs.disableAddons: log.info("Add-ons are disabled. Restart NVDA to enable them.") import appModuleHandler log.debug("Initializing appModule Handler") appModuleHandler.initialize() import NVDAHelper log.debug("Initializing NVDAHelper") NVDAHelper.initialize() import speechDictHandler log.debug("Speech Dictionary processing") speechDictHandler.initialize() import speech log.debug("Initializing speech") speech.initialize() if not globalVars.appArgs.minimal and (time.time() - globalVars.startTime) > 5: log.debugWarning("Slow starting core (%.2f sec)" % (time.time() - globalVars.startTime)) # Translators: This is spoken when NVDA is starting. speech.speakMessage(_("Loading NVDA. Please wait...")) import wx log.info("Using wx version %s" % wx.version()) class App(wx.App): def OnAssert(self, file, line, cond, msg): message = "{file}, line {line}:\nassert {cond}: {msg}".format( file=file, line=line, cond=cond, msg=msg) log.debugWarning(message, codepath="WX Widgets", stack_info=True) app = App(redirect=False) # We do support QueryEndSession events, but we don't want to do anything for them. app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None) def onEndSession(evt): # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. config.saveOnExit() speech.cancelSpeech() if not globalVars.appArgs.minimal and config.conf["general"][ "playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav", async=False) except: pass log.info("Windows session ending") app.Bind(wx.EVT_END_SESSION, onEndSession) import braille log.debug("Initializing braille") braille.initialize() log.debug("Initializing braille input") import brailleInput brailleInput.initialize() import displayModel log.debug("Initializing displayModel") displayModel.initialize() log.debug("Initializing GUI") import gui gui.initialize() import audioDucking if audioDucking.isAudioDuckingSupported(): # the GUI mainloop must be running for this to work so delay it wx.CallAfter(audioDucking.initialize) # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. # NVDA uses the main frame to check for and quit another instance of NVDA. # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. # We don't need to do anything else because wx handles WM_QUIT for all windows. import windowUtils class MessageWindow(windowUtils.CustomWindow): className = u"wxWindowClassNR" messageWindow = MessageWindow(unicode(versionInfo.name)) # initialize wxpython localization support locale = wx.Locale() lang = languageHandler.getLanguage() wxLang = locale.FindLanguageInfo(lang) if not wxLang and '_' in lang: wxLang = locale.FindLanguageInfo(lang.split('_')[0]) if hasattr(sys, 'frozen'): locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(), "locale")) if wxLang: try: locale.Init(wxLang.Language) except: log.error("Failed to initialize wx locale", exc_info=True) else: log.debugWarning("wx does not support language %s" % lang) import api import winUser import NVDAObjects.window desktopObject = NVDAObjects.window.Window( windowHandle=winUser.getDesktopWindow()) api.setDesktopObject(desktopObject) api.setFocusObject(desktopObject) api.setNavigatorObject(desktopObject) api.setMouseObject(desktopObject) import JABHandler log.debug("initializing Java Access Bridge support") try: JABHandler.initialize() except NotImplementedError: log.warning("Java Access Bridge not available") except: log.error("Error initializing Java Access Bridge support", exc_info=True) import winConsoleHandler log.debug("Initializing winConsole support") winConsoleHandler.initialize() import UIAHandler log.debug("Initializing UIA support") try: UIAHandler.initialize() except NotImplementedError: log.warning("UIA not available") except: log.error("Error initializing UIA support", exc_info=True) import IAccessibleHandler log.debug("Initializing IAccessible support") IAccessibleHandler.initialize() log.debug("Initializing input core") import inputCore inputCore.initialize() import keyboardHandler log.debug("Initializing keyboard handler") keyboardHandler.initialize() import mouseHandler log.debug("initializing mouse handler") mouseHandler.initialize() import touchHandler log.debug("Initializing touchHandler") try: touchHandler.initialize() except NotImplementedError: pass import globalPluginHandler log.debug("Initializing global plugin handler") globalPluginHandler.initialize() if globalVars.appArgs.install or globalVars.appArgs.installSilent: import wx import gui.installerGui wx.CallAfter(gui.installerGui.doSilentInstall, startAfterInstall=not globalVars.appArgs.installSilent) elif not globalVars.appArgs.minimal: try: # Translators: This is shown on a braille display (if one is connected) when NVDA starts. braille.handler.message(_("NVDA started")) except: log.error("", exc_info=True) if globalVars.appArgs.launcher: gui.LauncherDialog.run() # LauncherDialog will call doStartupDialogs() afterwards if required. else: wx.CallAfter(doStartupDialogs) import queueHandler # Queue the handling of initial focus, # as API handlers might need to be pumped to get the first focus event. queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) import watchdog import baseObject # Doing this here is a bit ugly, but we don't want these modules imported # at module level, including wx. log.debug("Initializing core pump") class CorePump(wx.Timer): "Checks the queues and executes functions." def Notify(self): global _isPumpPending _isPumpPending = False watchdog.alive() try: if touchHandler.handler: touchHandler.handler.pump() JABHandler.pumpAll() IAccessibleHandler.pumpAll() queueHandler.pumpAll() mouseHandler.pumpAll() braille.pumpAll() except: log.exception("errors in this core pump cycle") baseObject.AutoPropertyObject.invalidateCaches() watchdog.asleep() if _isPumpPending and not _pump.IsRunning(): # #3803: A pump was requested, but the timer was ignored by a modal loop # because timers aren't re-entrant. # Therefore, schedule another pump. _pump.Start(PUMP_MAX_DELAY, True) global _pump _pump = CorePump() requestPump() log.debug("Initializing watchdog") watchdog.initialize() try: import updateCheck except RuntimeError: updateCheck = None log.debug("Update checking not supported") else: log.debug("initializing updateCheck") updateCheck.initialize() log.info("NVDA initialized") log.debug("entering wx application main loop") app.MainLoop() log.info("Exiting") if updateCheck: _terminate(updateCheck) _terminate(watchdog) _terminate(globalPluginHandler, name="global plugin handler") _terminate(gui) config.saveOnExit() try: if globalVars.focusObject and hasattr(globalVars.focusObject, "event_loseFocus"): log.debug("calling lose focus on object with focus") globalVars.focusObject.event_loseFocus() except: log.exception("Lose focus error") try: speech.cancelSpeech() except: pass import treeInterceptorHandler _terminate(treeInterceptorHandler) _terminate(IAccessibleHandler, name="IAccessible support") _terminate(UIAHandler, name="UIA support") _terminate(winConsoleHandler, name="winConsole support") _terminate(JABHandler, name="Java Access Bridge support") _terminate(appModuleHandler, name="app module handler") _terminate(NVDAHelper) _terminate(touchHandler) _terminate(keyboardHandler, name="keyboard handler") _terminate(mouseHandler) _terminate(inputCore) _terminate(brailleInput) _terminate(braille) _terminate(speech) _terminate(addonHandler) if not globalVars.appArgs.minimal and config.conf["general"][ "playStartAndExitSounds"]: try: nvwave.playWaveFile("waves\\exit.wav", async=False) except: pass # #5189: Destroy the message window as late as possible # so new instances of NVDA can find this one even if it freezes during exit. messageWindow.destroy() log.debug("core done")
def postInit(self): super(AtcMixin, self).postInit() log.debug("Enabling ATC") self._display.atc = True
def enable(self): """Tells NVDA that you require that background audio be ducked from now until you call disable. This method may block for a short time while background audio ducks to a suitable level. It is safe to call this method more than once. @ returns: True if ducking was enabled, false if ducking was subsiquently disabled while waiting for the background audio to drop. """ debug = _isDebug() with self._lock: if self._enabled: if debug: log.debug("ignoring duplicate enable") return True self._enabled=True if debug: log.debug("enabling") whenWasDucked,modeChangeEvent=_ensureDucked() deltaMS=int((INITIAL_DUCKING_DELAY-whenWasDucked)*1000) disableEvent=self._disabledEvent=AutoEvent() if debug: log.debug("whenWasDucked %s, deltaMS %s"%(whenWasDucked,deltaMS)) if deltaMS<=0 or _audioDuckingMode==AUDIODUCKINGMODE_NONE: return True import NVDAHelper if not NVDAHelper.localLib.audioDucking_shouldDelay(): if debug: log.debug("No background audio, not delaying") return True if debug: log.debug("waiting %s ms or mode change"%deltaMS) wasCanceled=windll.kernel32.WaitForMultipleObjects(2,(wintypes.HANDLE*2)(disableEvent,modeChangeEvent),False,deltaMS)!=WAIT_TIMEOUT if debug: log.debug("Wait canceled" if wasCanceled else "timeout exceeded") return not wasCanceled
def listComPorts(onlyAvailable=True): """List com ports on the system. @param onlyAvailable: Only return ports that are currently available. @type onlyAvailable: bool @return: Generates dicts including keys of port, friendlyName and hardwareID. @rtype: generator of dict """ flags = DIGCF_DEVICEINTERFACE if onlyAvailable: flags |= DIGCF_PRESENT buf = ctypes.create_unicode_buffer(1024) g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, flags) try: for dwIndex in xrange(256): entry = {} did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces( g_hdi, None, ctypes.byref(GUID_CLASS_COMPORT), dwIndex, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dwNeeded), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_W(ctypes.Structure): _fields_ = ( ('cbSize', DWORD), ('DevicePath', WCHAR * (dwNeeded.value - ctypes.sizeof(DWORD))), ) def __str__(self): return "DevicePath:%s" % (self.DevicePath, ) idd = SP_DEVICE_INTERFACE_DETAIL_DATA_W() idd.cbSize = SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_W devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dwNeeded, None, ctypes.byref(devinfo)): raise ctypes.WinError() # hardware ID if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() else: hwID = entry["hardwareID"] = buf.value regKey = ctypes.windll.setupapi.SetupDiOpenDevRegKey( g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, winreg.KEY_READ) try: try: port = entry["port"] = winreg.QueryValueEx( regKey, "PortName")[0] except WindowsError: # #6015: In some rare cases, this value doesn't exist. log.debugWarning("No PortName value for hardware ID %s" % hwID) continue if not port: log.debugWarning( "Empty PortName value for hardware ID %s" % hwID) continue if hwID.startswith("BTHENUM\\"): # This is a Microsoft bluetooth port. try: addr = winreg.QueryValueEx( regKey, "Bluetooth_UniqueID")[0].split("#", 1)[1].split("_", 1)[0] addr = int(addr, 16) entry["bluetoothAddress"] = addr if addr: entry["bluetoothName"] = getBluetoothDeviceInfo( addr).szName except: pass elif hwID == r"Bluetooth\0004&0002": # This is a Toshiba bluetooth port. try: entry["bluetoothAddress"], entry[ "bluetoothName"] = getToshibaBluetoothPortInfo( port) except: pass elif hwID == r"{95C7A0A0-3094-11D7-A202-00508B9D7D5A}\BLUETOOTHPORT": try: entry["bluetoothAddress"], entry[ "bluetoothName"] = getWidcommBluetoothPortInfo( port) except: pass finally: ctypes.windll.advapi32.RegCloseKey(regKey) # friendly name if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None): # #6007: SPDRP_FRIENDLYNAME sometimes doesn't exist/isn't valid. log.debugWarning("Couldn't get SPDRP_FRIENDLYNAME for %r: %s" % (port, ctypes.WinError())) entry["friendlyName"] = port else: entry["friendlyName"] = buf.value if _isDebug(): log.debug("%r" % entry) yield entry finally: SetupDiDestroyDeviceInfoList(g_hdi) if _isDebug(): log.debug("Finished listing com ports")
def postInit(self): super(TimeSyncMixin, self).postInit() log.debug("Request current display time") self._display.sendExtendedPacket(HT_EXTPKT_GET_RTC)
def _doPostNvdaStartupAction(): log.debug("Notify of postNvdaStartup action") postNvdaStartup.notify()
def onNoButton(self, evt): log.debug("Usage stats gathering has been disallowed") config.conf['update']['askedAllowUsageStats'] = True config.conf['update']['allowUsageStats'] = False self.EndModal(wx.ID_NO)
def IUIAutomationEventHandler_HandleAutomationEvent(self, sender, eventID): if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. if _isDebug(): log.debug( "HandleAutomationEvent: event received while not fully initialized" ) 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. if _isDebug(): log.debug( "HandleAutomationEvent: Ignored MenuOpenedEvent while focus event pending" ) return NVDAEventName = UIAEventIdsToNVDAEventNames.get(eventID, None) if not NVDAEventName: if _isDebug(): log.debugWarning( f"HandleAutomationEvent: Don't know how to handle event {eventID}" ) return focus = api.getFocusObject() import NVDAObjects.UIA if (isinstance(focus, NVDAObjects.UIA.UIA) and self.clientObject.compareElements(focus.UIAElement, sender)): pass elif not self.isNativeUIAElement(sender): if _isDebug(): log.debug( f"HandleAutomationEvent: Ignoring event {NVDAEventName} for non native element" ) return window = self.getNearestWindowHandle(sender) if window and not eventHandler.shouldAcceptEvent(NVDAEventName, windowHandle=window): if _isDebug(): log.debug( f"HandleAutomationEvent: Ignoring event {NVDAEventName} for shouldAcceptEvent=False" ) return try: obj = NVDAObjects.UIA.UIA(UIAElement=sender) except Exception: if _isDebug(): log.debugWarning( f"HandleAutomationEvent: Exception while creating object for event {NVDAEventName}", exc_info=True) return if (not obj or (NVDAEventName == "gainFocus" and not obj.shouldAllowUIAFocusEvent) or (NVDAEventName == "liveRegionChange" and not obj._shouldAllowUIALiveRegionChangeEvent)): if _isDebug(): log.debug( "HandleAutomationEvent: " f"Ignoring event {NVDAEventName} because no object or ignored by object itself" ) return if obj == focus: obj = focus eventHandler.queueEvent(NVDAEventName, obj)
def resetConfiguration(factoryDefaults=False): """Loads the configuration, installs the correct language support and initialises audio so that it will use the configured synth and speech settings. """ import config import braille import brailleInput import speech import vision import languageHandler import inputCore import tones log.debug("Terminating vision") vision.terminate() log.debug("Terminating braille") braille.terminate() log.debug("Terminating brailleInput") brailleInput.terminate() log.debug("terminating speech") speech.terminate() log.debug("terminating tones") tones.terminate() log.debug("terminating addonHandler") addonHandler.terminate() log.debug("Reloading config") config.conf.reset(factoryDefaults=factoryDefaults) logHandler.setLogLevelFromConfig() #Language lang = config.conf["general"]["language"] log.debug("setting language to %s" % lang) languageHandler.setLanguage(lang) # Addons addonHandler.initialize() # Tones tones.initialize() #Speech log.debug("initializing speech") speech.initialize() #braille log.debug("Initializing brailleInput") brailleInput.initialize() log.debug("Initializing braille") braille.initialize() # Vision log.debug("initializing vision") vision.initialize() log.debug("Reloading user and locale input gesture maps") inputCore.manager.loadUserGestureMap() inputCore.manager.loadLocaleGestureMap() import audioDucking if audioDucking.isAudioDuckingSupported(): audioDucking.handlePostConfigProfileSwitch() log.info("Reverted to saved configuration")
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. if _isDebug(): log.debug( "HandlePropertyChangedEvent: event received while not fully initialized" ) return try: processId = sender.CachedProcessID except COMError: pass else: appMod = appModuleHandler.getAppModuleFromProcessID(processId) if not appMod.shouldProcessUIAPropertyChangedEvent( sender, propertyId): return NVDAEventName = UIAPropertyIdsToNVDAEventNames.get(propertyId, None) if not NVDAEventName: if _isDebug(): log.debugWarning( f"HandlePropertyChangedEvent: Don't know how to handle property {propertyId}" ) return focus = api.getFocusObject() import NVDAObjects.UIA if (isinstance(focus, NVDAObjects.UIA.UIA) and self.clientObject.compareElements(focus.UIAElement, sender)): pass elif not self.isNativeUIAElement(sender): if _isDebug(): log.debug( f"HandlePropertyChangedEvent: Ignoring event {NVDAEventName} for non native element" ) return window = self.getNearestWindowHandle(sender) if window and not eventHandler.shouldAcceptEvent(NVDAEventName, windowHandle=window): if _isDebug(): log.debug( f"HandlePropertyChangedEvent: Ignoring event {NVDAEventName} for shouldAcceptEvent=False" ) return try: obj = NVDAObjects.UIA.UIA(UIAElement=sender) except Exception: if _isDebug(): log.debugWarning( f"HandlePropertyChangedEvent: Exception while creating object for event {NVDAEventName}", exc_info=True) return if not obj: if _isDebug(): log.debug( f"HandlePropertyChangedEvent: Ignoring event {NVDAEventName} because no object" ) return if obj == focus: obj = focus eventHandler.queueEvent(NVDAEventName, obj)
def _handlePostConfigProfileSwitch(resetSpeechIfNeeded=True): log.debug("changing profile") dictHelper.reloadDictionaries()
def getActiveProfile(self): if globalVars.appArgs.secure: log.debug("safe profile") return log.debug(f"will return {self.profiles[-1].name}") return self.profiles[-1]
def dumpSpeechToLog(self): log.debug("All speech:\n{}".format(repr(self._nvdaSpeech)))
def processFocusWinEvent(window, objectID, childID, force=False): """checks to see if the focus win event is not the same as the existing focus, then converts the win event to an NVDA event (instantiating an NVDA Object) then calls processFocusNVDAEvent. If all is ok it returns True. @type window: integer @param objectID: a win event's object ID @type objectID: integer @param childID: a win event's child ID @type childID: integer @param force: If True, the shouldAllowIAccessibleFocusEvent property of the object is ignored. @type force: boolean @returns: True if the focus is valid and was handled, False otherwise. @rtype: boolean """ if isMSAADebugLoggingEnabled(): log.debug( f"Processing focus winEvent: {getWinEventLogInfo(window, objectID, childID)}, " f"force {force}" ) windowClassName = winUser.getClassName(window) # Generally, we must ignore focus on child windows of SDM windows as we only want the SDM MSAA events. # However, we don't want to ignore focus if the child ID isn't 0, # as this is a child control and the SDM MSAA events don't handle child controls. if ( childID == 0 and not windowClassName.startswith('bosa_sdm') and winUser.getClassName(winUser.getAncestor(window, winUser.GA_PARENT)).startswith('bosa_sdm') ): if isMSAADebugLoggingEnabled(): log.debug( f"Focus event for child window of MS Office SDM window. " f"Dropping winEvent {getWinEventLogInfo(window, objectID, childID)}, " ) return False # Notify appModuleHandler of this new foreground window appModuleHandler.update(winUser.getWindowThreadProcessID(window)[0]) # If Java access bridge is running, and this is a java window, then pass it to java and forget about it if ( childID == 0 and objectID == winUser.OBJID_CLIENT and JABHandler.isRunning and JABHandler.isJavaWindow(window) ): if isMSAADebugLoggingEnabled(): log.debug( f"Redirecting focus to Java window. WinEvent {getWinEventLogInfo(window, objectID, childID)}" ) JABHandler.event_enterJavaWindow(window) return True # Convert the win event to an NVDA event NVDAEvent = winEventToNVDAEvent(winUser.EVENT_OBJECT_FOCUS, window, objectID, childID, useCache=False) if not NVDAEvent: return False eventName, obj = NVDAEvent if ( (childID == 0 and obj.IAccessibleRole == oleacc.ROLE_SYSTEM_LIST) or (objectID == winUser.OBJID_CLIENT and "SysListView32" in obj.windowClassName) ): # Some controls incorrectly fire focus on child ID 0, even when there is a child with focus. try: realChildID = obj.IAccessibleObject.accFocus except: # noqa: E722 Bare except realChildID = None if isinstance(realChildID, int) and realChildID > 0 and realChildID != childID: realObj = NVDAObjects.IAccessible.IAccessible( IAccessibleObject=obj.IAccessibleObject, IAccessibleChildID=realChildID, event_windowHandle=window, event_objectID=objectID, event_childID=realChildID ) if realObj: obj = realObj return processFocusNVDAEvent(obj, force=force)
def listUsbDevices(onlyAvailable=True): """List USB devices on the system. @param onlyAvailable: Only return devices that are currently available. @type onlyAvailable: bool @return: The USB vendor and product IDs in the form "VID_xxxx&PID_xxxx" @rtype: generator of unicode """ flags = DIGCF_DEVICEINTERFACE if onlyAvailable: flags |= DIGCF_PRESENT buf = ctypes.create_unicode_buffer(1024) g_hdi = SetupDiGetClassDevs(GUID_DEVINTERFACE_USB_DEVICE, None, NULL, flags) try: for dwIndex in xrange(256): did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces( g_hdi, None, GUID_DEVINTERFACE_USB_DEVICE, dwIndex, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dwNeeded), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_W(ctypes.Structure): _fields_ = ( ('cbSize', DWORD), ('DevicePath', WCHAR * (dwNeeded.value - ctypes.sizeof(DWORD))), ) def __str__(self): return "DevicePath:%s" % (self.DevicePath, ) idd = SP_DEVICE_INTERFACE_DETAIL_DATA_W() idd.cbSize = SIZEOF_SP_DEVICE_INTERFACE_DETAIL_DATA_W devinfo = SP_DEVINFO_DATA() devinfo.cbSize = ctypes.sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dwNeeded, None, ctypes.byref(devinfo)): raise ctypes.WinError() # hardware ID if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID, None, ctypes.byref(buf), ctypes.sizeof(buf) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() else: # The string is of the form "usb\VID_xxxx&PID_xxxx&..." usbId = buf.value[4:21] # VID_xxxx&PID_xxxx if _isDebug(): log.debug("%r" % usbId) yield usbId finally: SetupDiDestroyDeviceInfoList(g_hdi) if _isDebug(): log.debug("Finished listing USB devices")
def stop(self): log.debug("Stop SystemTestSpyServer called") self._server.stop()