Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
	def _isUIAWindowHelper(self,hwnd):
		# UIA in NVDA's process freezes in Windows 7 and below
		processID=winUser.getWindowThreadProcessID(hwnd)[0]
		if windll.kernel32.GetCurrentProcessId()==processID:
			return False
		import NVDAObjects.window
		windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd))
		# A WDAG (Windows Defender Application Guard) Window is always native UIA, even if it doesn't report as such.
		if windowClass=='RAIL_WINDOW':
			return True
		# There are certain window classes that just had bad UIA implementations
		if windowClass in badUIAWindowClassNames:
			return False
		if windowClass=="NetUIHWND":
			parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT)
			# #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better.
			# #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA.
			if winUser.getClassName(parentHwnd) in {"Net UI Tool Window","NUIDialog"}:
				return False
		# allow the appModule for the window to also choose if this window is bad
		appModule=appModuleHandler.getAppModuleFromProcessID(processID)
		if appModule and appModule.isBadUIAWindow(hwnd):
			return False
		# Ask the window if it supports UIA natively
		res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
		if res:
			# the window does support UIA natively, but
			# Microsoft Word should not use UIA unless we can't inject or the user explicitly chose to use UIA with Microsoft word
			if windowClass=="_WwG" and not (config.conf['UIA']['useInMSWordWhenAvailable'] or not appModule.helperLocalBindingHandle):
				return False
		return bool(res)
Beispiel #4
0
	def _isUIAWindowHelper(self,hwnd):
		# UIA in NVDA's process freezes in Windows 7 and below
		processID=winUser.getWindowThreadProcessID(hwnd)[0]
		if windll.kernel32.GetCurrentProcessId()==processID:
			return False
		import NVDAObjects.window
		windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd))
		# For certain window classes, we always want to use UIA.
		if windowClass in goodUIAWindowClassNames:
			return True
		# allow the appModule for the window to also choose if this window is good
		# An appModule should be able to override bad UIA class names as prescribed by core
		appModule=appModuleHandler.getAppModuleFromProcessID(processID)
		if appModule and appModule.isGoodUIAWindow(hwnd):
			return True
		# There are certain window classes that just had bad UIA implementations
		if windowClass in badUIAWindowClassNames:
			return False
		if windowClass=="NetUIHWND":
			parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT)
			# #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better.
			# #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA.
			if winUser.getClassName(parentHwnd) in {"Net UI Tool Window","NUIDialog"}:
				return False
		# allow the appModule for the window to also choose if this window is bad
		if appModule and appModule.isBadUIAWindow(hwnd):
			return False
		# Ask the window if it supports UIA natively
		res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
		if res:
			# the window does support UIA natively, but
			# Microsoft Word should not use UIA unless we can't inject or the user explicitly chose to use UIA with Microsoft word
			if windowClass=="_WwG" and not (config.conf['UIA']['useInMSWordWhenAvailable'] or not appModule.helperLocalBindingHandle):
				return False
		return bool(res)
Beispiel #5
0
	def _get_parent(self):
		parentHandle=winUser.getAncestor(self.windowHandle,winUser.GA_PARENT)
		if parentHandle:
			#Because we, we need to get the APIclass manually need to  set the relation as parent
			kwargs=dict(windowHandle=parentHandle)
			APIClass=Window.findBestAPIClass(kwargs,relation="parent")
			return APIClass(**kwargs) if APIClass else None
