Exemplo n.º 1
0
    def _normalizeControlField(self, attrs):
        stdName = attrs.get("acrobat::stdname", "")
        try:
            role, level = normalizeStdName(stdName)
        except LookupError:
            role, level = None, None

        if not role:
            role = IAccessibleHandler.NVDARoleFromAttr(
                attrs['IAccessible::role'])
        states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs)
        role, states = controlTypes.transformRoleStates(role, states)

        if (role == controlTypes.Role.EDITABLETEXT and states.issuperset({
                controlTypes.State.READONLY, controlTypes.State.FOCUSABLE,
                controlTypes.State.LINKED
        })):
            # HACK: Acrobat sets focus states on text nodes beneath links,
            # making them appear as read only editable text fields.
            states.difference_update(
                {controlTypes.State.FOCUSABLE, controlTypes.State.FOCUSED})

        attrs['role'] = role
        attrs['states'] = states
        if level:
            attrs["level"] = level
        return super(AdobeAcrobat_TextInfo, self)._normalizeControlField(attrs)
Exemplo n.º 2
0
 def event_gainFocus(self):
     # When the list gains focus, it doesn't fire a focus event for the focused item.
     child = self.activeChild
     if child:
         self.event_focusEntered()
         # Redirect the focus to the active child.
         # We do this at the IAccessibleHandler level so that duplicate focus event checks will work properly.
         IAccessibleHandler.processFocusNVDAEvent(child)
     else:
         super(KeywordList, self).event_gainFocus()
Exemplo n.º 3
0
		def Notify(self):
			try:
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.alive()
Exemplo n.º 4
0
		def Notify(self):
			try:
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.alive()
Exemplo n.º 5
0
 def _get_parent(self):
     res = IAccessibleHandler.accParent(self.IAccessibleObject,
                                        self.IAccessibleChildID)
     if not res:
         # accParent is broken in Firefox for same-process iframe documents.
         # Use NODE_CHILD_OF instead.
         res = IAccessibleHandler.accNavigate(
             self.IAccessibleObject, self.IAccessibleChildID,
             IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
     if not res:
         return None
     return IAccessible(IAccessibleObject=res[0], IAccessibleChildID=res[1])
Exemplo n.º 6
0
def processPendingEvents(processEventQueue=True):
    # Import late to avoid circular import.
    import IAccessibleHandler
    import JABHandler
    import wx
    import queueHandler
    watchdog.alive()
    wx.Yield()
    JABHandler.pumpAll()
    IAccessibleHandler.pumpAll()
    import baseObject
    baseObject.AutoPropertyObject.invalidateCaches()
    if processEventQueue:
        queueHandler.flushQueue(queueHandler.eventQueue)
Exemplo n.º 7
0
Arquivo: api.py Projeto: lpintes/NVDA
def processPendingEvents(processEventQueue=True):
	# Import late to avoid circular import.
	import IAccessibleHandler
	import JABHandler
	import wx
	import queueHandler
	watchdog.alive()
	wx.Yield()
	JABHandler.pumpAll()
	IAccessibleHandler.pumpAll()
	import baseObject
	baseObject.AutoPropertyObject.invalidateCaches()
	if processEventQueue:
		queueHandler.flushQueue(queueHandler.eventQueue)
Exemplo n.º 8
0
def locateHTMLElementByID(document,ID):
	try:
		element=document.getElementsByName(ID).item(0)
	except COMError as e:
		log.debugWarning("document.getElementsByName failed with COMError %s"%e)
		element=None
	if element:
		return element
	try:
		nodeName=document.body.nodeName
	except COMError as e:
		log.debugWarning("document.body.nodeName failed with COMError %s"%e)
		return None
	if nodeName=="FRAMESET":
		tag="frame"
	else:
		tag="iframe"
	try:
		frames=document.getElementsByTagName(tag)
	except COMError as e:
		log.debugWarning("document.getElementsByTagName failed with COMError %s"%e)
		return None
	for frame in frames:
		pacc=IAccessibleFromHTMLNode(frame)
		res=IAccessibleHandler.accChild(pacc,1)
		if not res: continue
		childElement=HTMLNodeFromIAccessible(res[0])
		if not childElement: continue
		childElement=locateHTMLElementByID(childElement.document,ID)
		if not childElement: continue
		return childElement
Exemplo n.º 9
0
 def _get_parent(self):
     parent = super(GeckoPluginWindowRoot, self).parent
     if parent.IAccessibleRole == oleacc.ROLE_SYSTEM_CLIENT:
         # Skip the window wrapping the plugin window,
         # which doesn't expose a Gecko accessible in Gecko >= 11.
         parent = parent.parent.parent
     ver = getGeckoVersion(parent)
     if ver and ver.major != 1:
         res = IAccessibleHandler.accNavigate(
             parent.IAccessibleObject, 0,
             IAccessibleHandler.NAVRELATION_EMBEDS)
         if res:
             obj = IAccessible(IAccessibleObject=res[0],
                               IAccessibleChildID=res[1])
             if obj:
                 if controlTypes.STATE_OFFSCREEN not in obj.states:
                     return obj
                 else:
                     log.debugWarning(
                         "NAVRELATION_EMBEDS returned an offscreen document, name %r"
                         % obj.name)
             else:
                 log.debugWarning(
                     "NAVRELATION_EMBEDS returned an invalid object")
         else:
             log.debugWarning("NAVRELATION_EMBEDS failed")
     return parent
Exemplo n.º 10
0
	def _get_firstChild(self):
		# accNavigate incorrectly returns nothing for NAVDIR_FIRSTCHILD and requesting one child with AccessibleChildren causes a crash.
		# Therefore, we must use accChild(1).
		child = IAccessibleHandler.accChild(self.IAccessibleObject, 1)
		if not child:
			return None
		return IAccessible(IAccessibleObject=child[0], IAccessibleChildID=child[1])
Exemplo n.º 11
0
 def _get_firstChild(self):
     # accNavigate incorrectly returns nothing for NAVDIR_FIRSTCHILD and requesting one child with AccessibleChildren causes a crash.
     # Therefore, we must use accChild(1).
     child = IAccessibleHandler.accChild(self.IAccessibleObject, 1)
     if not child:
         return None
     return IAccessible(IAccessibleObject=child[0], IAccessibleChildID=child[1])
Exemplo n.º 12
0
	def _get_parent(self):
		#Special code to support Mozilla node_child_of relation (for comboboxes)
		res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
		if res and res!=(self.IAccessibleObject,self.IAccessibleChildID):
			newObj=IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1])
			if newObj:
				return newObj
		return super(Mozilla,self).parent
Exemplo n.º 13
0
	def _normalizeControlField(self,attrs):
		role=controlTypes.Role.STATICTEXT
		states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs)
		if controlTypes.State.LINKED in states:
			role=controlTypes.Role.LINK
		attrs['role']=role
		attrs['states']=states
		return super(LotusNotesRichText_TextInfo, self)._normalizeControlField(attrs)
Exemplo n.º 14
0
 def _get_parent(self):
     # Overridden so that accNavigate next/prev won't be called, as it causes the focus to move to another list item, even when called on the list.
     res = IAccessibleHandler.accParent(self.IAccessibleObject,
                                        self.IAccessibleChildID)
     if res:
         return self.correctAPIForRelation(IAccessible(
             IAccessibleObject=res[0], IAccessibleChildID=res[1]),
                                           relation="parent")
Exemplo n.º 15
0
 def getNVDAObjectFromIdentifier(self, docHandle, ID):
     try:
         pacc = self.rootNVDAObject.IAccessibleObject.accChild(ID)
     except COMError:
         return None
     return NVDAObjects.IAccessible.IAccessible(
         windowHandle=docHandle,
         IAccessibleObject=IAccessibleHandler.normalizeIAccessible(pacc),
         IAccessibleChildID=0)
Exemplo n.º 16
0
	def _get_parent(self):
		acc = IAccessibleHandler.accParent(self.IAccessibleObject, 0)
		if not acc:
			return super(IAccessible,self).parent
		# HACK: WindowFromAccessibleObject fails on some WebKit objects retrieved using accParent.
		# The window handle is the same for all nodes in a document anyway.
		# Note that WindowFromAccessibleObject seems to work for children and siblings,
		# so we don't need to do this for those.
		return IAccessible(IAccessibleObject=acc[0], IAccessibleChildID=0, windowHandle=self.windowHandle)
Exemplo n.º 17
0
def getChildHTMLNodeFromFrame(frame):
    try:
        pacc = IAccessibleFromHTMLNode(frame)
    except NotImplementedError:
        # #1569: It's not possible to get an IAccessible from frames marked with an ARIA role of presentation.
        # In this case, just skip this frame.
        return
    res = IAccessibleHandler.accChild(pacc, 1)
    if not res: return
    return HTMLNodeFromIAccessible(res[0])
Exemplo n.º 18
0
def getChildHTMLNodeFromFrame(frame):
	try:
		pacc=IAccessibleFromHTMLNode(frame)
	except NotImplementedError:
		# #1569: It's not possible to get an IAccessible from frames marked with an ARIA role of presentation.
		# In this case, just skip this frame.
		return
	res=IAccessibleHandler.accChild(pacc,1)
	if not res: return
	return HTMLNodeFromIAccessible(res[0])
Exemplo n.º 19
0
	def _get_parent(self):
		parent=super(GeckoPluginWindowRoot,self).parent
		ver=_getGeckoVersion(parent)
		if ver and not ver.startswith('1.'):
			res=IAccessibleHandler.accNavigate(parent.IAccessibleObject,0,IAccessibleHandler.NAVRELATION_EMBEDS)
			if res:
				obj=IAccessible(IAccessibleObject=res[0],IAccessibleChildID=res[1])
				if obj and controlTypes.STATE_OFFSCREEN not in obj.states:
					return obj
		return parent
Exemplo n.º 20
0
		def run(self):
			global _isPumpPending
			_isPumpPending = False
			watchdog.alive()
			try:
				if touchHandler.handler:
					touchHandler.handler.pump()
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.asleep()
			if _isPumpPending and not _pump.IsRunning():
				# #3803: Another pump was requested during this pump execution.
				# As our pump is not re-entrant, schedule another pump.
				_pump.Start(PUMP_MAX_DELAY, True)
Exemplo n.º 21
0
	def event_NVDAObject_init(self,obj):
		#The root document of HTML Metro Apps must be treeted as an application. 
		if isinstance(obj,Body) and obj.windowClassName=="Internet Explorer_Server":
			try:
				paccParent=obj.IAccessibleObject.accParent.accParent
				identity=IAccessibleHandler.getIAccIdentity(paccParent,0)
			except (COMError,AttributeError):
				identity=None
			if identity:
				windowHandle=identity.get('windowHandle')
				if windowHandle and winUser.getClassName(windowHandle)=="Web Platform Embedding":
					obj.role=controlTypes.ROLE_APPLICATION
Exemplo n.º 22
0
		def Notify(self):
			global _isPumpPending
			_isPumpPending = False
			watchdog.alive()
			try:
				if touchHandler.handler:
					touchHandler.handler.pump()
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.asleep()
			if _isPumpPending and not _pump.IsRunning():
				# #3803: A pump was requested, but the timer was ignored by a modal loop
				# because timers aren't re-entrant.
				# Therefore, schedule another pump.
				_pump.Start(PUMP_MAX_DELAY, True)
