def getNearestWindowHandle(self,UIAElement): if hasattr(UIAElement,"_nearestWindowHandle"): # Called previously. Use cached result. return UIAElement._nearestWindowHandle try: processID=UIAElement.cachedProcessID except COMError: return None appModule=appModuleHandler.getAppModuleFromProcessID(processID) # WDAG (Windows Defender application Guard) UIA elements should be treated as being from a remote machine, and therefore their window handles are completely invalid on this machine. # Therefore, jump all the way up to the root of the WDAG process and use that window handle as it is local to this machine. if appModule.appName==WDAG_PROCESS_NAME: condition=UIAUtils.createUIAMultiPropertyCondition({UIA_ClassNamePropertyId:[u'ApplicationFrameWindow',u'CabinetWClass']}) walker=self.clientObject.createTreeWalker(condition) else: # Not WDAG, just walk up to the nearest valid windowHandle walker=self.windowTreeWalker try: new=walker.NormalizeElementBuildCache(UIAElement,self.windowCacheRequest) except COMError: return None try: window=new.cachedNativeWindowHandle except COMError: window=None # Cache for future use to improve performance. UIAElement._nearestWindowHandle=window return window
def getNearestWindowHandle(self, UIAElement): if hasattr(UIAElement, "_nearestWindowHandle"): # Called previously. Use cached result. return UIAElement._nearestWindowHandle try: processID = UIAElement.cachedProcessID except COMError: return None appModule = appModuleHandler.getAppModuleFromProcessID(processID) # WDAG (Windows Defender application Guard) UIA elements should be treated as being from a remote machine, and therefore their window handles are completely invalid on this machine. # Therefore, jump all the way up to the root of the WDAG process and use that window handle as it is local to this machine. if appModule.appName == WDAG_PROCESS_NAME: condition = UIAUtils.createUIAMultiPropertyCondition({ UIA_ClassNamePropertyId: [u'ApplicationFrameWindow', u'CabinetWClass'] }) walker = self.clientObject.createTreeWalker(condition) else: # Not WDAG, just walk up to the nearest valid windowHandle walker = self.windowTreeWalker try: new = walker.NormalizeElementBuildCache(UIAElement, self.windowCacheRequest) except COMError: return None try: window = new.cachedNativeWindowHandle except COMError: window = None # Cache for future use to improve performance. UIAElement._nearestWindowHandle = window return window
def _isUIAWindowHelper(self,hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID=winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId()==processID: return False import NVDAObjects.window windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule=appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False if windowClass=="NetUIHWND": parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT) # #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better. # #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA. if winUser.getClassName(parentHwnd) in {"Net UI Tool Window","NUIDialog"}: return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # Microsoft Word should not use UIA unless we can't inject or the user explicitly chose to use UIA with Microsoft word if windowClass=="_WwG" and not (config.conf['UIA']['useInMSWordWhenAvailable'] or not appModule.helperLocalBindingHandle): return False return bool(res)
def _isUIAWindowHelper(self, hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID = winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId() == processID: return False import NVDAObjects.window windowClass = NVDAObjects.window.Window.normalizeWindowClassName( winUser.getClassName(hwnd)) # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False if windowClass == "NetUIHWND": parentHwnd = winUser.getAncestor(hwnd, winUser.GA_ROOT) # #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better. # #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA. if winUser.getClassName(parentHwnd) in { "Net UI Tool Window", "NUIDialog" }: return False # allow the appModule for the window to also choose if this window is bad appModule = appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively return windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
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 _isUIAWindowHelper(self, hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID = winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId() == processID: return False import NVDAObjects.window windowClass = NVDAObjects.window.Window.normalizeWindowClassName( winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule = appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively res = windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # MS Word documents now have a very usable UI Automation implementation. However, # Builds of MS Office 2016 before build 9000 or so had bugs which we cannot work around. # Therefore refuse to use UIA for builds earlier than this, if we can inject in-process. if ( # An MS Word document window windowClass == "_WwG" # Disabling is only useful if we can inject in-process (and use our older code) and appModule.helperLocalBindingHandle # Allow the user to explisitly force UIA support for MS Word documents no matter the Office version and not config.conf['UIA']['useInMSWordWhenAvailable']): # We can only safely check the version of known Office apps using the Word document control, as we know their versioning scheme. # But if the Word Document control is used in other unknown apps we should just use UIA if it has been implemented. if appModule.appName not in ('outlook', 'winword', 'excel'): log.debugWarning( "Unknown application using MS Word document control: %s" % appModule.appName) return True try: versionMajor, versionMinor, versionBuild, versionPatch = [ int(x) for x in appModule.productVersion.split('.') ] except Exception as e: log.error("Error parsing version information %s, %s" % (appModule.productVersion, e)) return True if (versionMajor < minMSWordUIAVersion.major or versionMajor == minMSWordUIAVersion.major and versionMinor == minMSWordUIAVersion.minor and versionBuild < minMSWordUIAVersion.build): return False return bool(res)
def nvdaController_setAppSleepMode(mode): import appModuleHandler pid = c_long() windll.rpcrt4.I_RpcBindingInqLocalClientPID(None, byref(pid)) pid = pid.value if not pid: log.error("Could not get process ID for RPC call") return -1 curApp = appModuleHandler.getAppModuleFromProcessID(pid) curApp.sleepMode = True if mode == 1 else False return 0
def _isUIAWindowHelper(self,hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID=winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId()==processID: return False import NVDAObjects.window windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd)) # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False if windowClass=="NetUIHWND": parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT) # #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better. if winUser.getClassName(parentHwnd)=="Net UI Tool Window": return False # allow the appModule for the window to also choose if this window is bad appModule=appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively return windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
def _isUIAWindowHelper(self, hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID = winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId() == processID: return False import NVDAObjects.window windowClass = NVDAObjects.window.Window.normalizeWindowClassName( winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule = appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False if windowClass == "NetUIHWND": parentHwnd = winUser.getAncestor(hwnd, winUser.GA_ROOT) # #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better. # #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA. if winUser.getClassName(parentHwnd) in { "Net UI Tool Window", "NUIDialog" }: return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively res = windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # Microsoft Word should not use UIA unless we can't inject or the user explicitly chose to use UIA with Microsoft word if windowClass == "_WwG" and not ( config.conf['UIA']['useInMSWordWhenAvailable'] or not appModule.helperLocalBindingHandle): return False return bool(res)
def _isUIAWindowHelper(self,hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID=winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId()==processID: return False import NVDAObjects.window windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule=appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if self._isBadUIAWindowClassName(windowClass): return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # MS Word documents now have a fairly usable UI Automation implementation. However, # Builds of MS Office 2016 before build 9000 or so had bugs which we cannot work around. # And even current builds of Office 2016 are still missing enough info from UIA that it is still impossible to switch to UIA completely. # Therefore, if we can inject in-process, refuse to use UIA and instead fall back to the MS Word object model. if ( # An MS Word document window windowClass=="_WwG" # Disabling is only useful if we can inject in-process (and use our older code) and appModule.helperLocalBindingHandle # Allow the user to explisitly force UIA support for MS Word documents no matter the Office version and not config.conf['UIA']['useInMSWordWhenAvailable'] ): return False return bool(res)
def _isUIAWindowHelper(self,hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID=winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId()==processID: return False import NVDAObjects.window windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule=appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if windowClass in badUIAWindowClassNames: return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False # Ask the window if it supports UIA natively res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # MS Word documents now have a fairly usable UI Automation implementation. However, # Builds of MS Office 2016 before build 9000 or so had bugs which we cannot work around. # And even current builds of Office 2016 are still missing enough info from UIA that it is still impossible to switch to UIA completely. # Therefore, if we can inject in-process, refuse to use UIA and instead fall back to the MS Word object model. if ( # An MS Word document window windowClass=="_WwG" # Disabling is only useful if we can inject in-process (and use our older code) and appModule.helperLocalBindingHandle # Allow the user to explisitly force UIA support for MS Word documents no matter the Office version and not config.conf['UIA']['useInMSWordWhenAvailable'] ): return False return bool(res)
def getWinEventLogInfo(window, objectID, childID, eventID=None, threadID=None): """ Formats the given winEvent parameters into a printable string. window, objectID and childID are mandatory, but eventID and threadID are optional. """ windowClassName = winUser.getClassName(window) or "unknown" objectIDName = getObjectIDName(objectID) processID = winUser.getWindowThreadProcessID(window)[0] if processID: processName = appModuleHandler.getAppModuleFromProcessID( processID).appName else: processName = "unknown application" messageList = [] if eventID is not None: eventName = getWinEventName(eventID) messageList.append(f"{eventName}") messageList.append( f"window {window} ({windowClassName}), objectID {objectIDName}, childID {childID}, " f"process {processID} ({processName})") if threadID is not None: messageList.append(f"thread {threadID}") return ", ".join(messageList)
def _isUIAWindowHelper(self, hwnd): # UIA in NVDA's process freezes in Windows 7 and below processID = winUser.getWindowThreadProcessID(hwnd)[0] if windll.kernel32.GetCurrentProcessId() == processID: return False import NVDAObjects.window windowClass = NVDAObjects.window.Window.normalizeWindowClassName( winUser.getClassName(hwnd)) # For certain window classes, we always want to use UIA. if windowClass in goodUIAWindowClassNames: return True # allow the appModule for the window to also choose if this window is good # An appModule should be able to override bad UIA class names as prescribed by core appModule = appModuleHandler.getAppModuleFromProcessID(processID) if appModule and appModule.isGoodUIAWindow(hwnd): return True # There are certain window classes that just had bad UIA implementations if self._isBadUIAWindowClassName(windowClass): return False # allow the appModule for the window to also choose if this window is bad if appModule and appModule.isBadUIAWindow(hwnd): return False if windowClass == "NetUIHWND" and appModule: # NetUIHWND is used for various controls in MS Office. # IAccessible should be used for NetUIHWND in versions older than 2016 # Fixes: lack of focus reporting (#4207), # Fixes: strange reporting of context menu items(#9252), # fixes: not being able to report ribbon sections when they starts with an edit field (#7067) # Note that #7067 is not fixed for Office 2016 and never. # Using IAccessible for NetUIHWND controls causes focus changes not to be reported # when the ribbon is collapsed. # Testing shows that these controls emits proper events but they are ignored by NVDA. isOfficeApp = appModule.productName.startswith( ("Microsoft Office", "Microsoft Outlook")) isOffice2013OrOlder = int( appModule.productVersion.split(".")[0]) < 16 if isOfficeApp and isOffice2013OrOlder: parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT) while parentHwnd: if winUser.getClassName(parentHwnd) in ( "Net UI Tool Window", "MsoCommandBar", ): return False parentHwnd = winUser.getAncestor(parentHwnd, winUser.GA_PARENT) # Ask the window if it supports UIA natively res = windll.UIAutomationCore.UiaHasServerSideProvider(hwnd) if res: # the window does support UIA natively, but # MS Word documents now have a fairly usable UI Automation implementation. However, # Builds of MS Office 2016 before build 9000 or so had bugs which we cannot work around. # And even current builds of Office 2016 are still missing enough info from UIA that it is still impossible to switch to UIA completely. # Therefore, if we can inject in-process, refuse to use UIA and instead fall back to the MS Word object model. canUseOlderInProcessApproach = bool( appModule.helperLocalBindingHandle) if ( # An MS Word document window windowClass == "_WwG" # Disabling is only useful if we can inject in-process (and use our older code) and canUseOlderInProcessApproach # Allow the user to explisitly force UIA support for MS Word documents no matter the Office version and not config.conf['UIA']['useInMSWordWhenAvailable']): return False # Unless explicitly allowed, all Chromium implementations (including Edge) should not be UIA, # As their IA2 implementation is still better at the moment. elif ( windowClass == "Chrome_RenderWidgetHostHWND" and (AllowUiaInChromium.getConfig() == AllowUiaInChromium.NO # Disabling is only useful if we can inject in-process (and use our older code) or (canUseOlderInProcessApproach and AllowUiaInChromium.getConfig() != AllowUiaInChromium.YES # Users can prefer to use UIA ))): return False return bool(res)
def elten_command(ac): global eltenmod global eltenbraille global eltenbrailletext global eltenindex global eltenindexid global eltenqueue try: if(('ac' in ac)==False): return {} if(ac['ac']=="speak"): eltenindex=None eltenindexid=None text="" if('text' in ac): text=ac['text'] if(speech.isBlank(text)==False): queueHandler.queueFunction(queueHandler.eventQueue,speech.speakText,text) if(ac['ac']=="speakindexed"): eltenindex=None eltenindexid=None texts=[] indexes=[] indid=None if('texts' in ac): texts=ac['texts'] if('indexes' in ac): indexes=ac['indexes'] if('indid' in ac): indid=ac['indid'] v=[] for i in range(0, len(texts)): if is_python_3_or_above: if(speech.isBlank(texts[i])): continue if(i<len(indexes)): v.append(EltenIndexCallback(indexes[i], indid)) if(i<len(indexes) and i>0 and texts[i-1]!="" and texts[i-1][-1]=="\n"): v.append(speech.EndUtteranceCommand()) else: eltenindexid=indid if(i<len(indexes)): v.append(speech.IndexCommand(indexes[i])) v.append(texts[i]) speech.cancelSpeech() speech.speak(v) if(ac['ac']=='stop'): speech.cancelSpeech() eltenindex=None eltenindexid=None if(ac['ac']=='sleepmode'): st=eltenmod.sleepMode if('st' in ac): st=ac['st'] eltenmod.sleepMode=st return {'st': st} if(ac['ac']=='init'): pid=0 if('pid' in ac): pid=ac['pid'] eltenmod = appModuleHandler.getAppModuleFromProcessID(pid) def script_eltengesture(self, gesture): global eltenqueue eltenqueue['gestures']+=gesture.identifiers eltenmod.__class__.script_eltengesture = types.MethodType(script_eltengesture, eltenmod.__class__) eltenmod.bindGesture('kb(laptop):NVDA+A', 'eltengesture') eltenmod.bindGesture('kb(laptop):NVDA+L', 'eltengesture') eltenmod.bindGesture('kb(desktop):NVDA+downArrow', 'eltengesture') eltenmod.bindGesture('kb(desktop):NVDA+upArrow', 'eltengesture') if(ac['ac']=='braille'): text="" if('text' in ac): text=ac['text'] if('type' in ac and 'index' in ac): if ac['type']==-1: text=eltenbrailletext[:ac['index']]+eltenbrailletext[ac['index']+1:] elif ac['type']==1: text=eltenbrailletext[:ac['index']]+text+eltenbrailletext[ac['index']:] eltenbrailletext=text+" " regions=[] for phrase in re.split("([.,:/\n?!])", eltenbrailletext): if phrase=="": continue if len(regions)>10000: continue; region=braille.TextRegion(phrase) if hasattr(region, 'parseUndefinedChars'): region.parseUndefinedChars=False region.update() regions.append(region) eltenbraille.regions=regions if('pos' in ac): poses = eltenbraille.rawToBraillePos if(ac['pos']<len(text) and ac['pos']<len(poses)): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['pos']]) eltenbraille.scrollTo(reg, pos) if('cursor' in ac and ac['cursor'] is not None): poses = eltenbraille.rawToBraillePos reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['cursor']]) reg.cursorPos=reg.brailleToRawPos[pos] reg.update() eltenbraille.update() braille.handler.update() if(ac['ac']=='braillepos' and 'pos' in ac and len(eltenbraille.regions)>0): poses = eltenbraille.rawToBraillePos if(ac['pos']<len(poses)): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['pos']]) eltenbraille.scrollTo(reg, pos) reg.update() if('cursor' in ac and ac['cursor'] is not None): reg, pos = eltenbraille.bufferPosToRegionPos(poses[ac['cursor']]) reg.cursorPos=reg.brailleToRawPos[pos] reg.update() eltenbraille.update() braille.handler.update() if(ac['ac']=='getversion'): return {'version': 33} if(ac['ac']=='getnvdaversion'): return {'version': buildVersion.version} if(ac['ac']=='getindex'): if(is_python_3_or_above): return {'index': eltenindex, 'indid': eltenindexid} else: return {'index': speech.getLastSpeechIndex(), 'indid': eltenindexid} except Exception as Argument: log.exception("Elten: command thread") return {} return {}