Beispiel #6
0
 def isGoodUIAWindow(self, hwnd):
     currentWinVer = winVersion.getWinVer()
     # #9204: shell raises window open event for emoji panel in build 18305 and later.
     if (currentWinVer >= winVersion.WIN10_1903
             and winUser.getClassName(hwnd) == "ApplicationFrameWindow"):
         return True
     # #13506: Windows 11 UI elements such as Taskbar should be reclassified as UIA windows,
     # letting NVDA announce shell elements when navigating with mouse and/or touch,
     # notably when interacting with windows labeled "DesktopWindowXamlSource".
     # WORKAROUND UNTIL A PERMANENT FIX IS FOUND ACROSS APPS
     if (currentWinVer >= winVersion.WIN11
             # Traverse parents until arriving at the top-level window with the below class names.
             # This is more so for the shell root (first class name), and for others, class name check would work
             # since they are top-level windows for windows shown on screen such as Task View.
             # However, look for the ancestor for consistency.
             and winUser.getClassName(
                 winUser.getAncestor(hwnd, winUser.GA_ROOT)) in
         (
             # Windows 11 shell UI root, housing various shell elements shown on screen if enabled.
             "Shell_TrayWnd",  # Start, Search, Widgets, other shell elements
             # Top-level window class names from Windows 11 shell features
             "Shell_InputSwitchTopLevelWindow",  # Language switcher
             "XamlExplorerHostIslandWindow",  # Task View and Snap Layouts
         )
             # #13717: on some systems, Windows 11 shell elements are reported as IAccessible,
             # notably Start button, causing IAccessible handler to report attribute error when handling events.
             and winUser.getClassName(hwnd) != "Start"):
         return True
     return False
Beispiel #7
0
 def _isUIAWindowHelper(self, hwnd):
     # UIA in NVDA's process freezes in Windows 7 and below
     processID = winUser.getWindowThreadProcessID(hwnd)[0]
     if windll.kernel32.GetCurrentProcessId() == processID:
         return False
     import NVDAObjects.window
     windowClass = NVDAObjects.window.Window.normalizeWindowClassName(
         winUser.getClassName(hwnd))
     # There are certain window classes that just had bad UIA implementations
     if windowClass in badUIAWindowClassNames:
         return False
     if windowClass == "NetUIHWND":
         parentHwnd = winUser.getAncestor(hwnd, winUser.GA_ROOT)
         # #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better.
         # #4056: Combo boxes in Office 2010 Options dialogs don't expose a name via UIA, but do via MSAA.
         if winUser.getClassName(parentHwnd) in {
                 "Net UI Tool Window", "NUIDialog"
         }:
             return False
     # allow the appModule for the window to also choose if this window is bad
     appModule = appModuleHandler.getAppModuleFromProcessID(processID)
     if appModule and appModule.isBadUIAWindow(hwnd):
         return False
     # Ask the window if it supports UIA natively
     return windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
Beispiel #8
0
	def event_NVDAObject_init(self, obj):
		windowClass = obj.windowClassName
		role = obj.role

		if windowClass == "ToolbarWindow32" and role == controlTypes.ROLE_POPUPMENU:
			parent = obj.parent
			if parent and parent.windowClassName == "SysPager" and not (obj.windowStyle & 0x80):
				# This is the menu for a group of icons on the task bar, which Windows stupidly names "Application".
				obj.name = None
			return

		if windowClass == "#32768":
			# Standard menu.
			parent = obj.parent
			if parent and not parent.parent:
				# Context menu.
				# We don't trust the names that Explorer gives to context menus, so better to have no name at all.
				obj.name = None
			return

		if windowClass == "DV2ControlHost" and role == controlTypes.ROLE_PANE:
			# Windows Vista/7 start menu.
			obj.presentationType=obj.presType_content
			obj.isPresentableFocusAncestor = True
			# In Windows 7, the description of this pane is extremely verbose help text, so nuke it.
			obj.description = None
			return

		# The Address bar is embedded inside a progressbar, how strange.
		# Lets hide that
		if windowClass=="msctls_progress32" and winUser.getClassName(winUser.getAncestor(obj.windowHandle,winUser.GA_PARENT))=="Address Band Root":
			obj.presentationType=obj.presType_layout
Beispiel #9
0
	def _get_parent(self):
		parentHandle=winUser.getAncestor(self.windowHandle,winUser.GA_PARENT)
		if parentHandle:
			#Because we, we need to get the APIclass manually need to  set the relation as parent
			kwargs=dict(windowHandle=parentHandle)
			APIClass=Window.findBestAPIClass(kwargs,relation="parent")
			return APIClass(**kwargs) if APIClass else None
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)
		# 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:
		log.error("winEventCallback", exc_info=True)
