Exemple #1
0
    def processInputEvent(self, script, inputEvent):
        """Processes an input event.  If settings.learnModeEnabled is True,
        this will merely report the description of the input event to braille
        and speech.  If settings.learnModeEnabled is False, this will call the
        function bound to this InputEventHandler instance, passing the
        inputEvent as the sole argument to the function.

        This function is expected to return True if it consumes the
        event; otherwise it is expected to return False.

        Arguments:
        - script:     the script (if any) associated with this event
        - inputEvent: the input event to pass to the function bound
                      to this InputEventHandler instance.
        """

        consumed = False

        if settings.learnModeEnabled and self._learnModeEnabled:
            if self._description:
                # These imports are here to eliminate circular imports.
                #
                import braille
                import speech
                braille.displayMessage(self._description)
                speech.speak(self._description)
                consumed = True
        else:
            try:
                consumed = self._function(script, inputEvent)
            except:
                debug.printException(debug.LEVEL_SEVERE)

        return consumed
def shutdown(script=None, inputEvent=None):
    """Exits Orca.  Unregisters any event listeners and cleans up.  Also
    quits the bonobo main loop and resets the initialized state to False.

    Returns True if the shutdown procedure ran or False if this module
    was never initialized.
    """

    global _initialized

    if not _initialized:
        return False

    # Try to say goodbye, but be defensive if something has hung.
    #
    if settings.timeoutCallback and (settings.timeoutTime > 0):
        signal.signal(signal.SIGALRM, settings.timeoutCallback)
        signal.alarm(settings.timeoutTime)

    # Translators: this is what Orca speaks and brailles when it quits.
    #
    speech.speak(_("Goodbye."))
    braille.displayMessage(_("Goodbye."))

    # Deregister our event listeners
    #
    registry = atspi.Registry()
    registry.deregisterEventListener(_onChildrenChanged,
                                     "object:children-changed:")
    registry.deregisterEventListener(_onMouseButton,
                                     "mouse:button")

    if _currentPresentationManager >= 0:
        _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()

    # Shutdown all the other support.
    #
    if settings.enableSpeech:
        speech.shutdown()
    if settings.enableBraille:
        braille.shutdown();
    if settings.enableMagnifier:
        mag.shutdown();

    registry.stop()

    if settings.timeoutCallback and (settings.timeoutTime > 0):
        signal.alarm(0)

    _initialized = False
    return True
Exemple #3
0
def shutdown(script=None, inputEvent=None):
    """Exits Orca.  Unregisters any event listeners and cleans up.  Also
    quits the bonobo main loop and resets the initialized state to False.

    Returns True if the shutdown procedure ran or False if this module
    was never initialized.
    """

    global _initialized

    if not _initialized:
        return False

    # Try to say goodbye, but be defensive if something has hung.
    #
    if settings.timeoutCallback and (settings.timeoutTime > 0):
        signal.signal(signal.SIGALRM, settings.timeoutCallback)
        signal.alarm(settings.timeoutTime)

    # Translators: this is what Orca speaks and brailles when it quits.
    #
    speech.speak(_("Goodbye."))
    braille.displayMessage(_("Goodbye."))

    # Deregister our event listeners
    #
    registry = atspi.Registry()
    registry.deregisterEventListener(_onChildrenChanged,
                                     "object:children-changed:")
    registry.deregisterEventListener(_onMouseButton, "mouse:button")

    if _currentPresentationManager >= 0:
        _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()

    # Shutdown all the other support.
    #
    if settings.enableSpeech:
        speech.shutdown()
    if settings.enableBraille:
        braille.shutdown()
    if settings.enableMagnifier:
        mag.shutdown()

    registry.stop()

    if settings.timeoutCallback and (settings.timeoutTime > 0):
        signal.alarm(0)

    _initialized = False
    return True
Exemple #4
0
def showPreferencesUI():
    global applicationName, appScript

    # There must be an application with focus for this to work.
    #
    if not orca_state.locusOfFocus or not orca_state.locusOfFocus.getApplication():
        message = _("No application has focus.")
        braille.displayMessage(message)
        speech.speak(message)
        return

    appScript = orca_state.activeScript

    # The name of the application that currently has focus.
    #
    applicationName = orca_state.activeScript.app.name
    if not orca_state.appOS and not orca_state.orcaOS:
        # Translators: Orca Preferences in this case, is a configuration GUI
        # for allowing users to set application specific settings from within
        # Orca for the application that currently has focus.
        #
        line = _("Starting Orca Preferences for %s.") % applicationName
        appScript.presentMessage(line)

        prefsDict = orca_prefs.readPreferences()
        orca_state.prefsUIFile = os.path.join(
            orca_platform.prefix, orca_platform.datadirname, orca_platform.package, "ui", "orca-setup.ui"
        )

        orca_state.appOS = OrcaSetupGUI(orca_state.prefsUIFile, "orcaSetupWindow", prefsDict)
        orca_state.appOS.initAppGUIState(appScript)

        orca_state.appOS.init()
    else:
        if not orca_state.orcaWD:
            orca_state.orcaWarningDialogUIFile = os.path.join(
                orca_platform.prefix,
                orca_platform.datadirname,
                orca_platform.package,
                "ui",
                "orca-preferences-warning.ui",
            )
            orca_state.orcaWD = WarningDialogGUI(orca_state.orcaWarningDialogUIFile, "orcaPrefsWarningDialog")
            warningDialog = orca_state.orcaWD.getPrefsWarningDialog()
            warningDialog.realize()
            warningDialog.show()
        return

    orca_state.appOS.showGUI()