Exemplo n.º 23
0
 def Notify(self):
     global _isPumpPending
     _isPumpPending = False
     watchdog.alive()
     try:
         if touchHandler.handler:
             touchHandler.handler.pump()
         JABHandler.pumpAll()
         IAccessibleHandler.pumpAll()
         queueHandler.pumpAll()
         mouseHandler.pumpAll()
         braille.pumpAll()
     except:
         log.exception("errors in this core pump cycle")
     baseObject.AutoPropertyObject.invalidateCaches()
     watchdog.asleep()
     if _isPumpPending and not _pump.IsRunning():
         # #3803: A pump was requested, but the timer was ignored by a modal loop
         # because timers aren't re-entrant.
         # Therefore, schedule another pump.
         _pump.Start(PUMP_MAX_DELAY, True)
Exemplo n.º 24
0
def locateHTMLElementByID(document, ID):
    try:
        elements = document.getElementsByName(ID)
        if elements is not None:
            element = elements.item(0)
        else:  # probably IE 10 in standards mode (#3151)
            try:
                element = document.all.item(ID)
            except:
                element = None
    except COMError as e:
        log.debugWarning("document.getElementsByName failed with COMError %s" % e)
        element = None
    if element:
        return element
    try:
        nodeName = document.body.nodeName
    except COMError as e:
        log.debugWarning("document.body.nodeName failed with COMError %s" % e)
        return None
    if nodeName:
        nodeName = nodeName.upper()
    if nodeName == "FRAMESET":
        tag = "frame"
    else:
        tag = "iframe"
    try:
        frames = document.getElementsByTagName(tag)
    except COMError as e:
        log.debugWarning("document.getElementsByTagName failed with COMError %s" % e)
        return None
    if not frames:  # frames can be None in IE 10
        return None
    for frame in frames:
        try:
            pacc = IAccessibleFromHTMLNode(frame)
        except NotImplementedError:
            # #1569: It's not possible to get an IAccessible from frames marked with an ARIA role of presentation.
            # In this case, just skip this frame.
            continue
        res = IAccessibleHandler.accChild(pacc, 1)
        if not res:
            continue
        childElement = HTMLNodeFromIAccessible(res[0])
        if not childElement:
            continue
        childElement = locateHTMLElementByID(childElement.document, ID)
        if not childElement:
            continue
        return childElement
Exemplo n.º 25
0
	def _getPhysicalFocus(self):
		try:
			paccParent=self.IAccessibleObject.accParent
		except COMError:
			paccParent=None
		if not paccParent:
			return
		try:
			paccFocus=paccParent.accFocus
		except COMError:
			paccFocus=None
		if not paccFocus:
			return
		return IAccessible(IAccessibleObject=IAccessibleHandler.normalizeIAccessible(paccFocus),IAccessibleChildID=0)
Exemplo n.º 26
0
 def event_NVDAObject_init(self, obj):
     #The root document of HTML Metro Apps must be treeted as an application.
     if isinstance(
             obj,
             Body) and obj.windowClassName == "Internet Explorer_Server":
         try:
             paccParent = obj.IAccessibleObject.accParent.accParent
             identity = IAccessibleHandler.getIAccIdentity(paccParent, 0)
         except (COMError, AttributeError):
             identity = None
         if identity:
             windowHandle = identity.get('windowHandle')
             if windowHandle and winUser.getClassName(
                     windowHandle) == "Web Platform Embedding":
                 obj.role = controlTypes.ROLE_APPLICATION
Exemplo n.º 27
0
	def _get_parent(self):
		#Special code to support Mozilla node_child_of relation (for comboboxes)
		res=IAccessibleHandler.accNavigate(self.IAccessibleObject,self.IAccessibleChildID,IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
		if res and res!=(self.IAccessibleObject,self.IAccessibleChildID):
			#Gecko can sometimes give back a broken application node with a windowHandle of 0
			#The application node is annoying, even if it wasn't broken
			#So only use the node_child_of object if it has a valid IAccessible2 windowHandle
			try:
				windowHandle=res[0].windowHandle
			except (COMError,AttributeError):
				windowHandle=None
			if windowHandle:
				newObj=IAccessible(windowHandle=windowHandle,IAccessibleObject=res[0],IAccessibleChildID=res[1])
				if newObj:
					return newObj
		return super(Mozilla,self).parent
Exemplo n.º 28
0
 def event_NVDAObject_init(self, obj):
     handle = obj.windowHandle
     if handle in self.seenHandles:
         pass
     if obj.windowClassName == '#32770' and obj.role == controlTypes.ROLE_PANE:
         #obj.role=controlTypes.ROLE_DIALOG
         obj.isFocusable = False
     # avoid the ampersand in dialogs
     if obj.windowClassName == 'Button' and not obj.role in [
             controlTypes.ROLE_MENUBAR, controlTypes.ROLE_MENUITEM,
             controlTypes.ROLE_POPUPMENU
     ]:
         obj.name = api.winUser.getWindowText(obj.windowHandle).replace(
             '&', '')
     # define the toolbars as real toolbars
     # such that the name is spoken automatically on focus entered.
     if obj.role == controlTypes.ROLE_PANE and obj.name:
         if ('audacity' in obj.name.lower()
             ) and obj.firstChild.role != controlTypes.ROLE_STATUSBAR:
             obj.role = controlTypes.ROLE_TOOLBAR
             obj.name = obj.name.lstrip('Audacity ').rstrip('Toolbar')
         elif obj.name == 'Timeline':
             obj.role = controlTypes.ROLE_RULER
     # groupings for controls in e.g. preferences
     if obj  and obj.role in [5, 6, 8, 9, 13, 24, 36] \
      and not obj.windowHandle in self.seenHandles \
      and obj.container and not obj.container.role==controlTypes.ROLE_GROUPING:
         # Code snippet by David
         # work around for reading group boxes. In Audacity, any group box is a previous
         # sibling of a control, rather than a previous sibling of the parent of a control.
         # restrict the search two the roles listed above
         groupBox = IAccessibleHandler.findGroupboxObject(obj)
         if groupBox:
             obj.container = groupBox
         else:
             # don't check again
             self.seenHandles.add(obj.windowHandle)
     if obj.windowClassName == '#32768' and obj.role == controlTypes.ROLE_POPUPMENU:
         obj.name = 'DropDown'
     if obj.role == 11 and '\\' in obj.name:
         # rearrange the items in the recent files menu such
         # that the file name comes before the full qualified path.
         obj.name = '{2}, {0}{1}{2}'.format(*obj.name.rpartition('\\'))
     # append percent to slider positions
     if obj and obj.role == 24 and obj.name == None and obj.previous and obj.previous.role == 8:
         obj.description = ' %'
Exemplo n.º 29
0
 def _getPhysicalFocus(self):
     try:
         paccParent = self.IAccessibleObject.accParent
     except COMError:
         paccParent = None
     if not paccParent:
         return
     try:
         paccFocus = paccParent.accFocus
     except COMError:
         paccFocus = None
     if not paccFocus:
         return
     return IAccessible(
         IAccessibleObject=IAccessibleHandler.normalizeIAccessible(
             paccFocus),
         IAccessibleChildID=0)
Exemplo n.º 30
0
 def _get_parent(self):
     #Special code to support Mozilla node_child_of relation (for comboboxes)
     res = IAccessibleHandler.accNavigate(
         self.IAccessibleObject, self.IAccessibleChildID,
         IAccessibleHandler.NAVRELATION_NODE_CHILD_OF)
     if res and res != (self.IAccessibleObject, self.IAccessibleChildID):
         #Gecko can sometimes give back a broken application node with a windowHandle of 0
         #The application node is annoying, even if it wasn't broken
         #So only use the node_child_of object if it has a valid IAccessible2 windowHandle
         try:
             windowHandle = res[0].windowHandle
         except (COMError, AttributeError):
             windowHandle = None
         if windowHandle:
             newObj = IAccessible(windowHandle=windowHandle,
                                  IAccessibleObject=res[0],
                                  IAccessibleChildID=res[1])
             if newObj:
                 return newObj
     return super(Mozilla, self).parent
Exemplo n.º 31
0
 def _get_parent(self):
     parent = super(GeckoPluginWindowRoot, self).parent
     if parent.IAccessibleRole == oleacc.ROLE_SYSTEM_CLIENT:
         # Skip the window wrapping the plugin window,
         # which doesn't expose a Gecko accessible in Gecko >= 11.
         parent = parent.parent.parent
     ver = getGeckoVersion(parent)
     if ver and ver.major != 1:
         res = IAccessibleHandler.accNavigate(parent.IAccessibleObject, 0, IAccessibleHandler.NAVRELATION_EMBEDS)
         if res:
             obj = IAccessible(IAccessibleObject=res[0], IAccessibleChildID=res[1])
             if obj:
                 if controlTypes.STATE_OFFSCREEN not in obj.states:
                     return obj
                 else:
                     log.debugWarning("NAVRELATION_EMBEDS returned an offscreen document, name %r" % obj.name)
             else:
                 log.debugWarning("NAVRELATION_EMBEDS returned an invalid object")
         else:
             log.debugWarning("NAVRELATION_EMBEDS failed")
     return parent
Exemplo n.º 32
0
	def _normalizeControlField(self, attrs: textInfos.ControlField):
		accRole=attrs['IAccessible::role']
		role = level = None
		if accRole.isdigit():
			accRole = int(accRole)
		else:
			if "H1" <= accRole <= "H6":
				role = controlTypes.Role.HEADING
				level = int(accRole[1])
			else:
				accRole = accRole.lower()

		if not role:
			role = IAccessibleHandler.IAccessibleRolesToNVDARoles.get(accRole, controlTypes.Role.UNKNOWN)
		states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs)
		role, states = controlTypes.transformRoleStates(role, states)

		attrs["role"] = role
		attrs["states"] = states
		if level:
			attrs["level"] = level
		return super(WebKit_TextInfo, self)._normalizeControlField(attrs)
Exemplo n.º 33
0
 def appliesTo(cls, obj):
     return obj.childCount > 0 and not IAccessibleHandler.accNavigate(
         obj.IAccessibleObject, obj.IAccessibleChildID, oleacc.NAVDIR_FIRSTCHILD
     )