Beispiel #11
0
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 (instantiating 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
    # 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 (childID == 0 and objectID == winUser.OBJID_CLIENT
            and 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:  # noqa: E722 Bare 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)
Beispiel #12
0
	def event_NVDAObject_init(self,obj):
		controlID=obj.windowControlID
		windowHandle=obj.windowHandle
		parentWindow=winUser.getAncestor(windowHandle,winUser.GA_PARENT)
		parentClassName=winUser.getClassName(parentWindow)
		#If this object is an email header field, and we have a custom label for it,
		#Then set the object's name to the label 
		if parentClassName=="OE_Envelope" and obj.IAccessibleChildID==0 and envelopeNames.has_key(controlID):
			obj.name=envelopeNames[controlID]
			obj.useITextDocumentSupport=True
			obj.editValueUnit=textInfos.UNIT_STORY
Beispiel #13
0
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)
Beispiel #14
0
	def event_NVDAObject_init(self,obj):
		if not isinstance(obj,Window): return
		controlID=obj.windowControlID
		windowHandle=obj.windowHandle
		parentWindow=winUser.getAncestor(windowHandle,winUser.GA_PARENT)
		parentClassName=winUser.getClassName(parentWindow)
		#If this object is an email header field, and we have a custom label for it,
		#Then set the object's name to the label 
		if parentClassName=="OE_Envelope" and isinstance(obj,IAccessible) and obj.IAccessibleChildID==0 and controlID in envelopeNames:
			obj.name=envelopeNames[controlID]
			obj.useITextDocumentSupport=True
			obj.editValueUnit=textInfos.UNIT_STORY
Beispiel #15
0
	def isBadUIAWindow(self,hwnd):
		windowClass=winUser.getClassName(hwnd)
		# #2816: Outlook versions before 2016 auto complete does not fire enough UIA events, IAccessible is better.
		if windowClass=="NetUIHWND":
			parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT)
			if winUser.getClassName(parentHwnd)=="Net UI Tool Window":
				versionMajor=int(self.productVersion.split('.')[0])
				if versionMajor<16:
					return True
		if windowClass in ("WeekViewWnd","DayViewWnd"):
			return True
		return False
Beispiel #16
0
	def isBadUIAWindow(self,hwnd):
		windowClass=winUser.getClassName(hwnd)
		# #2816: Outlook versions before 2016 auto complete does not fire enough UIA events, IAccessible is better.
		if windowClass=="NetUIHWND":
			parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT)
			if winUser.getClassName(parentHwnd)=="Net UI Tool Window":
				versionMajor=int(self.productVersion.split('.')[0])
				if versionMajor<16:
					return True
		if windowClass in ("WeekViewWnd","DayViewWnd"):
			return True
		return False