def showPreferencesUI():
    global applicationName, appScript, OS

    # There must be an application with focus for this to work.
    #
    if not orca_state.locusOfFocus or not orca_state.locusOfFocus.app:
        message = _("No application has focus.")
        braille.displayMessage(message)
        speech.speak(message)
        return

    appScript = orca_state.activeScript

    # The name of the application that currently has focus.
    #
    applicationName = orca_state.locusOfFocus.app.name

    # Translators: Orca Preferences in this case, is a configuration GUI 
    # for allowing users to set application specific settings from within
    # Orca for the application that currently has focus.
    #
    line = _("Starting Orca Preferences for %s. This may take a while.") % \
           applicationName
    braille.displayMessage(line)
    speech.speak(line)

    removeGeneralPane = False
    if not OS:
        gladeFile = os.path.join(platform.prefix,
                                 platform.datadirname,
                                 platform.package,
                                 "glade",
                                 "orca-setup.glade")
        OS = orcaSetupGUI(gladeFile, "orcaSetupWindow")
        removeGeneralPane = True

    OS._init()
    if removeGeneralPane:
        OS._initAppGUIState(appScript)
    OS._showGUI()
Exemple #6
0
    def _outputElements(self, output_obj):
        """Output the given elements.
        TODO: Now we are mainly using WhereAmI, we might need to find out a
        better, less verbose output method.

        Arguments:
        - output_obj: A list of objects to output, could be accessibles and
        text.
        """
        if output_obj:
            speech.stop()
        for obj in output_obj:
            if obj is None:
                continue
            if isinstance(obj, str):
                speech.speak(obj)
                # TODO: There is probably something more useful that we could
                # display.
                braille.displayMessage(obj)
            else:
                speech.speak(self._currentMouseOver.script.speechGenerator.generateSpeech(obj))
                self._currentMouseOver.script.updateBraille(obj)
Exemple #7
0
def showPreferencesUI():
    global applicationName, appScript, OS

    # There must be an application with focus for this to work.
    #
    if not orca_state.locusOfFocus or not orca_state.locusOfFocus.app:
        message = _("No application has focus.")
        braille.displayMessage(message)
        speech.speak(message)
        return

    appScript = orca_state.activeScript

    # The name of the application that currently has focus.
    #
    applicationName = orca_state.locusOfFocus.app.name

    # Translators: Orca Preferences in this case, is a configuration GUI
    # for allowing users to set application specific settings from within
    # Orca for the application that currently has focus.
    #
    line = _("Starting Orca Preferences for %s. This may take a while.") % \
           applicationName
    braille.displayMessage(line)
    speech.speak(line)

    removeGeneralPane = False
    if not OS:
        gladeFile = os.path.join(platform.prefix, platform.datadirname,
                                 platform.package, "glade", "orca-setup.glade")
        OS = orcaSetupGUI(gladeFile, "orcaSetupWindow")
        removeGeneralPane = True

    OS._init()
    if removeGeneralPane:
        OS._initAppGUIState(appScript)
    OS._showGUI()
    def _dequeueEvent(self):
        """Handles all events destined for scripts.  Called by the GTK
        idle thread.
        """

        rerun = True

        if settings.debugEventQueue:
            debug.println(debug.LEVEL_ALL,
                          "Entering focus_tracking_presenter._dequeueEvent" \
                          + " %d" % self._dequeueEventCount)
            self._dequeueEventCount += 1

        try:
            event = self._eventQueue.get_nowait()

            if isinstance(event, input_event.KeyboardEvent):
                if event.type == atspi.Accessibility.KEY_PRESSED_EVENT:
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED KEYPRESS '%s' (%d) <----------" \
                                  % (event.event_string, event.hw_code))
                    pressRelease = "PRESS"
                elif event.type == atspi.Accessibility.KEY_RELEASED_EVENT:
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED KEYRELEASE '%s' (%d) <----------" \
                                  % (event.event_string, event.hw_code))
                    pressRelease = "RELEASE"
                debug.println(debug.eventDebugLevel,
                              "\nvvvvv PROCESS KEY %s EVENT %s vvvvv"\
                              % (pressRelease, event.event_string))
                self._processKeyboardEvent(event)
                debug.println(debug.eventDebugLevel,
                              "\n^^^^^ PROCESS KEY %s EVENT %s ^^^^^"\
                              % (pressRelease, event.event_string))
            elif isinstance(event, input_event.BrailleEvent):
                debug.println(debug.LEVEL_ALL,
                              "DEQUEUED BRAILLE COMMAND %d <----------" \
                              % event.event)
                debug.println(debug.eventDebugLevel,
                              "\nvvvvv PROCESS BRAILLE EVENT %d vvvvv"\
                              % event.event)
                self._processBrailleEvent(event)
                debug.println(debug.eventDebugLevel,
                              "\n^^^^^ PROCESS BRAILLE EVENT %d ^^^^^"\
                              % event.event)
            else:
                if (not debug.eventDebugFilter) \
                    or (debug.eventDebugFilter \
                        and debug.eventDebugFilter.match(event.type)):
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED EVENT %s <----------" \
                                  % event.type)
                    debug.println(debug.eventDebugLevel,
                                  "\nvvvvv PROCESS OBJECT EVENT %s vvvvv" \
                                  % event.type)
                self._processObjectEvent(event)
                if (not debug.eventDebugFilter) \
                    or (debug.eventDebugFilter \
                        and debug.eventDebugFilter.match(event.type)):
                    debug.println(debug.eventDebugLevel,
                                  "^^^^^ PROCESS OBJECT EVENT %s ^^^^^\n" \
                                  % event.type)

            # [[[TODO: HACK - it would seem logical to only do this if we
            # discover the queue is empty, but this inroduces a hang for
            # some reason if done inside an acquire/release block for a
            # lock.  So...we do it here.]]]
            #
            noFocus = (not orca_state.activeScript) \
                      or ((not orca_state.locusOfFocus) \
                          and (self.noFocusTimestamp \
                               != orca_state.noFocusTimestamp))

            self._gidleLock.acquire()
            if self._eventQueue.empty():
                if noFocus:
                    if settings.gilSleepTime:
                        time.sleep(settings.gilSleepTime)
                    # Translators: this is intended to be a short phrase to
                    # speak and braille to tell the user that no component
                    # has keyboard focus.
                    #
                    message = _("No focus")
                    if settings.brailleVerbosityLevel == \
                        settings.VERBOSITY_LEVEL_VERBOSE:
                        braille.displayMessage(message)
                    if settings.speechVerbosityLevel == \
                        settings.VERBOSITY_LEVEL_VERBOSE:
                        speech.speak(message)
                    self.noFocusTimestamp = orca_state.noFocusTimestamp
                self._gidleId = 0
                rerun = False # destroy and don't call again
            self._gidleLock.release()
        except Queue.Empty:
            debug.println(debug.LEVEL_SEVERE,
                          "focus_tracking_presenter:_dequeueEvent: " \
                          + " the event queue is empty!")
        except:
            debug.printException(debug.LEVEL_SEVERE)

        if settings.debugEventQueue:
            self._dequeueEventCount -= 1
            debug.println(debug.LEVEL_ALL,
                          "Leaving focus_tracking_presenter._dequeueEvent" \
                          + " %d" % self._dequeueEventCount)

        return rerun