Exemplo n.º 34
0
def main():
	"""NVDA's core main loop.
This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and installs the core pump timer, which checks the queues and executes functions every 1 ms. Finally, it starts the wx main loop.
"""
	log.debug("Core starting")
	import config
	if not globalVars.appArgs.configPath:
		globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher)
	#Initialize the config path (make sure it exists)
	config.initConfigPath()
	log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath))
	log.debug("loading config")
	import config
	config.load()
	if not globalVars.appArgs.minimal:
		try:
			nvwave.playWaveFile("waves\\start.wav")
		except:
			pass
	logHandler.setLogLevelFromConfig()
	try:
		lang = config.conf["general"]["language"]
		import languageHandler
		log.debug("setting language to %s"%lang)
		languageHandler.setLanguage(lang)
	except:
		log.warning("Could not set language to %s"%lang)
	import versionInfo
	log.info("NVDA version %s" % versionInfo.version)
	log.info("Using Windows version %r" % (sys.getwindowsversion(),))
	log.info("Using Python version %s"%sys.version)
	log.info("Using comtypes version %s"%comtypes.__version__)
	# Set a reasonable timeout for any socket connections NVDA makes.
	import socket
	socket.setdefaulttimeout(10)
	log.debug("Initializing addons system.")
	addonHandler.initialize()
	import appModuleHandler
	log.debug("Initializing appModule Handler")
	appModuleHandler.initialize()
	import NVDAHelper
	log.debug("Initializing NVDAHelper")
	NVDAHelper.initialize()
	import speechDictHandler
	log.debug("Speech Dictionary processing")
	speechDictHandler.initialize()
	import speech
	log.debug("Initializing speech")
	speech.initialize()
	if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5:
		log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime))
		# Translators: This is spoken when NVDA is starting.
		speech.speakMessage(_("Loading NVDA. Please wait..."))
	import wx
	log.info("Using wx version %s"%wx.version())
	app = wx.App(redirect=False)
	# HACK: wx currently raises spurious assertion failures when a timer is stopped but there is already an event in the queue for that timer.
	# Unfortunately, these assertion exceptions are raised in the middle of other code, which causes problems.
	# Therefore, disable assertions for now.
	app.SetAssertMode(wx.PYAPP_ASSERT_SUPPRESS)
	# We do support QueryEndSession events, but we don't want to do anything for them.
	app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None)
	def onEndSession(evt):
		# NVDA will be terminated as soon as this function returns, so save configuration if appropriate.
		config.saveOnExit()
		speech.cancelSpeech()
		if not globalVars.appArgs.minimal:
			try:
				nvwave.playWaveFile("waves\\exit.wav",async=False)
			except:
				pass
		log.info("Windows session ending")
	app.Bind(wx.EVT_END_SESSION, onEndSession)
	import braille
	log.debug("Initializing braille")
	braille.initialize()
	log.debug("Initializing braille input")
	import brailleInput
	brailleInput.initialize()
	import displayModel
	log.debug("Initializing displayModel")
	displayModel.initialize()
	log.debug("Initializing GUI")
	import gui
	gui.initialize()
	# initialize wxpython localization support
	locale = wx.Locale()
	lang=languageHandler.getLanguage()
	if '_' in lang:
		wxLang=lang.split('_')[0]
	else:
		wxLang=lang
	if hasattr(sys,'frozen'):
		locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale"))
	try:
		locale.Init(lang,wxLang)
	except:
		pass
	import api
	import winUser
	import NVDAObjects.window
	desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow())
	api.setDesktopObject(desktopObject)
	api.setFocusObject(desktopObject)
	api.setNavigatorObject(desktopObject)
	api.setMouseObject(desktopObject)
	import JABHandler
	log.debug("initializing Java Access Bridge support")
	try:
		JABHandler.initialize()
	except NotImplementedError:
		log.warning("Java Access Bridge not available")
	except:
		log.error("Error initializing Java Access Bridge support", exc_info=True)
	import winConsoleHandler
	log.debug("Initializing winConsole support")
	winConsoleHandler.initialize()
	import UIAHandler
	log.debug("Initializing UIA support")
	try:
		UIAHandler.initialize()
	except NotImplementedError:
		log.warning("UIA not available")
	except:
		log.error("Error initializing UIA support", exc_info=True)
	import IAccessibleHandler
	log.debug("Initializing IAccessible support")
	IAccessibleHandler.initialize()
	log.debug("Initializing input core")
	import inputCore
	inputCore.initialize()
	import keyboardHandler
	log.debug("Initializing keyboard handler")
	keyboardHandler.initialize()
	import mouseHandler
	log.debug("initializing mouse handler")
	mouseHandler.initialize()
	import touchHandler
	log.debug("Initializing touchHandler")
	try:
		touchHandler.initialize()
	except NotImplementedError:
		pass
	import globalPluginHandler
	log.debug("Initializing global plugin handler")
	globalPluginHandler.initialize()
	if globalVars.appArgs.install:
		import wx
		import gui.installerGui
		wx.CallAfter(gui.installerGui.doSilentInstall)
	elif not globalVars.appArgs.minimal:
		try:
			# Translators: This is shown on a braille display (if one is connected) when NVDA starts.
			braille.handler.message(_("NVDA started"))
		except:
			log.error("", exc_info=True)
		if globalVars.appArgs.launcher:
			gui.LauncherDialog.run()
			# LauncherDialog will call doStartupDialogs() afterwards if required.
		else:
			wx.CallAfter(doStartupDialogs)
	import queueHandler
	# Queue the handling of initial focus,
	# as API handlers might need to be pumped to get the first focus event.
	queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus)
	import watchdog
	import baseObject
	class CorePump(wx.Timer):
		"Checks the queues and executes functions."
		def __init__(self,*args,**kwargs):
			log.debug("Core pump starting")
			super(CorePump,self).__init__(*args,**kwargs)
		def Notify(self):
			try:
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.alive()
	log.debug("starting core pump")
	pump = CorePump()
	pump.Start(1)
	log.debug("Initializing watchdog")
	watchdog.initialize()
	try:
		import updateCheck
	except RuntimeError:
		updateCheck=None
		log.debug("Update checking not supported")
	else:
		log.debug("initializing updateCheck")
		updateCheck.initialize()
	log.info("NVDA initialized")

	log.debug("entering wx application main loop")
	app.MainLoop()

	log.info("Exiting")
	if updateCheck:
		log.debug("Terminating updateCheck")
		updateCheck.terminate()
	log.debug("Terminating watchdog")
	watchdog.terminate()
	log.debug("Terminating global plugin handler")
	globalPluginHandler.terminate()
	log.debug("Terminating GUI")
	gui.terminate()
	config.saveOnExit()
	try:
		if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"):
			log.debug("calling lose focus on object with focus")
			globalVars.focusObject.event_loseFocus()
	except:
		log.error("Lose focus error",exc_info=True)
	try:
		speech.cancelSpeech()
	except:
		pass
	log.debug("Cleaning up running treeInterceptors")
	try:
		import treeInterceptorHandler
		treeInterceptorHandler.terminate()
	except:
		log.error("Error cleaning up treeInterceptors",exc_info=True)
	log.debug("Terminating IAccessible support")
	try:
		IAccessibleHandler.terminate()
	except:
		log.error("Error terminating IAccessible support",exc_info=True)
	log.debug("Terminating UIA support")
	try:
		UIAHandler.terminate()
	except:
		log.error("Error terminating UIA support",exc_info=True)
	log.debug("Terminating winConsole support")
	try:
		winConsoleHandler.terminate()
	except:
		log.error("Error terminating winConsole support",exc_info=True)
	log.debug("Terminating Java Access Bridge support")
	try:
		JABHandler.terminate()
	except:
		log.error("Error terminating Java Access Bridge support",exc_info=True)
	log.debug("Terminating app module handler")
	appModuleHandler.terminate()
	log.debug("Terminating NVDAHelper")
	try:
		NVDAHelper.terminate()
	except:
		log.error("Error terminating NVDAHelper",exc_info=True)
	log.debug("Terminating touchHandler")
	try:
		touchHandler.terminate()
	except:
		log.error("Error terminating touchHandler")
	log.debug("Terminating keyboard handler")
	try:
		keyboardHandler.terminate()
	except:
		log.error("Error terminating keyboard handler")
	log.debug("Terminating mouse handler")
	try:
		mouseHandler.terminate()
	except:
		log.error("error terminating mouse handler",exc_info=True)
	log.debug("Terminating input core")
	inputCore.terminate()
	log.debug("Terminating brailleInput")
	brailleInput.terminate()
	log.debug("Terminating braille")
	try:
		braille.terminate()
	except:
		log.error("Error terminating braille",exc_info=True)
	log.debug("Terminating speech")
	try:
		speech.terminate()
	except:
		log.error("Error terminating speech",exc_info=True)
	try:
		addonHandler.terminate()
	except:
		log.error("Error terminating addonHandler",exc_info=True)
	if not globalVars.appArgs.minimal:
		try:
			nvwave.playWaveFile("waves\\exit.wav",async=False)
		except:
			pass
	log.debug("core done")
Exemplo n.º 35
0
Arquivo: MSHTML.py Projeto: hss16/nvda
    def _normalizeControlField(self,
                               attrs: textInfos.ControlField):  # noqa: C901
        level = None

        isCurrent = self._getIsCurrentAttribute(attrs)
        if isCurrent != controlTypes.IsCurrent.NO:
            attrs['current'] = isCurrent

        placeholder = self._getPlaceholderAttribute(
            attrs, 'HTMLAttrib::aria-placeholder')
        if placeholder:
            attrs['placeholder'] = placeholder
        nodeName = attrs.get('IHTMLDOMNode::nodeName', "")
        roleAttrib = attrs.get("HTMLAttrib::role", "")
        ariaRoles = [ar for ar in roleAttrib.split(" ") if ar]
        #choose role
        #Priority is aria role -> HTML tag name -> IAccessible role
        role = next((aria.ariaRolesToNVDARoles[ar]
                     for ar in ariaRoles if ar in aria.ariaRolesToNVDARoles),
                    controlTypes.Role.UNKNOWN)
        if role == controlTypes.Role.UNKNOWN and nodeName:
            role = NVDAObjects.IAccessible.MSHTML.nodeNamesToNVDARoles.get(
                nodeName, controlTypes.Role.UNKNOWN)

        if role == controlTypes.Role.UNKNOWN:
            role = IAccessibleHandler.NVDARoleFromAttr(
                attrs.get('IAccessible::role'))

        roleText = attrs.get('HTMLAttrib::aria-roledescription')
        if roleText:
            attrs['roleText'] = roleText

        states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs)
        role, states = controlTypes.transformRoleStates(role, states)

        if attrs.get('HTMLAttrib::longdesc'):
            states.add(controlTypes.State.HASLONGDESC)
        #IE exposes destination anchors as links, this is wrong
        if nodeName == "A" and role == controlTypes.Role.LINK and controlTypes.State.LINKED not in states:
            role = controlTypes.Role.TEXTFRAME
        if 'IHTMLElement::isContentEditable' in attrs:
            states.add(controlTypes.State.EDITABLE)
        if 'HTMLAttrib::onclick' in attrs or 'HTMLAttrib::onmousedown' in attrs or 'HTMLAttrib::onmouseup' in attrs:
            states.add(controlTypes.State.CLICKABLE)
        if 'HTMLAttrib::required' in attrs or attrs.get(
                'HTMLAttrib::aria-required', 'false') == 'true':
            states.add(controlTypes.State.REQUIRED)
        description = None
        ariaDescribedBy = attrs.get('HTMLAttrib::aria-describedby')
        if ariaDescribedBy:
            ariaDescribedByIds = ariaDescribedBy.split()
            description = ""
            for ariaDescribedById in ariaDescribedByIds:
                descNode = None
                try:
                    descNode = self.obj.rootNVDAObject.HTMLNode.document.getElementById(
                        ariaDescribedById)
                except (COMError, NameError):
                    descNode = None
                if not descNode:
                    try:
                        descNode = NVDAObjects.IAccessible.MSHTML.locateHTMLElementByID(
                            self.obj.rootNVDAObject.HTMLNode.document,
                            ariaDescribedById)
                    except (COMError, NameError):
                        descNode = None
                if descNode:
                    try:
                        description = description + " " + self.obj.makeTextInfo(
                            NVDAObjects.IAccessible.MSHTML.MSHTML(
                                HTMLNode=descNode)).text
                    except:
                        pass
        ariaSort = attrs.get('HTMLAttrib::aria-sort')
        state = aria.ariaSortValuesToNVDAStates.get(ariaSort)
        if state is not None:
            states.add(state)
        ariaSelected = attrs.get('HTMLAttrib::aria-selected')
        if ariaSelected == "true":
            states.add(controlTypes.State.SELECTED)
        elif ariaSelected == "false":
            states.discard(controlTypes.State.SELECTED)
        ariaExpanded = attrs.get('HTMLAttrib::aria-expanded')
        if ariaExpanded == "true":
            states.add(controlTypes.State.EXPANDED)
        elif ariaExpanded == "false":
            states.add(controlTypes.State.COLLAPSED)
        if attrs.get('HTMLAttrib::aria-invalid', 'false') == 'true':
            states.add(controlTypes.State.INVALID_ENTRY)
        if attrs.get('HTMLAttrib::aria-multiline', 'false') == 'true':
            states.add(controlTypes.State.MULTILINE)
        if attrs.get('HTMLAttrib::aria-dropeffect', 'none') != 'none':
            states.add(controlTypes.State.DROPTARGET)
        ariaGrabbed = attrs.get('HTMLAttrib::aria-grabbed', None)
        if ariaGrabbed == 'false':
            states.add(controlTypes.State.DRAGGABLE)
        elif ariaGrabbed == 'true':
            states.add(controlTypes.State.DRAGGING)
        if nodeName == "TEXTAREA":
            states.add(controlTypes.State.MULTILINE)
        if "H1" <= nodeName <= "H6":
            level = nodeName[1:]
        if nodeName in ("UL", "OL", "DL"):
            states.add(controlTypes.State.READONLY)
        if role == controlTypes.Role.UNKNOWN:
            role = controlTypes.Role.TEXTFRAME
        if role == controlTypes.Role.GRAPHIC:
            # MSHTML puts the unavailable state on all graphics when the showing of graphics is disabled.
            # This is rather annoying and irrelevant to our users, so discard it.
            states.discard(controlTypes.State.UNAVAILABLE)
        lRole = aria.htmlNodeNameToAriaRoles.get(nodeName.lower())
        if lRole:
            ariaRoles.append(lRole)
        # If the first role is a landmark role, use it.
        landmark = ariaRoles[
            0] if ariaRoles and ariaRoles[0] in aria.landmarkRoles else None
        ariaLevel = attrs.get('HTMLAttrib::aria-level', None)
        ariaLevel = int(ariaLevel) if ariaLevel is not None else None
        if ariaLevel:
            level = ariaLevel
        if role:
            attrs['role'] = role
        attrs['states'] = states
        if level:
            attrs["level"] = level
        if landmark:
            attrs["landmark"] = landmark
        if description:
            attrs["description"] = description
        return super(MSHTMLTextInfo, self)._normalizeControlField(attrs)