Beispiel #17
0
 def chooseNVDAObjectOverlayClasses(self, obj, clsList):
     if UIAWordDocument in clsList:
         # Overlay class for Outlook message viewer when UI Automation for MS Word is enabled.
         clsList.insert(0, OutlookUIAWordDocument)
     if isinstance(obj, UIA) and obj.UIAElement.cachedClassName in (
             "LeafRow", "ThreadItem", "ThreadHeader"):
         clsList.insert(0, UIAGridRow)
     role = obj.role
     windowClassName = obj.windowClassName
     # AutoComplete listItems.
     # This class is abstract enough to  support both UIA and MSAA
     if role == controlTypes.ROLE_LISTITEM and (
             windowClassName.startswith("REListBox")
             or windowClassName.startswith("NetUIHWND")):
         clsList.insert(0, AutoCompleteListItem)
     #  all   remaining classes are IAccessible
     if not isinstance(obj, IAccessible):
         return
     # Outlook uses dialogs for many forms such as appointment / meeting creation. In these cases, there is no sane dialog caption that can be calculated as the dialog inly contains controls.
     # Therefore remove the Dialog behavior for these imbedded dialog forms so as to not announce junk as the caption
     if Dialog in clsList:
         parentWindow = winUser.getAncestor(obj.windowHandle,
                                            winUser.GA_PARENT)
         if parentWindow and winUser.getClassName(
                 parentWindow) == "AfxWndW":
             clsList.remove(Dialog)
     if WordDocument in clsList:
         clsList.insert(0, OutlookWordDocument)
     states = obj.states
     controlID = obj.windowControlID
     # Support the date picker in Outlook Meeting / Appointment creation forms
     if controlID == 4352 and role == controlTypes.ROLE_BUTTON:
         clsList.insert(0, DatePickerButton)
     elif role == controlTypes.ROLE_TABLECELL and windowClassName == "rctrl_renwnd32":
         clsList.insert(0, DatePickerCell)
     elif windowClassName == "REListBox20W" and role == controlTypes.ROLE_CHECKBOX:
         clsList.insert(0, REListBox20W_CheckBox)
     if role == controlTypes.ROLE_LISTITEM and windowClassName == "OUTEXVLB":
         clsList.insert(0, AddressBookEntry)
         return
     if (windowClassName == "SUPERGRID"
             and controlID == 4704) or (windowClassName == "rctrl_renwnd32"
                                        and controlID == 109):
         outlookVersion = self.outlookVersion
         if (outlookVersion and outlookVersion > 9
                 and obj.event_objectID == winUser.OBJID_CLIENT
                 and obj.event_childID == 0):
             clsList.insert(0, SuperGridClient2010)
     if (windowClassName == "AfxWndW"
             and controlID == 109) or (windowClassName
                                       in ("WeekViewWnd", "DayViewWnd")):
         clsList.insert(0, CalendarView)
Beispiel #18
0
    def event_NVDAObject_init(self, obj):
        windowClass = obj.windowClassName
        role = obj.role

        if windowClass == "ToolbarWindow32" and role == controlTypes.Role.POPUPMENU:
            parent = obj.parent
            if parent and parent.windowClassName == "SysPager" and not (
                    obj.windowStyle & 0x80):
                # This is the menu for a group of icons on the task bar, which Windows stupidly names "Application".
                obj.name = None
            return

        if windowClass == "#32768":
            # Standard menu.
            parent = obj.parent
            if parent and not parent.parent:
                # Context menu.
                # We don't trust the names that Explorer gives to context menus, so better to have no name at all.
                obj.name = None
            return

        if windowClass == "DV2ControlHost" and role == controlTypes.Role.PANE:
            # Windows 7 start menu.
            obj.presentationType = obj.presType_content
            obj.isPresentableFocusAncestor = True
            # In Windows 7, the description of this pane is extremely verbose help text, so nuke it.
            obj.description = None
            return

        # The Address bar is embedded inside a progressbar, how strange.
        # Lets hide that
        if windowClass == "msctls_progress32" and winUser.getClassName(
                winUser.getAncestor(obj.windowHandle,
                                    winUser.GA_PARENT)) == "Address Band Root":
            obj.presentationType = obj.presType_layout
            return

        if windowClass == "DirectUIHWND" and role == controlTypes.Role.LIST:
            # Is this a list containing search results in Windows 7 start menu?
            isWin7SearchResultsList = False
            try:
                if obj.parent and obj.parent.parent:
                    parent = obj.parent.parent.parent
                    isWin7SearchResultsList = parent is not None and parent.windowClassName == "Desktop Search Open View"
            except AttributeError:
                isWin7SearchResultsList = False
            if isWin7SearchResultsList:
                # Namae of this list is not useful and should be  discarded.
                obj.name = None
                return