def _processKeyboardEvent(event):
    """The primary key event handler for Orca.  Keeps track of various
    attributes, such as the lastInputEvent.  Also calls keyEcho as well
    as any local keybindings before passing the event on to the active
    presentation manager.  This method is called synchronously from the
    AT-SPI registry and should be performant.  In addition, it
    must return True if it has consumed the event (and False if not).

    Arguments:
    - event: an AT-SPI DeviceEvent

    Returns True if the event should be consumed.
    """
    global _orcaModifierPressed

    orca_state.lastInputEventTimestamp = event.timestamp

    # Log the keyboard event for future playback, if desired.
    # Note here that the key event_string being output is
    # exactly what we received.  The KeyboardEvent object,
    # however, will translate the event_string for control
    # characters to their upper case ASCII equivalent.
    #
    string = atspi.KeystrokeListener.keyEventToString(event)
    if _recordingKeystrokes and _keystrokesFile \
       and (event.event_string != "Pause") \
       and (event.event_string != "F21"):
        _keystrokesFile.write(string + "\n")
    debug.printInputEvent(debug.LEVEL_FINE, string)

    keyboardEvent = KeyboardEvent(event)

    # See if this is one of our special Orca modifier keys.
    #
    # [[[TODO: WDW - Note that just looking at the keycode should
    # suffice, but there is a "feature" in the Java Access Bridge
    # where it chooses to emit Java platform-independent keycodes
    # instead of the keycodes for the base platform:
    #
    # http://bugzilla.gnome.org/show_bug.cgi?id=106004
    # http://bugzilla.gnome.org/show_bug.cgi?id=318615
    #
    # So...we need to workaround this problem.
    #
    # If you make the following expression True we will get a positive
    # match for all keysyms associated with a given keysym specified
    # as an Orca modifier key.
    #
    # For example, assume the Orca modifier is set to \ for some
    # reason.  The key that has \ on it produces \ without the Shift
    # key and | with the Shift key.  If the following expression is
    # True, both the \ and | will be viewed as the Orca modifier.  If
    # the following expression is False, only the \ will be viewed as
    # the Orca modifier (i.e., Shift+\ will still function as the |
    # character).  In general, I think we want to avoid sucking in all
    # possible keysyms because it can have unexpected results.]]]
    #
    if False:
        allPossibleKeysyms = []
        for keysym in settings.orcaModifierKeys:
            allPossibleKeysyms.extend(keybindings.getAllKeysyms(keysym))
    else:
        allPossibleKeysyms = settings.orcaModifierKeys

    isOrcaModifier = allPossibleKeysyms.count(keyboardEvent.event_string) > 0

    if event.type == atspi.Accessibility.KEY_PRESSED_EVENT:
        # Key presses always interrupt speech.
        #
        speech.stop()

        # If learn mode is enabled, it will echo the keys.
        #
        if not settings.learnModeEnabled:
            _keyEcho(keyboardEvent)

        # We treat the Insert key as a modifier - so just swallow it and
        # set our internal state.
        #
        if isOrcaModifier:
            _orcaModifierPressed = True

    elif isOrcaModifier \
        and (keyboardEvent.type == atspi.Accessibility.KEY_RELEASED_EVENT):
        _orcaModifierPressed = False

    if _orcaModifierPressed:
        keyboardEvent.modifiers = keyboardEvent.modifiers \
                                  | (1 << settings.MODIFIER_ORCA)

    # Orca gets first stab at the event.  Then, the presenter gets
    # a shot. [[[TODO: WDW - might want to let the presenter try first?
    # The main reason this is staying as is is that we may not want
    # scripts to override fundamental Orca key bindings.]]]
    #
    consumed = False
    try:
        if orca_state.capturingKeys:
            _processKeyCaptured(keyboardEvent)
        else:
            consumed = _keyBindings.consumeKeyboardEvent(None, keyboardEvent)
            if (not consumed) and (_currentPresentationManager >= 0):
                consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].\
                           processKeyboardEvent(keyboardEvent)
            if (not consumed) and settings.learnModeEnabled:
                if keyboardEvent.type \
                    == atspi.Accessibility.KEY_PRESSED_EVENT:
                    clickCount = orca_state.activeScript.getClickCount(\
                                                orca_state.lastInputEvent,
                                                keyboardEvent)
                    if clickCount == 2:
                        orca_state.activeScript.phoneticSpellCurrentItem(\
                            keyboardEvent.event_string)
                    else:
                        # Check to see if there are localized words to be
                        # spoken for this key event.
                        #
                        braille.displayMessage(keyboardEvent.event_string)
                        event_string = keyboardEvent.event_string
                        event_string = keynames.getKeyName(event_string)
                        speech.speak(event_string)
                consumed = True
    except:
        debug.printException(debug.LEVEL_SEVERE)

    orca_state.lastInputEvent = keyboardEvent

    # If this is a key event for a non-modifier key, save a handle to it.
    # This is needed to help determine user actions when a multi-key chord
    # has been pressed, and we might get the key events in different orders.
    # See comment #15 of bug #435201 for more details.
    #
    if not _isModifierKey(keyboardEvent.event_string):
        orca_state.lastNonModifierKeyEvent = keyboardEvent

    return consumed or isOrcaModifier