Exemplo n.º 36
0
 def appliesTo(cls, obj):
     return obj.childCount > 0 and not IAccessibleHandler.accNavigate(
         obj.IAccessibleObject, obj.IAccessibleChildID,
         oleacc.NAVDIR_FIRSTCHILD)
Exemplo n.º 37
0
def main():
	"""NVDA's core main loop.
This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop.
"""
	log.debug("Core starting")

	try:
		# Windows >= Vista
		ctypes.windll.user32.SetProcessDPIAware()
	except AttributeError:
		pass

	import config
	if not globalVars.appArgs.configPath:
		globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher)
	#Initialize the config path (make sure it exists)
	config.initConfigPath()
	log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath))
	log.debug("loading config")
	import config
	config.initialize()
	if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
		try:
			nvwave.playWaveFile("waves\\start.wav")
		except:
			pass
	logHandler.setLogLevelFromConfig()
	try:
		lang = config.conf["general"]["language"]
		import languageHandler
		log.debug("setting language to %s"%lang)
		languageHandler.setLanguage(lang)
	except:
		log.warning("Could not set language to %s"%lang)
	import versionInfo
	log.info("NVDA version %s" % versionInfo.version)
	log.info("Using Windows version %s" % winVersion.winVersionText)
	log.info("Using Python version %s"%sys.version)
	log.info("Using comtypes version %s"%comtypes.__version__)
	# Set a reasonable timeout for any socket connections NVDA makes.
	import socket
	socket.setdefaulttimeout(10)
	log.debug("Initializing add-ons system")
	addonHandler.initialize()
	if globalVars.appArgs.disableAddons:
		log.info("Add-ons are disabled. Restart NVDA to enable them.")
	import appModuleHandler
	log.debug("Initializing appModule Handler")
	appModuleHandler.initialize()
	import NVDAHelper
	log.debug("Initializing NVDAHelper")
	NVDAHelper.initialize()
	import speechDictHandler
	log.debug("Speech Dictionary processing")
	speechDictHandler.initialize()
	import speech
	log.debug("Initializing speech")
	speech.initialize()
	if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5:
		log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime))
		# Translators: This is spoken when NVDA is starting.
		speech.speakMessage(_("Loading NVDA. Please wait..."))
	import wx
	log.info("Using wx version %s"%wx.version())
	class App(wx.App):
		def OnAssert(self,file,line,cond,msg):
			message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg)
			log.debugWarning(message,codepath="WX Widgets",stack_info=True)
	app = App(redirect=False)
	# We do support QueryEndSession events, but we don't want to do anything for them.
	app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None)
	def onEndSession(evt):
		# NVDA will be terminated as soon as this function returns, so save configuration if appropriate.
		config.saveOnExit()
		speech.cancelSpeech()
		if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
			try:
				nvwave.playWaveFile("waves\\exit.wav",async=False)
			except:
				pass
		log.info("Windows session ending")
	app.Bind(wx.EVT_END_SESSION, onEndSession)
	import braille
	log.debug("Initializing braille")
	braille.initialize()
	log.debug("Initializing braille input")
	import brailleInput
	brailleInput.initialize()
	import displayModel
	log.debug("Initializing displayModel")
	displayModel.initialize()
	log.debug("Initializing GUI")
	import gui
	gui.initialize()
	import audioDucking
	if audioDucking.isAudioDuckingSupported():
		# the GUI mainloop must be running for this to work so delay it
		wx.CallAfter(audioDucking.initialize)

	# #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR.
	# NVDA uses the main frame to check for and quit another instance of NVDA.
	# To remain compatible with older versions of NVDA, create our own wxWindowClassNR.
	# We don't need to do anything else because wx handles WM_QUIT for all windows.
	import windowUtils
	class MessageWindow(windowUtils.CustomWindow):
		className = u"wxWindowClassNR"
	messageWindow = MessageWindow(unicode(versionInfo.name))

	# initialize wxpython localization support
	locale = wx.Locale()
	lang=languageHandler.getLanguage()
	wxLang=locale.FindLanguageInfo(lang)
	if not wxLang and '_' in lang:
		wxLang=locale.FindLanguageInfo(lang.split('_')[0])
	if hasattr(sys,'frozen'):
		locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale"))
	if wxLang:
		try:
			locale.Init(wxLang.Language)
		except:
			log.error("Failed to initialize wx locale",exc_info=True)
	else:
		log.debugWarning("wx does not support language %s" % lang)

	import api
	import winUser
	import NVDAObjects.window
	desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow())
	api.setDesktopObject(desktopObject)
	api.setFocusObject(desktopObject)
	api.setNavigatorObject(desktopObject)
	api.setMouseObject(desktopObject)
	import JABHandler
	log.debug("initializing Java Access Bridge support")
	try:
		JABHandler.initialize()
	except NotImplementedError:
		log.warning("Java Access Bridge not available")
	except:
		log.error("Error initializing Java Access Bridge support", exc_info=True)
	import winConsoleHandler
	log.debug("Initializing winConsole support")
	winConsoleHandler.initialize()
	import UIAHandler
	log.debug("Initializing UIA support")
	try:
		UIAHandler.initialize()
	except NotImplementedError:
		log.warning("UIA not available")
	except:
		log.error("Error initializing UIA support", exc_info=True)
	import IAccessibleHandler
	log.debug("Initializing IAccessible support")
	IAccessibleHandler.initialize()
	log.debug("Initializing input core")
	import inputCore
	inputCore.initialize()
	import keyboardHandler
	log.debug("Initializing keyboard handler")
	keyboardHandler.initialize()
	import mouseHandler
	log.debug("initializing mouse handler")
	mouseHandler.initialize()
	import touchHandler
	log.debug("Initializing touchHandler")
	try:
		touchHandler.initialize()
	except NotImplementedError:
		pass
	import globalPluginHandler
	log.debug("Initializing global plugin handler")
	globalPluginHandler.initialize()
	if globalVars.appArgs.install or globalVars.appArgs.installSilent:
		import wx
		import gui.installerGui
		wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent)
	elif not globalVars.appArgs.minimal:
		try:
			# Translators: This is shown on a braille display (if one is connected) when NVDA starts.
			braille.handler.message(_("NVDA started"))
		except:
			log.error("", exc_info=True)
		if globalVars.appArgs.launcher:
			gui.LauncherDialog.run()
			# LauncherDialog will call doStartupDialogs() afterwards if required.
		else:
			wx.CallAfter(doStartupDialogs)
	import queueHandler
	# Queue the handling of initial focus,
	# as API handlers might need to be pumped to get the first focus event.
	queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus)
	import watchdog
	import baseObject

	# Doing this here is a bit ugly, but we don't want these modules imported
	# at module level, including wx.
	log.debug("Initializing core pump")
	class CorePump(wx.Timer):
		"Checks the queues and executes functions."
		def Notify(self):
			global _isPumpPending
			_isPumpPending = False
			watchdog.alive()
			try:
				if touchHandler.handler:
					touchHandler.handler.pump()
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.asleep()
			if _isPumpPending and not _pump.IsRunning():
				# #3803: A pump was requested, but the timer was ignored by a modal loop
				# because timers aren't re-entrant.
				# Therefore, schedule another pump.
				_pump.Start(PUMP_MAX_DELAY, True)
	global _pump
	_pump = CorePump()
	requestPump()

	log.debug("Initializing watchdog")
	watchdog.initialize()
	try:
		import updateCheck
	except RuntimeError:
		updateCheck=None
		log.debug("Update checking not supported")
	else:
		log.debug("initializing updateCheck")
		updateCheck.initialize()
	log.info("NVDA initialized")

	log.debug("entering wx application main loop")
	app.MainLoop()

	log.info("Exiting")
	if updateCheck:
		_terminate(updateCheck)

	_terminate(watchdog)
	_terminate(globalPluginHandler, name="global plugin handler")
	_terminate(gui)
	config.saveOnExit()

	try:
		if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"):
			log.debug("calling lose focus on object with focus")
			globalVars.focusObject.event_loseFocus()
	except:
		log.exception("Lose focus error")
	try:
		speech.cancelSpeech()
	except:
		pass

	import treeInterceptorHandler
	_terminate(treeInterceptorHandler)
	_terminate(IAccessibleHandler, name="IAccessible support")
	_terminate(UIAHandler, name="UIA support")
	_terminate(winConsoleHandler, name="winConsole support")
	_terminate(JABHandler, name="Java Access Bridge support")
	_terminate(appModuleHandler, name="app module handler")
	_terminate(NVDAHelper)
	_terminate(touchHandler)
	_terminate(keyboardHandler, name="keyboard handler")
	_terminate(mouseHandler)
	_terminate(inputCore)
	_terminate(brailleInput)
	_terminate(braille)
	_terminate(speech)
	_terminate(addonHandler)

	if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
		try:
			nvwave.playWaveFile("waves\\exit.wav",async=False)
		except:
			pass
	# #5189: Destroy the message window as late as possible
	# so new instances of NVDA can find this one even if it freezes during exit.
	messageWindow.destroy()
	log.debug("core done")