Beispiel #19
0
	def event_NVDAObject_init(self, obj):
		if not isinstance(obj, Window):
			return
		role = obj.role
		if role == controlTypes.ROLE_WINDOW:
			return
		wclass = Window.normalizeWindowClassName(obj.windowClassName)

		if wclass == "Window.8" and role == controlTypes.ROLE_PANE:
			# optimisation: There are quite a lot of these, so let's not instantiate parent NVDAObjects unnecessarily.
			parentWindow = winUser.getAncestor(obj.windowHandle, winUser.GA_PARENT)
			if parentWindow and Window.normalizeWindowClassName(winUser.getClassName(parentWindow)) == "SysTabControl32":
				obj.role = controlTypes.ROLE_PROPERTYPAGE

		elif wclass == "SysTabControl32":
			obj.isPresentableFocusAncestor = False
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)
Beispiel #21
0
    def event_NVDAObject_init(self, obj):
        if not isinstance(obj, Window):
            return
        role = obj.role
        if role == controlTypes.ROLE_WINDOW:
            return
        wclass = Window.normalizeWindowClassName(obj.windowClassName)

        if wclass == "Window.8" and role == controlTypes.ROLE_PANE:
            # optimisation: There are quite a lot of these, so let's not instantiate parent NVDAObjects unnecessarily.
            parentWindow = winUser.getAncestor(obj.windowHandle,
                                               winUser.GA_PARENT)
            if parentWindow and Window.normalizeWindowClassName(
                    winUser.getClassName(parentWindow)) == "SysTabControl32":
                obj.role = controlTypes.ROLE_PROPERTYPAGE

        elif wclass == "SysTabControl32":
            obj.isPresentableFocusAncestor = False
Beispiel #22
0
	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
Beispiel #23
0
	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
Beispiel #24
0
	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
		if UIAWordDocument in clsList:
			# Overlay class for Outlook message viewer when UI Automation for MS Word is enabled.
			clsList.insert(0,OutlookUIAWordDocument)
		if isinstance(obj,UIA) and obj.UIAElement.cachedClassName in ("LeafRow","ThreadItem","ThreadHeader"):
			clsList.insert(0,UIAGridRow)
		role=obj.role
		windowClassName=obj.windowClassName
		# AutoComplete listItems.
		# This class is abstract enough to  support both UIA and MSAA
		if role==controlTypes.ROLE_LISTITEM and (windowClassName.startswith("REListBox") or windowClassName.startswith("NetUIHWND")):
			clsList.insert(0,AutoCompleteListItem)
		#  all   remaining classes are IAccessible
		if not isinstance(obj,IAccessible):
			return
		# Outlook uses dialogs for many forms such as appointment / meeting creation. In these cases, there is no sane dialog caption that can be calculated as the dialog inly contains controls.
		# Therefore remove the Dialog behavior for these imbedded dialog forms so as to not announce junk as the caption
		if Dialog in clsList:
			parentWindow=winUser.getAncestor(obj.windowHandle,winUser.GA_PARENT)
			if parentWindow and winUser.getClassName(parentWindow)=="AfxWndW":
				clsList.remove(Dialog)
		if WordDocument in clsList:
			clsList.insert(0,OutlookWordDocument)
		states=obj.states
		controlID=obj.windowControlID
		# Support the date picker in Outlook Meeting / Appointment creation forms 
		if controlID==4352 and role==controlTypes.ROLE_BUTTON:
			clsList.insert(0,DatePickerButton)
		elif role==controlTypes.ROLE_TABLECELL and windowClassName=="rctrl_renwnd32":
			clsList.insert(0,DatePickerCell)
		elif windowClassName=="REListBox20W" and role==controlTypes.ROLE_CHECKBOX:
			clsList.insert(0,REListBox20W_CheckBox)
		if role==controlTypes.ROLE_LISTITEM and windowClassName=="OUTEXVLB":
			clsList.insert(0, AddressBookEntry)
			return
		if (windowClassName=="SUPERGRID" and controlID==4704) or (windowClassName=="rctrl_renwnd32" and controlID==109):
			outlookVersion=self.outlookVersion
			if outlookVersion and outlookVersion<=9:
				clsList.insert(0, MessageList_pre2003)
			elif obj.event_objectID==winUser.OBJID_CLIENT and obj.event_childID==0:
				clsList.insert(0,SuperGridClient2010)
		if (windowClassName == "AfxWndW" and controlID==109) or (windowClassName in ("WeekViewWnd","DayViewWnd")):
			clsList.insert(0,CalendarView)
	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
	# Note: chooseNVDAObjectOverlayClasses needs to be explicitely called in the mother class; else, NVDA will skip it.
		for cls in clsList:
			if issubclass(cls, editableText.EditableText):
				isEditable = True
				break
		else:
			isEditable = False
		if isEditable:
			isLogViewer = False
			hParent = winUser.getAncestor(obj.windowHandle, winUser.GA_PARENT)
			if hParent:
				text = winUser.getWindowText(hParent)
				isLogViewer = text == nvdaTranslations("NVDA Log Viewer")
			if isLogViewer:
				clsList.insert(0, LogViewerLogContainer)
			else:
				clsList.insert(0, EditableTextLogContainer)
		if obj.role == controlTypes.Role.DOCUMENT:
			clsList.insert(0, DocumentWithLog)