def main():
    """The main entry point for Orca.  The exit codes for Orca will
    loosely be based on signals, where the exit code will be the
    signal used to terminate Orca (if a signal was used).  Otherwise,
    an exit code of 0 means normal completion and an exit code of 50
    means Orca exited because of a hang."""

    global _commandLineSettings

    # Method to call when we think something might be hung.
    #
    settings.timeoutCallback = timeout

    # Various signal handlers we want to listen for.
    #
    signal.signal(signal.SIGHUP, shutdownOnSignal)
    signal.signal(signal.SIGINT, shutdownOnSignal)
    signal.signal(signal.SIGTERM, shutdownOnSignal)
    signal.signal(signal.SIGQUIT, shutdownOnSignal)
    signal.signal(signal.SIGSEGV, abortOnSignal)

    # See if the desktop is running.  If it is, the import of gtk will
    # succeed.  If it isn't, the import will fail.
    #
    desktopRunning = False
    try:
        if gtk.gdk.display_get_default():
            desktopRunning = True
    except:
        pass

    # Parse the command line options.
    #
    # Run the preferences setup if the user has specified
    # "--setup" or "--text-setup" on the command line.  If the
    # desktop is not running, we will fallback to the console-based
    # method as appropriate.
    #
    bypassSetup     = False
    setupRequested  = False
    showGUI         = False

    # We hack a little here because the shell script to start orca can
    # conflate all of command line arguments into one string, which is
    # not what we want.  We detect this by seeing if the length of the
    # argument list is 1.
    #
    arglist = sys.argv[1:]
    if len(arglist) == 1:
        arglist = arglist[0].split()

    try:
        # ? is for help
        # e is for enabling a feature
        # d is for disabling a feature
        # h is for help
        # u is for alternate user preferences location
        # s is for setup
        # n is for no setup
        # t is for text setup
        # v is for version
        #
        opts, args = getopt.getopt(
            arglist,
            "?stnvd:e:u:",
            ["help",
             "user-prefs-dir=",
             "enable=",
             "disable=",
             "setup",
             "gui-setup",
             "text-setup",
             "no-setup",
             "version"])
        for opt, val in opts:
            if opt in ("-u", "--user-prefs-dir"):
                userPrefsDir = val.strip();
                try:
                    os.chdir(userPrefsDir)
                    settings.userPrefsDir = userPrefsDir
                except:
                    debug.printException(debug.LEVEL_FINEST)

            if opt in ("-e", "--enable"):
                feature = val.strip()
                if feature == "speech":
                    _commandLineSettings["enableSpeech"] = True
                elif feature == "braille":
                    _commandLineSettings["enableBraille"] = True
                elif feature == "braille-monitor":
                    _commandLineSettings["enableBrailleMonitor"] = True
                elif feature == "magnifier":
                    _commandLineSettings["enableMagnifier"] = True
                elif feature == "main-window":
                    _commandLineSettings["showMainWindow"] = True
                else:
                    usage()
                    os._exit(2)

            if opt in ("-d", "--disable"):
                feature = val.strip()
                if feature == "speech":
                    _commandLineSettings["enableSpeech"] = False
                elif feature == "braille":
                    _commandLineSettings["enableBraille"] = False
                elif feature == "braille-monitor":
                    _commandLineSettings["enableBrailleMonitor"] = False
                elif feature == "magnifier":
                    _commandLineSettings["enableMagnifier"] = False
                elif feature == "main-window":
                    _commandLineSettings["showMainWindow"] = False
                else:
                    usage()
                    os._exit(2)

            if opt in ("-s", "--gui-setup", "--setup"):
                setupRequested = True
                showGUI = desktopRunning
            if opt in ("-t", "--text-setup"):
                setupRequested = True
                showGUI = False
            if opt in ("-n", "--no-setup"):
                bypassSetup = True
            if opt in ("-?", "--help"):
                usage()
                os._exit(0)
            if opt in ("-v", "--version"):
                print "Orca %s" % platform.version
                os._exit(0)
    except:
        debug.printException(debug.LEVEL_OFF)
        usage()
        os._exit(2)

    # Do not run Orca if accessibility has not been enabled.
    # We do allow, however, one to force Orca to run via the
    # "-n" switch.  The main reason is so that things such
    # as accessible login can work -- in those cases, the gconf
    # setting is typically not set since the gdm user does not
    # have a home.
    #
    a11yEnabled = settings.isAccessibilityEnabled()
    if (not bypassSetup) and (not a11yEnabled):
        _showPreferencesConsole()
        abort()

    if setupRequested and (not bypassSetup) and (not showGUI):
        _showPreferencesConsole()

    if not desktopRunning:
        print "Cannot start Orca because it cannot connect"
        print "to the Desktop.  Please make sure the DISPLAY"
        print "environment variable has been set."
        return 1

    userprefs = settings.userPrefsDir
    sys.path.insert(0, userprefs)
    sys.path.insert(0, '') # current directory

    registry = atspi.Registry()
    init(registry)

    try:
        message = _("Welcome to Orca.")
        speech.speak(message)
        braille.displayMessage(message)
    except:
        debug.printException(debug.LEVEL_SEVERE)

    # Check to see if the user wants the configuration GUI. It's
    # done here so that the user's existing preferences can be used
    # to set the initial GUI state.  We'll also force the set to
    # be run if the preferences file doesn't exist, unless the
    # user has bypassed any setup via the --no-setup switch.
    #
    if setupRequested and (not bypassSetup) and showGUI:
        _showPreferencesGUI()
    elif (not _userSettings) and (not bypassSetup):
        if desktopRunning:
            _showPreferencesGUI()
        else:
            _showPreferencesConsole()

    start(registry) # waits until we stop the registry
    return 0
