def event_gainFocus(self): if eventHandler.isPendingEvents("gainFocus"): return super(JAB,self).event_gainFocus() if eventHandler.isPendingEvents("gainFocus"): return activeDescendant=self.activeDescendant if activeDescendant: eventHandler.queueEvent("gainFocus",activeDescendant)
def event_caret(self): global selOffsetsAtLastCaretEvent #Fetching formatting and calculating word offsets needs to move the caret, so try to ignore these events selOffsets=self.makeTextInfo(textInfos.POSITION_SELECTION).bookmark if selOffsets==selOffsetsAtLastCaretEvent: return selOffsetsAtLastCaretEvent=selOffsets #Make sure that this object *really* has the focus before bothering to speak any possible selection change api.processPendingEvents() if self is not api.getFocusObject() or eventHandler.isPendingEvents('gainFocus'): return if eventHandler.isPendingEvents('valueChange',self): self.hasContentChangedSinceLastSelection=True super(Edit,self).event_caret()
def handleSelectionChange(self): """Pushes focus to the newly selected object.""" obj=self.selection if not obj: obj=DocumentWindow(windowHandle=self.windowHandle) if obj and obj!=api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): eventHandler.queueEvent("gainFocus",obj)
def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID): if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. return if eventID==UIA_MenuOpenedEventId and eventHandler.isPendingEvents("gainFocus"): # We don't need the menuOpened event if focus has been fired, # as focus should be more correct. return NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return if not self.isNativeUIAElement(sender): return window=self.getNearestWindowHandle(sender) if window and not eventHandler.shouldAcceptEvent(NVDAEventName,windowHandle=window): return import NVDAObjects.UIA obj=NVDAObjects.UIA.UIA(UIAElement=sender) if ( not obj or (NVDAEventName=="gainFocus" and not obj.shouldAllowUIAFocusEvent) or (NVDAEventName=="liveRegionChange" and not obj._shouldAllowUIALiveRegionChangeEvent) ): return focus=api.getFocusObject() if obj==focus: obj=focus eventHandler.queueEvent(NVDAEventName,obj)
def event_gainFocus(self): if mouseHandler.lastMouseEventTime < time.time() - 0.2: # This focus change was not caused by a mouse event. # If the mouse is on another toolbar control, the notification area toolbar will rudely # bounce the focus back to the object under the mouse after a brief pause. # Moving the mouse to the focus object isn't a good solution because # sometimes, the focus can't be moved away from the object under the mouse. # Therefore, move the mouse out of the way. winUser.setCursorPos(0, 0) if self.role == controlTypes.ROLE_TOOLBAR: # Sometimes, the toolbar itself receives the focus instead of the focused child. # However, the focused child still has the focused state. for child in self.children: if child.hasFocus: # Redirect the focus to the focused child. eventHandler.executeEvent("gainFocus", child) return # We've really landed on the toolbar itself. # This was probably caused by moving the mouse out of the way in a previous focus event. # This previous focus event is no longer useful, so cancel speech. speech.cancelSpeech() if eventHandler.isPendingEvents("gainFocus"): return super(NotificationArea, self).event_gainFocus()
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03): """ Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued. @param bookmark: a bookmark representing the position of the caret before it was instructed to move @type bookmark: bookmark @param retryInterval: the interval of time in seconds this method should wait before checking the caret each time. @type retryInterval: float @param timeout: the over all amount of time in seconds the method should wait before giving up completely. @type timeout: float @return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event. @rtype: tuple """ elapsed = 0 newInfo=None while elapsed < timeout: if isScriptWaiting(): return (False,None) api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return (True,None) #The caret may stop working as the focus jumps, we want to stay in the while loop though try: newInfo = self.makeTextInfo(textInfos.POSITION_CARET) newBookmark = newInfo.bookmark except (RuntimeError,NotImplementedError): newInfo=None else: if newBookmark!=bookmark: return (True,newInfo) time.sleep(retryInterval) elapsed += retryInterval return (False,newInfo)
def event_caret(self): if self is api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): braille.handler.handleCaretMove(self) if config.conf["reviewCursor"]["followCaret"] and api.getNavigatorObject() is self: try: api.setReviewPosition(self.makeTextInfo(textInfos.POSITION_CARET)) except (NotImplementedError, RuntimeError): pass
def event_gainFocus(self): child = self.firstChild if child and controlTypes.STATE_FOCUSED in child.states and not eventHandler.isPendingEvents("gainFocus"): # UIA reports that focus is on the top level pane, even when it's actually on the frame below. # This causes us to incorrectly use UIA for the top level pane, which causes this pane to be spoken again when the focus moves. # Therefore, bounce the focus to the correct object. eventHandler.queueEvent("gainFocus", child) return return super(LogonDialog, self).event_gainFocus()
def event_gainFocus(self, obj, nextHandler): if not eventHandler.isPendingEvents("gainFocus") and obj.windowClassName == "Chrome_WidgetWin_0" and obj.role == controlTypes.ROLE_WINDOW: # Spotify doesn't fire focus on the correct object when it gets the foreground. try: focus = obj.activeChild.activeChild except AttributeError: focus = None if focus: return eventHandler.executeEvent("gainFocus", focus) return nextHandler()
def setFocus(self): oldFocus=self._getPhysicalFocus() super(Mozilla,self).setFocus() # Although all versions of Firefox block inSetFocus or in accFocus until the physical focus has moved, # Firefox 57 and above return before they fire a focus winEvent communicating the focus change to ATs. # Therefore, If the call to setFocus did change the physical focus, # Wait for a focus event to be queued to NVDA before returning. newFocus=self._getPhysicalFocus() if newFocus and newFocus!=oldFocus: while not eventHandler.isPendingEvents("gainFocus"): api.processPendingEvents(processEventQueue=False)
def reportSelectedCandidate(candidateObject,allowDuplicate=False,newList=False): if not eventHandler.isPendingEvents("gainFocus") and (allowDuplicate or candidateObject!=api.getFocusObject()): if not isinstance(api.getFocusObject(),BaseCandidateItem): oldCandidateItemsText=None candidateObject.container=api.getFocusObject() eventHandler.queueEvent("foreground",candidateObject) else: oldCandidateItemsText=api.getFocusObject().visibleCandidateItemsText candidateObject.container=api.getFocusObject().container if config.conf["inputComposition"]["autoReportAllCandidates"] and (newList or candidateObject.visibleCandidateItemsText!=oldCandidateItemsText): queueHandler.queueFunction(queueHandler.eventQueue,ui.message,candidateObject.visibleCandidateItemsText) eventHandler.queueEvent("gainFocus",candidateObject)
def event_gainFocus(self): if eventHandler.isPendingEvents("gainFocus"): return child = self.activeChild if child: # QT doesn't fire focus on the active child as it should, so redirect the focus. self.event_focusEntered() eventHandler.executeEvent("gainFocus", child) return return super(Container, self).event_gainFocus()
def script_caret_changeSelection(self,gesture): try: oldInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: gesture.send() return gesture.send() if isScriptWaiting() or eventHandler.isPendingEvents("gainFocus"): return try: self.reportSelectionChange(oldInfo) except: return
def event_gainFocus(self): if eventHandler.isPendingEvents("gainFocus"): return widget = self._containedWidget if widget: # This is a widget container. # Redirect the focus to the contained widget, since QT doesn't do it properly. self.event_focusEntered() eventHandler.executeEvent("gainFocus", widget) return return super(Client, self).event_gainFocus()
def event_gainFocus(self): """On gaining focus, simply set the focus on a child of type word document. This is just a container window. """ if eventHandler.isPendingEvents("gainFocus"): return document=next((x for x in self.children if isinstance(x,WordDocument)), None) if document: curThreadID=ctypes.windll.kernel32.GetCurrentThreadId() ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,True) ctypes.windll.user32.SetFocus(document.windowHandle) ctypes.windll.user32.AttachThreadInput(curThreadID,document.windowThreadID,False) if not document.WinwordWindowObject.active: document.WinwordWindowObject.activate()
def script_caret_changeSelection(self,gesture): try: oldInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: gesture.send() return gesture.send() if isScriptWaiting() or eventHandler.isPendingEvents("gainFocus"): return api.processPendingEvents(processEventQueue=False) try: newInfo=self.makeTextInfo(textInfos.POSITION_SELECTION) except: return speech.speakSelectionChange(oldInfo,newInfo)
def consoleWinEventHook(handle,eventID,window,objectID,childID,threadID,timestamp): #We don't want to do anything with the event if the event is not for the window this console is in if window!=consoleObject.windowHandle: return if eventID==winUser.EVENT_CONSOLE_CARET and not eventHandler.isPendingEvents("caret",consoleObject): eventHandler.queueEvent("caret",consoleObject) # It is safe to call this event from this callback. # This avoids an extra core cycle. consoleObject.event_textChange() if eventID==winUser.EVENT_CONSOLE_UPDATE_SIMPLE: x=winUser.GET_X_LPARAM(objectID) y=winUser.GET_Y_LPARAM(objectID) consoleScreenBufferInfo=wincon.GetConsoleScreenBufferInfo(consoleOutputHandle) if x<consoleScreenBufferInfo.dwCursorPosition.x and (y==consoleScreenBufferInfo.dwCursorPosition.y or y==consoleScreenBufferInfo.dwCursorPosition.y+1): eventHandler.queueEvent("typedCharacter",consoleObject,ch=unichr(winUser.LOWORD(childID)))
def turnPage(self,previous=False): try: self.IAccessibleActionObject.doAction(1 if previous else 0) except COMError: raise RuntimeError("no more pages") startTime=curTime=time.time() while (curTime-startTime)<0.5: api.processPendingEvents(processEventQueue=False) # should only check for pending pageChange for this object specifically, but object equality seems to fail sometimes? if eventHandler.isPendingEvents("pageChange"): self.invalidateCache() break time.sleep(0.05) curTime=time.time() else: raise RuntimeError("no more pages")
def event_gainFocus(self): # #6671: Normally we do not allow WorkerW thread to send gain focus event, # as it causes 'pane" to be announced when minimizing windows or moving to desktop. # However when closing Windows 7 Start Menu in some cases # focus lands on it instead of the focused desktop item. # Simply ignore the event if running on anything other than Win 7. if winVersion.getWinVer() > winVersion.WIN7_SP1: return if eventHandler.isPendingEvents("gainFocus"): return if self.simpleFirstChild: # If focus is not going to be moved autotically # we need to forcefully move it to the focused desktop item. # As we are interested in the first focusable object below the pane use simpleFirstChild. self.simpleFirstChild.setFocus() return super().event_gainFocus()
def _getDropdown(self): w=winUser.getAncestor(self.windowHandle,winUser.GA_ROOT) if not w: log.debugWarning("Could not get ancestor window (GA_ROOT)") return obj=Window(windowHandle=w,chooseBestAPI=False) if not obj: log.debugWarning("Could not instnaciate NVDAObject for ancestor window") return threadID=obj.windowThreadID while not eventHandler.isPendingEvents("gainFocus"): obj=obj.previous if not obj or not isinstance(obj,Window) or obj.windowThreadID!=threadID: log.debugWarning("Could not locate dropdown list in previous objects") return if obj.windowClassName=='EXCEL:': break return obj
def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID): if not self.MTAThreadInitEvent.isSet: # UIAHandler hasn't finished initialising yet, so just ignore this event. return if eventID==UIA_MenuOpenedEventId and eventHandler.isPendingEvents("gainFocus"): # We don't need the menuOpened event if focus has been fired, # as focus should be more correct. return NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return if not self.isNativeUIAElement(sender): return import NVDAObjects.UIA obj=NVDAObjects.UIA.UIA(UIAElement=sender) if not obj or (NVDAEventName=="gainFocus" and not obj.shouldAllowUIAFocusEvent): return eventHandler.queueEvent(NVDAEventName,obj)
def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID): if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. return if eventID==UIA_MenuOpenedEventId and eventHandler.isPendingEvents("gainFocus"): # We don't need the menuOpened event if focus has been fired, # as focus should be more correct. return NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None) if not NVDAEventName: return if not self.isNativeUIAElement(sender): return import NVDAObjects.UIA obj=NVDAObjects.UIA.UIA(UIAElement=sender) if not obj or (NVDAEventName=="gainFocus" and not obj.shouldAllowUIAFocusEvent): return eventHandler.queueEvent(NVDAEventName,obj)
def event_gainFocus(self): """On gaining focus, simply set the focus on a child of type word document. This is just a container window. """ if eventHandler.isPendingEvents("gainFocus"): return document = next( (x for x in self.children if isinstance(x, WordDocument)), None) if document: curThreadID = ctypes.windll.kernel32.GetCurrentThreadId() ctypes.windll.user32.AttachThreadInput(curThreadID, document.windowThreadID, True) ctypes.windll.user32.SetFocus(document.windowHandle) ctypes.windll.user32.AttachThreadInput(curThreadID, document.windowThreadID, False) if not document.WinwordWindowObject.active: document.WinwordWindowObject.activate()
def script_changeSelection(self,gesture): oldSelection=self._getSelection() gesture.send() newSelection=None curTime=startTime=time.time() while (curTime-startTime)<=0.15: if scriptHandler.isScriptWaiting(): # Prevent lag if keys are pressed rapidly return if eventHandler.isPendingEvents('gainFocus'): return newSelection=self._getSelection() if newSelection and newSelection!=oldSelection: break api.processPendingEvents(processEventQueue=False) time.sleep(0.015) curTime=time.time() if newSelection: eventHandler.executeEvent('gainFocus',newSelection)
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=0.03): elapsed = 0 while elapsed < timeout: if isScriptWaiting(): return False api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return True #The caret may stop working as the focus jumps, we want to stay in the while loop though try: newBookmark = self.makeTextInfo(textInfos.POSITION_CARET).bookmark except (RuntimeError,NotImplementedError): pass else: if newBookmark!=bookmark: return True time.sleep(retryInterval) elapsed += retryInterval return False
def processDestroyWinEvent(window, objectID, childID): """Process a destroy win event. This removes the object associated with the event parameters from L{liveNVDAObjectTable} if such an object exists. """ try: del liveNVDAObjectTable[(window, objectID, childID)] except KeyError: pass # Specific support for input method MSAA candidate lists. # When their window is destroyed we must correct focus to its parent - which could be a composition string # so can't use generic focus correction. (#2695) focus = api.getFocusObject() from NVDAObjects.IAccessible.mscandui import BaseCandidateItem if (objectID == 0 and childID == 0 and isinstance(focus, BaseCandidateItem) and window == focus.windowHandle and not eventHandler.isPendingEvents("gainFocus")): obj = focus.container if obj: eventHandler.queueEvent("gainFocus", obj)
def _get_focusRedirect(self): if self.role == controlTypes.ROLE_UNKNOWN: # The control is inaccessible, try several times to find the CellEdit UIA element with focus and use that instead. for count in range(10): if count >= 1: api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return time.sleep(0.05) e = UIAHandler.handler.lastFocusedUIAElement if e and e.cachedAutomationID == "CellEdit": obj = UIA(UIAElement=e) oldFocus = api.getFocusObject() if isinstance(oldFocus, ExcelCell): # Set the edit control's parent as the cell that previously had focus. I.e. the cell being edited. # otherwise a whole bunch of UIA focus ancestors for the edit control will be reported. obj.parent = oldFocus # Cache this for as long as this object exists. self.focusRedirect = obj return obj
def _get_focusRedirect(self): if self.role==controlTypes.ROLE_UNKNOWN: # The control is inaccessible, try several times to find the CellEdit UIA element with focus and use that instead. for count in xrange(10): if count>=1: api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): return time.sleep(0.05) e=UIAHandler.handler.lastFocusedUIAElement if e and e.cachedAutomationID=="CellEdit": obj=UIA(UIAElement=e) oldFocus=api.getFocusObject() if isinstance(oldFocus,ExcelCell): # Set the edit control's parent as the cell that previously had focus. I.e. the cell being edited. # otherwise a whole bunch of UIA focus ancestors for the edit control will be reported. obj.parent=oldFocus # Cache this for as long as this object exists. self.focusRedirect=obj return obj
def reportSelectedCandidate(candidateObject, allowDuplicate=False, newList=False): if not eventHandler.isPendingEvents("gainFocus") and ( allowDuplicate or candidateObject != api.getFocusObject()): if not isinstance(api.getFocusObject(), BaseCandidateItem): oldCandidateItemsText = None candidateObject.container = api.getFocusObject() eventHandler.queueEvent("foreground", candidateObject) else: oldCandidateItemsText = api.getFocusObject( ).visibleCandidateItemsText candidateObject.container = api.getFocusObject().container if config.conf["inputComposition"]["autoReportAllCandidates"] and ( newList or candidateObject.visibleCandidateItemsText != oldCandidateItemsText): queueHandler.queueFunction( queueHandler.eventQueue, ui.message, candidateObject.visibleCandidateItemsText) eventHandler.queueEvent("gainFocus", candidateObject)
def script_openDropdown(self,gesture): gesture.send() d=None curTime=startTime=time.time() while (curTime-startTime)<=0.25: if scriptHandler.isScriptWaiting(): # Prevent lag if keys are pressed rapidly return if eventHandler.isPendingEvents('gainFocus'): return d=self._getDropdown() if d: break api.processPendingEvents(processEventQueue=False) time.sleep(0.025) curTime=time.time() if not d: log.debugWarning("Failed to get dropDown, giving up") return d.parent=self eventHandler.queueEvent("gainFocus",d)
def consoleWinEventHook(handle, eventID, window, objectID, childID, threadID, timestamp): #We don't want to do anything with the event if the event is not for the window this console is in if window != consoleObject.windowHandle: return if eventID == winUser.EVENT_CONSOLE_CARET and not eventHandler.isPendingEvents( "caret", consoleObject): eventHandler.queueEvent("caret", consoleObject) # It is safe to call this event from this callback. # This avoids an extra core cycle. consoleObject.event_textChange() if eventID == winUser.EVENT_CONSOLE_UPDATE_SIMPLE: x = winUser.GET_X_LPARAM(objectID) y = winUser.GET_Y_LPARAM(objectID) consoleScreenBufferInfo = wincon.GetConsoleScreenBufferInfo( consoleOutputHandle) if x < consoleScreenBufferInfo.dwCursorPosition.x and ( y == consoleScreenBufferInfo.dwCursorPosition.y or y == consoleScreenBufferInfo.dwCursorPosition.y + 1): eventHandler.queueEvent("typedCharacter", consoleObject, ch=chr(winUser.LOWORD(childID)))
def enterJavaWindow_helper(hwnd): vmID=c_long() accContext=JOBJECT64() timeout=time.time()+0.2 while time.time()<timeout and not eventHandler.isPendingEvents("gainFocus"): try: bridgeDll.getAccessibleContextWithFocus(hwnd,byref(vmID),byref(accContext)) except: pass if vmID and accContext: break time.sleep(0.01) if not vmID or not accContext: try: bridgeDll.getAccessibleContextFromHWND(hwnd,byref(vmID),byref(accContext)) except: return vmID=vmID.value vmIDsToWindowHandles[vmID]=hwnd lastFocus=eventHandler.lastQueuedFocusObject if isinstance(lastFocus,NVDAObjects.JAB.JAB) and lastFocus.windowHandle==hwnd: return event_gainFocus(vmID,accContext,hwnd)
def enterJavaWindow_helper(hwnd): vmID=c_long() accContext=JOBJECT64() gotFocus=False timeout=time.time()+0.2 while time.time()<timeout and not eventHandler.isPendingEvents("gainFocus"): try: bridgeDll.getAccessibleContextWithFocus(hwnd,byref(vmID),byref(accContext)) except: pass if vmID and accContext: break time.sleep(0.01) if not vmID or not accContext: try: bridgeDll.getAccessibleContextFromHWND(hwnd,byref(vmID),byref(accContext)) except: return vmID=vmID.value vmIDsToWindowHandles[vmID]=hwnd lastFocus=eventHandler.lastQueuedFocusObject if isinstance(lastFocus,NVDAObjects.JAB.JAB) and lastFocus.windowHandle==hwnd: return event_gainFocus(vmID,accContext,hwnd)
def event_gainFocus(self, obj, nextHandler): if obj.windowClassName == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents("gainFocus"): # When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus. # Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it. # Therefore, if there is a pending focus event, don't bother handling this event. return nextHandler()
def event_caret(self): super(EditableText, self).event_caret() if self is api.getFocusObject() and not eventHandler.isPendingEvents( 'gainFocus'): self.detectPossibleSelectionChange()
def _caretScriptPostMovedHelper(self, speakUnit, gesture, info=None): if eventHandler.isPendingEvents("gainFocus"): return super()._caretScriptPostMovedHelper(speakUnit, gesture, info)
def event_caret(self): if self is api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): braille.handler.handleCaretMove(self) brailleInput.handler.handleCaretMove(self) review.handleCaretMove(self)
def event_caret(self): if self is api.getFocusObject() and not eventHandler.isPendingEvents("gainFocus"): braille.handler.handleCaretMove(self) review.handleCaretMove(self)
def event_gainFocus(self, obj, nextHandler): wClass = obj.windowClassName if wClass == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents( "gainFocus"): # When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus. # Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it. # Therefore, if there is a pending focus event, don't bother handling this event. return if wClass == "ForegroundStaging": # #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears. # This causes NVDA to report "unknown", so ignore it. # We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground. return if wClass == "WorkerW" and obj.role == controlTypes.ROLE_PANE and obj.name is None: # #6671: Never allow WorkerW thread to send gain focus event, as it causes 'pane" to be announced when minimizing windows or moving to desktop. return nextHandler()
def event_typedCharacter(self, ch): if eventHandler.isPendingEvents("caret"): return self.appModule.reportLastInsertedText(self, "typed")
def processDestroyWinEvent(window,objectID,childID): """Process a destroy win event. This removes the object associated with the event parameters from L{liveNVDAObjectTable} if such an object exists. """ try: del liveNVDAObjectTable[(window,objectID,childID)] except KeyError: pass #Specific support for input method MSAA candidate lists. #When their window is destroyed we must correct focus to its parent - which could be a composition string # so can't use generic focus correction. (#2695) focus=api.getFocusObject() from NVDAObjects.IAccessible.mscandui import BaseCandidateItem if objectID==0 and childID==0 and isinstance(focus,BaseCandidateItem) and window==focus.windowHandle and not eventHandler.isPendingEvents("gainFocus"): obj=focus.container if obj: eventHandler.queueEvent("gainFocus",obj)
def IUIAutomationEventHandler_HandleAutomationEvent(self, sender, eventID): if not self.MTAThreadInitEvent.isSet(): # UIAHandler hasn't finished initialising yet, so just ignore this event. if _isDebug(): log.debug( "HandleAutomationEvent: event received while not fully initialized" ) return if eventID == UIA_MenuOpenedEventId and eventHandler.isPendingEvents( "gainFocus"): # We don't need the menuOpened event if focus has been fired, # as focus should be more correct. if _isDebug(): log.debug( "HandleAutomationEvent: Ignored MenuOpenedEvent while focus event pending" ) return NVDAEventName = UIAEventIdsToNVDAEventNames.get(eventID, None) if not NVDAEventName: if _isDebug(): log.debugWarning( f"HandleAutomationEvent: Don't know how to handle event {eventID}" ) return focus = api.getFocusObject() import NVDAObjects.UIA if (isinstance(focus, NVDAObjects.UIA.UIA) and self.clientObject.compareElements(focus.UIAElement, sender)): pass elif not self.isNativeUIAElement(sender): if _isDebug(): log.debug( f"HandleAutomationEvent: Ignoring event {NVDAEventName} for non native element" ) return window = self.getNearestWindowHandle(sender) if window and not eventHandler.shouldAcceptEvent(NVDAEventName, windowHandle=window): if _isDebug(): log.debug( f"HandleAutomationEvent: Ignoring event {NVDAEventName} for shouldAcceptEvent=False" ) return try: obj = NVDAObjects.UIA.UIA(UIAElement=sender) except Exception: if _isDebug(): log.debugWarning( f"HandleAutomationEvent: Exception while creating object for event {NVDAEventName}", exc_info=True) return if (not obj or (NVDAEventName == "gainFocus" and not obj.shouldAllowUIAFocusEvent) or (NVDAEventName == "liveRegionChange" and not obj._shouldAllowUIALiveRegionChangeEvent)): if _isDebug(): log.debug( "HandleAutomationEvent: " f"Ignoring event {NVDAEventName} because no object or ignored by object itself" ) return if obj == focus: obj = focus eventHandler.queueEvent(NVDAEventName, obj)
def event_gainFocus(self, obj, nextHandler): wClass = obj.windowClassName if wClass == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents("gainFocus"): # When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus. # Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it. # Therefore, if there is a pending focus event, don't bother handling this event. return if wClass == "ForegroundStaging": # #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears. # This causes NVDA to report "unknown", so ignore it. # We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground. return nextHandler()
def event_gainFocus(self, obj, nextHandler): wClass = obj.windowClassName if wClass == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents("gainFocus"): # When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus. # Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it. # Therefore, if there is a pending focus event, don't bother handling this event. return if wClass in ("ForegroundStaging", "LauncherTipWnd", "ApplicationManager_DesktopShellWindow"): # #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window and foreground staging screen before and after it appears. # This causes NVDA to report "unknown", so ignore it. # We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground. # #8137: also seen when opening quick link menu (Windows+X) on Windows 8 and later. return if wClass == "WorkerW" and obj.role == controlTypes.ROLE_PANE and obj.name is None: # #6671: Never allow WorkerW thread to send gain focus event, as it causes 'pane" to be announced when minimizing windows or moving to desktop. return nextHandler()
def _hasCaretMoved(self, bookmark, retryInterval=0.01, timeout=None, origWord=None): """ Waits for the caret to move, for a timeout to elapse, or for a new focus event or script to be queued. @param bookmark: a bookmark representing the position of the caret before it was instructed to move @type bookmark: bookmark @param retryInterval: the interval of time in seconds this method should wait before checking the caret each time. @type retryInterval: float @param timeout: the over all amount of time in seconds the method should wait before giving up completely, C{None} to use the value from the configuration. @type timeout: float @param origWord: The word at the caret before the movement command, C{None} if the word at the caret should not be used to detect movement. This is intended for use with the delete key. @return: a tuple containing a boolean denoting whether this method timed out, and a TextInfo representing the old or updated caret position or None if interupted by a script or focus event. @rtype: tuple """ if timeout is None: timeoutMs = config.conf["editableText"]["caretMoveTimeoutMs"] else: # This function's arguments are in seconds, but we want ms. timeoutMs = timeout * 1000 # time.sleep accepts seconds, so retryInterval is in seconds. # Convert to integer ms to avoid floating point precision errors when adding to elapsed. retryMs = int(retryInterval * 1000) elapsed = 0 newInfo = None while True: if isScriptWaiting(): return (False, None) api.processPendingEvents(processEventQueue=False) if eventHandler.isPendingEvents("gainFocus"): log.debug("Focus event. Elapsed: %d ms" % elapsed) return (True, None) # If the focus changes after this point, fetching the caret may fail, # but we still want to stay in this loop. try: newInfo = self.makeTextInfo(textInfos.POSITION_CARET) except (RuntimeError, NotImplementedError): newInfo = None # Caret events are unreliable in some controls. # Try to detect with bookmarks. newBookmark = None if newInfo: try: newBookmark = newInfo.bookmark except (RuntimeError, NotImplementedError): pass if newBookmark and newBookmark != bookmark: log.debug( "Caret move detected using bookmarks. Elapsed: %d ms" % elapsed) return (True, newInfo) if origWord is not None and newInfo: # When pressing delete, bookmarks might not be enough to detect caret movement. wordInfo = newInfo.copy() wordInfo.expand(textInfos.UNIT_WORD) word = wordInfo.text if word != origWord: log.debug("Word at caret changed. Elapsed: %d ms" % elapsed) return (True, newInfo) if elapsed >= timeoutMs: break time.sleep(retryInterval) elapsed += retryMs log.debug("Caret didn't move before timeout. Elapsed: %d ms" % elapsed) return (False, newInfo)
def event_caret(self): super(EditableText, self).event_caret() if self is api.getFocusObject() and not eventHandler.isPendingEvents('gainFocus'): self.detectPossibleSelectionChange()
def event_gainFocus(self, obj, nextHandler): wClass = obj.windowClassName if wClass == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents( "gainFocus"): # When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus. # Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it. # Therefore, if there is a pending focus event, don't bother handling this event. return if wClass in ("ForegroundStaging", "LauncherTipWnd", "ApplicationManager_DesktopShellWindow"): # #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window and foreground staging screen before and after it appears. # This causes NVDA to report "unknown", so ignore it. # We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground. # #8137: also seen when opening quick link menu (Windows+X) on Windows 8 and later. return nextHandler()