def _get_isAlive(self): if not winUser.isWindow(self.rootNVDAObject.windowHandle): return False try: self.rootNVDAObject.UIAElement.currentProviderDescription except COMError: return False return True
def _get_isAlive(self): if not winUser.isWindow(self.rootNVDAObject.windowHandle): return False try: return self.rootNVDAObject.excelWorksheetObject.name==self.rootNVDAObject.excelApplicationObject.activeSheet.name except (COMError,AttributeError,NameError): log.debugWarning("could not compare sheet names",exc_info=True) return False
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle) or root.role == controlTypes.ROLE_UNKNOWN: return False return True
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False states=root.states if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_DEFUNCT in states or controlTypes.STATE_READONLY not in states: return False return True
def winEventCallback(handle,eventID,window,objectID,childID,threadID,timestamp): try: #Ignore all object IDs from alert onwards (sound, nativeom etc) as we don't support them if objectID<=winUser.OBJID_ALERT: return #Ignore all locationChange events except ones for the caret if eventID==winUser.EVENT_OBJECT_LOCATIONCHANGE and objectID!=winUser.OBJID_CARET: return if eventID==winUser.EVENT_OBJECT_DESTROY: processDestroyWinEvent(window,objectID,childID) return #Change window objIDs to client objIDs for better reporting of objects if (objectID==0) and (childID==0): objectID=winUser.OBJID_CLIENT #Ignore events with invalid window handles isWindow = winUser.isWindow(window) if window else 0 if window==0 or (not isWindow and eventID in (winUser.EVENT_SYSTEM_SWITCHSTART,winUser.EVENT_SYSTEM_SWITCHEND,winUser.EVENT_SYSTEM_MENUEND,winUser.EVENT_SYSTEM_MENUPOPUPEND)): window=winUser.getDesktopWindow() elif not isWindow: return if childID<0: tempWindow=window while tempWindow and not winUser.getWindowStyle(tempWindow)&winUser.WS_POPUP and winUser.getClassName(tempWindow)=="MozillaWindowClass": tempWindow=winUser.getAncestor(tempWindow,winUser.GA_PARENT) if tempWindow and winUser.getClassName(tempWindow).startswith('Mozilla'): window=tempWindow windowClassName=winUser.getClassName(window) #At the moment we can't handle show, hide or reorder events on Mozilla Firefox Location bar,as there are just too many of them #Ignore show, hide and reorder on MozillaDropShadowWindowClass windows. if windowClassName.startswith('Mozilla') and eventID in (winUser.EVENT_OBJECT_SHOW,winUser.EVENT_OBJECT_HIDE,winUser.EVENT_OBJECT_REORDER) and childID<0: #Mozilla Gecko can sometimes fire win events on a catch-all window which isn't really the real window #Move up the ancestry to find the real mozilla Window and use that if winUser.getClassName(window)=='MozillaDropShadowWindowClass': return if eventID==winUser.EVENT_SYSTEM_FOREGROUND: #We never want to see foreground events for the Program Manager or Shell (task bar) if windowClassName in ("Progman","Shell_TrayWnd"): return # #3831: Event handling can be deferred if Windows takes a while to change the foreground window. # See pumpAll for details. global _deferUntilForegroundWindow,_foregroundDefers _deferUntilForegroundWindow=window _foregroundDefers=0 if windowClassName=="MSNHiddenWindowClass": # HACK: Events get fired by this window in Windows Live Messenger 2009 when it starts. # If we send a WM_NULL to this window at this point (which happens in accessibleObjectFromEvent), Messenger will silently exit (#677). # Therefore, completely ignore these events, which is useless to us anyway. return if winEventLimiter.addEvent(eventID,window,objectID,childID,threadID): core.requestPump() except: log.error("winEventCallback", exc_info=True)
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle): return False try: isDefunct=bool(root.IAccessibleObject.states&IAccessibleHandler.IA2_STATE_DEFUNCT) except COMError: # If IAccessible2 states can not be fetched at all, defunct should be assumed as the object has clearly been disconnected or is dead isDefunct=True return not isDefunct
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_DEFUNCT in root.states: return False try: if not NVDAObjects.IAccessible.getNVDAObjectFromEvent(root.windowHandle,winUser.OBJID_CLIENT,root.IA2UniqueID): return False except: return False return True
def __init__(self, handle=None, windowTitle=None, appName=None): if handle: if winUser.isWindow(handle) == 0: raise ValueError( "Cannot create object for non existing window") else: self.handle = handle self.windowTitle = windowTitle self.appName = appName else: self.handle = api.getForegroundObject().windowHandle self.windowTitle = api.getForegroundObject().name self.appName = appModuleHandler.getAppNameFromProcessID( api.getForegroundObject().processID, True)
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} """ NVDAEventName = winEventIDsToNVDAEventNames.get(eventID, None) if not NVDAEventName: return None # Ignore any events with invalid window handles if not window or not winUser.isWindow(window): return None # Make sure this window does not have a ghost window if possible if NVDAObjects.window.GhostWindowFromHungWindow and NVDAObjects.window.GhostWindowFromHungWindow( window): return None # We do not support MSAA object proxied from native UIA if UIAHandler.handler and UIAHandler.handler.isUIAWindow(window): 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 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: 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 return (NVDAEventName, obj)
def _get_isAlive(self): if self.isLoading: return True root = self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle): return False try: isDefunct = bool(root.IAccessibleObject.states & IAccessibleHandler.IA2_STATE_DEFUNCT) except COMError: # If IAccessible2 states can not be fetched at all, defunct should be assumed as the object has clearly been disconnected or is dead isDefunct = True return not isDefunct
def _get_isAlive(self): if self.isLoading: return True root = self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle ) or controlTypes.STATE_DEFUNCT in root.states: return False try: if not NVDAObjects.IAccessible.getNVDAObjectFromEvent( root.windowHandle, winUser.OBJID_CLIENT, root.IA2UniqueID): return False except: return False return True
def _get_isAlive(self): if self.isLoading: return True root = self.rootNVDAObject if not root: return False try: if not root.IAccessibleRole: # The root object is dead. return False except watchdog.CallCancelled: # #1831: If the root object isn't responding, treat the buffer as dead. # Otherwise, we'll keep querying it on every focus change and freezing. return False states = root.states if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_EDITABLE in states: return False return True
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} """ NVDAEventName=winEventIDsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return None #Ignore any events with invalid window handles if not window or not winUser.isWindow(window): return None #Make sure this window does not have a ghost window if possible if NVDAObjects.window.GhostWindowFromHungWindow and NVDAObjects.window.GhostWindowFromHungWindow(window): return None #We do not support MSAA object proxied from native UIA if UIAHandler.handler and UIAHandler.handler.isUIAWindow(window): 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 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: 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 return (NVDAEventName,obj)
def _get_isAlive(self): if self.isLoading: return True root = self.rootNVDAObject if not root: return False try: if not root.IAccessibleRole: # The root object is dead. return False except watchdog.CallCancelled: # #1831: If the root object isn't responding, treat the buffer as dead. # Otherwise, we'll keep querying it on every focus change and freezing. return False states = root.states if not winUser.isWindow( root.windowHandle) or controlTypes.STATE_EDITABLE in states: return False return True
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} """ #We can't handle MSAA create events. (Destroys are handled elsewhere.) if eventID == winUser.EVENT_OBJECT_CREATE: return None #Handle the special MSAA caret object's locationChange and show events as 'caret' events for the focus object NVDAEventName=winEventIDsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return None #Ignore any events with invalid window handles if not window or not winUser.isWindow(window): 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 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: 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 return (NVDAEventName,obj)
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle): return False if not root.isInForeground: # #7818: Subsequent checks make COM calls. # The chances of a buffer dying while the window is in the background are # low, so don't make COM calls in this case; just treat it as alive. # This prevents freezes on every focus change if the browser process # stops responding; e.g. it froze, crashed or is being debugged. return True try: isDefunct=bool(root.IAccessibleObject.states&IAccessibleHandler.IA2_STATE_DEFUNCT) except COMError: # If IAccessible2 states can not be fetched at all, defunct should be assumed as the object has clearly been disconnected or is dead isDefunct=True return not isDefunct
def _get_isAlive(self): if self.isLoading: return True root=self.rootNVDAObject if not root: return False if not winUser.isWindow(root.windowHandle): return False if root.appModule.appName.startswith('wwahost') and not winUser.isDescendantWindow(winUser.getForegroundWindow(),root.windowHandle): # #4572: When a wwahost hosted app is in the background it gets suspended and all COM calls freeze. # Therefore we don't have enough info to say whether its dead or not. We assume it is alive until we can get a better answer. return True try: if not root.IAccessibleRole: # The root object is dead. return False except watchdog.CallCancelled: # #1831: If the root object isn't responding, treat the buffer as dead. # Otherwise, we'll keep querying it on every focus change and freezing. return False states=root.states if controlTypes.STATE_EDITABLE in states: return False return True
winKernel.PROCESS_TERMINATE | winKernel.SYNCHRONIZE, False, processID) if not h: raise OSError("Could not open process for termination") try: winKernel.TerminateProcess(h, 1) winKernel.waitForSingleObject(h, 2000) finally: winKernel.closeHandle(h) #Handle running multiple instances of NVDA try: oldAppWindowHandle = winUser.FindWindow(u'wxWindowClassNR', u'NVDA') except: oldAppWindowHandle = 0 if not winUser.isWindow(oldAppWindowHandle): oldAppWindowHandle = 0 if oldAppWindowHandle and not globalVars.appArgs.easeOfAccess: if globalVars.appArgs.check_running: # NVDA is running. sys.exit(0) try: terminateRunningNVDA(oldAppWindowHandle) except: sys.exit(1) if globalVars.appArgs.quit or (oldAppWindowHandle and globalVars.appArgs.easeOfAccess): sys.exit(0) elif globalVars.appArgs.check_running: # NVDA is not running. sys.exit(1)
def _get_isAlive(self): root = self.rootNVDAObject return winUser.isWindow(root.windowHandle)
def isAlive(self): return winUser.isWindow(self.rootNVDAObject.windowHandle)
def winEventCallback(handle, eventID, window, objectID, childID, threadID, timestamp): # noqa: C901 if isMSAADebugLoggingEnabled(): log.debug( f"Hook received winEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) try: # Ignore all object IDs from alert onwards (sound, nativeom etc) as we don't support them if objectID <= winUser.OBJID_ALERT: if isMSAADebugLoggingEnabled(): log.debug( f"objectID not supported. " f"Dropping winEvent {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) return # Ignore all locationChange events except ones for the caret if eventID == winUser.EVENT_OBJECT_LOCATIONCHANGE and objectID != winUser.OBJID_CARET: if isMSAADebugLoggingEnabled(): log.debug( f"locationChange for something other than the caret. " f"Dropping winEvent {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) return if eventID == winUser.EVENT_OBJECT_DESTROY: _processDestroyWinEvent(window, objectID, childID) return # Change window objIDs to client objIDs for better reporting of objects if (objectID == 0) and (childID == 0): objectID = winUser.OBJID_CLIENT if isMSAADebugLoggingEnabled(): log.debug( f"Changing OBJID_WINDOW to OBJID_CLIENT " f"for winEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) # Ignore events with invalid window handles isWindow = winUser.isWindow(window) if window else 0 if window == 0 or (not isWindow and eventID in ( winUser.EVENT_SYSTEM_SWITCHSTART, winUser.EVENT_SYSTEM_SWITCHEND, winUser.EVENT_SYSTEM_MENUEND, winUser.EVENT_SYSTEM_MENUPOPUPEND, )): if isMSAADebugLoggingEnabled(): log.debug( f"Changing NULL or invalid window to desktop window " f"for winEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) window = winUser.getDesktopWindow() elif not isWindow: if isMSAADebugLoggingEnabled(): log.debug( f"Invalid window. " f"Dropping winEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) return windowClassName = winUser.getClassName(window) if windowClassName == "ConsoleWindowClass": # #10113: we need to use winEvents to track the real thread for console windows. consoleWindowsToThreadIDs[window] = threadID # Modern IME candidate list windows fire menu events which confuse us # and can't be used properly in conjunction with input composition support. if windowClassName == "Microsoft.IME.UIManager.CandidateWindow.Host" and eventID in MENU_EVENTIDS: if isMSAADebugLoggingEnabled(): log.debug( f"Dropping menu event for IME window. " f"WinEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) return if eventID == winUser.EVENT_SYSTEM_FOREGROUND: # We never want to see foreground events for the Program Manager or Shell (task bar) if windowClassName in ("Progman", "Shell_TrayWnd"): if isMSAADebugLoggingEnabled(): log.debug( f"Progman or shell_trayWnd window. " f"Dropping winEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) return # #3831: Event handling can be deferred if Windows takes a while to change the foreground window. # See pumpAll for details. global _deferUntilForegroundWindow, _foregroundDefers _deferUntilForegroundWindow = window _foregroundDefers = 0 if isMSAADebugLoggingEnabled(): log.debug( f"Recording foreground defer " f"for WinEvent: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) if windowClassName == "MSNHiddenWindowClass": # HACK: Events get fired by this window in Windows Live Messenger 2009 when it starts. If we send a # WM_NULL to this window at this point (which happens in accessibleObjectFromEvent), Messenger will # silently exit (#677). Therefore, completely ignore these events, which is useless to us anyway. return if isMSAADebugLoggingEnabled(): log.debug( f"Adding winEvent to limiter: {getWinEventLogInfo(window, objectID, childID, eventID, threadID)}" ) if winEventLimiter.addEvent(eventID, window, objectID, childID, threadID): core.requestPump() except Exception: log.error("winEventCallback", exc_info=True)
def winEventCallback(handle, eventID, window, objectID, childID, threadID, timestamp): # noqa: C901 try: # Ignore all object IDs from alert onwards (sound, nativeom etc) as we don't support them if objectID <= winUser.OBJID_ALERT: return # Ignore all locationChange events except ones for the caret if eventID == winUser.EVENT_OBJECT_LOCATIONCHANGE and objectID != winUser.OBJID_CARET: return if eventID == winUser.EVENT_OBJECT_DESTROY: _processDestroyWinEvent(window, objectID, childID) return # Change window objIDs to client objIDs for better reporting of objects if (objectID == 0) and (childID == 0): objectID = winUser.OBJID_CLIENT # Ignore events with invalid window handles isWindow = winUser.isWindow(window) if window else 0 if window == 0 or ( not isWindow and eventID in ( winUser.EVENT_SYSTEM_SWITCHSTART, winUser.EVENT_SYSTEM_SWITCHEND, winUser.EVENT_SYSTEM_MENUEND, winUser.EVENT_SYSTEM_MENUPOPUPEND, ) ): window = winUser.getDesktopWindow() elif not isWindow: return if childID < 0: tempWindow = window while ( tempWindow and not winUser.getWindowStyle(tempWindow) & winUser.WS_POPUP and winUser.getClassName(tempWindow) == "MozillaWindowClass" ): tempWindow = winUser.getAncestor(tempWindow, winUser.GA_PARENT) if tempWindow and winUser.getClassName(tempWindow).startswith('Mozilla'): window = tempWindow windowClassName = winUser.getClassName(window) if windowClassName == "ConsoleWindowClass": # #10113: we need to use winEvents to track the real thread for console windows. consoleWindowsToThreadIDs[window] = threadID # Modern IME candidate list windows fire menu events which confuse us # and can't be used properly in conjunction with input composition support. if windowClassName == "Microsoft.IME.UIManager.CandidateWindow.Host" and eventID in MENU_EVENTIDS: return # At the moment we can't handle show, hide or reorder events on Mozilla Firefox Location bar, # as there are just too many of them Ignore show, hide and reorder on MozillaDropShadowWindowClass # windows. if ( windowClassName.startswith('Mozilla') and eventID in ( winUser.EVENT_OBJECT_SHOW, winUser.EVENT_OBJECT_HIDE, winUser.EVENT_OBJECT_REORDER ) and childID < 0 ): # Mozilla Gecko can sometimes fire win events on a catch-all window which isn't really the real window # Move up the ancestry to find the real mozilla Window and use that if winUser.getClassName(window) == 'MozillaDropShadowWindowClass': return if eventID == winUser.EVENT_SYSTEM_FOREGROUND: # We never want to see foreground events for the Program Manager or Shell (task bar) if windowClassName in ("Progman", "Shell_TrayWnd"): return # #3831: Event handling can be deferred if Windows takes a while to change the foreground window. # See pumpAll for details. global _deferUntilForegroundWindow, _foregroundDefers _deferUntilForegroundWindow = window _foregroundDefers = 0 if windowClassName == "MSNHiddenWindowClass": # HACK: Events get fired by this window in Windows Live Messenger 2009 when it starts. If we send a # WM_NULL to this window at this point (which happens in accessibleObjectFromEvent), Messenger will # silently exit (#677). Therefore, completely ignore these events, which is useless to us anyway. return if winEventLimiter.addEvent(eventID, window, objectID, childID, threadID): core.requestPump() except: # noqa: E722 Bare except log.error("winEventCallback", exc_info=True)
def isAlive(self): return bool(winUser.isWindow(self.handle))
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)