Exemple #11
0
    def _dequeue(self):
        """Handles all events destined for scripts. Called by the GTK
        idle thread."""

        rerun = True

        if settings.debugEventQueue:
            debug.println(debug.LEVEL_ALL, "event_manager._dequeue %d" % self._dequeueCount)
            self._dequeueCount += 1

        try:
            event = self._eventQueue.get_nowait()
            self._queuePrintln(event, isEnqueue=False)
            inputEvents = (input_event.KeyboardEvent, input_event.BrailleEvent)
            if isinstance(event, inputEvents):
                self._processInputEvent(event)
            else:
                orca_state.currentObjectEvent = event
                debugging = not debug.eventDebugFilter or debug.eventDebugFilter.match(event.type)
                if debugging:
                    startTime = time.time()
                    debug.println(debug.eventDebugLevel, "\nvvvvv PROCESS OBJECT EVENT %s vvvvv" % event.type)
                self._processObjectEvent(event)
                if debugging:
                    debug.println(debug.eventDebugLevel, "TOTAL PROCESSING TIME: %.4f" % (time.time() - startTime))
                    debug.println(debug.eventDebugLevel, "^^^^^ PROCESS OBJECT EVENT %s ^^^^^\n" % event.type)
                orca_state.currentObjectEvent = None

            # [[[TODO: HACK - it would seem logical to only do this if we
            # discover the queue is empty, but this inroduces a hang for
            # some reason if done inside an acquire/release block for a
            # lock.  So...we do it here.]]]
            #
            noFocus = not orca_state.activeScript or (
                not orca_state.locusOfFocus and self.noFocusTimestamp != orca_state.noFocusTimestamp
            )

            self._gidleLock.acquire()
            if self._eventQueue.empty():
                if noFocus:
                    if settings.gilSleepTime:
                        time.sleep(settings.gilSleepTime)
                    # Translators: this is intended to be a short phrase to
                    # speak and braille to tell the user that no component
                    # has keyboard focus.
                    #
                    message = _("No focus")
                    if settings.brailleVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
                        braille.displayMessage(message)
                    if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
                        speech.speak(message)
                    self.noFocusTimestamp = orca_state.noFocusTimestamp
                self._gidleId = 0
                rerun = False  # destroy and don't call again
            self._gidleLock.release()
        except Queue.Empty:
            debug.println(debug.LEVEL_SEVERE, "event_manager._dequeue: the event queue is empty!")
            self._gidleId = 0
            rerun = False  # destroy and don't call again
        except:
            debug.printException(debug.LEVEL_SEVERE)

        if settings.debugEventQueue:
            self._dequeueCount -= 1
            debug.println(debug.LEVEL_ALL, "Leaving _dequeue. Count: %d" % self._dequeueCount)

        return rerun
