def setFocusObject(obj): """Stores an object as the current focus object. (Note: this does not physically change the window with focus in the operating system, but allows NVDA to keep track of the correct object). Before overriding the last object, this function calls event_loseFocus on the object to notify it that it is loosing focus. @param obj: the object that will be stored as the focus object @type obj: NVDAObjects.NVDAObject """ if not isinstance(obj, NVDAObjects.NVDAObject): return False if globalVars.focusObject: eventHandler.executeEvent("loseFocus", globalVars.focusObject) oldFocusLine = globalVars.focusAncestors #add the old focus to the old focus ancestors, but only if its not None (is none at NVDA initialization) if globalVars.focusObject: oldFocusLine.append(globalVars.focusObject) oldAppModules = [o.appModule for o in oldFocusLine if o and o.appModule] appModuleHandler.cleanup() ancestors = [] tempObj = obj matchedOld = False focusDifferenceLevel = 0 oldFocusLineLength = len(oldFocusLine) # Starting from the focus, move up the ancestor chain. safetyCount = 0 while tempObj: if safetyCount < 100: safetyCount += 1 else: try: log.error( "Never ending focus ancestry: last object: %s, %s, window class %s, application name %s" % (tempObj.name, controlTypes.roleLabels[tempObj.role], tempObj.windowClassName, tempObj.appModule.appName)) except: pass tempObj = getDesktopObject() # Scan backwards through the old ancestors looking for a match. for index in range(oldFocusLineLength - 1, -1, -1): watchdog.alive() if tempObj == oldFocusLine[index]: # Match! The old and new focus ancestors converge at this point. # Copy the old ancestors up to and including this object. origAncestors = oldFocusLine[0:index + 1] #make sure to cache the last old ancestor as a parent on the first new ancestor so as not to leave a broken parent cache if ancestors and origAncestors: ancestors[0].container = origAncestors[-1] origAncestors.extend(ancestors) ancestors = origAncestors focusDifferenceLevel = index + 1 # We don't need to process any more in either this loop or the outer loop; we have all of the ancestors. matchedOld = True break if matchedOld: break # We're moving backwards along the ancestor chain, so add this to the start of the list. ancestors.insert(0, tempObj) container = tempObj.container tempObj.container = container # Cache the parent. tempObj = container #Remove the final new ancestor as this will be the new focus object del ancestors[-1] # #5467: Ensure that the appModule of the real focus is included in the newAppModule list for profile switching # Rather than an original focus ancestor which happened to match the new focus. newAppModules = [o.appModule for o in ancestors if o and o.appModule] if obj.appModule: newAppModules.append(obj.appModule) try: treeInterceptorHandler.cleanup() except watchdog.CallCancelled: pass treeInterceptorObject = None o = None watchdog.alive() for o in ancestors[focusDifferenceLevel:] + [obj]: try: treeInterceptorObject = treeInterceptorHandler.update(o) except: log.error("Error updating tree interceptor", exc_info=True) #Always make sure that the focus object's treeInterceptor is forced to either the found treeInterceptor (if its in it) or to None #This is to make sure that the treeInterceptor does not have to be looked up, which can cause problems for winInputHook if obj is o or obj in treeInterceptorObject: obj.treeInterceptor = treeInterceptorObject else: obj.treeInterceptor = None # #3804: handleAppSwitch should be called as late as possible, # as triggers must not be out of sync with global focus variables. # setFocusObject shouldn't fail earlier anyway, but it's best to be safe. appModuleHandler.handleAppSwitch(oldAppModules, newAppModules) # Set global focus variables. globalVars.focusDifferenceLevel = focusDifferenceLevel globalVars.focusObject = obj globalVars.focusAncestors = ancestors braille.invalidateCachedFocusAncestors(focusDifferenceLevel) if config.conf["reviewCursor"]["followFocus"]: setNavigatorObject(obj, isFocus=True) return True
def setFocusObject(obj): """Stores an object as the current focus object. (Note: this does not physically change the window with focus in the operating system, but allows NVDA to keep track of the correct object). Before overriding the last object, this function calls event_loseFocus on the object to notify it that it is loosing focus. @param obj: the object that will be stored as the focus object @type obj: NVDAObjects.NVDAObject """ if not isinstance(obj,NVDAObjects.NVDAObject): return False if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): try: globalVars.focusObject.event_loseFocus() except: log.error("event_loseFocus in focusObject", exc_info=True) oldFocusLine=globalVars.focusAncestors #add the old focus to the old focus ancestors, but only if its not None (is none at NVDA initialization) if globalVars.focusObject: oldFocusLine.append(globalVars.focusObject) oldAppModuleSet=set(o.appModule for o in oldFocusLine if o and o.appModule) ancestors=[] tempObj=obj matchedOld=False focusDifferenceLevel=0 oldFocusLineLength=len(oldFocusLine) # Starting from the focus, move up the ancestor chain. safetyCount=0 while tempObj: if safetyCount<100: safetyCount+=1 else: try: log.error("Never ending focus ancestry: last object: %s, %s, window class %s, application name %s"%(tempObj.name,controlTypes.speechRoleLabels[tempObj.role],tempObj.windowClassName,tempObj.appModule.appName)) except: pass tempObj=getDesktopObject() # Scan backwards through the old ancestors looking for a match. for index in xrange(oldFocusLineLength-1,-1,-1): if tempObj==oldFocusLine[index]: # Match! The old and new focus ancestors converge at this point. # Copy the old ancestors up to and including this object. origAncestors=oldFocusLine[0:index+1] #make sure to cache the last old ancestor as a parent on the first new ancestor so as not to leave a broken parent cache if ancestors and origAncestors: ancestors[0].parent=origAncestors[-1] origAncestors.extend(ancestors) ancestors=origAncestors focusDifferenceLevel=index+1 # We don't need to process any more in either this loop or the outer loop; we have all of the ancestors. matchedOld=True break if matchedOld: break # We're moving backwards along the ancestor chain, so add this to the start of the list. ancestors.insert(0,tempObj) container=tempObj.container tempObj.container=container # Cache the parent. tempObj=container #Remove the final new ancestor as this will be the new focus object del ancestors[-1] newAppModuleSet=set(o.appModule for o in ancestors+[obj] if o and o.appModule) for removedMod in oldAppModuleSet-newAppModuleSet: if not removedMod.sleepMode and hasattr(removedMod,'event_appModule_loseFocus'): removedMod.event_appModule_loseFocus() for addedMod in newAppModuleSet-oldAppModuleSet: if not addedMod.sleepMode and hasattr(addedMod,'event_appModule_gainFocus'): addedMod.event_appModule_gainFocus() treeInterceptorHandler.cleanup() treeInterceptorObject=None o=None for o in ancestors[focusDifferenceLevel:]+[obj]: treeInterceptorObject=treeInterceptorHandler.update(o) #Always make sure that the focus object's treeInterceptor is forced to either the found treeInterceptor (if its in it) or to None #This is to make sure that the treeInterceptor does not have to be looked up, which can cause problems for winInputHook if obj is o or obj in treeInterceptorObject: obj.treeInterceptor=treeInterceptorObject else: obj.treeInterceptor=None # Set global focus variables. globalVars.focusDifferenceLevel=focusDifferenceLevel globalVars.focusObject=obj globalVars.focusAncestors=ancestors braille.invalidateCachedFocusAncestors(focusDifferenceLevel) if config.conf["reviewCursor"]["followFocus"]: setNavigatorObject(obj if not obj.treeInterceptor or obj.treeInterceptor.passThrough or not obj.treeInterceptor.isReady else obj.treeInterceptor.rootNVDAObject) return True
def setFocusObject(obj): """Stores an object as the current focus object. (Note: this does not physically change the window with focus in the operating system, but allows NVDA to keep track of the correct object). Before overriding the last object, this function calls event_loseFocus on the object to notify it that it is loosing focus. @param obj: the object that will be stored as the focus object @type obj: NVDAObjects.NVDAObject """ if not isinstance(obj,NVDAObjects.NVDAObject): return False if globalVars.focusObject: eventHandler.executeEvent("loseFocus",globalVars.focusObject) oldFocusLine=globalVars.focusAncestors #add the old focus to the old focus ancestors, but only if its not None (is none at NVDA initialization) if globalVars.focusObject: oldFocusLine.append(globalVars.focusObject) oldAppModules=[o.appModule for o in oldFocusLine if o and o.appModule] appModuleHandler.cleanup() ancestors=[] tempObj=obj matchedOld=False focusDifferenceLevel=0 oldFocusLineLength=len(oldFocusLine) # Starting from the focus, move up the ancestor chain. safetyCount=0 while tempObj: if safetyCount<100: safetyCount+=1 else: try: log.error("Never ending focus ancestry: last object: %s, %s, window class %s, application name %s"%(tempObj.name,controlTypes.roleLabels[tempObj.role],tempObj.windowClassName,tempObj.appModule.appName)) except: pass tempObj=getDesktopObject() # Scan backwards through the old ancestors looking for a match. for index in xrange(oldFocusLineLength-1,-1,-1): watchdog.alive() if tempObj==oldFocusLine[index]: # Match! The old and new focus ancestors converge at this point. # Copy the old ancestors up to and including this object. origAncestors=oldFocusLine[0:index+1] #make sure to cache the last old ancestor as a parent on the first new ancestor so as not to leave a broken parent cache if ancestors and origAncestors: ancestors[0].container=origAncestors[-1] origAncestors.extend(ancestors) ancestors=origAncestors focusDifferenceLevel=index+1 # We don't need to process any more in either this loop or the outer loop; we have all of the ancestors. matchedOld=True break if matchedOld: break # We're moving backwards along the ancestor chain, so add this to the start of the list. ancestors.insert(0,tempObj) container=tempObj.container tempObj.container=container # Cache the parent. tempObj=container newAppModules=[o.appModule for o in ancestors if o and o.appModule] #Remove the final new ancestor as this will be the new focus object del ancestors[-1] try: treeInterceptorHandler.cleanup() except watchdog.CallCancelled: pass treeInterceptorObject=None o=None watchdog.alive() for o in ancestors[focusDifferenceLevel:]+[obj]: try: treeInterceptorObject=treeInterceptorHandler.update(o) except: log.exception("Error updating tree interceptor") #Always make sure that the focus object's treeInterceptor is forced to either the found treeInterceptor (if its in it) or to None #This is to make sure that the treeInterceptor does not have to be looked up, which can cause problems for winInputHook if obj is o or obj in treeInterceptorObject: obj.treeInterceptor=treeInterceptorObject else: obj.treeInterceptor=None # #3804: handleAppSwitch should be called as late as possible, # as triggers must not be out of sync with global focus variables. # setFocusObject shouldn't fail earlier anyway, but it's best to be safe. appModuleHandler.handleAppSwitch(oldAppModules,newAppModules) # Set global focus variables. globalVars.focusDifferenceLevel=focusDifferenceLevel globalVars.focusObject=obj globalVars.focusAncestors=ancestors braille.invalidateCachedFocusAncestors(focusDifferenceLevel) if config.conf["reviewCursor"]["followFocus"]: setNavigatorObject(obj,isFocus=True) return True