Exemplo n.º 38
0
	def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
		obj = self.obj
		try:
			startOffset,endOffset,attribsString=obj.IAccessibleTextObject.attributes(offset)
		except COMError:
			log.debugWarning("could not get attributes",exc_info=True)
			return textInfos.FormatField(),(self._startOffset,self._endOffset)
		formatField=textInfos.FormatField()
		if not attribsString and offset>0:
			try:
				attribsString=obj.IAccessibleTextObject.attributes(offset-1)[2]
			except COMError:
				pass
		if attribsString:
			formatField.update(IAccessibleHandler.splitIA2Attribs(attribsString))

		try:
			escapement = int(formatField["CharEscapement"])
			if escapement < 0:
				textPos = "sub"
			elif escapement > 0:
				textPos = "super"
			else:
				textPos = "baseline"
			formatField["text-position"] = textPos
		except KeyError:
			pass
		try:
			formatField["font-name"] = formatField["CharFontName"]
		except KeyError:
			pass
		try:
			formatField["font-size"] = "%spt" % formatField["CharHeight"]
		except KeyError:
			pass
		try:
			formatField["italic"] = formatField["CharPosture"] == "2"
		except KeyError:
			pass
		try:
			formatField["strikethrough"] = formatField["CharStrikeout"] == "1"
		except KeyError:
			pass
		try:
			underline = formatField["CharUnderline"]
			if underline == "10":
				# Symphony doesn't provide for semantic communication of spelling errors, so we have to rely on the WAVE underline type.
				formatField["invalid-spelling"] = True
			else:
				formatField["underline"] = underline != "0"
		except KeyError:
			pass
		try:
			formatField["bold"] = float(formatField["CharWeight"]) > 100
		except KeyError:
			pass
		try:
			color=formatField.pop('CharColor')
		except KeyError:
			color=None
		if color:
			formatField['color']=colors.RGB.fromString(color) 
		try:
			backgroundColor=formatField.pop('CharBackColor')
		except KeyError:
			backgroundColor=None
		if backgroundColor:
			formatField['background-color']=colors.RGB.fromString(backgroundColor)

		# optimisation: Assume a hyperlink occupies a full attribute run.
		try:
			if obj.IAccessibleTextObject.QueryInterface(IAccessibleHandler.IAccessibleHypertext).hyperlinkIndex(offset) != -1:
				formatField["link"] = True
		except COMError:
			pass

		if offset == 0:
			# Only include the list item prefix on the first line of the paragraph.
			numbering = formatField.get("Numbering")
			if numbering:
				formatField["line-prefix"] = numbering.get("NumberingPrefix") or numbering.get("BulletChar")

		if obj.hasFocus:
			# Symphony exposes some information for the caret position as attributes on the document object.
			# optimisation: Use the tree interceptor to get the document.
			try:
				docAttribs = obj.treeInterceptor.rootNVDAObject.IA2Attributes
			except AttributeError:
				# No tree interceptor, so we can't efficiently fetch this info.
				pass
			else:
				try:
					formatField["page-number"] = docAttribs["page-number"]
				except KeyError:
					pass
				try:
					formatField["line-number"] = docAttribs["line-number"]
				except KeyError:
					pass

		return formatField,(startOffset,endOffset)
Exemplo n.º 39
0
    def _normalizeControlField(self, attrs):  # noqa: C901
        for attr in ("table-rownumber-presentational",
                     "table-columnnumber-presentational",
                     "table-rowcount-presentational",
                     "table-columncount-presentational"):
            attrVal = attrs.get(attr)
            if attrVal is not None and attrVal.lstrip('-').isdigit():
                attrs[attr] = int(attrVal)
            else:
                attrs[attr] = None

        attrs["_description-from"] = self._calculateDescriptionFrom(attrs)
        attrs.update(_getNormalizedCurrentAttrs(attrs))

        placeholder = self._getPlaceholderAttribute(
            attrs, "IAccessible2::attribute_placeholder")
        if placeholder is not None:
            attrs['placeholder'] = placeholder

        role = IAccessibleHandler.NVDARoleFromAttr(attrs['IAccessible::role'])
        if attrs.get('IAccessible2::attribute_tag',
                     "").lower() == "blockquote":
            role = controlTypes.Role.BLOCKQUOTE

        states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs)
        states |= IAccessibleHandler.getStatesSetFromIAccessible2Attrs(attrs)
        role, states = controlTypes.transformRoleStates(role, states)

        if role == controlTypes.Role.EDITABLETEXT and not (
                controlTypes.State.FOCUSABLE in states
                or controlTypes.State.UNAVAILABLE in states
                or controlTypes.State.EDITABLE in states):
            # This is a text leaf.
            # See NVDAObjects.Iaccessible.mozilla.findOverlayClasses for an explanation of these checks.
            role = controlTypes.Role.STATICTEXT
        if attrs.get("IAccessibleAction_showlongdesc") is not None:
            states.add(controlTypes.State.HASLONGDESC)
        if "IAccessibleAction_click" in attrs:
            states.add(controlTypes.State.CLICKABLE)
        grabbed = attrs.get("IAccessible2::attribute_grabbed")
        if grabbed == "false":
            states.add(controlTypes.State.DRAGGABLE)
        elif grabbed == "true":
            states.add(controlTypes.State.DRAGGING)
        sorted = attrs.get("IAccessible2::attribute_sort")
        if sorted == "ascending":
            states.add(controlTypes.State.SORTED_ASCENDING)
        elif sorted == "descending":
            states.add(controlTypes.State.SORTED_DESCENDING)
        elif sorted == "other":
            states.add(controlTypes.State.SORTED)
        roleText = attrs.get("IAccessible2::attribute_roledescription")
        if roleText:
            attrs['roleText'] = roleText
        if attrs.get("IAccessible2::attribute_dropeffect", "none") != "none":
            states.add(controlTypes.State.DROPTARGET)
        if role == controlTypes.Role.LINK and controlTypes.State.LINKED not in states:
            # This is a named link destination, not a link which can be activated. The user doesn't care about these.
            role = controlTypes.Role.TEXTFRAME
        level = attrs.get('IAccessible2::attribute_level', "")
        xmlRoles = attrs.get("IAccessible2::attribute_xml-roles",
                             "").split(" ")
        landmark = next((xr for xr in xmlRoles if xr in aria.landmarkRoles),
                        None)
        if landmark and role != controlTypes.Role.LANDMARK and landmark != xmlRoles[
                0]:
            # Ignore the landmark role
            landmark = None
        if role == controlTypes.Role.DOCUMENT and xmlRoles[0] == "article":
            role = controlTypes.Role.ARTICLE
        elif role == controlTypes.Role.GROUPING and xmlRoles[0] == "figure":
            role = controlTypes.Role.FIGURE
        elif role in (controlTypes.Role.LANDMARK,
                      controlTypes.Role.SECTION) and xmlRoles[0] == "region":
            role = controlTypes.Role.REGION
        elif xmlRoles[0] == "switch":
            # role="switch" gets mapped to IA2_ROLE_TOGGLE_BUTTON, but it uses the
            # checked state instead of pressed. The simplest way to deal with this
            # identity crisis is to map it to a check box.
            role = controlTypes.Role.CHECKBOX
            states.discard(controlTypes.State.PRESSED)
        attrs['role'] = role
        attrs['states'] = states
        if level != "" and level is not None:
            attrs['level'] = level
        if landmark:
            attrs["landmark"] = landmark
        return super(Gecko_ia2_TextInfo, self)._normalizeControlField(attrs)