Beispiel #26
0
	def _isUIAWindowHelper(self,hwnd):
		# UIA in NVDA's process freezes in Windows 7 and below
		processID=winUser.getWindowThreadProcessID(hwnd)[0]
		if windll.kernel32.GetCurrentProcessId()==processID:
			return False
		import NVDAObjects.window
		windowClass=NVDAObjects.window.Window.normalizeWindowClassName(winUser.getClassName(hwnd))
		# There are certain window classes that just had bad UIA implementations
		if windowClass in badUIAWindowClassNames:
			return False
		if windowClass=="NetUIHWND":
			parentHwnd=winUser.getAncestor(hwnd,winUser.GA_ROOT)
			# #2816: Outlook 2010 auto complete does not fire enough UIA events, IAccessible is better.
			if winUser.getClassName(parentHwnd)=="Net UI Tool Window":
				return False
		# allow the appModule for the window to also choose if this window is bad
		appModule=appModuleHandler.getAppModuleFromProcessID(processID)
		if appModule and appModule.isBadUIAWindow(hwnd):
			return False
		# Ask the window if it supports UIA natively
		return windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
Beispiel #27
0
def getScreenPosition(obj):
	"""
	Fetches a TextInfo instance suitable for reviewing the screen, positioned at the given object's coordinates. 
	@param obj: the NVDAObject to review
	@type obj: L{NVDAObject}
	@return: the TextInfo instance and the Scriptable object the TextInfo instance is referencing, or None on error. 
	@rtype: (L{TextInfo},L{ScriptableObject})
	"""
	focus=api.getFocusObject()
	while focus and not isinstance(focus,Window):
		focus=focus.parent
	if not focus: return None
	w=winUser.getAncestor(focus.windowHandle,winUser.GA_ROOT) or focus.windowHandle
	s=Window(windowHandle=w)
	if s:
		s.redraw()
		try:
			pos=DisplayModelTextInfo(s,obj)
		except LookupError:
			pos=DisplayModelTextInfo(s,textInfos.POSITION_FIRST)
		return pos,pos.obj
Beispiel #28
0
def getScreenPosition(obj):
    """
	Fetches a TextInfo instance suitable for reviewing the screen, positioned at the given object's coordinates. 
	@param obj: the NVDAObject to review
	@type obj: L{NVDAObject}
	@return: the TextInfo instance and the Scriptable object the TextInfo instance is referencing, or None on error. 
	@rtype: (L{TextInfo},L{ScriptableObject})
	"""
    focus = api.getFocusObject()
    while focus and not isinstance(focus, Window):
        focus = focus.parent
    if not focus: return None
    w = winUser.getAncestor(focus.windowHandle,
                            winUser.GA_ROOT) or focus.windowHandle
    s = Window(windowHandle=w)
    if s:
        s.redraw()
        try:
            pos = DisplayModelTextInfo(s, obj)
        except LookupError:
            pos = DisplayModelTextInfo(s, textInfos.POSITION_FIRST)
        return pos, pos.obj
