def shouldAcceptEvent(eventName, windowHandle=None): """Check whether an event should be accepted from a platform API. Creating NVDAObjects and executing events can be expensive and might block the main thread noticeably if the object is slow to respond. Therefore, this should be used before NVDAObject creation to filter out any unnecessary events. A platform API handler may do its own filtering before this. """ if not windowHandle: # We can't filter without a window handle. return True key = (eventName, winUser.getWindowThreadProcessID(windowHandle)[0], winUser.getClassName(windowHandle)) if key in _acceptEvents: return True if eventName == "valueChange" and config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]: return True if eventName == "show": # Only accept 'show' events for specific cases, as otherwise we get flooded. return winUser.getClassName(windowHandle) in ( "Frame Notification Bar", # notification bars "tooltips_class32", # tooltips "mscandui21.candidate", "mscandui40.candidate", "MSCandUIWindow_Candidate", # IMM candidates "TTrayAlert", # 5405: Skype ) if eventName == "reorder": # Prevent another flood risk. return winUser.getClassName(windowHandle) == "TTrayAlert" # #4841: Skype if eventName == "alert" and winUser.getClassName(winUser.getAncestor(windowHandle, winUser.GA_PARENT)) == "ToastChildWindowClass": # Toast notifications. return True if eventName in ("menuEnd", "switchEnd", "desktopSwitch"): # #5302, #5462: These events can be fired on the desktop window # or windows that would otherwise be blocked. # Platform API handlers will translate these events to focus events anyway, # so we must allow them here. return True if windowHandle == winUser.getDesktopWindow(): # #5595: Events for the cursor get mapped to the desktop window. return True fg = winUser.getForegroundWindow() if (winUser.isDescendantWindow(fg, windowHandle) # #3899, #3905: Covers cases such as the Firefox Page Bookmarked window and OpenOffice/LibreOffice context menus. or winUser.isDescendantWindow(fg, winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER))): # This is for the foreground application. return True if (winUser.user32.GetWindowLongW(windowHandle, winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST or winUser.user32.GetWindowLongW(winUser.getAncestor(windowHandle, winUser.GA_ROOT), winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST): # This window or its root is a topmost window. # This includes menus, combo box pop-ups and the task switching list. return True return False
def shouldAcceptEvent(eventName, windowHandle=None): """Check whether an event should be accepted from a platform API. Creating NVDAObjects and executing events can be expensive and might block the main thread noticeably if the object is slow to respond. Therefore, this should be used before NVDAObject creation to filter out any unnecessary events. A platform API handler may do its own filtering before this. """ if not windowHandle: # We can't filter without a window handle. return True key = (eventName, winUser.getWindowThreadProcessID(windowHandle)[0], winUser.getClassName(windowHandle)) if key in _acceptEvents: return True if eventName == "valueChange" and config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]: return True if eventName == "show": # Only accept 'show' events for specific cases, as otherwise we get flooded. return winUser.getClassName(windowHandle) in ( "Frame Notification Bar", # notification bars "tooltips_class32", # tooltips "mscandui21.candidate", "mscandui40.candidate", "MSCandUIWindow_Candidate", # IMM candidates "TTrayAlert", # 5405: Skype ) if eventName == "reorder": # Prevent another flood risk. return winUser.getClassName(windowHandle) == "TTrayAlert" # #4841: Skype if eventName == "alert" and winUser.getClassName(winUser.getAncestor(windowHandle, winUser.GA_PARENT)) == "ToastChildWindowClass": # Toast notifications. return True if eventName in ("menuEnd", "switchEnd", "desktopSwitch"): # #5302, #5462: These events can be fired on the desktop window # or windows that would otherwise be blocked. # Platform API handlers will translate these events to focus events anyway, # so we must allow them here. return True fg = winUser.getForegroundWindow() if (winUser.isDescendantWindow(fg, windowHandle) # #3899, #3905: Covers cases such as the Firefox Page Bookmarked window and OpenOffice/LibreOffice context menus. or winUser.isDescendantWindow(fg, winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER))): # This is for the foreground application. return True if (winUser.user32.GetWindowLongW(windowHandle, winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST or winUser.user32.GetWindowLongW(winUser.getAncestor(windowHandle, winUser.GA_ROOT), winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST): # This window or its root is a topmost window. # This includes menus, combo box pop-ups and the task switching list. return True return False
def __contains__(self, obj): if not (isinstance(obj, NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject, IAccessibleHandler.IAccessible2) ) or not obj.windowClassName.startswith( 'Mozilla') or not winUser.isDescendantWindow( self.rootNVDAObject.windowHandle, obj.windowHandle): return False acc = obj.IAccessibleObject accId = obj.IA2UniqueID while True: if not accId: # Dead object. return False if accId == self.rootID: return True try: self.rootNVDAObject.IAccessibleObject.accChild(accId) # The object is definitely a descendant of the document. break except COMError: pass # accChild failed. This might be because the object is in an # out-of-process iframe, in which case the embedder document won't know # about it. Try the embedder iframe. acc = self._getEmbedderOfContainingDocument(acc) if not acc: return False try: accId = acc.uniqueID except COMError: # Dead object. return False return not self._isNVDAObjectInApplication(obj)
def event_gainFocus(self, obj, nextHandler): if self.chatWindow and not winUser.isDescendantWindow(self.chatWindow, obj.windowHandle): self.conversationLostFocus() # A conversation might have its own top level window, # but foreground changes often trigger gainFocus instead of focusEntered. self.conversationMaybeFocused(obj) nextHandler()
def __contains__(self, obj): #Special code to handle Mozilla combobox lists if obj.windowClassName.startswith( 'Mozilla') and winUser.getWindowStyle( obj.windowHandle) & winUser.WS_POPUP: parent = obj.parent while parent and parent.windowHandle == obj.windowHandle: parent = parent.parent if parent: obj = parent.parent if not (isinstance(obj, NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject, IAccessibleHandler.IAccessible2) ) or not obj.windowClassName.startswith( 'Mozilla') or not winUser.isDescendantWindow( self.rootNVDAObject.windowHandle, obj.windowHandle): return False if self.rootNVDAObject.windowHandle == obj.windowHandle: ID = obj.IA2UniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except COMError: return ID == self.rootNVDAObject.IA2UniqueID return not self._isNVDAObjectInApplication(obj)
def event_valueChange(self): global lastMSNHistoryValue if winUser.isDescendantWindow(winUser.getForegroundWindow(),self.windowHandle): value=self.value if value!=lastMSNHistoryValue and config.conf["presentation"]["reportDynamicContentChanges"]: speech.speakText(value) lastMSNHistoryValue=value
def event_gainFocus(vmID,accContext): tempContext=accContext while tempContext: try: tempContext=bridgeDll.getActiveDescendent(vmID,tempContext) except: tempContext=None try: depth=bridgeDll.getObjectDepth(vmID,tempContext) except: depth=-1 if tempContext and (depth<=0 or bridgeDll.isSameObject(vmID,accContext,tempContext)): tempContext=None if tempContext: bridgeDll.releaseJavaObject(vmID,accContext) accContext=tempContext jabContext=JABContext(vmID=vmID,accContext=accContext) if not winUser.isDescendantWindow(winUser.getForegroundWindow(),jabContext.hwnd): return focus=eventHandler.lastQueuedFocusObject if (isinstance(focus,NVDAObjects.JAB.JAB) and focus.jabContext==jabContext): return obj=NVDAObjects.JAB.JAB(jabContext=jabContext) if obj.role==controlTypes.ROLE_UNKNOWN: return eventHandler.queueEvent("gainFocus",obj)
def __contains__(self,obj): if not obj.windowClassName.startswith("Internet Explorer_"): return False #'select' tag lists have MSAA list items which do not relate to real HTML nodes. #Go up one parent for these and use it instead if isinstance(obj,NVDAObjects.IAccessible.IAccessible) and not isinstance(obj,NVDAObjects.IAccessible.MSHTML.MSHTML) and obj.role==controlTypes.ROLE_LISTITEM: parent=obj.parent if parent and isinstance(parent,NVDAObjects.IAccessible.MSHTML.MSHTML): obj=parent #Combo box lists etc are popup windows, so rely on accessibility hierarchi instead of window hierarchi for those. #However only helps in IE8. if obj.windowStyle&winUser.WS_POPUP: parent=obj.parent obj.parent=parent while parent and parent.windowHandle==obj.windowHandle: newParent=parent.parent parent.parent=newParent parent=newParent if parent and parent.windowClassName.startswith('Internet Explorer_'): obj=parent if not winUser.isDescendantWindow(self.rootDocHandle,obj.windowHandle) and obj.windowHandle!=self.rootDocHandle: return False newObj=obj while isinstance(newObj,NVDAObjects.IAccessible.MSHTML.MSHTML): if newObj==self.rootNVDAObject: return True if newObj.role in (controlTypes.ROLE_APPLICATION,controlTypes.ROLE_DIALOG): break newObj=newObj.parent 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): 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
def __contains__(self, obj): if not obj.windowClassName.startswith("Internet Explorer_"): return False if not winUser.isDescendantWindow( self.rootDocHandle, obj.windowHandle) and obj.windowHandle != self.rootDocHandle: return False return not self._isNVDAObjectInApplication(obj)
def event_valueChange(self): if self.event_childID==0 and self.event_objectID == winUser.OBJID_CLIENT and winUser.isDescendantWindow(winUser.getForegroundWindow(),self.windowHandle): # Acrobat has indicated that a page has died and been replaced by a new one. # The new page has the same event params, so we must bypass NVDA's IAccessible caching. obj = getNVDAObjectFromEvent(self.windowHandle, -4, 0) if not obj: return eventHandler.queueEvent("gainFocus",obj)
def _getNVDAObjectFromOffset(self,offset): try: p=self._getPointFromOffset(offset) except (NotImplementedError,LookupError): return self.obj obj=api.getDesktopObject().objectFromPoint(p.x,p.y) from NVDAObjects.window import Window if not obj or not isinstance(obj,Window) or not winUser.isDescendantWindow(self.obj.windowHandle,obj.windowHandle): return self.obj return obj
def event_gainFocus(vmID,accContext,hwnd): jabContext=JABContext(hwnd=hwnd,vmID=vmID,accContext=accContext) if not winUser.isDescendantWindow(winUser.getForegroundWindow(),jabContext.hwnd): return focus=eventHandler.lastQueuedFocusObject if (isinstance(focus,NVDAObjects.JAB.JAB) and focus.jabContext==jabContext): return obj=NVDAObjects.JAB.JAB(jabContext=jabContext) if obj.role==controlTypes.ROLE_UNKNOWN: return eventHandler.queueEvent("gainFocus",obj)
def _get_SDMChild(self): if controlTypes.STATE_FOCUSED in self.states: hwndFocus=winUser.getGUIThreadInfo(0).hwndFocus if hwndFocus and hwndFocus!=self.windowHandle and winUser.isDescendantWindow(self.windowHandle,hwndFocus) and not winUser.getClassName(hwndFocus).startswith('bosa_sdm'): obj=getNVDAObjectFromEvent(hwndFocus,winUser.OBJID_CLIENT,0) if not obj: return None if getattr(obj,'parentSDMCanOverrideName',True): obj.name=self.name obj.keyboardShortcut=self.keyboardShortcut obj.parent=self return obj return None
def _get_SDMChild(self): if controlTypes.State.FOCUSED in self.states: hwndFocus=winUser.getGUIThreadInfo(0).hwndFocus if hwndFocus and hwndFocus!=self.windowHandle and winUser.isDescendantWindow(self.windowHandle,hwndFocus) and not winUser.getClassName(hwndFocus).startswith('bosa_sdm'): obj=getNVDAObjectFromEvent(hwndFocus,winUser.OBJID_CLIENT,0) if not obj: return None if getattr(obj,'parentSDMCanOverrideName',True): obj.name=self.name obj.keyboardShortcut=self.keyboardShortcut obj.parent=self return obj return None
def event_stateChange(self): # iTunes has indicated that a page has died and been replaced by a new one. focus = api.getFocusObject() if not winUser.isDescendantWindow(self.windowHandle, focus.windowHandle): return # The new page has the same event params, so we must bypass NVDA's IAccessible caching. obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent(focus.windowHandle, winUser.OBJID_CLIENT, 0) if not obj: return if focus.treeInterceptor: speech.cancelSpeech() treeInterceptorHandler.killTreeInterceptor(focus.treeInterceptor) eventHandler.queueEvent("gainFocus",obj)
def event_stateChange(self): # iTunes has indicated that a page has died and been replaced by a new one. focus = api.getFocusObject() if not winUser.isDescendantWindow(self.windowHandle, focus.windowHandle): return if focus.role: # The old document is still alive. return # The new page has the same event params, so we must bypass NVDA's IAccessible caching. obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent(focus.windowHandle, winUser.OBJID_CLIENT, 0) if not obj: return eventHandler.queueEvent("gainFocus",obj)
def event_stateChange(self): # iTunes has indicated that a page has died and been replaced by a new one. focus = api.getFocusObject() if not winUser.isDescendantWindow(self.windowHandle, focus.windowHandle): return # The new page has the same event params, so we must bypass NVDA's IAccessible caching. obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent( focus.windowHandle, winUser.OBJID_CLIENT, 0) if not obj: return if focus.treeInterceptor: speech.cancelSpeech() treeInterceptorHandler.killTreeInterceptor(focus.treeInterceptor) eventHandler.queueEvent("gainFocus", obj)
def event_stateChange(self): # iTunes has indicated that a page has died and been replaced by a new one. focus = api.getFocusObject() if not winUser.isDescendantWindow(self.windowHandle, focus.windowHandle): return if focus.role: # The old document is still alive. return # The new page has the same event params, so we must bypass NVDA's IAccessible caching. obj = NVDAObjects.IAccessible.getNVDAObjectFromEvent( focus.windowHandle, winUser.OBJID_CLIENT, 0) if not obj: return eventHandler.queueEvent("gainFocus", obj)
def __contains__(self, obj): if not (isinstance(obj, NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject, IAccessibleHandler.IAccessible2) ) or not obj.windowClassName.startswith( 'Mozilla') or not winUser.isDescendantWindow( self.rootNVDAObject.windowHandle, obj.windowHandle): return False if self.rootNVDAObject.windowHandle == obj.windowHandle: ID = obj.IA2UniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except COMError: return ID == self.rootNVDAObject.IA2UniqueID return not self._isNVDAObjectInApplication(obj)
def __contains__(self, obj): if self.isWindowless: if not isinstance(obj, NVDAObjects.IAccessible.IAccessible): return False if obj.windowHandle != self.rootDocHandle: return False info = obj.IAccessibleIdentity if not info: return False ID = info['objectID'] try: self.rootNVDAObject.IAccessibleObject.accChild(ID) return True except COMError: return False return winUser.isDescendantWindow(self.rootDocHandle, obj.windowHandle)
def __contains__(self,obj): if self.isWindowless: if not isinstance(obj, NVDAObjects.IAccessible.IAccessible): return False if obj.windowHandle != self.rootDocHandle: return False info = obj.IAccessibleIdentity if not info: return False ID=info['objectID'] try: self.rootNVDAObject.IAccessibleObject.accChild(ID) return True except COMError: return False return winUser.isDescendantWindow(self.rootDocHandle, obj.windowHandle)
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 (instanciating 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 """ 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'): return False rootWindow=winUser.getAncestor(window,winUser.GA_ROOT) # If this window is not within the foreground window and this window or its root window is not a popup window, and this window's root window is not the highest in the z-order if not winUser.isDescendantWindow(winUser.getForegroundWindow(),window) and not (winUser.getWindowStyle(window) & winUser.WS_POPUP or winUser.getWindowStyle(rootWindow)&winUser.WS_POPUP) and winUser.getPreviousWindow(rootWindow)!=0: # This is a focus event from a background window, so ignore it. 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) 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: 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 _shouldRecoverAfterMinTimeout(): info=winUser.getGUIThreadInfo(0) #If hwndFocus is 0, then the OS is clearly busy and we don't want to timeout prematurely. if not info.hwndFocus: return False # Import late to avoid circular import. import api #If a system menu has been activated but NVDA's focus is not yet in the menu then use min timeout if info.flags&winUser.GUI_SYSTEMMENUMODE and info.hwndMenuOwner and api.getFocusObject().windowClassName!='#32768': return True if winUser.getClassName(info.hwndFocus) in safeWindowClassSet: return False if not winUser.isDescendantWindow(info.hwndActive, api.getFocusObject().windowHandle): # The foreground window has changed. return True newHwnd=info.hwndFocus newThreadID=winUser.getWindowThreadProcessID(newHwnd)[1] return newThreadID!=api.getFocusObject().windowThreadID
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 """ # Ignore foreground events on windows that aren't the current foreground window if window != winUser.getForegroundWindow(): 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)): 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): 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) return True # Convert the win event to an NVDA event NVDAEvent = winEventToNVDAEvent(winUser.EVENT_SYSTEM_FOREGROUND, window, objectID, childID, useCache=False) if not NVDAEvent: return False eventHandler.queueEvent(*NVDAEvent) return True
def _shouldRecoverAfterMinTimeout(): info=winUser.getGUIThreadInfo(0) if not info.hwndFocus: # The foreground thread is frozen or there is no foreground thread (probably due to a freeze elsewhere). return True # Import late to avoid circular import. import api #If a system menu has been activated but NVDA's focus is not yet in the menu then use min timeout if info.flags&winUser.GUI_SYSTEMMENUMODE and info.hwndMenuOwner and api.getFocusObject().windowClassName!='#32768': return True if winUser.getClassName(info.hwndFocus) in safeWindowClassSet: return False if not winUser.isDescendantWindow(info.hwndActive, api.getFocusObject().windowHandle): # The foreground window has changed. return True newHwnd=info.hwndFocus newThreadID=winUser.getWindowThreadProcessID(newHwnd)[1] return newThreadID!=api.getFocusObject().windowThreadID
def __contains__(self,obj): if not obj.windowClassName.startswith("Internet Explorer_"): return False #Combo box lists etc are popup windows, so rely on accessibility hierarchi instead of window hierarchi for those. #However only helps in IE8. if obj.windowStyle&winUser.WS_POPUP: parent=obj.parent obj.parent=parent while parent and parent.windowHandle==obj.windowHandle: newParent=parent.parent parent.parent=newParent parent=newParent if parent and parent.windowClassName.startswith('Internet Explorer_'): obj=parent if obj.windowHandle==self.rootDocHandle: return True if winUser.isDescendantWindow(self.rootDocHandle,obj.windowHandle): return True return False
def __contains__(self, obj): # if this is a Mozilla combo box popup, we want to work with the combo box. combo = self._getExpandedComboBox(obj) if combo: obj = combo if not (isinstance(obj, NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject, IAccessibleHandler.IAccessible2) ) or not obj.windowClassName.startswith( 'Mozilla') or not winUser.isDescendantWindow( self.rootNVDAObject.windowHandle, obj.windowHandle): return False if self.rootNVDAObject.windowHandle == obj.windowHandle: ID = obj.IA2UniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except COMError: return ID == self.rootNVDAObject.IA2UniqueID return not self._isNVDAObjectInApplication(obj)
def __contains__(self, obj): if (not (isinstance(obj, NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject, IA2.IAccessible2)) or not obj.windowClassName.startswith('Mozilla') or not winUser.isDescendantWindow( self.rootNVDAObject.windowHandle, obj.windowHandle)): return False for accId in self._iterIdsToTryWithAccChild(obj): if accId == self.rootID: return True try: self.rootNVDAObject.IAccessibleObject.accChild(accId) # The object is definitely a descendant of the document. break except COMError: pass else: # The object is definitely not a descendant of the document. return False return not self._isNVDAObjectInApplication(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 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
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 (instanciating 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 """ #Ignore foreground events on windows that aren't the current foreground window if window!=winUser.getForegroundWindow(): 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): 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: 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) return True #Convert the win event to an NVDA event NVDAEvent=winEventToNVDAEvent(winUser.EVENT_SYSTEM_FOREGROUND,window,objectID,childID,useCache=False) if not NVDAEvent: return False eventHandler.queueEvent(*NVDAEvent) return True
def __contains__(self,obj): # if this is a Mozilla combo box popup, we want to work with the combo box. combo = self._getExpandedComboBox(obj) if combo: obj = combo if not (isinstance(obj,NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject,IAccessibleHandler.IAccessible2)) or not obj.windowClassName.startswith('Mozilla') or not winUser.isDescendantWindow(self.rootNVDAObject.windowHandle,obj.windowHandle): return False if self.rootNVDAObject.windowHandle==obj.windowHandle: ID=obj.IA2UniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except COMError: return ID==self.rootNVDAObject.IA2UniqueID return not self._isNVDAObjectInApplication(obj)
def IsActive(self): #4714: In wxPython 3, ProgressDialog.IsActive always seems to return False. return winUser.isDescendantWindow(winUser.getForegroundWindow(), self.Handle)
def __contains__(self,obj): if not (isinstance(obj,NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject,IAccessibleHandler.IAccessible2)) or not obj.windowClassName.startswith('Mozilla') or not winUser.isDescendantWindow(self.rootNVDAObject.windowHandle,obj.windowHandle): return False if self.rootNVDAObject.windowHandle==obj.windowHandle: ID=obj.IA2UniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except COMError: return ID==self.rootNVDAObject.IA2UniqueID return not self._isNVDAObjectInApplication(obj)
def shouldAcceptEvent(eventName, windowHandle=None): """Check whether an event should be accepted from a platform API. Creating NVDAObjects and executing events can be expensive and might block the main thread noticeably if the object is slow to respond. Therefore, this should be used before NVDAObject creation to filter out any unnecessary events. A platform API handler may do its own filtering before this. """ if not windowHandle: # We can't filter without a window handle. return True wClass = winUser.getClassName(windowHandle) key = (eventName, winUser.getWindowThreadProcessID(windowHandle)[0], wClass) if key in _acceptEvents: return True if eventName == "valueChange" and config.conf["presentation"][ "progressBarUpdates"]["reportBackgroundProgressBars"]: return True if eventName == "hide": return False if eventName == "show": # Only accept 'show' events for specific cases, as otherwise we get flooded. return wClass in ( "Frame Notification Bar", # notification bars "tooltips_class32", # tooltips "mscandui21.candidate", "mscandui40.candidate", "MSCandUIWindow_Candidate", # IMM candidates "TTrayAlert", # 5405: Skype ) if eventName == "alert" and winUser.getClassName( winUser.getAncestor(windowHandle, winUser.GA_PARENT)) == "ToastChildWindowClass": # Toast notifications. return True if eventName in ("menuEnd", "switchEnd", "desktopSwitch"): # #5302, #5462: These events can be fired on the desktop window # or windows that would otherwise be blocked. # Platform API handlers will translate these events to focus events anyway, # so we must allow them here. return True if windowHandle == winUser.getDesktopWindow(): # #5595: Events for the cursor get mapped to the desktop window. return True # #6713: Edge (and soon all UWP apps) will no longer have windows as descendants of the foreground window. # However, it does look like they are always equal to or descendants of the "active" window of the input thread. gi = winUser.getGUIThreadInfo(0) if wClass.startswith('Windows.UI.Core'): if winUser.isDescendantWindow(gi.hwndActive, windowHandle): return True fg = winUser.getForegroundWindow() fgClassName = winUser.getClassName(fg) if wClass == "NetUIHWND" and fgClassName in ("Net UI Tool Window Layered", "Net UI Tool Window"): # #5504: In Office >= 2013 with the ribbon showing only tabs, # when a tab is expanded, the window we get from the focus object is incorrect. # This window isn't beneath the foreground window, # so our foreground application checks fail. # Just compare the root owners. if winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER) == winUser.getAncestor( fg, winUser.GA_ROOTOWNER): return True if (winUser.isDescendantWindow(fg, windowHandle) # #3899, #3905: Covers cases such as the Firefox Page Bookmarked window and OpenOffice/LibreOffice context menus. or winUser.isDescendantWindow( fg, winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER))): # This is for the foreground application. return True if (winUser.user32.GetWindowLongW(windowHandle, winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST or winUser.user32.GetWindowLongW( winUser.getAncestor(windowHandle, winUser.GA_ROOT), winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST): # This window or its root is a topmost window. # This includes menus, combo box pop-ups and the task switching list. return True # This may be an event for a windowless embedded Chrome document # (E.g. Microsoft Loop component). if wClass == "Chrome_RenderWidgetHostHWND": # The event is for a Chromium document if winUser.getClassName(gi.hwndFocus) == "Chrome_WidgetWin_0": # The real win32 focus is on a Chrome embedding window. # See if we can get from the event's Chromium document to the Chrome embedding window # via ancestors in the UIA tree. rootWindowHandle = winUser.getAncestor(windowHandle, winUser.GA_ROOT) import UIAHandler try: rootElement = UIAHandler.handler.clientObject.elementFromHandle( rootWindowHandle) except COMError: log.debugWarning( "Could not create UIA element for root of Chromium document", exc_info=True) else: condition = UIAHandler.handler.clientObject.CreatePropertyCondition( UIAHandler.UIA_NativeWindowHandlePropertyId, gi.hwndFocus) try: walker = UIAHandler.handler.clientObject.CreateTreeWalker( condition) ancestorElement = walker.NormalizeElement(rootElement) except COMError: log.debugWarning( "Unable to normalize root Chromium element to focused ancestor", exc_info=True) ancestorElement = None if ancestorElement: # The real focused window is an ancestor of the Chromium document in the UIA tree. return True return False
def __contains__(self,obj): if not obj.windowClassName.startswith("Internet Explorer_"): return False if not winUser.isDescendantWindow(self.rootDocHandle,obj.windowHandle) and obj.windowHandle!=self.rootDocHandle: return False return not self._isNVDAObjectInApplication(obj)
def __contains__(self, obj): return winUser.isDescendantWindow(self.rootNVDAObject.windowHandle, obj.windowHandle)
def _get_isInForeground(self): fg=winUser.getForegroundWindow() return self.windowHandle==fg or winUser.isDescendantWindow(fg,self.windowHandle)
def shouldAcceptEvent(eventName, windowHandle=None): """Check whether an event should be accepted from a platform API. Creating NVDAObjects and executing events can be expensive and might block the main thread noticeably if the object is slow to respond. Therefore, this should be used before NVDAObject creation to filter out any unnecessary events. A platform API handler may do its own filtering before this. """ if not windowHandle: # We can't filter without a window handle. return True wClass = winUser.getClassName(windowHandle) key = (eventName, winUser.getWindowThreadProcessID(windowHandle)[0], wClass) if key in _acceptEvents: return True if eventName == "valueChange" and config.conf["presentation"][ "progressBarUpdates"]["reportBackgroundProgressBars"]: return True if eventName == "show": # Only accept 'show' events for specific cases, as otherwise we get flooded. return wClass in ( "Frame Notification Bar", # notification bars "tooltips_class32", # tooltips "mscandui21.candidate", "mscandui40.candidate", "MSCandUIWindow_Candidate", # IMM candidates "TTrayAlert", # 5405: Skype ) if eventName == "reorder": # Prevent another flood risk. return wClass == "TTrayAlert" # #4841: Skype if eventName == "alert" and winUser.getClassName( winUser.getAncestor(windowHandle, winUser.GA_PARENT)) == "ToastChildWindowClass": # Toast notifications. return True if eventName in ("menuEnd", "switchEnd", "desktopSwitch"): # #5302, #5462: These events can be fired on the desktop window # or windows that would otherwise be blocked. # Platform API handlers will translate these events to focus events anyway, # so we must allow them here. return True if windowHandle == winUser.getDesktopWindow(): # #5595: Events for the cursor get mapped to the desktop window. return True # #6713: Edge (and soon all UWP apps) will no longer have windows as descendants of the foreground window. # However, it does look like they are always equal to or descendants of the "active" window of the input thread. if wClass.startswith('Windows.UI.Core'): gi = winUser.getGUIThreadInfo(0) if winUser.isDescendantWindow(gi.hwndActive, windowHandle): return True fg = winUser.getForegroundWindow() if wClass == "NetUIHWND" and winUser.getClassName( fg) == "Net UI Tool Window Layered": # #5504: In Office >= 2013 with the ribbon showing only tabs, # when a tab is expanded, the window we get from the focus object is incorrect. # This window isn't beneath the foreground window, # so our foreground application checks fail. # Just compare the root owners. if winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER) == winUser.getAncestor( fg, winUser.GA_ROOTOWNER): return True if (winUser.isDescendantWindow(fg, windowHandle) # #3899, #3905: Covers cases such as the Firefox Page Bookmarked window and OpenOffice/LibreOffice context menus. or winUser.isDescendantWindow( fg, winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER))): # This is for the foreground application. return True if (winUser.user32.GetWindowLongW(windowHandle, winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST or winUser.user32.GetWindowLongW( winUser.getAncestor(windowHandle, winUser.GA_ROOT), winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST): # This window or its root is a topmost window. # This includes menus, combo box pop-ups and the task switching list. return True return False
def event_gainFocus(self, obj, nextHandler): if self.conversation and not winUser.isDescendantWindow(self.conversation.windowHandle, obj.windowHandle): self.conversation.lostFocus() nextHandler()
def __contains__(self,obj): #Special code to handle Mozilla combobox lists if obj.windowClassName.startswith('Mozilla') and winUser.getWindowStyle(obj.windowHandle)&winUser.WS_POPUP: parent=obj.parent while parent and parent.windowHandle==obj.windowHandle: parent=parent.parent if parent: obj=parent.parent if not (isinstance(obj,NVDAObjects.IAccessible.IAccessible) and isinstance(obj.IAccessibleObject,IAccessibleHandler.IAccessible2)) or not obj.windowClassName.startswith('Mozilla') or not winUser.isDescendantWindow(self.rootNVDAObject.windowHandle,obj.windowHandle): return False if self.rootNVDAObject.windowHandle==obj.windowHandle: ID=obj.IAccessibleObject.uniqueID try: self.rootNVDAObject.IAccessibleObject.accChild(ID) except: return False return self._isNVDAObjectInApplication(obj)
def __contains__(self,obj): return winUser.isDescendantWindow(self.rootNVDAObject.windowHandle, obj.windowHandle)
def shouldAcceptEvent(eventName, windowHandle=None): """Check whether an event should be accepted from a platform API. Creating NVDAObjects and executing events can be expensive and might block the main thread noticeably if the object is slow to respond. Therefore, this should be used before NVDAObject creation to filter out any unnecessary events. A platform API handler may do its own filtering before this. """ if not windowHandle: # We can't filter without a window handle. return True wClass = winUser.getClassName(windowHandle) key = (eventName, winUser.getWindowThreadProcessID(windowHandle)[0], wClass) if key in _acceptEvents: return True if eventName == "valueChange" and config.conf["presentation"]["progressBarUpdates"]["reportBackgroundProgressBars"]: return True if eventName == "show": # Only accept 'show' events for specific cases, as otherwise we get flooded. return wClass in ( "Frame Notification Bar", # notification bars "tooltips_class32", # tooltips "mscandui21.candidate", "mscandui40.candidate", "MSCandUIWindow_Candidate", # IMM candidates "TTrayAlert", # 5405: Skype ) if eventName == "reorder": # Prevent another flood risk. return wClass == "TTrayAlert" # #4841: Skype if eventName == "alert" and winUser.getClassName(winUser.getAncestor(windowHandle, winUser.GA_PARENT)) == "ToastChildWindowClass": # Toast notifications. return True if eventName in ("menuEnd", "switchEnd", "desktopSwitch"): # #5302, #5462: These events can be fired on the desktop window # or windows that would otherwise be blocked. # Platform API handlers will translate these events to focus events anyway, # so we must allow them here. return True if windowHandle == winUser.getDesktopWindow(): # #5595: Events for the cursor get mapped to the desktop window. return True # #6713: Edge (and soon all UWP apps) will no longer have windows as descendants of the foreground window. # However, it does look like they are always equal to or descendants of the "active" window of the input thread. if wClass.startswith('Windows.UI.Core'): gi=winUser.getGUIThreadInfo(0) if winUser.isDescendantWindow(gi.hwndActive,windowHandle): return True fg = winUser.getForegroundWindow() if wClass == "NetUIHWND" and winUser.getClassName(fg) == "Net UI Tool Window Layered": # #5504: In Office >= 2013 with the ribbon showing only tabs, # when a tab is expanded, the window we get from the focus object is incorrect. # This window isn't beneath the foreground window, # so our foreground application checks fail. # Just compare the root owners. if winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER) == winUser.getAncestor(fg, winUser.GA_ROOTOWNER): return True if (winUser.isDescendantWindow(fg, windowHandle) # #3899, #3905: Covers cases such as the Firefox Page Bookmarked window and OpenOffice/LibreOffice context menus. or winUser.isDescendantWindow(fg, winUser.getAncestor(windowHandle, winUser.GA_ROOTOWNER))): # This is for the foreground application. return True if (winUser.user32.GetWindowLongW(windowHandle, winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST or winUser.user32.GetWindowLongW(winUser.getAncestor(windowHandle, winUser.GA_ROOT), winUser.GWL_EXSTYLE) & winUser.WS_EX_TOPMOST): # This window or its root is a topmost window. # This includes menus, combo box pop-ups and the task switching list. return True return False