Exemple #12
0
    def _dequeueEvent(self):
        """Handles all events destined for scripts.  Called by the GTK
        idle thread.
        """

        rerun = True

        if settings.debugEventQueue:
            debug.println(debug.LEVEL_ALL,
                          "Entering focus_tracking_presenter._dequeueEvent" \
                          + " %d" % self._dequeueEventCount)
            self._dequeueEventCount += 1

        try:
            event = self._eventQueue.get_nowait()

            if isinstance(event, input_event.KeyboardEvent):
                if event.type == atspi.Accessibility.KEY_PRESSED_EVENT:
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED KEYPRESS '%s' (%d) <----------" \
                                  % (event.event_string, event.hw_code))
                    pressRelease = "PRESS"
                elif event.type == atspi.Accessibility.KEY_RELEASED_EVENT:
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED KEYRELEASE '%s' (%d) <----------" \
                                  % (event.event_string, event.hw_code))
                    pressRelease = "RELEASE"
                debug.println(debug.eventDebugLevel,
                              "\nvvvvv PROCESS KEY %s EVENT %s vvvvv"\
                              % (pressRelease, event.event_string))
                self._processKeyboardEvent(event)
                debug.println(debug.eventDebugLevel,
                              "\n^^^^^ PROCESS KEY %s EVENT %s ^^^^^"\
                              % (pressRelease, event.event_string))
            elif isinstance(event, input_event.BrailleEvent):
                debug.println(debug.LEVEL_ALL,
                              "DEQUEUED BRAILLE COMMAND %d <----------" \
                              % event.event)
                debug.println(debug.eventDebugLevel,
                              "\nvvvvv PROCESS BRAILLE EVENT %d vvvvv"\
                              % event.event)
                self._processBrailleEvent(event)
                debug.println(debug.eventDebugLevel,
                              "\n^^^^^ PROCESS BRAILLE EVENT %d ^^^^^"\
                              % event.event)
            else:
                if (not debug.eventDebugFilter) \
                    or (debug.eventDebugFilter \
                        and debug.eventDebugFilter.match(event.type)):
                    debug.println(debug.LEVEL_ALL,
                                  "DEQUEUED EVENT %s <----------" \
                                  % event.type)
                    debug.println(debug.eventDebugLevel,
                                  "\nvvvvv PROCESS OBJECT EVENT %s vvvvv" \
                                  % event.type)
                self._processObjectEvent(event)
                if (not debug.eventDebugFilter) \
                    or (debug.eventDebugFilter \
                        and debug.eventDebugFilter.match(event.type)):
                    debug.println(debug.eventDebugLevel,
                                  "^^^^^ PROCESS OBJECT EVENT %s ^^^^^\n" \
                                  % event.type)

            # [[[TODO: HACK - it would seem logical to only do this if we
            # discover the queue is empty, but this inroduces a hang for
            # some reason if done inside an acquire/release block for a
            # lock.  So...we do it here.]]]
            #
            noFocus = (not orca_state.activeScript) \
                      or ((not orca_state.locusOfFocus) \
                          and (self.noFocusTimestamp \
                               != orca_state.noFocusTimestamp))

            self._gidleLock.acquire()
            if self._eventQueue.empty():
                if noFocus:
                    if settings.gilSleepTime:
                        time.sleep(settings.gilSleepTime)
                    # Translators: this is intended to be a short phrase to
                    # speak and braille to tell the user that no component
                    # has keyboard focus.
                    #
                    message = _("No focus")
                    if settings.brailleVerbosityLevel == \
                        settings.VERBOSITY_LEVEL_VERBOSE:
                        braille.displayMessage(message)
                    if settings.speechVerbosityLevel == \
                        settings.VERBOSITY_LEVEL_VERBOSE:
                        speech.speak(message)
                    self.noFocusTimestamp = orca_state.noFocusTimestamp
                self._gidleId = 0
                rerun = False  # destroy and don't call again
            self._gidleLock.release()
        except Queue.Empty:
            debug.println(debug.LEVEL_SEVERE,
                          "focus_tracking_presenter:_dequeueEvent: " \
                          + " the event queue is empty!")
        except:
            debug.printException(debug.LEVEL_SEVERE)

        if settings.debugEventQueue:
            self._dequeueEventCount -= 1
            debug.println(debug.LEVEL_ALL,
                          "Leaving focus_tracking_presenter._dequeueEvent" \
                          + " %d" % self._dequeueEventCount)

        return rerun