Exemplo n.º 40
0
def main():
    """NVDA's core main loop.
	This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI.
	Then it initialises the wx application object and sets up the core pump,
	which checks the queues and executes functions when requested.
	Finally, it starts the wx main loop.
	"""
    log.debug("Core starting")

    ctypes.windll.user32.SetProcessDPIAware()

    import config
    if not globalVars.appArgs.configPath:
        globalVars.appArgs.configPath = config.getUserDefaultConfigPath(
            useInstalledPathIfExists=globalVars.appArgs.launcher)
    #Initialize the config path (make sure it exists)
    config.initConfigPath()
    log.info(f"Config dir: {globalVars.appArgs.configPath}")
    log.debug("loading config")
    import config
    config.initialize()
    if config.conf['development']['enableScratchpadDir']:
        log.info("Developer Scratchpad mode enabled")
    if not globalVars.appArgs.minimal and config.conf["general"][
            "playStartAndExitSounds"]:
        try:
            nvwave.playWaveFile(
                os.path.join(globalVars.appDir, "waves", "start.wav"))
        except:
            pass
    logHandler.setLogLevelFromConfig()
    try:
        lang = config.conf["general"]["language"]
        import languageHandler
        log.debug("setting language to %s" % lang)
        languageHandler.setLanguage(lang)
    except:
        log.warning("Could not set language to %s" % lang)
    log.info(f"Windows version: {winVersion.getWinVer()}")
    log.info("Using Python version %s" % sys.version)
    log.info("Using comtypes version %s" % comtypes.__version__)
    import configobj
    log.info("Using configobj version %s with validate version %s" %
             (configobj.__version__, configobj.validate.__version__))
    # Set a reasonable timeout for any socket connections NVDA makes.
    import socket
    socket.setdefaulttimeout(10)
    log.debug("Initializing add-ons system")
    addonHandler.initialize()
    if globalVars.appArgs.disableAddons:
        log.info("Add-ons are disabled. Restart NVDA to enable them.")
    import appModuleHandler
    log.debug("Initializing appModule Handler")
    appModuleHandler.initialize()
    import NVDAHelper
    log.debug("Initializing NVDAHelper")
    NVDAHelper.initialize()
    log.debug("Initializing tones")
    import tones
    tones.initialize()
    import speechDictHandler
    log.debug("Speech Dictionary processing")
    speechDictHandler.initialize()
    import speech
    log.debug("Initializing speech")
    speech.initialize()
    if not globalVars.appArgs.minimal and (time.time() -
                                           globalVars.startTime) > 5:
        log.debugWarning("Slow starting core (%.2f sec)" %
                         (time.time() - globalVars.startTime))
        # Translators: This is spoken when NVDA is starting.
        speech.speakMessage(_("Loading NVDA. Please wait..."))
    import wx
    import six
    log.info("Using wx version %s with six version %s" %
             (wx.version(), six.__version__))

    class App(wx.App):
        def OnAssert(self, file, line, cond, msg):
            message = "{file}, line {line}:\nassert {cond}: {msg}".format(
                file=file, line=line, cond=cond, msg=msg)
            log.debugWarning(message, codepath="WX Widgets", stack_info=True)

        def InitLocale(self):
            # Backport of `InitLocale` from wx Python 4.1.2 as the current version tries to set a Python
            # locale to an nonexistent one when creating an instance of `wx.App`.
            # This causes a crash when running under a particular version of Universal CRT (#12160)
            import locale
            locale.setlocale(locale.LC_ALL, "C")

    app = App(redirect=False)

    # We support queryEndSession events, but in general don't do anything for them.
    # However, when running as a Windows Store application, we do want to request to be restarted for updates
    def onQueryEndSession(evt):
        if config.isAppX:
            # Automatically restart NVDA on Windows Store update
            ctypes.windll.kernel32.RegisterApplicationRestart(None, 0)

    app.Bind(wx.EVT_QUERY_END_SESSION, onQueryEndSession)

    def onEndSession(evt):
        # NVDA will be terminated as soon as this function returns, so save configuration if appropriate.
        config.saveOnExit()
        speech.cancelSpeech()
        if not globalVars.appArgs.minimal and config.conf["general"][
                "playStartAndExitSounds"]:
            try:
                nvwave.playWaveFile(os.path.join(globalVars.appDir, "waves",
                                                 "exit.wav"),
                                    asynchronous=False)
            except:
                pass
        log.info("Windows session ending")

    app.Bind(wx.EVT_END_SESSION, onEndSession)
    log.debug("Initializing braille input")
    import brailleInput
    brailleInput.initialize()
    import braille
    log.debug("Initializing braille")
    braille.initialize()
    import vision
    log.debug("Initializing vision")
    vision.initialize()
    import displayModel
    log.debug("Initializing displayModel")
    displayModel.initialize()
    log.debug("Initializing GUI")
    import gui
    gui.initialize()
    import audioDucking
    if audioDucking.isAudioDuckingSupported():
        # the GUI mainloop must be running for this to work so delay it
        wx.CallAfter(audioDucking.initialize)

    # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR.
    # NVDA uses the main frame to check for and quit another instance of NVDA.
    # To remain compatible with older versions of NVDA, create our own wxWindowClassNR.
    # We don't need to do anything else because wx handles WM_QUIT for all windows.
    import windowUtils

    class MessageWindow(windowUtils.CustomWindow):
        className = u"wxWindowClassNR"
        # Windows constants for power / display changes
        WM_POWERBROADCAST = 0x218
        PBT_APMPOWERSTATUSCHANGE = 0xA
        UNKNOWN_BATTERY_STATUS = 0xFF
        AC_ONLINE = 0X1
        NO_SYSTEM_BATTERY = 0X80
        #States for screen orientation
        ORIENTATION_NOT_INITIALIZED = 0
        ORIENTATION_PORTRAIT = 1
        ORIENTATION_LANDSCAPE = 2

        def __init__(self, windowName=None):
            super(MessageWindow, self).__init__(windowName)
            self.oldBatteryStatus = None
            self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED
            self.orientationCoordsCache = (0, 0)
            self.handlePowerStatusChange()

        def windowProc(self, hwnd, msg, wParam, lParam):
            post_windowMessageReceipt.notify(msg=msg,
                                             wParam=wParam,
                                             lParam=lParam)
            if msg == self.WM_POWERBROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE:
                self.handlePowerStatusChange()
            elif msg == winUser.WM_DISPLAYCHANGE:
                self.handleScreenOrientationChange(lParam)

        def handleScreenOrientationChange(self, lParam):
            import ui
            import winUser
            # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx.
            #The low word is the width and hiword is height.
            width = winUser.LOWORD(lParam)
            height = winUser.HIWORD(lParam)
            self.orientationCoordsCache = (width, height)
            if width > height:
                # If the height and width are the same, it's actually a screen flip, and we do want to alert of those!
                if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (
                        width, height):
                    return
                #Translators: The screen is oriented so that it is wider than it is tall.
                ui.message(_("Landscape"))
                self.orientationStateCache = self.ORIENTATION_LANDSCAPE
            else:
                if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (
                        width, height):
                    return
                #Translators: The screen is oriented in such a way that the height is taller than it is wide.
                ui.message(_("Portrait"))
                self.orientationStateCache = self.ORIENTATION_PORTRAIT

        def handlePowerStatusChange(self):
            #Mostly taken from script_say_battery_status, but modified.
            import ui
            import winKernel
            sps = winKernel.SYSTEM_POWER_STATUS()
            if not winKernel.GetSystemPowerStatus(
                    sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS:
                return
            if sps.BatteryFlag & self.NO_SYSTEM_BATTERY:
                return
            if self.oldBatteryStatus is None:
                #Just initializing the cache, do not report anything.
                self.oldBatteryStatus = sps.ACLineStatus
                return
            if sps.ACLineStatus == self.oldBatteryStatus:
                #Sometimes, this double fires. This also fires when the battery level decreases by 3%.
                return
            self.oldBatteryStatus = sps.ACLineStatus
            if sps.ACLineStatus & self.AC_ONLINE:
                #Translators: Reported when the battery is plugged in, and now is charging.
                ui.message(
                    _("Charging battery. %d percent") % sps.BatteryLifePercent)
            else:
                #Translators: Reported when the battery is no longer plugged in, and now is not charging.
                ui.message(
                    _("Not charging battery. %d percent") %
                    sps.BatteryLifePercent)

    import versionInfo
    messageWindow = MessageWindow(versionInfo.name)

    # initialize wxpython localization support
    locale = wx.Locale()
    wxLang = getWxLangOrNone()
    if hasattr(sys, 'frozen'):
        locale.AddCatalogLookupPathPrefix(
            os.path.join(globalVars.appDir, "locale"))
    if wxLang:
        try:
            locale.Init(wxLang.Language)
        except:
            log.error("Failed to initialize wx locale", exc_info=True)
        finally:
            # Revert wx's changes to the python locale
            languageHandler.setLocale(languageHandler.curLang)

    log.debug("Initializing garbageHandler")
    garbageHandler.initialize()

    import api
    import winUser
    import NVDAObjects.window
    desktopObject = NVDAObjects.window.Window(
        windowHandle=winUser.getDesktopWindow())
    api.setDesktopObject(desktopObject)
    api.setFocusObject(desktopObject)
    api.setNavigatorObject(desktopObject)
    api.setMouseObject(desktopObject)
    import JABHandler
    log.debug("initializing Java Access Bridge support")
    try:
        JABHandler.initialize()
        log.info("Java Access Bridge support initialized")
    except NotImplementedError:
        log.warning("Java Access Bridge not available")
    except:
        log.error("Error initializing Java Access Bridge support",
                  exc_info=True)
    import winConsoleHandler
    log.debug("Initializing legacy winConsole support")
    winConsoleHandler.initialize()
    import UIAHandler
    log.debug("Initializing UIA support")
    try:
        UIAHandler.initialize()
    except RuntimeError:
        log.warning("UIA disabled in configuration")
    except:
        log.error("Error initializing UIA support", exc_info=True)
    import IAccessibleHandler
    log.debug("Initializing IAccessible support")
    IAccessibleHandler.initialize()
    log.debug("Initializing input core")
    import inputCore
    inputCore.initialize()
    import keyboardHandler
    log.debug("Initializing keyboard handler")
    keyboardHandler.initialize()
    import mouseHandler
    log.debug("initializing mouse handler")
    mouseHandler.initialize()
    import touchHandler
    log.debug("Initializing touchHandler")
    try:
        touchHandler.initialize()
    except NotImplementedError:
        pass
    import globalPluginHandler
    log.debug("Initializing global plugin handler")
    globalPluginHandler.initialize()
    if globalVars.appArgs.install or globalVars.appArgs.installSilent:
        import gui.installerGui
        wx.CallAfter(gui.installerGui.doSilentInstall,
                     copyPortableConfig=globalVars.appArgs.copyPortableConfig,
                     startAfterInstall=not globalVars.appArgs.installSilent)
    elif globalVars.appArgs.portablePath and (
            globalVars.appArgs.createPortable
            or globalVars.appArgs.createPortableSilent):
        import gui.installerGui
        wx.CallAfter(
            gui.installerGui.doCreatePortable,
            portableDirectory=globalVars.appArgs.portablePath,
            silent=globalVars.appArgs.createPortableSilent,
            startAfterCreate=not globalVars.appArgs.createPortableSilent)
    elif not globalVars.appArgs.minimal:
        try:
            # Translators: This is shown on a braille display (if one is connected) when NVDA starts.
            braille.handler.message(_("NVDA started"))
        except:
            log.error("", exc_info=True)
        if globalVars.appArgs.launcher:
            from gui.startupDialogs import LauncherDialog
            LauncherDialog.run()
            # LauncherDialog will call doStartupDialogs() afterwards if required.
        else:
            wx.CallAfter(doStartupDialogs)
    import queueHandler
    # Queue the handling of initial focus,
    # as API handlers might need to be pumped to get the first focus event.
    queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus)
    import watchdog
    import baseObject

    # Doing this here is a bit ugly, but we don't want these modules imported
    # at module level, including wx.
    log.debug("Initializing core pump")

    class CorePump(gui.NonReEntrantTimer):
        "Checks the queues and executes functions."

        def run(self):
            global _isPumpPending
            _isPumpPending = False
            watchdog.alive()
            try:
                if touchHandler.handler:
                    touchHandler.handler.pump()
                JABHandler.pumpAll()
                IAccessibleHandler.pumpAll()
                queueHandler.pumpAll()
                mouseHandler.pumpAll()
                braille.pumpAll()
                vision.pumpAll()
            except:
                log.exception("errors in this core pump cycle")
            baseObject.AutoPropertyObject.invalidateCaches()
            watchdog.asleep()
            if _isPumpPending and not _pump.IsRunning():
                # #3803: Another pump was requested during this pump execution.
                # As our pump is not re-entrant, schedule another pump.
                _pump.Start(PUMP_MAX_DELAY, True)

    global _pump
    _pump = CorePump()
    requestPump()

    log.debug("Initializing watchdog")
    watchdog.initialize()
    try:
        import updateCheck
    except RuntimeError:
        updateCheck = None
        log.debug("Update checking not supported")
    else:
        log.debug("initializing updateCheck")
        updateCheck.initialize()
    log.info("NVDA initialized")

    # Queue the firing of the postNVDAStartup notification.
    # This is queued so that it will run from within the core loop,
    # and initial focus has been reported.
    def _doPostNvdaStartupAction():
        log.debug("Notify of postNvdaStartup action")
        postNvdaStartup.notify()

    queueHandler.queueFunction(queueHandler.eventQueue,
                               _doPostNvdaStartupAction)

    log.debug("entering wx application main loop")
    app.MainLoop()

    log.info("Exiting")
    # If MainLoop is terminated through WM_QUIT, such as starting an NVDA instance older than 2021.1,
    # triggerNVDAExit has not been called yet
    if triggerNVDAExit():
        log.debug("NVDA not already exiting, hit catch-all exit trigger."
                  " This likely indicates NVDA is exiting due to WM_QUIT.")
        queueHandler.pumpAll()
    _terminate(gui)
    config.saveOnExit()

    try:
        if globalVars.focusObject and hasattr(globalVars.focusObject,
                                              "event_loseFocus"):
            log.debug("calling lose focus on object with focus")
            globalVars.focusObject.event_loseFocus()
    except:
        log.exception("Lose focus error")
    try:
        speech.cancelSpeech()
    except:
        pass

    import treeInterceptorHandler
    _terminate(treeInterceptorHandler)
    _terminate(IAccessibleHandler, name="IAccessible support")
    _terminate(UIAHandler, name="UIA support")
    _terminate(winConsoleHandler, name="Legacy winConsole support")
    _terminate(JABHandler, name="Java Access Bridge support")
    _terminate(appModuleHandler, name="app module handler")
    _terminate(tones)
    _terminate(NVDAHelper)
    _terminate(touchHandler)
    _terminate(keyboardHandler, name="keyboard handler")
    _terminate(mouseHandler)
    _terminate(inputCore)
    _terminate(vision)
    _terminate(brailleInput)
    _terminate(braille)
    _terminate(speech)
    _terminate(addonHandler)
    _terminate(garbageHandler)
    # DMP is only started if needed.
    # Terminate manually (and let it write to the log if necessary)
    # as core._terminate always writes an entry.
    try:
        import diffHandler
        diffHandler._dmp._terminate()
    except Exception:
        log.exception("Exception while terminating DMP")

    if not globalVars.appArgs.minimal and config.conf["general"][
            "playStartAndExitSounds"]:
        try:
            nvwave.playWaveFile(os.path.join(globalVars.appDir, "waves",
                                             "exit.wav"),
                                asynchronous=False)
        except:
            pass
    # #5189: Destroy the message window as late as possible
    # so new instances of NVDA can find this one even if it freezes during exit.
    messageWindow.destroy()
    log.debug("core done")
