Module core
[hide private]
[frames] | no frames]

Source Code for Module core

  1  #core.py 
  2  #A part of NonVisual Desktop Access (NVDA) 
  3  #Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/> 
  4  #This file is covered by the GNU General Public License. 
  5  #See the file COPYING for more details. 
  6   
  7  """NVDA core""" 
  8   
  9  # Do this first to initialise comtypes.client.gen_dir and the comtypes.gen search path. 
 10  import comtypes.client 
 11  # Append our comInterfaces directory to the comtypes.gen search path. 
 12  import comtypes.gen 
 13  import comInterfaces 
 14  comtypes.gen.__path__.append(comInterfaces.__path__[0]) 
 15   
 16  #Monkey patch comtypes to support byref in variants 
 17  from comtypes.automation import VARIANT, VT_BYREF 
 18  from ctypes import cast, c_void_p 
 19  from _ctypes import _Pointer 
 20  oldVARIANT_value_fset=VARIANT.value.fset 
21 -def newVARIANT_value_fset(self,value):
22 realValue=value 23 if isinstance(value,_Pointer): 24 try: 25 value=value.contents 26 except (NameError,AttributeError): 27 pass 28 oldVARIANT_value_fset(self,value) 29 if realValue is not value: 30 self.vt|=VT_BYREF 31 self._.c_void_p=cast(realValue,c_void_p)
32 VARIANT.value=property(VARIANT.value.fget,newVARIANT_value_fset,VARIANT.value.fdel) 33 34 #Monkeypatch comtypes lazybind dynamic IDispatch support to fallback to the more basic dynamic IDispatch support if the former does not work 35 #Example: ITypeComp.bind gives back a vardesc, which comtypes does not yet support 36 import comtypes.client.lazybind 37 old__getattr__=comtypes.client.lazybind.Dispatch.__getattr__
38 -def new__getattr__(self,name):
39 try: 40 return old__getattr__(self,name) 41 except (NameError, AttributeError): 42 return getattr(comtypes.client.dynamic._Dispatch(self._comobj),name)
43 comtypes.client.lazybind.Dispatch.__getattr__=new__getattr__ 44 45 #Monkeypatch comtypes to allow its basic dynamic Dispatch support to support invoke 0 (calling the actual IDispatch object itself)
46 -def new__call__(self,*args,**kwargs):
47 return comtypes.client.dynamic.MethodCaller(0,self)(*args,**kwargs)
48 comtypes.client.dynamic._Dispatch.__call__=new__call__ 49 50 51 import sys 52 import nvwave 53 import os 54 import time 55 import logHandler 56 import globalVars 57 from logHandler import log 58 59 # Work around an issue with comtypes where __del__ seems to be called twice on COM pointers. 60 # This causes Release() to be called more than it should, which is very nasty and will eventually cause us to access pointers which have been freed. 61 from comtypes import _compointer_base 62 _cpbDel = _compointer_base.__del__
63 -def newCpbDel(self):
64 if hasattr(self, "_deleted"): 65 # Don't allow this to be called more than once. 66 log.debugWarning("COM pointer %r already deleted" % self) 67 return 68 _cpbDel(self) 69 self._deleted = True
70 newCpbDel.__name__ = "__del__" 71 _compointer_base.__del__ = newCpbDel 72 del _compointer_base 73
74 -def doStartupDialogs():
75 import config 76 import gui 77 if config.conf["general"]["showWelcomeDialogAtStartup"]: 78 gui.WelcomeDialog.run() 79 if globalVars.configFileError: 80 gui.ConfigFileErrorDialog.run() 81 import inputCore 82 if inputCore.manager.userGestureMap.lastUpdateContainedError: 83 import wx 84 gui.messageBox(_("Your gesture map file contains errors.\n" 85 "More details about the errors can be found in the log file."), 86 _("gesture map File Error"), wx.OK|wx.ICON_EXCLAMATION)
87
88 -def restart():
89 """Restarts NVDA by starting a new copy with -r.""" 90 import subprocess 91 import shellapi 92 shellapi.ShellExecute(None,None,unicode(sys.executable),unicode(subprocess.list2cmdline(sys.argv+['-r'])),None,0)
93
94 -def resetConfiguration():
95 """Loads the configuration, installs the correct language support and initialises audio so that it will use the configured synth and speech settings. 96 """ 97 import config 98 import braille 99 import speech 100 import languageHandler 101 import inputCore 102 log.debug("Terminating braille") 103 braille.terminate() 104 log.debug("terminating speech") 105 speech.terminate() 106 log.debug("Reloading config") 107 config.load() 108 logHandler.setLogLevelFromConfig() 109 #Language 110 lang = config.conf["general"]["language"] 111 log.debug("setting language to %s"%lang) 112 languageHandler.setLanguage(lang) 113 #Speech 114 log.debug("initializing speech") 115 speech.initialize() 116 #braille 117 log.debug("Initializing braille") 118 braille.initialize() 119 log.debug("Reloading user and locale input gesture maps") 120 inputCore.manager.loadUserGestureMap() 121 inputCore.manager.loadLocaleGestureMap() 122 log.info("Reverted to saved configuration")
123
124 -def _setInitialFocus():
125 """Sets the initial focus if no focus event was received at startup. 126 """ 127 import eventHandler 128 import api 129 if eventHandler.lastQueuedFocusObject: 130 # The focus has already been set or a focus event is pending. 131 return 132 try: 133 focus = api.getDesktopObject().objectWithFocus() 134 if focus: 135 eventHandler.queueEvent('gainFocus', focus) 136 except: 137 log.exception("Error retrieving initial focus")
138
139 -def main():
140 """NVDA's core main loop. 141 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. 142 """ 143 log.debug("Core starting") 144 log.info("Config dir: %s"%os.path.abspath(globalVars.appArgs.configPath)) 145 log.debug("loading config") 146 import config 147 config.load() 148 if not globalVars.appArgs.minimal: 149 try: 150 nvwave.playWaveFile("waves\\start.wav") 151 except: 152 pass 153 logHandler.setLogLevelFromConfig() 154 try: 155 lang = config.conf["general"]["language"] 156 import languageHandler 157 log.debug("setting language to %s"%lang) 158 languageHandler.setLanguage(lang) 159 except: 160 log.warning("Could not set language to %s"%lang) 161 import versionInfo 162 log.info("NVDA version %s" % versionInfo.version) 163 log.info("Using Windows version %r" % (sys.getwindowsversion(),)) 164 log.info("Using Python version %s"%sys.version) 165 log.info("Using comtypes version %s"%comtypes.__version__) 166 log.debug("Creating wx application instance") 167 import speechDictHandler 168 log.debug("Speech Dictionary processing") 169 speechDictHandler.initialize() 170 import speech 171 log.debug("Initializing speech") 172 speech.initialize() 173 if not globalVars.appArgs.minimal and (time.time()-globalVars.startTime)>5: 174 log.debugWarning("Slow starting core (%.2f sec)" % (time.time()-globalVars.startTime)) 175 speech.speakMessage(_("Loading NVDA. Please wait...")) 176 import wx 177 log.info("Using wx version %s"%wx.version()) 178 app = wx.App(redirect=False) 179 # HACK: wx currently raises spurious assertion failures when a timer is stopped but there is already an event in the queue for that timer. 180 # Unfortunately, these assertion exceptions are raised in the middle of other code, which causes problems. 181 # Therefore, disable assertions for now. 182 app.SetAssertMode(wx.PYAPP_ASSERT_SUPPRESS) 183 # We do support QueryEndSession events, but we don't want to do anything for them. 184 app.Bind(wx.EVT_QUERY_END_SESSION, lambda evt: None) 185 def onEndSession(evt): 186 # NVDA will be terminated as soon as this function returns, so save configuration if appropriate. 187 config.saveOnExit() 188 speech.cancelSpeech() 189 if not globalVars.appArgs.minimal: 190 try: 191 nvwave.playWaveFile("waves\\exit.wav",async=False) 192 except: 193 pass 194 log.info("Windows session ending")
195 app.Bind(wx.EVT_END_SESSION, onEndSession) 196 import braille 197 log.debug("Initializing braille") 198 braille.initialize() 199 import NVDAHelper 200 log.debug("Initializing NVDAHelper") 201 NVDAHelper.initialize() 202 import displayModel 203 log.debug("Initializing displayModel") 204 displayModel.initialize() 205 log.debug("Initializing GUI") 206 import gui 207 gui.initialize() 208 # initialize wxpython localization support 209 locale = wx.Locale() 210 lang=languageHandler.getLanguage() 211 if '_' in lang: 212 wxLang=lang.split('_')[0] 213 else: 214 wxLang=lang 215 if hasattr(sys,'frozen'): 216 locale.AddCatalogLookupPathPrefix(os.path.join(os.getcwdu(),"locale")) 217 try: 218 locale.Init(lang,wxLang) 219 except: 220 pass 221 import appModuleHandler 222 log.debug("Initializing appModule Handler") 223 appModuleHandler.initialize() 224 import api 225 import winUser 226 import NVDAObjects.window 227 desktopObject=NVDAObjects.window.Window(windowHandle=winUser.getDesktopWindow()) 228 api.setDesktopObject(desktopObject) 229 api.setFocusObject(desktopObject) 230 api.setNavigatorObject(desktopObject) 231 api.setMouseObject(desktopObject) 232 import JABHandler 233 log.debug("initializing Java Access Bridge support") 234 try: 235 JABHandler.initialize() 236 except NotImplementedError: 237 log.warning("Java Access Bridge not available") 238 except: 239 log.error("Error initializing Java Access Bridge support", exc_info=True) 240 import winConsoleHandler 241 log.debug("Initializing winConsole support") 242 winConsoleHandler.initialize() 243 import UIAHandler 244 log.debug("Initializing UIA support") 245 try: 246 UIAHandler.initialize() 247 except NotImplementedError: 248 log.warning("UIA not available") 249 except: 250 log.error("Error initializing UIA support", exc_info=True) 251 import IAccessibleHandler 252 log.debug("Initializing IAccessible support") 253 IAccessibleHandler.initialize() 254 log.debug("Initializing input core") 255 import inputCore 256 inputCore.initialize() 257 import keyboardHandler 258 log.debug("Initializing keyboard handler") 259 keyboardHandler.initialize() 260 import mouseHandler 261 log.debug("initializing mouse handler") 262 mouseHandler.initialize() 263 import globalPluginHandler 264 log.debug("Initializing global plugin handler") 265 globalPluginHandler.initialize() 266 if not globalVars.appArgs.minimal: 267 try: 268 braille.handler.message(_("NVDA started")) 269 except: 270 log.error("", exc_info=True) 271 wx.CallAfter(doStartupDialogs) 272 import queueHandler 273 # Queue the handling of initial focus, 274 # as API handlers might need to be pumped to get the first focus event. 275 queueHandler.queueFunction(queueHandler.eventQueue, _setInitialFocus) 276 import watchdog 277 import baseObject 278 class CorePump(wx.Timer): 279 "Checks the queues and executes functions." 280 def __init__(self,*args,**kwargs): 281 log.debug("Core pump starting") 282 super(CorePump,self).__init__(*args,**kwargs) 283 def Notify(self): 284 try: 285 JABHandler.pumpAll() 286 IAccessibleHandler.pumpAll() 287 queueHandler.pumpAll() 288 mouseHandler.pumpAll() 289 except: 290 log.exception("errors in this core pump cycle") 291 baseObject.AutoPropertyObject.invalidateCaches() 292 watchdog.alive() 293 log.debug("starting core pump") 294 pump = CorePump() 295 pump.Start(1) 296 log.debug("Initializing watchdog") 297 watchdog.initialize() 298 log.info("NVDA initialized") 299 300 log.debug("entering wx application main loop") 301 app.MainLoop() 302 303 log.info("Exiting") 304 log.debug("Terminating watchdog") 305 watchdog.terminate() 306 log.debug("Terminating GUI") 307 gui.terminate() 308 config.saveOnExit() 309 try: 310 if globalVars.focusObject and hasattr(globalVars.focusObject,"event_loseFocus"): 311 log.debug("calling lose focus on object with focus") 312 globalVars.focusObject.event_loseFocus() 313 except: 314 log.error("Lose focus error",exc_info=True) 315 try: 316 speech.cancelSpeech() 317 except: 318 pass 319 log.debug("Cleaning up running treeInterceptors") 320 try: 321 import treeInterceptorHandler 322 treeInterceptorHandler.terminate() 323 except: 324 log.error("Error cleaning up treeInterceptors",exc_info=True) 325 log.debug("Terminating global plugin handler") 326 globalPluginHandler.terminate() 327 log.debug("Terminating IAccessible support") 328 try: 329 IAccessibleHandler.terminate() 330 except: 331 log.error("Error terminating IAccessible support",exc_info=True) 332 log.debug("Terminating UIA support") 333 try: 334 UIAHandler.terminate() 335 except: 336 log.error("Error terminating UIA support",exc_info=True) 337 log.debug("Terminating winConsole support") 338 try: 339 winConsoleHandler.terminate() 340 except: 341 log.error("Error terminating winConsole support",exc_info=True) 342 log.debug("Terminating Java Access Bridge support") 343 try: 344 JABHandler.terminate() 345 except: 346 log.error("Error terminating Java Access Bridge support",exc_info=True) 347 log.debug("Terminating app module handler") 348 appModuleHandler.terminate() 349 log.debug("Terminating NVDAHelper") 350 try: 351 NVDAHelper.terminate() 352 except: 353 log.error("Error terminating NVDAHelper",exc_info=True) 354 log.debug("Terminating keyboard handler") 355 try: 356 keyboardHandler.terminate() 357 except: 358 log.error("Error terminating keyboard handler") 359 log.debug("Terminating mouse handler") 360 try: 361 mouseHandler.terminate() 362 except: 363 log.error("error terminating mouse handler",exc_info=True) 364 log.debug("Terminating input core") 365 inputCore.terminate() 366 log.debug("Terminating braille") 367 try: 368 braille.terminate() 369 except: 370 log.error("Error terminating braille",exc_info=True) 371 log.debug("Terminating speech") 372 try: 373 speech.terminate() 374 except: 375 log.error("Error terminating speech",exc_info=True) 376 if not globalVars.appArgs.minimal: 377 try: 378 nvwave.playWaveFile("waves\\exit.wav",async=False) 379 except: 380 pass 381 log.debug("core done") 382