Exemple #13
0
def _processKeyboardEvent(event):
    """The primary key event handler for Orca.  Keeps track of various
    attributes, such as the lastInputEvent.  Also calls keyEcho as well
    as any local keybindings before passing the event on to the active
    presentation manager.  This method is called synchronously from the
    AT-SPI registry and should be performant.  In addition, it
    must return True if it has consumed the event (and False if not).

    Arguments:
    - event: an AT-SPI DeviceEvent

    Returns True if the event should be consumed.
    """
    global _orcaModifierPressed

    orca_state.lastInputEventTimestamp = event.timestamp

    # Log the keyboard event for future playback, if desired.
    # Note here that the key event_string being output is
    # exactly what we received.  The KeyboardEvent object,
    # however, will translate the event_string for control
    # characters to their upper case ASCII equivalent.
    #
    string = atspi.KeystrokeListener.keyEventToString(event)
    if _recordingKeystrokes and _keystrokesFile \
       and (event.event_string != "Pause") \
       and (event.event_string != "F21"):
        _keystrokesFile.write(string + "\n")
    debug.printInputEvent(debug.LEVEL_FINE, string)

    keyboardEvent = KeyboardEvent(event)

    # See if this is one of our special Orca modifier keys.
    #
    # [[[TODO: WDW - Note that just looking at the keycode should
    # suffice, but there is a "feature" in the Java Access Bridge
    # where it chooses to emit Java platform-independent keycodes
    # instead of the keycodes for the base platform:
    #
    # http://bugzilla.gnome.org/show_bug.cgi?id=106004
    # http://bugzilla.gnome.org/show_bug.cgi?id=318615
    #
    # So...we need to workaround this problem.
    #
    # If you make the following expression True we will get a positive
    # match for all keysyms associated with a given keysym specified
    # as an Orca modifier key.
    #
    # For example, assume the Orca modifier is set to \ for some
    # reason.  The key that has \ on it produces \ without the Shift
    # key and | with the Shift key.  If the following expression is
    # True, both the \ and | will be viewed as the Orca modifier.  If
    # the following expression is False, only the \ will be viewed as
    # the Orca modifier (i.e., Shift+\ will still function as the |
    # character).  In general, I think we want to avoid sucking in all
    # possible keysyms because it can have unexpected results.]]]
    #
    if False:
        allPossibleKeysyms = []
        for keysym in settings.orcaModifierKeys:
            allPossibleKeysyms.extend(keybindings.getAllKeysyms(keysym))
    else:
        allPossibleKeysyms = settings.orcaModifierKeys

    isOrcaModifier = allPossibleKeysyms.count(keyboardEvent.event_string) > 0

    if event.type == atspi.Accessibility.KEY_PRESSED_EVENT:
        # Key presses always interrupt speech.
        #
        speech.stop()

        # If learn mode is enabled, it will echo the keys.
        #
        if not settings.learnModeEnabled:
            _keyEcho(keyboardEvent)

        # We treat the Insert key as a modifier - so just swallow it and
        # set our internal state.
        #
        if isOrcaModifier:
            _orcaModifierPressed = True

    elif isOrcaModifier \
        and (keyboardEvent.type == atspi.Accessibility.KEY_RELEASED_EVENT):
        _orcaModifierPressed = False

    if _orcaModifierPressed:
        keyboardEvent.modifiers = keyboardEvent.modifiers \
                                  | (1 << settings.MODIFIER_ORCA)

    # Orca gets first stab at the event.  Then, the presenter gets
    # a shot. [[[TODO: WDW - might want to let the presenter try first?
    # The main reason this is staying as is is that we may not want
    # scripts to override fundamental Orca key bindings.]]]
    #
    consumed = False
    try:
        if orca_state.capturingKeys:
            _processKeyCaptured(keyboardEvent)
        else:
            consumed = _keyBindings.consumeKeyboardEvent(None, keyboardEvent)
            if (not consumed) and (_currentPresentationManager >= 0):
                consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].\
                           processKeyboardEvent(keyboardEvent)
            if (not consumed) and settings.learnModeEnabled:
                if keyboardEvent.type \
                    == atspi.Accessibility.KEY_PRESSED_EVENT:
                    clickCount = orca_state.activeScript.getClickCount(\
                                                orca_state.lastInputEvent,
                                                keyboardEvent)
                    if clickCount == 2:
                        orca_state.activeScript.phoneticSpellCurrentItem(\
                            keyboardEvent.event_string)
                    else:
                        # Check to see if there are localized words to be
                        # spoken for this key event.
                        #
                        braille.displayMessage(keyboardEvent.event_string)
                        event_string = keyboardEvent.event_string
                        event_string = keynames.getKeyName(event_string)
                        speech.speak(event_string)
                consumed = True
    except:
        debug.printException(debug.LEVEL_SEVERE)

    orca_state.lastInputEvent = keyboardEvent

    # If this is a key event for a non-modifier key, save a handle to it.
    # This is needed to help determine user actions when a multi-key chord
    # has been pressed, and we might get the key events in different orders.
    # See comment #15 of bug #435201 for more details.
    #
    if not _isModifierKey(keyboardEvent.event_string):
        orca_state.lastNonModifierKeyEvent = keyboardEvent

    return consumed or isOrcaModifier