Exemplo n.º 41
0
def main():
    """NVDA's core main loop.
This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop.
"""
    log.debug("Core starting")

    try:
        # Windows >= Vista
        ctypes.windll.user32.SetProcessDPIAware()
    except AttributeError:
        pass

    import config
    if not globalVars.appArgs.configPath:
        globalVars.appArgs.configPath = config.getUserDefaultConfigPath(
            useInstalledPathIfExists=globalVars.appArgs.launcher)
    #Initialize the config path (make sure it exists)
    config.initConfigPath()
    log.info("Config dir: %s" % os.path.abspath(globalVars.appArgs.configPath))
    log.debug("loading config")
    import config
    config.initialize()
    if not globalVars.appArgs.minimal and config.conf["general"][
            "playStartAndExitSounds"]:
        try:
            nvwave.playWaveFile("waves\\start.wav")
        except:
            pass
    logHandler.setLogLevelFromConfig()
    logHandler.setPlayErrorSoundFromConfig()
    try:
        lang = config.conf["general"]["language"]
        import languageHandler
        log.debug("setting language to %s" % lang)
        languageHandler.setLanguage(lang)
    except:
        log.warning("Could not set language to %s" % lang)
    import versionInfo
    log.info("NVDA version %s" % versionInfo.version)
    log.info("Using Windows version %s" % winVersion.winVersionText)
    log.info("Using Python version %s" % sys.version)
    log.info("Using comtypes version %s" % comtypes.__version__)
    # Set a reasonable timeout for any socket connections NVDA makes.
    import socket
    socket.setdefaulttimeout(10)
    log.debug("Initializing add-ons system")
    addonHandler.initialize()
    if globalVars.appArgs.disableAddons:
        log.info("Add-ons are disabled. Restart NVDA to enable them.")
    import appModuleHandler
    log.debug("Initializing appModule Handler")
    appModuleHandler.initialize()
    import NVDAHelper
    log.debug("Initializing NVDAHelper")
    NVDAHelper.initialize()
    import speechDictHandler
    log.debug("Speech Dictionary processing")
    speechDictHandler.initialize()
    import speech
    log.debug("Initializing speech")
    speech.initialize()
    if not globalVars.appArgs.minimal and (time.time() -
                                           globalVars.startTime) > 5:
        log.debugWarning("Slow starting core (%.2f sec)" %
                         (time.time() - globalVars.startTime))
        # Translators: This is spoken when NVDA is starting.
        speech.speakMessage(_("Loading NVDA. Please wait..."))
    import wx
    log.info("Using wx version %s" % wx.version())

    class App(wx.App):
        def OnAssert(self, file, line, cond, msg):
            message = "{file}, line {line}:\nassert {cond}: {msg}".format(
                file=file, line=line, cond=cond, msg=msg)
            log.debugWarning(message, codepath="WX Widgets", stack_info=True)

    app = App(redirect=False)
    # We do support QueryEndSession events, but we don't want to do anything for them.
    app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None)

    def onEndSession(evt):
        # NVDA will be terminated as soon as this function returns, so save configuration if appropriate.
        config.saveOnExit()
        speech.cancelSpeech()
        if not globalVars.appArgs.minimal and config.conf["general"][
                "playStartAndExitSounds"]:
            try:
                nvwave.playWaveFile("waves\\exit.wav", async=False)
            except:
                pass
        log.info("Windows session ending")

    app.Bind(wx.EVT_END_SESSION, onEndSession)
    import braille
    log.debug("Initializing braille")
    braille.initialize()
    log.debug("Initializing braille input")
    import brailleInput
    brailleInput.initialize()
    import displayModel
    log.debug("Initializing displayModel")
    displayModel.initialize()
    log.debug("Initializing GUI")
    import gui
    gui.initialize()
    import audioDucking
    if audioDucking.isAudioDuckingSupported():
        # the GUI mainloop must be running for this to work so delay it
        wx.CallAfter(audioDucking.initialize)

    # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR.
    # NVDA uses the main frame to check for and quit another instance of NVDA.
    # To remain compatible with older versions of NVDA, create our own wxWindowClassNR.
    # We don't need to do anything else because wx handles WM_QUIT for all windows.
    import windowUtils

    class MessageWindow(windowUtils.CustomWindow):
        className = u"wxWindowClassNR"

    messageWindow = MessageWindow(unicode(versionInfo.name))

    # initialize wxpython localization support
    locale = wx.Locale()
    lang = languageHandler.getLanguage()
    wxLang = locale.FindLanguageInfo(lang)
    if not wxLang and '_' in lang:
        wxLang = locale.FindLanguageInfo(lang.split('_')[0])
    if hasattr(sys, 'frozen'):
        locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(), "locale"))
    if wxLang:
        try:
            locale.Init(wxLang.Language)
        except:
            log.error("Failed to initialize wx locale", exc_info=True)
    else:
        log.debugWarning("wx does not support language %s" % lang)

    import api
    import winUser
    import NVDAObjects.window
    desktopObject = NVDAObjects.window.Window(
        windowHandle=winUser.getDesktopWindow())
    api.setDesktopObject(desktopObject)
    api.setFocusObject(desktopObject)
    api.setNavigatorObject(desktopObject)
    api.setMouseObject(desktopObject)
    import JABHandler
    log.debug("initializing Java Access Bridge support")
    try:
        JABHandler.initialize()
    except NotImplementedError:
        log.warning("Java Access Bridge not available")
    except:
        log.error("Error initializing Java Access Bridge support",
                  exc_info=True)
    import winConsoleHandler
    log.debug("Initializing winConsole support")
    winConsoleHandler.initialize()
    import UIAHandler
    log.debug("Initializing UIA support")
    try:
        UIAHandler.initialize()
    except NotImplementedError:
        log.warning("UIA not available")
    except:
        log.error("Error initializing UIA support", exc_info=True)
    import IAccessibleHandler
    log.debug("Initializing IAccessible support")
    IAccessibleHandler.initialize()
    log.debug("Initializing input core")
    import inputCore
    inputCore.initialize()
    import keyboardHandler
    log.debug("Initializing keyboard handler")
    keyboardHandler.initialize()
    import mouseHandler
    log.debug("initializing mouse handler")
    mouseHandler.initialize()
    import touchHandler
    log.debug("Initializing touchHandler")
    try:
        touchHandler.initialize()
    except NotImplementedError:
        pass
    import globalPluginHandler
    log.debug("Initializing global plugin handler")
    globalPluginHandler.initialize()
    if globalVars.appArgs.install or globalVars.appArgs.installSilent:
        import wx
        import gui.installerGui
        wx.CallAfter(gui.installerGui.doSilentInstall,
                     startAfterInstall=not globalVars.appArgs.installSilent)
    elif not globalVars.appArgs.minimal:
        try:
            # Translators: This is shown on a braille display (if one is connected) when NVDA starts.
            braille.handler.message(_("NVDA started"))
        except:
            log.error("", exc_info=True)
        if globalVars.appArgs.launcher:
            gui.LauncherDialog.run()
            # LauncherDialog will call doStartupDialogs() afterwards if required.
        else:
            wx.CallAfter(doStartupDialogs)
    import queueHandler
    # Queue the handling of initial focus,
    # as API handlers might need to be pumped to get the first focus event.
    queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus)
    import watchdog
    import baseObject

    # Doing this here is a bit ugly, but we don't want these modules imported
    # at module level, including wx.
    log.debug("Initializing core pump")

    class CorePump(wx.Timer):
        "Checks the queues and executes functions."

        def Notify(self):
            global _isPumpPending
            _isPumpPending = False
            watchdog.alive()
            try:
                if touchHandler.handler:
                    touchHandler.handler.pump()
                JABHandler.pumpAll()
                IAccessibleHandler.pumpAll()
                queueHandler.pumpAll()
                mouseHandler.pumpAll()
                braille.pumpAll()
            except:
                log.exception("errors in this core pump cycle")
            baseObject.AutoPropertyObject.invalidateCaches()
            watchdog.asleep()
            if _isPumpPending and not _pump.IsRunning():
                # #3803: A pump was requested, but the timer was ignored by a modal loop
                # because timers aren't re-entrant.
                # Therefore, schedule another pump.
                _pump.Start(PUMP_MAX_DELAY, True)

    global _pump
    _pump = CorePump()
    requestPump()

    log.debug("Initializing watchdog")
    watchdog.initialize()
    try:
        import updateCheck
    except RuntimeError:
        updateCheck = None
        log.debug("Update checking not supported")
    else:
        log.debug("initializing updateCheck")
        updateCheck.initialize()
    log.info("NVDA initialized")

    log.debug("entering wx application main loop")
    app.MainLoop()

    log.info("Exiting")
    if updateCheck:
        _terminate(updateCheck)

    _terminate(watchdog)
    _terminate(globalPluginHandler, name="global plugin handler")
    _terminate(gui)
    config.saveOnExit()

    try:
        if globalVars.focusObject and hasattr(globalVars.focusObject,
                                              "event_loseFocus"):
            log.debug("calling lose focus on object with focus")
            globalVars.focusObject.event_loseFocus()
    except:
        log.exception("Lose focus error")
    try:
        speech.cancelSpeech()
    except:
        pass

    import treeInterceptorHandler
    _terminate(treeInterceptorHandler)
    _terminate(IAccessibleHandler, name="IAccessible support")
    _terminate(UIAHandler, name="UIA support")
    _terminate(winConsoleHandler, name="winConsole support")
    _terminate(JABHandler, name="Java Access Bridge support")
    _terminate(appModuleHandler, name="app module handler")
    _terminate(NVDAHelper)
    _terminate(touchHandler)
    _terminate(keyboardHandler, name="keyboard handler")
    _terminate(mouseHandler)
    _terminate(inputCore)
    _terminate(brailleInput)
    _terminate(braille)
    _terminate(speech)
    _terminate(addonHandler)

    if not globalVars.appArgs.minimal and config.conf["general"][
            "playStartAndExitSounds"]:
        try:
            nvwave.playWaveFile("waves\\exit.wav", async=False)
        except:
            pass
    # #5189: Destroy the message window as late as possible
    # so new instances of NVDA can find this one even if it freezes during exit.
    messageWindow.destroy()
    log.debug("core done")
Exemplo n.º 42
0
	def getNVDAObjectFromIdentifier(self, docHandle, ID):
		try:
			pacc=self.rootNVDAObject.IAccessibleObject.accChild(ID)
		except COMError:
			return None
		return NVDAObjects.IAccessible.IAccessible(windowHandle=docHandle,IAccessibleObject=IAccessibleHandler.normalizeIAccessible(pacc),IAccessibleChildID=0)
