[orca] Create a separate caret navigation module
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Create a separate caret navigation module
- Date: Tue, 9 Jun 2015 02:21:18 +0000 (UTC)
commit 42193c04bfb154fa983d98b7c7f561e4d18ed98c
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Mon Jun 8 19:46:40 2015 -0400
Create a separate caret navigation module
src/orca/Makefile.am | 1 +
src/orca/caret_navigation.py | 495 +++++++++++++++++++++++++++
src/orca/messages.py | 11 +-
src/orca/script.py | 5 +
src/orca/scripts/toolkits/Gecko/Makefile.am | 1 -
src/orca/scripts/toolkits/Gecko/keymaps.py | 62 ----
src/orca/scripts/toolkits/Gecko/script.py | 465 +++----------------------
7 files changed, 554 insertions(+), 486 deletions(-)
---
diff --git a/src/orca/Makefile.am b/src/orca/Makefile.am
index 87adb66..6445bfc 100644
--- a/src/orca/Makefile.am
+++ b/src/orca/Makefile.am
@@ -14,6 +14,7 @@ orca_python_PYTHON = \
braille_rolenames.py \
brlmon.py \
brltablenames.py \
+ caret_navigation.py \
chat.py \
chnames.py \
cmdnames.py \
diff --git a/src/orca/caret_navigation.py b/src/orca/caret_navigation.py
new file mode 100644
index 0000000..7e06e47
--- /dev/null
+++ b/src/orca/caret_navigation.py
@@ -0,0 +1,495 @@
+# Orca
+#
+# Copyright 2013-2015 Igalia, S.L.
+# Author: Joanmarie Diggs <jdiggs igalia com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA 02110-1301 USA.
+
+"""Provides an Orca-controlled caret for text content."""
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+__date__ = "$Date$"
+__copyright__ = "Copyright (c) 2013-2015 Igalia, S.L."
+__license__ = "LGPL"
+
+from . import cmdnames
+from . import debug
+from . import input_event
+from . import keybindings
+from . import messages
+from . import settings_manager
+
+
+class CaretNavigation:
+ """Implements the caret navigation support available to scripts."""
+
+ def __init__(self, script):
+ if not (script and script.app):
+ msg = "INFO: Caret navigation requires a script and app."
+ debug.println(debug.LEVEL_INFO, msg)
+
+ self._script = script
+ self._handlers = self._setup_handlers()
+ self._bindings = self._setup_bindings()
+
+ def handles_navigation(self, handler):
+ """Returns True if handler is a navigation command."""
+
+ if not handler in self._handlers.values():
+ return False
+
+ if handler.function == self._toggle_enabled:
+ return False
+
+ return True
+
+ def get_bindings(self):
+ """Returns the caret-navigation keybindings."""
+
+ return self._bindings
+
+ def get_handlers(self):
+ """Returns the caret-navigation handlers."""
+
+ return self._handlers
+
+ def _setup_handlers(self):
+ """Sets up and returns the caret-navigation input event handlers."""
+
+ handlers = {}
+
+ if not (self._script and self._script.app):
+ return handlers
+
+ handlers["toggle_enabled"] = \
+ input_event.InputEventHandler(
+ self._toggle_enabled,
+ cmdnames.CARET_NAVIGATION_TOGGLE)
+
+ handlers["next_character"] = \
+ input_event.InputEventHandler(
+ self._next_character,
+ cmdnames.CARET_NAVIGATION_NEXT_CHAR)
+
+ handlers["previous_character"] = \
+ input_event.InputEventHandler(
+ self._previous_character,
+ cmdnames.CARET_NAVIGATION_PREV_CHAR)
+
+ handlers["next_word"] = \
+ input_event.InputEventHandler(
+ self._next_word,
+ cmdnames.CARET_NAVIGATION_NEXT_WORD)
+
+ handlers["previous_word"] = \
+ input_event.InputEventHandler(
+ self._previous_word,
+ cmdnames.CARET_NAVIGATION_PREV_WORD)
+
+ handlers["next_line"] = \
+ input_event.InputEventHandler(
+ self._next_line,
+ cmdnames.CARET_NAVIGATION_NEXT_LINE)
+
+ handlers["previous_line"] = \
+ input_event.InputEventHandler(
+ self._previous_line,
+ cmdnames.CARET_NAVIGATION_PREV_LINE)
+
+ handlers["start_of_file"] = \
+ input_event.InputEventHandler(
+ self._start_of_file,
+ cmdnames.CARET_NAVIGATION_FILE_START)
+
+ handlers["end_of_file"] = \
+ input_event.InputEventHandler(
+ self._end_of_file,
+ cmdnames.CARET_NAVIGATION_FILE_END)
+
+ handlers["start_of_line"] = \
+ input_event.InputEventHandler(
+ self._start_of_line,
+ cmdnames.CARET_NAVIGATION_LINE_START)
+
+ handlers["end_of_line"] = \
+ input_event.InputEventHandler(
+ self._end_of_line,
+ cmdnames.CARET_NAVIGATION_LINE_END)
+
+ return handlers
+
+ def _setup_bindings(self):
+ """Sets up and returns the caret-navigation key bindings."""
+
+ bindings = keybindings.KeyBindings()
+
+ if not (self._script and self._script.app):
+ return bindings
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "F12",
+ keybindings.defaultModifierMask,
+ keybindings.ORCA_MODIFIER_MASK,
+ self._handlers.get("toggle_enabled")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Right",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("next_character")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Left",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("previous_character")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Right",
+ keybindings.defaultModifierMask,
+ keybindings.CTRL_MODIFIER_MASK,
+ self._handlers.get("next_word")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Left",
+ keybindings.defaultModifierMask,
+ keybindings.CTRL_MODIFIER_MASK,
+ self._handlers.get("previous_word")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Down",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("next_line")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Up",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("previous_line")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "End",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("end_of_line")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Home",
+ keybindings.defaultModifierMask,
+ keybindings.NO_MODIFIER_MASK,
+ self._handlers.get("start_of_line")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "End",
+ keybindings.defaultModifierMask,
+ keybindings.CTRL_MODIFIER_MASK,
+ self._handlers.get("end_of_file")))
+
+ bindings.add(
+ keybindings.KeyBinding(
+ "Home",
+ keybindings.defaultModifierMask,
+ keybindings.CTRL_MODIFIER_MASK,
+ self._handlers.get("start_of_file")))
+
+ return bindings
+
+ @staticmethod
+ def _toggle_enabled(script, event):
+ """Toggles caret navigation."""
+
+ if not event:
+ return False
+
+ _settings_manager = settings_manager.getManager()
+ enabled = not _settings_manager.getSetting('caretNavigationEnabled')
+ if enabled:
+ string = messages.CARET_CONTROL_ORCA
+ else:
+ string = messages.CARET_CONTROL_APP
+
+ script.presentMessage(string)
+ _settings_manager.setSetting('caretNavigationEnabled', enabled)
+ return True
+
+ @staticmethod
+ def _next_character(script, event):
+ """Moves to the next character."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.nextContext()
+ if not obj:
+ return False
+
+ script.utilities.setCaretPosition(obj, offset)
+ script.updateBraille(obj)
+ script.sayCharacter(obj)
+ return True
+
+ @staticmethod
+ def _previous_character(script, event):
+ """Moves to the previous character."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.previousContext()
+ if not obj:
+ return False
+
+ script.utilities.setCaretPosition(obj, offset)
+ script.updateBraille(obj)
+ script.sayCharacter(obj)
+ return True
+
+ @staticmethod
+ def _next_word(script, event):
+ """Moves to the next word."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.nextContext(skipSpace=True)
+ contents = script.utilities.getWordContentsAtOffset(obj, offset)
+ if not contents:
+ return False
+
+ obj, end, string = contents[-1][0], contents[-1][2], contents[-1][3]
+ if string and not string[-1].isalnum():
+ end -= 1
+
+ script.utilities.setCaretPosition(obj, end)
+ script.updateBraille(obj)
+ script.sayWord(obj)
+ return True
+
+ @staticmethod
+ def _previous_word(script, event):
+ """Moves to the previous word."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.previousContext(skipSpace=True)
+ contents = script.utilities.getWordContentsAtOffset(obj, offset)
+ if not contents:
+ return False
+
+ obj, start = contents[0][0], contents[0][1]
+ script.utilities.setCaretPosition(obj, start)
+ script.updateBraille(obj)
+ script.sayWord(obj)
+ return True
+
+ @staticmethod
+ def _next_line(script, event):
+ """Moves to the next line."""
+
+ if not event:
+ return False
+
+ if script.inSayAll():
+ _settings_manager = settings_manager.getManager()
+ if _settings_manager.getSetting('rewindAndFastForwardInSayAll'):
+ msg = "INFO: inSayAll and rewindAndFastforwardInSayAll is enabled"
+ debug.println(debug.LEVEL_INFO, msg)
+ return True
+
+ obj, offset = script.utilities.getCaretContext()
+ msg = "INFO: Current context is: %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ if obj and script.utilities.isZombie(obj):
+ msg = "INFO: Current context obj %s is zombie" % obj
+ debug.println(debug.LEVEL_INFO, msg)
+
+ line = script.utilities.getLineContentsAtOffset(obj, offset)
+ msg = "INFO: Line contents for %s, %i: %s" % (obj, offset, line)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ if not (line and line[0]):
+ return False
+
+ lastObj, lastOffset = line[-1][0], line[-1][2] - 1
+ msg = "INFO: Last context on line is: %s, %i" % (lastObj, lastOffset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ obj, offset = script.utilities.nextContext(lastObj, lastOffset, True)
+ msg = "INFO: Next context is: %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ contents = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not contents:
+ msg = "INFO: Could not get line contents for %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+ return False
+
+ obj, start = contents[0][0], contents[0][1]
+ script.utilities.setCaretPosition(obj, start)
+ script.speakContents(contents)
+ script.displayContents(contents)
+ return True
+
+ @staticmethod
+ def _previous_line(script, event):
+ """Moves to the previous line."""
+
+ if not event:
+ return False
+
+ if script.inSayAll():
+ _settings_manager = settings_manager.getManager()
+ if _settings_manager.getSetting('rewindAndFastForwardInSayAll'):
+ msg = "INFO: inSayAll and rewindAndFastforwardInSayAll is enabled"
+ debug.println(debug.LEVEL_INFO, msg)
+ return True
+
+ obj, offset = script.utilities.getCaretContext()
+ msg = "INFO: Current context is: %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ if obj and script.utilities.isZombie(obj):
+ msg = "INFO: Current context obj %s is zombie" % obj
+ debug.println(debug.LEVEL_INFO, msg)
+
+ line = script.utilities.getLineContentsAtOffset(obj, offset)
+ msg = "INFO: Line contents for %s, %i: %s" % (obj, offset, line)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ if not (line and line[0]):
+ return False
+
+ firstObj, firstOffset = line[0][0], line[0][1]
+ msg = "INFO: First context on line is: %s, %i" % (firstObj, firstOffset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ obj, offset = script.utilities.previousContext(firstObj, firstOffset, True)
+ msg = "INFO: Previous context is: %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+
+ contents = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not contents:
+ msg = "INFO: Could not get line contents for %s, %i" % (obj, offset)
+ debug.println(debug.LEVEL_INFO, msg)
+ return False
+
+ obj, start = contents[0][0], contents[0][1]
+ script.utilities.setCaretPosition(obj, start)
+ script.speakContents(contents)
+ script.displayContents(contents)
+ return True
+
+ @staticmethod
+ def _start_of_line(script, event):
+ """Moves to the start of the line."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.getCaretContext()
+ line = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not (line and line[0]):
+ return False
+
+ obj, start = line[0][0], line[0][1]
+ script.utilities.setCaretPosition(obj, start)
+ script.sayCharacter(obj)
+ script.displayContents(line)
+ return True
+
+ @staticmethod
+ def _end_of_line(script, event):
+ """Moves to the end of the line."""
+
+ if not event:
+ return False
+
+ obj, offset = script.utilities.getCaretContext()
+ line = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not (line and line[0]):
+ return False
+
+ obj, end, string = line[-1][0], line[-1][2], line[-1][3]
+ if string.strip() and string[-1].isspace():
+ end -= 1
+
+ script.utilities.setCaretPosition(obj, end)
+ script.sayCharacter(obj)
+ script.displayContents(line)
+ return True
+
+ @staticmethod
+ def _start_of_file(script, event):
+ """Moves to the start of the file."""
+
+ if not event:
+ return False
+
+ document = script.utilities.documentFrame()
+ obj, offset = script.utilities.findFirstCaretContext(document, 0)
+ contents = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not contents:
+ return False
+
+ obj, offset = contents[0][0], contents[0][1]
+ script.utilities.setCaretPosition(obj, offset)
+ script.speakContents(contents)
+ script.displayContents(contents)
+ return True
+
+ @staticmethod
+ def _end_of_file(script, event):
+ """Moves to the end of the file."""
+
+ if not event:
+ return False
+
+ document = script.utilities.documentFrame()
+ obj = script.utilities.getLastObjectInDocument(document)
+ offset = 0
+ text = script.utilities.queryNonEmptyText(obj)
+ if text:
+ offset = text.characterCount - 1
+
+ while obj:
+ lastobj, lastoffset = script.utilities.nextContext(obj, offset)
+ if not lastobj:
+ break
+ obj, offset = lastobj, lastoffset
+
+ contents = script.utilities.getLineContentsAtOffset(obj, offset)
+ if not contents:
+ return False
+
+ obj, offset = contents[-1][0], contents[-1][2]
+ script.utilities.setCaretPosition(obj, offset)
+ script.speakContents(contents)
+ script.displayContents(contents)
+ return True
diff --git a/src/orca/messages.py b/src/orca/messages.py
index 2771a2b..429119a 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -164,11 +164,12 @@ CAPITALIZATION_SPELL_BRIEF = C_("capitalization style", "spell")
# to get into a GUI.
CAPITALIZATION_SPELL_FULL = _("Capitalization style set to spell.")
-# Translators: Gecko native caret navigation is where Firefox (or Thunderbird)
-# itself controls how the arrow keys move the caret around HTML content. It's
-# often broken, so Orca needs to provide its own support. As such, Orca offers
-# the user the ability to toggle which application is controlling the caret.
-CARET_CONTROL_GECKO = _("Gecko is controlling the caret.")
+# Translators: Native application caret navigation does not always work as the
+# Orca user wants. As such, Orca offers the user the ability to toggle between
+# the application controlling the caret and Orca controlling it. This message
+# is presented to indicate that the application's native caret navigation is
+# active / not being overridden by Orca.
+CARET_CONTROL_APP = _("The application is controlling the caret.")
# Translators: Gecko native caret navigation is where Firefox (or Thunderbird)
# itself controls how the arrow keys move the caret around HTML content. It's
diff --git a/src/orca/script.py b/src/orca/script.py
index 05e1ae3..a228382 100644
--- a/src/orca/script.py
+++ b/src/orca/script.py
@@ -100,6 +100,7 @@ class Script:
self.utilities = self.getUtilities()
self.labelInference = self.getLabelInference()
self.structuralNavigation = self.getStructuralNavigation()
+ self.caretNavigation = self.getCaretNavigation()
self.bookmarks = self.getBookmarks()
self.liveRegionManager = self.getLiveRegionManager()
@@ -226,6 +227,10 @@ class Script:
"""Returns the spellcheck support for this script."""
return None
+ def getCaretNavigation(self):
+ """Returns the caret navigation support for this script."""
+ return None
+
def getUtilities(self):
"""Returns the utilites for this script.
"""
diff --git a/src/orca/scripts/toolkits/Gecko/Makefile.am b/src/orca/scripts/toolkits/Gecko/Makefile.am
index 9086687..ddcdb9c 100644
--- a/src/orca/scripts/toolkits/Gecko/Makefile.am
+++ b/src/orca/scripts/toolkits/Gecko/Makefile.am
@@ -2,7 +2,6 @@ orca_python_PYTHON = \
__init__.py \
bookmarks.py \
braille_generator.py \
- keymaps.py \
script.py \
script_utilities.py \
speech_generator.py \
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 0424d5e..8520ff2 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -43,6 +43,7 @@ import pyatspi
import time
import orca.braille as braille
+import orca.caret_navigation as caret_navigation
import orca.cmdnames as cmdnames
import orca.debug as debug
import orca.scripts.default as default
@@ -59,7 +60,6 @@ import orca.settings_manager as settings_manager
import orca.speech as speech
import orca.speechserver as speechserver
-from . import keymaps
from .braille_generator import BrailleGenerator
from .speech_generator import SpeechGenerator
from .bookmarks import GeckoBookmarks
@@ -106,21 +106,6 @@ class Script(default.Script):
self.autoFocusModeCaretNavCheckButton = None
self.layoutModeCheckButton = None
- # _caretNavigationFunctions are functions that represent fundamental
- # ways to move the caret (e.g., by the arrow keys).
- #
- self._caretNavigationFunctions = \
- [Script.goNextCharacter,
- Script.goPreviousCharacter,
- Script.goNextWord,
- Script.goPreviousWord,
- Script.goNextLine,
- Script.goPreviousLine,
- Script.goTopOfFile,
- Script.goBottomOfFile,
- Script.goBeginningOfLine,
- Script.goEndOfLine]
-
if _settingsManager.getSetting('caretNavigationEnabled') == None:
_settingsManager.setSetting('caretNavigationEnabled', True)
if _settingsManager.getSetting('sayAllOnLoad') == None:
@@ -296,71 +281,23 @@ class Script(default.Script):
enable = _settingsManager.getSetting('structuralNavigationEnabled')
return GeckoStructuralNavigation(self, types, enable)
- def setupInputEventHandlers(self):
- """Defines InputEventHandler fields for this script that can be
- called by the key and braille bindings.
- """
-
- default.Script.setupInputEventHandlers(self)
- self.inputEventHandlers.update(\
- self.structuralNavigation.inputEventHandlers)
+ def getCaretNavigation(self):
+ """Returns the caret navigation support for this script."""
- self.inputEventHandlers.update(self.liveRegionManager.inputEventHandlers)
+ return caret_navigation.CaretNavigation(self)
- self.inputEventHandlers["goNextCharacterHandler"] = \
- input_event.InputEventHandler(
- Script.goNextCharacter,
- cmdnames.CARET_NAVIGATION_NEXT_CHAR)
-
- self.inputEventHandlers["goPreviousCharacterHandler"] = \
- input_event.InputEventHandler(
- Script.goPreviousCharacter,
- cmdnames.CARET_NAVIGATION_PREV_CHAR)
-
- self.inputEventHandlers["goNextWordHandler"] = \
- input_event.InputEventHandler(
- Script.goNextWord,
- cmdnames.CARET_NAVIGATION_NEXT_WORD)
-
- self.inputEventHandlers["goPreviousWordHandler"] = \
- input_event.InputEventHandler(
- Script.goPreviousWord,
- cmdnames.CARET_NAVIGATION_PREV_WORD)
-
- self.inputEventHandlers["goNextLineHandler"] = \
- input_event.InputEventHandler(
- Script.goNextLine,
- cmdnames.CARET_NAVIGATION_NEXT_LINE)
-
- self.inputEventHandlers["goPreviousLineHandler"] = \
- input_event.InputEventHandler(
- Script.goPreviousLine,
- cmdnames.CARET_NAVIGATION_PREV_LINE)
-
- self.inputEventHandlers["goTopOfFileHandler"] = \
- input_event.InputEventHandler(
- Script.goTopOfFile,
- cmdnames.CARET_NAVIGATION_FILE_START)
-
- self.inputEventHandlers["goBottomOfFileHandler"] = \
- input_event.InputEventHandler(
- Script.goBottomOfFile,
- cmdnames.CARET_NAVIGATION_FILE_END)
+ def setupInputEventHandlers(self):
+ """Defines InputEventHandlers for this script."""
- self.inputEventHandlers["goBeginningOfLineHandler"] = \
- input_event.InputEventHandler(
- Script.goBeginningOfLine,
- cmdnames.CARET_NAVIGATION_LINE_START)
+ super().setupInputEventHandlers()
+ self.inputEventHandlers.update(
+ self.structuralNavigation.inputEventHandlers)
- self.inputEventHandlers["goEndOfLineHandler"] = \
- input_event.InputEventHandler(
- Script.goEndOfLine,
- cmdnames.CARET_NAVIGATION_LINE_END)
+ self.inputEventHandlers.update(
+ self.caretNavigation.get_handlers())
- self.inputEventHandlers["toggleCaretNavigationHandler"] = \
- input_event.InputEventHandler(
- Script.toggleCaretNavigation,
- cmdnames.CARET_NAVIGATION_TOGGLE)
+ self.inputEventHandlers.update(
+ self.liveRegionManager.inputEventHandlers)
self.inputEventHandlers["sayAllHandler"] = \
input_event.InputEventHandler(
@@ -394,28 +331,17 @@ class Script(default.Script):
Script.enableStickyFocusMode,
cmdnames.SET_FOCUS_MODE_STICKY)
- def __getArrowBindings(self):
- """Returns an instance of keybindings.KeyBindings that use the
- arrow keys for navigating HTML content.
- """
-
- keyBindings = keybindings.KeyBindings()
- keyBindings.load(keymaps.arrowKeymap, self.inputEventHandlers)
- return keyBindings
-
def getToolkitKeyBindings(self):
"""Returns the toolkit-specific keybindings for this script."""
keyBindings = keybindings.KeyBindings()
- keyBindings.load(keymaps.commonKeymap, self.inputEventHandlers)
-
- if _settingsManager.getSetting('caretNavigationEnabled'):
- for keyBinding in self.__getArrowBindings().keyBindings:
- keyBindings.add(keyBinding)
+ structNavBindings = self.structuralNavigation.keyBindings
+ for keyBinding in structNavBindings.keyBindings:
+ keyBindings.add(keyBinding)
- bindings = self.structuralNavigation.keyBindings
- for keyBinding in bindings.keyBindings:
+ caretNavBindings = self.caretNavigation.get_bindings()
+ for keyBinding in caretNavBindings.keyBindings:
keyBindings.add(keyBinding)
liveRegionBindings = self.liveRegionManager.keyBindings
@@ -627,85 +553,41 @@ class Script(default.Script):
}
def consumesKeyboardEvent(self, keyboardEvent):
- """Called when a key is pressed on the keyboard.
-
- Arguments:
- - keyboardEvent: an instance of input_event.KeyboardEvent
-
- Returns True if the event is of interest.
- """
+ """Returns True if the script will consume this keyboard event."""
# We need to do this here. Orca caret and structural navigation
# often result in the user being repositioned without our getting
# a corresponding AT-SPI event. Without an AT-SPI event, script.py
# won't know to dump the generator cache. See bgo#618827.
- #
self.generatorCache = {}
- # The reason we override this method is that we only want
- # to consume keystrokes under certain conditions. For
- # example, we only control the arrow keys when we're
- # managing caret navigation and we're inside document content.
- #
- # [[[TODO: WDW - this might be broken when we're inside a
- # text area that's inside document (or anything else that
- # we want to allow to control its own destiny).]]]
-
- user_bindings = None
- user_bindings_map = _settingsManager.getSetting('keyBindingsMap')
- if self.__module__ in user_bindings_map:
- user_bindings = user_bindings_map[self.__module__]
- elif "default" in user_bindings_map:
- user_bindings = user_bindings_map["default"]
-
- consumes = False
- if user_bindings:
- handler = user_bindings.getInputHandler(keyboardEvent)
- if handler and handler.function in self._caretNavigationFunctions:
- consumes = self.useCaretNavigationModel(keyboardEvent)
- self._lastCommandWasCaretNav = consumes
- self._lastCommandWasStructNav = False
- self._lastCommandWasMouseButton = False
- elif handler and handler.function in self.structuralNavigation.functions:
- consumes = self.useStructuralNavigationModel()
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = consumes
- self._lastCommandWasMouseButton = False
- elif handler and handler.function in self.liveRegionManager.functions:
- # This is temporary.
- consumes = self.useStructuralNavigationModel()
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = consumes
- self._lastCommandWasMouseButton = False
- else:
- consumes = handler != None
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = False
- self._lastCommandWasMouseButton = False
- if not consumes:
- handler = self.keyBindings.getInputHandler(keyboardEvent)
- if handler and handler.function in self._caretNavigationFunctions:
- consumes = self.useCaretNavigationModel(keyboardEvent)
- self._lastCommandWasCaretNav = consumes
- self._lastCommandWasStructNav = False
- self._lastCommandWasMouseButton = False
- elif handler and handler.function in self.structuralNavigation.functions:
- consumes = self.useStructuralNavigationModel()
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = consumes
- self._lastCommandWasMouseButton = False
- elif handler and handler.function in self.liveRegionManager.functions:
- # This is temporary.
- consumes = self.useStructuralNavigationModel()
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = consumes
- self._lastCommandWasMouseButton = False
- else:
- consumes = handler != None
- self._lastCommandWasCaretNav = False
- self._lastCommandWasStructNav = False
- self._lastCommandWasMouseButton = False
- return consumes
+ handler = self.keyBindings.getInputHandler(keyboardEvent)
+ if handler and self.caretNavigation.handles_navigation(handler):
+ consumes = self.useCaretNavigationModel(keyboardEvent)
+ self._lastCommandWasCaretNav = consumes
+ self._lastCommandWasStructNav = False
+ self._lastCommandWasMouseButton = False
+ return consumes
+
+ if handler and handler.function in self.structuralNavigation.functions:
+ consumes = self.useStructuralNavigationModel()
+ self._lastCommandWasCaretNav = False
+ self._lastCommandWasStructNav = consumes
+ self._lastCommandWasMouseButton = False
+ return consumes
+
+ if handler and handler.function in self.liveRegionManager.functions:
+ # This is temporary.
+ consumes = self.useStructuralNavigationModel()
+ self._lastCommandWasCaretNav = False
+ self._lastCommandWasStructNav = consumes
+ self._lastCommandWasMouseButton = False
+ return consumes
+
+ self._lastCommandWasCaretNav = False
+ self._lastCommandWasStructNav = False
+ self._lastCommandWasMouseButton = False
+ return handler != None
# TODO - JD: This needs to be moved out of the scripts.
def textLines(self, obj, offset=None):
@@ -1711,8 +1593,7 @@ class Script(default.Script):
return True
def useCaretNavigationModel(self, keyboardEvent):
- """Returns True if we should do our own caret navigation.
- """
+ """Returns True if we should do our own caret navigation."""
if not _settingsManager.getSetting('caretNavigationEnabled') \
or self._inFocusMode:
@@ -1721,15 +1602,9 @@ class Script(default.Script):
if not self.utilities.inDocumentContent():
return False
- if keyboardEvent.event_string in ["Page_Up", "Page_Down"]:
- return False
-
if keyboardEvent.modifiers & keybindings.SHIFT_MODIFIER_MASK:
return False
- if not orca_state.locusOfFocus:
- return False
-
return True
def useStructuralNavigationModel(self):
@@ -1849,235 +1724,6 @@ class Script(default.Script):
self.inMouseOverObject = False
self.lastMouseOverObject = None
- def goNextCharacter(self, inputEvent):
- """Positions the caret offset to the next character or object
- in the document window.
- """
- [obj, characterOffset] = self.utilities.getCaretContext()
- while obj:
- [obj, characterOffset] = self.utilities.findNextCaretInOrder(obj,
- characterOffset)
- if obj and obj.getState().contains(pyatspi.STATE_VISIBLE):
- break
-
- if not obj:
- [obj, characterOffset] = self.utilities.getBottomOfFile()
-
- self.utilities.setCaretPosition(obj, characterOffset)
- self.speakCharacterAtOffset(obj, characterOffset)
- self.updateBraille(obj)
-
- def goPreviousCharacter(self, inputEvent):
- """Positions the caret offset to the previous character or object
- in the document window.
- """
- [obj, characterOffset] = self.utilities.getCaretContext()
- while obj:
- [obj, characterOffset] = self.utilities.findPreviousCaretInOrder(
- obj, characterOffset)
- if obj and obj.getState().contains(pyatspi.STATE_VISIBLE):
- break
-
- if not obj:
- [obj, characterOffset] = self.utilities.getTopOfFile()
-
- self.utilities.setCaretPosition(obj, characterOffset)
- self.speakCharacterAtOffset(obj, characterOffset)
- self.updateBraille(obj)
-
- def goPreviousWord(self, inputEvent):
- """Positions the caret offset to beginning of the previous
- word or object in the document window.
- """
-
- [obj, characterOffset] = self.utilities.getCaretContext()
-
- # Make sure we have a word.
- #
- [obj, characterOffset] = \
- self.utilities.findPreviousCaretInOrder(obj, characterOffset)
-
- contents = self.utilities.getWordContentsAtOffset(obj, characterOffset)
- if not len(contents):
- return
-
- [obj, startOffset, endOffset, string] = contents[0]
- if len(contents) == 1 \
- and endOffset - startOffset == 1 \
- and self.utilities.getCharacterAtOffset(obj, startOffset) == " ":
- # Our "word" is just a space. This can happen if the previous
- # word was a mark of punctuation surrounded by whitespace (e.g.
- # " | ").
- #
- [obj, characterOffset] = \
- self.utilities.findPreviousCaretInOrder(obj, startOffset)
- contents = self.utilities.getWordContentsAtOffset(obj, characterOffset)
- if len(contents):
- [obj, startOffset, endOffset, string] = contents[0]
-
- self.utilities.setCaretPosition(obj, startOffset)
- self.updateBraille(obj)
- self.speakMisspelledIndicator(obj, startOffset)
- self.speakContents(contents)
-
- def goNextWord(self, inputEvent):
- """Positions the caret offset to the end of next word or object
- in the document window.
- """
-
- [obj, characterOffset] = self.utilities.getCaretContext()
-
- # Make sure we have a word.
- #
- characterOffset = max(0, characterOffset)
- [obj, characterOffset] = \
- self.utilities.findNextCaretInOrder(obj, characterOffset)
-
- contents = self.utilities.getWordContentsAtOffset(obj, characterOffset)
- if not (len(contents) and contents[-1][2]):
- return
-
- [obj, startOffset, endOffset, string] = contents[-1]
- if string and string[-1].isspace():
- endOffset -= 1
- self.utilities.setCaretPosition(obj, endOffset)
- self.updateBraille(obj)
- self.speakMisspelledIndicator(obj, startOffset)
- self.speakContents(contents)
-
- def goPreviousLine(self, inputEvent):
- """Positions the caret offset at the previous line in the document
- window, attempting to preserve horizontal caret position.
-
- Returns True if we actually moved.
- """
-
- if self._inSayAll \
- and _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
- msg = "INFO: inSayAll and rewindAndFastforwardInSayAll is enabled"
- debug.println(debug.LEVEL_INFO, msg)
- return True
-
- obj, offset = self.utilities.getCaretContext()
- msg = "INFO: Current context is: %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
-
- if obj and self.utilities.isZombie(obj):
- msg = "INFO: Current context obj %s is zombie" % obj
- debug.println(debug.LEVEL_INFO, msg)
-
- line = self.utilities.getLineContentsAtOffset(obj, offset)
- msg = "INFO: Line contents for %s, %i: %s" % (obj, offset, line)
- debug.println(debug.LEVEL_INFO, msg)
-
- if not (line and line[0]):
- return False
-
- firstObj, firstOffset = line[0][0], line[0][1]
- msg = "INFO: First context on line is: %s, %i" % (firstObj, firstOffset)
- debug.println(debug.LEVEL_INFO, msg)
-
- obj, offset = self.utilities.previousContext(firstObj, firstOffset, True)
- msg = "INFO: Previous context is: %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
-
- contents = self.utilities.getLineContentsAtOffset(obj, offset)
- if not contents:
- msg = "INFO: Could not get line contents for %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
- return False
-
- obj, start = contents[0][0], contents[0][1]
- self.utilities.setCaretPosition(obj, start)
- self.displayContents(contents)
- self.speakContents(contents)
-
- return True
-
- def goNextLine(self, inputEvent):
- """Positions the caret offset at the next line in the document
- window, attempting to preserve horizontal caret position.
-
- Returns True if we actually moved.
- """
-
- if self._inSayAll \
- and _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
- msg = "INFO: inSayAll and rewindAndFastforwardInSayAll is enabled"
- debug.println(debug.LEVEL_INFO, msg)
- return True
-
- obj, offset = self.utilities.getCaretContext()
- msg = "INFO: Current context is: %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
-
- if obj and self.utilities.isZombie(obj):
- msg = "INFO: Current context obj %s is zombie" % obj
- debug.println(debug.LEVEL_INFO, msg)
-
- line = self.utilities.getLineContentsAtOffset(obj, offset)
- msg = "INFO: Line contents for %s, %i: %s" % (obj, offset, line)
- debug.println(debug.LEVEL_INFO, msg)
-
- if not (line and line[0]):
- return False
-
- lastObj, lastOffset = line[-1][0], line[-1][2] - 1
- msg = "INFO: Last context on line is: %s, %i" % (lastObj, lastOffset)
- debug.println(debug.LEVEL_INFO, msg)
-
- obj, offset = self.utilities.nextContext(lastObj, lastOffset, True)
- msg = "INFO: Next context is: %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
-
- contents = self.utilities.getLineContentsAtOffset(obj, offset)
- if not contents:
- msg = "INFO: Could not get line contents for %s, %i" % (obj, offset)
- debug.println(debug.LEVEL_INFO, msg)
- return False
-
- obj, start = contents[0][0], contents[0][1]
- self.utilities.setCaretPosition(obj, start)
- self.speakContents(contents)
- self.displayContents(contents)
- return True
-
- def goBeginningOfLine(self, inputEvent):
- """Positions the caret offset at the beginning of the line."""
-
- [obj, characterOffset] = self.utilities.getCaretContext()
- line = self.utilities.getLineContentsAtOffset(obj, characterOffset)
- obj, characterOffset = self.utilities.findFirstCaretContext(line[0][0], line[0][1])
- self.utilities.setCaretPosition(obj, characterOffset)
- if not isinstance(orca_state.lastInputEvent, input_event.BrailleEvent):
- self.speakCharacterAtOffset(obj, characterOffset)
- self.updateBraille(obj)
-
- def goEndOfLine(self, inputEvent):
- """Positions the caret offset at the end of the line."""
-
- [obj, characterOffset] = self.utilities.getCaretContext()
- line = self.utilities.getLineContentsAtOffset(obj, characterOffset)
- obj, characterOffset = line[-1][0], line[-1][2] - 1
- self.utilities.setCaretPosition(obj, characterOffset)
- if not isinstance(orca_state.lastInputEvent, input_event.BrailleEvent):
- self.speakCharacterAtOffset(obj, characterOffset)
- self.updateBraille(obj)
-
- def goTopOfFile(self, inputEvent):
- """Positions the caret offset at the beginning of the document."""
-
- [obj, characterOffset] = self.utilities.getTopOfFile()
- self.utilities.setCaretPosition(obj, characterOffset)
- self.presentLine(obj, characterOffset)
-
- def goBottomOfFile(self, inputEvent):
- """Positions the caret offset at the end of the document."""
-
- [obj, characterOffset] = self.utilities.getBottomOfFile()
- self.utilities.setCaretPosition(obj, characterOffset)
- self.presentLine(obj, characterOffset)
-
def enableStickyFocusMode(self, inputEvent):
self._inFocusMode = True
self._focusModeIsSticky = True
@@ -2101,23 +1747,6 @@ class Script(default.Script):
self._inFocusMode = not self._inFocusMode
self._focusModeIsSticky = False
- def toggleCaretNavigation(self, inputEvent):
- """Toggles between Firefox native and Orca caret navigation."""
-
- if _settingsManager.getSetting('caretNavigationEnabled'):
- for keyBinding in self.__getArrowBindings().keyBindings:
- self.keyBindings.removeByHandler(keyBinding.handler)
- _settingsManager.setSetting('caretNavigationEnabled', False)
- string = messages.CARET_CONTROL_GECKO
- else:
- _settingsManager.setSetting('caretNavigationEnabled', True)
- for keyBinding in self.__getArrowBindings().keyBindings:
- self.keyBindings.add(keyBinding)
- string = messages.CARET_CONTROL_ORCA
-
- debug.println(debug.LEVEL_CONFIGURATION, string)
- self.presentMessage(string)
-
def speakWordUnderMouse(self, acc):
"""Determine if the speak-word-under-mouse capability applies to
the given accessible.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]