Exemple #14
0
def main():
    """The main entry point for Orca.  The exit codes for Orca will
    loosely be based on signals, where the exit code will be the
    signal used to terminate Orca (if a signal was used).  Otherwise,
    an exit code of 0 means normal completion and an exit code of 50
    means Orca exited because of a hang."""

    global _commandLineSettings

    # Method to call when we think something might be hung.
    #
    settings.timeoutCallback = timeout

    # Various signal handlers we want to listen for.
    #
    signal.signal(signal.SIGHUP, shutdownOnSignal)
    signal.signal(signal.SIGINT, shutdownOnSignal)
    signal.signal(signal.SIGTERM, shutdownOnSignal)
    signal.signal(signal.SIGQUIT, shutdownOnSignal)
    signal.signal(signal.SIGSEGV, abortOnSignal)

    # See if the desktop is running.  If it is, the import of gtk will
    # succeed.  If it isn't, the import will fail.
    #
    desktopRunning = False
    try:
        if gtk.gdk.display_get_default():
            desktopRunning = True
    except:
        pass

    # Parse the command line options.
    #
    # Run the preferences setup if the user has specified
    # "--setup" or "--text-setup" on the command line.  If the
    # desktop is not running, we will fallback to the console-based
    # method as appropriate.
    #
    bypassSetup = False
    setupRequested = False
    showGUI = False

    # We hack a little here because the shell script to start orca can
    # conflate all of command line arguments into one string, which is
    # not what we want.  We detect this by seeing if the length of the
    # argument list is 1.
    #
    arglist = sys.argv[1:]
    if len(arglist) == 1:
        arglist = arglist[0].split()

    try:
        # ? is for help
        # e is for enabling a feature
        # d is for disabling a feature
        # h is for help
        # u is for alternate user preferences location
        # s is for setup
        # n is for no setup
        # t is for text setup
        # v is for version
        #
        opts, args = getopt.getopt(arglist, "?stnvd:e:u:", [
            "help", "user-prefs-dir=", "enable=", "disable=", "setup",
            "gui-setup", "text-setup", "no-setup", "version"
        ])
        for opt, val in opts:
            if opt in ("-u", "--user-prefs-dir"):
                userPrefsDir = val.strip()
                try:
                    os.chdir(userPrefsDir)
                    settings.userPrefsDir = userPrefsDir
                except:
                    debug.printException(debug.LEVEL_FINEST)

            if opt in ("-e", "--enable"):
                feature = val.strip()
                if feature == "speech":
                    _commandLineSettings["enableSpeech"] = True
                elif feature == "braille":
                    _commandLineSettings["enableBraille"] = True
                elif feature == "braille-monitor":
                    _commandLineSettings["enableBrailleMonitor"] = True
                elif feature == "magnifier":
                    _commandLineSettings["enableMagnifier"] = True
                elif feature == "main-window":
                    _commandLineSettings["showMainWindow"] = True
                else:
                    usage()
                    os._exit(2)

            if opt in ("-d", "--disable"):
                feature = val.strip()
                if feature == "speech":
                    _commandLineSettings["enableSpeech"] = False
                elif feature == "braille":
                    _commandLineSettings["enableBraille"] = False
                elif feature == "braille-monitor":
                    _commandLineSettings["enableBrailleMonitor"] = False
                elif feature == "magnifier":
                    _commandLineSettings["enableMagnifier"] = False
                elif feature == "main-window":
                    _commandLineSettings["showMainWindow"] = False
                else:
                    usage()
                    os._exit(2)

            if opt in ("-s", "--gui-setup", "--setup"):
                setupRequested = True
                showGUI = desktopRunning
            if opt in ("-t", "--text-setup"):
                setupRequested = True
                showGUI = False
            if opt in ("-n", "--no-setup"):
                bypassSetup = True
            if opt in ("-?", "--help"):
                usage()
                os._exit(0)
            if opt in ("-v", "--version"):
                print "Orca %s" % platform.version
                os._exit(0)
    except:
        debug.printException(debug.LEVEL_OFF)
        usage()
        os._exit(2)

    # Do not run Orca if accessibility has not been enabled.
    # We do allow, however, one to force Orca to run via the
    # "-n" switch.  The main reason is so that things such
    # as accessible login can work -- in those cases, the gconf
    # setting is typically not set since the gdm user does not
    # have a home.
    #
    a11yEnabled = settings.isAccessibilityEnabled()
    if (not bypassSetup) and (not a11yEnabled):
        _showPreferencesConsole()
        abort()

    if setupRequested and (not bypassSetup) and (not showGUI):
        _showPreferencesConsole()

    if not desktopRunning:
        print "Cannot start Orca because it cannot connect"
        print "to the Desktop.  Please make sure the DISPLAY"
        print "environment variable has been set."
        return 1

    userprefs = settings.userPrefsDir
    sys.path.insert(0, userprefs)
    sys.path.insert(0, '')  # current directory

    registry = atspi.Registry()
    init(registry)

    try:
        message = _("Welcome to Orca.")
        speech.speak(message)
        braille.displayMessage(message)
    except:
        debug.printException(debug.LEVEL_SEVERE)

    # Check to see if the user wants the configuration GUI. It's
    # done here so that the user's existing preferences can be used
    # to set the initial GUI state.  We'll also force the set to
    # be run if the preferences file doesn't exist, unless the
    # user has bypassed any setup via the --no-setup switch.
    #
    if setupRequested and (not bypassSetup) and showGUI:
        _showPreferencesGUI()
    elif (not _userSettings) and (not bypassSetup):
        if desktopRunning:
            _showPreferencesGUI()
        else:
            _showPreferencesConsole()

    start(registry)  # waits until we stop the registry
    return 0