def getParent(hWnd):
	hWndParent = winUser.getAncestor(hWnd, winUser.GA_PARENT)
	# check if parent is not desktop window (desktop has no parent)
	if winUser.getAncestor(hWndParent, winUser.GA_PARENT):
		return hWndParent
	return 0
Beispiel #30
0
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
Beispiel #31
0
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
Beispiel #32
0
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
Beispiel #33
0
 def _isUIAWindowHelper(self, hwnd):
     # UIA in NVDA's process freezes in Windows 7 and below
     processID = winUser.getWindowThreadProcessID(hwnd)[0]
     if windll.kernel32.GetCurrentProcessId() == processID:
         return False
     import NVDAObjects.window
     windowClass = NVDAObjects.window.Window.normalizeWindowClassName(
         winUser.getClassName(hwnd))
     # For certain window classes, we always want to use UIA.
     if windowClass in goodUIAWindowClassNames:
         return True
     # allow the appModule for the window to also choose if this window is good
     # An appModule should be able to override bad UIA class names as prescribed by core
     appModule = appModuleHandler.getAppModuleFromProcessID(processID)
     if appModule and appModule.isGoodUIAWindow(hwnd):
         return True
     # There are certain window classes that just had bad UIA implementations
     if self._isBadUIAWindowClassName(windowClass):
         return False
     # allow the appModule for the window to also choose if this window is bad
     if appModule and appModule.isBadUIAWindow(hwnd):
         return False
     if windowClass == "NetUIHWND" and appModule:
         # NetUIHWND is used for various controls in MS Office.
         # IAccessible should be used for NetUIHWND in versions older than 2016
         # Fixes: lack of focus reporting (#4207),
         # Fixes: strange reporting of context menu items(#9252),
         # fixes: not being able to report ribbon sections when they starts with an edit  field (#7067)
         # Note that #7067 is not fixed for Office 2016 and never.
         # Using IAccessible for NetUIHWND controls causes focus changes not to be reported
         # when the ribbon is collapsed.
         # Testing shows that these controls emits proper events but they are ignored by NVDA.
         isOfficeApp = appModule.productName.startswith(
             ("Microsoft Office", "Microsoft Outlook"))
         isOffice2013OrOlder = int(
             appModule.productVersion.split(".")[0]) < 16
         if isOfficeApp and isOffice2013OrOlder:
             parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT)
             while parentHwnd:
                 if winUser.getClassName(parentHwnd) in (
                         "Net UI Tool Window",
                         "MsoCommandBar",
                 ):
                     return False
                 parentHwnd = winUser.getAncestor(parentHwnd,
                                                  winUser.GA_PARENT)
     # Ask the window if it supports UIA natively
     res = windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
     if res:
         # the window does support UIA natively, but
         # MS Word documents now have a fairly usable UI Automation implementation. However,
         # Builds of MS Office 2016 before build 9000 or so had bugs which we cannot work around.
         # And even current builds of Office 2016 are still missing enough info from UIA that it is still impossible to switch to UIA completely.
         # Therefore, if we can inject in-process, refuse to use UIA and instead fall back to the MS Word object model.
         canUseOlderInProcessApproach = bool(
             appModule.helperLocalBindingHandle)
         if (
                 # An MS Word document window
                 windowClass == "_WwG"
                 # Disabling is only useful if we can inject in-process (and use our older code)
                 and canUseOlderInProcessApproach
                 # Allow the user to explisitly force UIA support for MS Word documents no matter the Office version
                 and not config.conf['UIA']['useInMSWordWhenAvailable']):
             return False
         # Unless explicitly allowed, all Chromium implementations (including Edge) should not be UIA,
         # As their IA2 implementation is still better at the moment.
         elif (
                 windowClass == "Chrome_RenderWidgetHostHWND" and
             (AllowUiaInChromium.getConfig() == AllowUiaInChromium.NO
              # Disabling is only useful if we can inject in-process (and use our older code)
              or (canUseOlderInProcessApproach
                  and AllowUiaInChromium.getConfig() !=
                  AllowUiaInChromium.YES  # Users can prefer to use UIA
                  ))):
             return False
     return bool(res)