Ejemplo n.º 1
0
        def run(self):
            global _isPumpPending
            _isPumpPending = False
            # print("pumpujuuu")
            watchdog.alive()
            try:
                # if touchHandler.handler:
                #     touchHandler.handler.pump()
                JABHandler.pumpAll()
                # IAccessibleHandler.pumpAll()
                queueHandler.pumpAll()
                # mouseHandler.pumpAll()
                # braille.pumpAll()
                # vision.pumpAll()
            except Exception as e:

                print("errors in this core pump cycle", e)
                # raise
            # baseObject.AutoPropertyObject.invalidateCaches()
            # print("spinkam")
            watchdog.asleep()
            # print("vstalsem")
            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)
Ejemplo n.º 2
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()
Ejemplo n.º 3
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()
Ejemplo n.º 4
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)
Ejemplo n.º 5
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)
Ejemplo n.º 6
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)
Ejemplo n.º 7
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")
Ejemplo n.º 8
0
    def pumpAll(self):
        """Call queueHandler.pumpAll
		@note This is required to process pending events (indexReached, doneSpeaking) for SpeechManager.
		"""
        queueHandler.pumpAll()