Exemplo n.º 43
0
def main():
	"""NVDA's core main loop.
This initializes all modules such as audio, IAccessible, keyboard, mouse, and GUI. Then it initialises the wx application object and sets up the core pump, which checks the queues and executes functions when requested. Finally, it starts the wx main loop.
"""
	log.debug("Core starting")

	ctypes.windll.user32.SetProcessDPIAware()

	import config
	if not globalVars.appArgs.configPath:
		globalVars.appArgs.configPath=config.getUserDefaultConfigPath(useInstalledPathIfExists=globalVars.appArgs.launcher)
	#Initialize the config path (make sure it exists)
	config.initConfigPath()
	log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath))
	log.debug("loading config")
	import config
	config.initialize()
	if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
		try:
			nvwave.playWaveFile("waves\\start.wav")
		except:
			pass
	logHandler.setLogLevelFromConfig()
	try:
		lang = config.conf["general"]["language"]
		import languageHandler
		log.debug("setting language to %s"%lang)
		languageHandler.setLanguage(lang)
	except:
		log.warning("Could not set language to %s"%lang)
	import versionInfo
	log.info("NVDA version %s" % versionInfo.version)
	log.info("Using Windows version %s" % winVersion.winVersionText)
	log.info("Using Python version %s"%sys.version)
	log.info("Using comtypes version %s"%comtypes.__version__)
	import configobj
	log.info("Using configobj version %s with validate version %s"%(configobj.__version__,configobj.validate.__version__))
	# Set a reasonable timeout for any socket connections NVDA makes.
	import socket
	socket.setdefaulttimeout(10)
	log.debug("Initializing add-ons system")
	addonHandler.initialize()
	if globalVars.appArgs.disableAddons:
		log.info("Add-ons are disabled. Restart NVDA to enable them.")
	import appModuleHandler
	log.debug("Initializing appModule Handler")
	appModuleHandler.initialize()
	import NVDAHelper
	log.debug("Initializing NVDAHelper")
	NVDAHelper.initialize()
	import speechDictHandler
	log.debug("Speech Dictionary processing")
	speechDictHandler.initialize()
	import speech
	log.debug("Initializing speech")
	speech.initialize()
	if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5:
		log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime))
		# Translators: This is spoken when NVDA is starting.
		speech.speakMessage(_("Loading NVDA. Please wait..."))
	import wx
	# wxPython 4 no longer has either of these constants (despite the documentation saying so), some add-ons may rely on
	# them so we add it back into wx. https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.Centre
	wx.CENTER_ON_SCREEN = wx.CENTRE_ON_SCREEN = 0x2
	log.info("Using wx version %s"%wx.version())
	class App(wx.App):
		def OnAssert(self,file,line,cond,msg):
			message="{file}, line {line}:\nassert {cond}: {msg}".format(file=file,line=line,cond=cond,msg=msg)
			log.debugWarning(message,codepath="WX Widgets",stack_info=True)
	app = App(redirect=False)
	# We support queryEndSession events, but in general don't do anything for them.
	# However, when running as a Windows Store application, we do want to request to be restarted for updates
	def onQueryEndSession(evt):
		if config.isAppX:
			# Automatically restart NVDA on Windows Store update
			ctypes.windll.kernel32.RegisterApplicationRestart(None,0)
	app.Bind(wx.EVT_QUERY_END_SESSION, onQueryEndSession)
	def onEndSession(evt):
		# NVDA will be terminated as soon as this function returns, so save configuration if appropriate.
		config.saveOnExit()
		speech.cancelSpeech()
		if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
			try:
				nvwave.playWaveFile("waves\\exit.wav",async=False)
			except:
				pass
		log.info("Windows session ending")
	app.Bind(wx.EVT_END_SESSION, onEndSession)
	log.debug("Initializing braille input")
	import brailleInput
	brailleInput.initialize()
	import braille
	log.debug("Initializing braille")
	braille.initialize()
	import displayModel
	log.debug("Initializing displayModel")
	displayModel.initialize()
	log.debug("Initializing GUI")
	import gui
	gui.initialize()
	import audioDucking
	if audioDucking.isAudioDuckingSupported():
		# the GUI mainloop must be running for this to work so delay it
		wx.CallAfter(audioDucking.initialize)

	# #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR.
	# NVDA uses the main frame to check for and quit another instance of NVDA.
	# To remain compatible with older versions of NVDA, create our own wxWindowClassNR.
	# We don't need to do anything else because wx handles WM_QUIT for all windows.
	import windowUtils
	class MessageWindow(windowUtils.CustomWindow):
		className = u"wxWindowClassNR"
		#Just define these constants here, so we don't have to import win32con
		WM_POWERBROADCAST = 0x218
		WM_DISPLAYCHANGE = 0x7e
		PBT_APMPOWERSTATUSCHANGE = 0xA
		UNKNOWN_BATTERY_STATUS = 0xFF
		AC_ONLINE = 0X1
		NO_SYSTEM_BATTERY = 0X80
		#States for screen orientation
		ORIENTATION_NOT_INITIALIZED = 0
		ORIENTATION_PORTRAIT = 1
		ORIENTATION_LANDSCAPE = 2

		def __init__(self, windowName=None):
			super(MessageWindow, self).__init__(windowName)
			self.oldBatteryStatus = None
			self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED
			self.orientationCoordsCache = (0,0)
			self.handlePowerStatusChange()

		def windowProc(self, hwnd, msg, wParam, lParam):
			post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam)
			if msg == self.WM_POWERBROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE:
				self.handlePowerStatusChange()
			elif msg == self.WM_DISPLAYCHANGE:
				self.handleScreenOrientationChange(lParam)

		def handleScreenOrientationChange(self, lParam):
			import ui
			import winUser
			# Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx.
			#The low word is the width and hiword is height.
			width = winUser.LOWORD(lParam)
			height = winUser.HIWORD(lParam)
			self.orientationCoordsCache = (width,height)
			if width > height:
				# If the height and width are the same, it's actually a screen flip, and we do want to alert of those!
				if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height):
					return
				#Translators: The screen is oriented so that it is wider than it is tall.
				ui.message(_("Landscape" ))
				self.orientationStateCache = self.ORIENTATION_LANDSCAPE
			else:
				if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height):
					return
				#Translators: The screen is oriented in such a way that the height is taller than it is wide.
				ui.message(_("Portrait"))
				self.orientationStateCache = self.ORIENTATION_PORTRAIT

		def handlePowerStatusChange(self):
			#Mostly taken from script_say_battery_status, but modified.
			import ui
			import winKernel
			sps = winKernel.SYSTEM_POWER_STATUS()
			if not winKernel.GetSystemPowerStatus(sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS:
				return
			if sps.BatteryFlag & self.NO_SYSTEM_BATTERY:
				return
			if self.oldBatteryStatus is None:
				#Just initializing the cache, do not report anything.
				self.oldBatteryStatus = sps.ACLineStatus
				return
			if sps.ACLineStatus == self.oldBatteryStatus:
				#Sometimes, this double fires. This also fires when the battery level decreases by 3%.
				return
			self.oldBatteryStatus = sps.ACLineStatus
			if sps.ACLineStatus & self.AC_ONLINE:
				#Translators: Reported when the battery is plugged in, and now is charging.
				ui.message(_("Charging battery. %d percent") % sps.BatteryLifePercent)
			else:
				#Translators: Reported when the battery is no longer plugged in, and now is not charging.
				ui.message(_("Not charging battery. %d percent") %sps.BatteryLifePercent)

	messageWindow = MessageWindow(unicode(versionInfo.name))

	# initialize wxpython localization support
	locale = wx.Locale()
	lang=languageHandler.getLanguage()
	wxLang=locale.FindLanguageInfo(lang)
	if not wxLang and '_' in lang:
		wxLang=locale.FindLanguageInfo(lang.split('_')[0])
	if hasattr(sys,'frozen'):
		locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale"))
	# #8064: Wx might know the language, but may not actually contain a translation database for that language.
	# If we try to initialize this language, wx will show a warning dialog.
	# Therefore treat this situation like wx not knowing the language at all.
	if not locale.IsAvailable(wxLang.Language):
		wxLang=None
	if wxLang:
		try:
			locale.Init(wxLang.Language)
		except:
			log.error("Failed to initialize wx locale",exc_info=True)
	else:
		log.debugWarning("wx does not support language %s" % lang)

	import api
	import winUser
	import NVDAObjects.window
	desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow())
	api.setDesktopObject(desktopObject)
	api.setFocusObject(desktopObject)
	api.setNavigatorObject(desktopObject)
	api.setMouseObject(desktopObject)
	import JABHandler
	log.debug("initializing Java Access Bridge support")
	try:
		JABHandler.initialize()
	except NotImplementedError:
		log.warning("Java Access Bridge not available")
	except:
		log.error("Error initializing Java Access Bridge support", exc_info=True)
	import winConsoleHandler
	log.debug("Initializing winConsole support")
	winConsoleHandler.initialize()
	import UIAHandler
	log.debug("Initializing UIA support")
	try:
		UIAHandler.initialize()
	except NotImplementedError:
		log.warning("UIA not available")
	except:
		log.error("Error initializing UIA support", exc_info=True)
	import IAccessibleHandler
	log.debug("Initializing IAccessible support")
	IAccessibleHandler.initialize()
	log.debug("Initializing input core")
	import inputCore
	inputCore.initialize()
	import keyboardHandler
	log.debug("Initializing keyboard handler")
	keyboardHandler.initialize()
	import mouseHandler
	log.debug("initializing mouse handler")
	mouseHandler.initialize()
	import touchHandler
	log.debug("Initializing touchHandler")
	try:
		touchHandler.initialize()
	except NotImplementedError:
		pass
	import globalPluginHandler
	log.debug("Initializing global plugin handler")
	globalPluginHandler.initialize()
	if globalVars.appArgs.install or globalVars.appArgs.installSilent:
		import gui.installerGui
		wx.CallAfter(gui.installerGui.doSilentInstall,startAfterInstall=not globalVars.appArgs.installSilent)
	elif globalVars.appArgs.portablePath and (globalVars.appArgs.createPortable or globalVars.appArgs.createPortableSilent):
		import gui.installerGui
		wx.CallAfter(gui.installerGui.doCreatePortable,portableDirectory=globalVars.appArgs.portablePath,
			silent=globalVars.appArgs.createPortableSilent,startAfterCreate=not globalVars.appArgs.createPortableSilent)
	elif not globalVars.appArgs.minimal:
		try:
			# Translators: This is shown on a braille display (if one is connected) when NVDA starts.
			braille.handler.message(_("NVDA started"))
		except:
			log.error("", exc_info=True)
		if globalVars.appArgs.launcher:
			gui.LauncherDialog.run()
			# LauncherDialog will call doStartupDialogs() afterwards if required.
		else:
			wx.CallAfter(doStartupDialogs)
	import queueHandler
	# Queue the handling of initial focus,
	# as API handlers might need to be pumped to get the first focus event.
	queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus)
	import watchdog
	import baseObject

	# Doing this here is a bit ugly, but we don't want these modules imported
	# at module level, including wx.
	log.debug("Initializing core pump")
	class CorePump(gui.NonReEntrantTimer):
		"Checks the queues and executes functions."
		def run(self):
			global _isPumpPending
			_isPumpPending = False
			watchdog.alive()
			try:
				if touchHandler.handler:
					touchHandler.handler.pump()
				JABHandler.pumpAll()
				IAccessibleHandler.pumpAll()
				queueHandler.pumpAll()
				mouseHandler.pumpAll()
				braille.pumpAll()
			except:
				log.exception("errors in this core pump cycle")
			baseObject.AutoPropertyObject.invalidateCaches()
			watchdog.asleep()
			if _isPumpPending and not _pump.IsRunning():
				# #3803: Another pump was requested during this pump execution.
				# As our pump is not re-entrant, schedule another pump.
				_pump.Start(PUMP_MAX_DELAY, True)
	global _pump
	_pump = CorePump()
	requestPump()

	log.debug("Initializing watchdog")
	watchdog.initialize()
	try:
		import updateCheck
	except RuntimeError:
		updateCheck=None
		log.debug("Update checking not supported")
	else:
		log.debug("initializing updateCheck")
		updateCheck.initialize()
	log.info("NVDA initialized")
	postNvdaStartup.notify()

	log.debug("entering wx application main loop")
	app.MainLoop()

	log.info("Exiting")
	if updateCheck:
		_terminate(updateCheck)

	_terminate(watchdog)
	_terminate(globalPluginHandler, name="global plugin handler")
	_terminate(gui)
	config.saveOnExit()

	try:
		if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"):
			log.debug("calling lose focus on object with focus")
			globalVars.focusObject.event_loseFocus()
	except:
		log.exception("Lose focus error")
	try:
		speech.cancelSpeech()
	except:
		pass

	import treeInterceptorHandler
	_terminate(treeInterceptorHandler)
	_terminate(IAccessibleHandler, name="IAccessible support")
	_terminate(UIAHandler, name="UIA support")
	_terminate(winConsoleHandler, name="winConsole support")
	_terminate(JABHandler, name="Java Access Bridge support")
	_terminate(appModuleHandler, name="app module handler")
	_terminate(NVDAHelper)
	_terminate(touchHandler)
	_terminate(keyboardHandler, name="keyboard handler")
	_terminate(mouseHandler)
	_terminate(inputCore)
	_terminate(brailleInput)
	_terminate(braille)
	_terminate(speech)
	_terminate(addonHandler)

	if not globalVars.appArgs.minimal and config.conf["general"]["playStartAndExitSounds"]:
		try:
			nvwave.playWaveFile("waves\\exit.wav",async=False)
		except:
			pass
	# #5189: Destroy the message window as late as possible
	# so new instances of NVDA can find this one even if it freezes during exit.
	messageWindow.destroy()
	log.debug("core done")