orca r3909 - in trunk: . src/orca src/orca/scripts/apps/gedit src/orca/scripts/apps/soffice
- From: richb svn gnome org
- To: svn-commits-list gnome org
- Subject: orca r3909 - in trunk: . src/orca src/orca/scripts/apps/gedit src/orca/scripts/apps/soffice
- Date: Tue, 20 May 2008 20:27:27 +0000 (UTC)
Author: richb
Date: Tue May 20 20:27:27 2008
New Revision: 3909
URL: http://svn.gnome.org/viewvc/orca?rev=3909&view=rev
Log:
* src/orca/scripts/apps/gedit/script.py:
src/orca/scripts/apps/soffice/script.py:
src/orca/default.py:
src/orca/where_am_I.py:
Fixed bug #517048 - Orca does not always speak the correct
information when navigating and/or selecting text across
object boundaries in OOo Writer.
Modified:
trunk/ChangeLog
trunk/src/orca/default.py
trunk/src/orca/scripts/apps/gedit/script.py
trunk/src/orca/scripts/apps/soffice/script.py
trunk/src/orca/where_am_I.py
Modified: trunk/src/orca/default.py
==============================================================================
--- trunk/src/orca/default.py (original)
+++ trunk/src/orca/default.py Tue May 20 20:27:27 2008
@@ -3133,8 +3133,81 @@
self.pointOfReference['oldName'] = event.source.name
orca.visualAppearanceChanged(event, event.source)
- def _presentTextAtNewCaretPosition(self, event):
+ def _speakContiguousSelection(self, obj, relationship):
+ """Check if the contiguous object has a selection. If it does, then
+ speak it. If the user pressed Shift-Down, then look for an object
+ with a RELATION_FLOWS_FROM relationship. If they pressed Shift-Up,
+ then look for a RELATION_FLOWS_TO relationship.
+
+ Arguments:
+ - the current text object
+ - the flows relationship (RELATION_FLOWS_FROM or RELATION_FLOWS_TO).
+
+ Returns an indication of whether anything was spoken.
+ """
+
+ lastPos = self.pointOfReference.get("lastCursorPosition")
+
+ # Reasons to NOT speak contiguous selections:
+ #
+ # 1. The new cursor position is in the same object as the old
+ # cursor position. (The change in selection is all within
+ # the current object.)
+ # 2. If we are selecting up line by line from the beginning of
+ # the line and have just crossed into a new object, the change
+ # in selection is the previous line (which has just become
+ # selected). Nothing has changed on the line we came from.
+ #
+ if self.isSameObject(lastPos[0], obj) \
+ or relationship == pyatspi.RELATION_FLOWS_TO and lastPos[1] == 0:
+ return False
+
+ selSpoken = False
+ current = obj
+ for relation in current.getRelationSet():
+ if relation.getRelationType() == relationship:
+ obj = relation.getTarget(0)
+ objText = obj.queryText()
+
+ # When selecting down across paragraph boundaries, what
+ # we've (un)selected on (what is now) the previous line
+ # is from wherever the cursor used to be to the end of
+ # the line.
+ #
+ if relationship == pyatspi.RELATION_FLOWS_FROM:
+ start, end = lastPos[1], objText.characterCount
+
+ # When selecting up across paragraph boundaries, what
+ # we've (un)selected on (what is now) the next line is
+ # from the beginning of the line to wherever the cursor
+ # used to be.
+ #
+ else:
+ start, end = 0, lastPos[1]
+ if objText.getNSelections() > 0:
+ [textContents, startOffset, endOffset] = \
+ self.whereAmI.getTextSelection(obj)
+
+ # Now that we have the full selection, adjust based
+ # on the relation type. (see above comment)
+ #
+ startOffset = start or startOffset
+ endOffset = end or endOffset
+ self.sayPhrase(obj, startOffset, endOffset)
+ selSpoken = True
+ else:
+ # We don't have selections in this object. But we're
+ # here, which means that something is selected in a
+ # neighboring object and the text in this object must
+ # have just become unselected and needs to be spoken.
+ #
+ self.sayPhrase(obj, start, end)
+ selSpoken = True
+
+ return selSpoken
+
+ def _presentTextAtNewCaretPosition(self, event):
obj = event.source
text = obj.queryText()
@@ -3179,7 +3252,8 @@
mods = orca_state.lastInputEvent.modifiers
isControlKey = mods & (1 << pyatspi.MODIFIER_CONTROL)
isShiftKey = mods & (1 << pyatspi.MODIFIER_SHIFT)
- hasLastPos = self.pointOfReference.has_key("lastCursorPosition")
+ lastPos = self.pointOfReference.get("lastCursorPosition")
+ hasLastPos = (lastPos != None)
if (keyString == "Up") or (keyString == "Down"):
# If the user has typed Shift-Up or Shift-Down, then we want
@@ -3188,8 +3262,39 @@
# currently positioned.
#
if hasLastPos and isShiftKey and not isControlKey:
- [startOffset, endOffset] = self.getOffsetsForPhrase(obj)
- self.sayPhrase(obj, startOffset, endOffset)
+ if keyString == "Up":
+ # If we have just crossed a paragraph boundary with
+ # Shift+Up, what we've selected in this object starts
+ # with the current offset and goes to the end of the
+ # paragraph.
+ #
+ if not self.isSameObject(lastPos[0], obj):
+ [startOffset, endOffset] = \
+ text.caretOffset, text.characterCount
+ else:
+ [startOffset, endOffset] \
+ = self.getOffsetsForPhrase(obj)
+ self.sayPhrase(obj, startOffset, endOffset)
+ selSpoken = self._speakContiguousSelection(obj,
+ pyatspi.RELATION_FLOWS_TO)
+ else:
+ selSpoken = self._speakContiguousSelection(obj,
+ pyatspi.RELATION_FLOWS_FROM)
+
+ # If we have just crossed a paragraph boundary with
+ # Shift+Down, what we've selected in this object starts
+ # with the beginning of the paragraph and goes to the
+ # current offset.
+ #
+ if not self.isSameObject(lastPos[0], obj):
+ [startOffset, endOffset] = 0, text.caretOffset
+ else:
+ [startOffset, endOffset] \
+ = self.getOffsetsForPhrase(obj)
+
+ if startOffset != endOffset:
+ self.sayPhrase(obj, startOffset, endOffset)
+
else:
[startOffset, endOffset] = self.getOffsetsForLine(obj)
self.sayLine(obj)
@@ -3201,12 +3306,17 @@
# or Control-Right, we speak the current word otherwise we speak
# the character at the text cursor position.
#
- if hasLastPos and isShiftKey and isControlKey:
+ inNewObj = hasLastPos and not self.isSameObject(lastPos[0], obj)
+
+ if hasLastPos and not inNewObj and isShiftKey and isControlKey:
[startOffset, endOffset] = self.getOffsetsForPhrase(obj)
self.sayPhrase(obj, startOffset, endOffset)
- elif isControlKey:
+ elif isControlKey and not inNewObj:
[startOffset, endOffset] = self.getOffsetsForWord(obj)
- self.sayWord(obj)
+ if startOffset == endOffset:
+ self.sayCharacter(obj)
+ else:
+ self.sayWord(obj)
else:
[startOffset, endOffset] = self.getOffsetsForChar(obj)
self.sayCharacter(obj)
@@ -3262,7 +3372,7 @@
startOffset = text.caretOffset
endOffset = text.caretOffset
- self._saveLastCursorPosition(text)
+ self._saveLastCursorPosition(obj, text.caretOffset)
self._saveSpokenTextRange(startOffset, endOffset)
def onCaretMoved(self, event):
@@ -3686,7 +3796,8 @@
"""
text = obj.queryText()
- startOffset = self.pointOfReference["lastCursorPosition"]
+ lastPos = self.pointOfReference.get("lastCursorPosition")
+ startOffset = lastPos[1]
endOffset = text.caretOffset
# Swap values if in wrong order (StarOffice is fussy about that).
@@ -3750,13 +3861,37 @@
- event: the Event
"""
- startOffset = 0
- endOffset = 0
- if "spokenTextRange" in self.pointOfReference:
- startOffset = self.pointOfReference["spokenTextRange"][0]
- endOffset = self.pointOfReference["spokenTextRange"][1]
- self.speakTextSelectionState(event.source, startOffset, endOffset)
+ obj = event.source
+ spokenRange = self.pointOfReference.get("spokenTextRange") or [0, 0]
+ startOffset, endOffset = spokenRange
+
+ if not obj.getState().contains(pyatspi.STATE_FOCUSED):
+ # If we are selecting text across object boundaries with
+ # Shift+Down and doing so from the very beginning of the
+ # line, we will get an event telling us that the selection
+ # has changed for the line we just left. Because nothing
+ # is selected on the line which contains the caret, we won't
+ # speak "selected." So check to see if the event is for the
+ # object we just left and be sure that we don't have a spoken
+ # range (otherwise, we'll say selected twice when we are
+ # selecting across boundaries from the middle of the line).
+ #
+ lastPos = self.pointOfReference.get("lastCursorPosition")
+ if not lastPos or spokenRange != [0, 0]:
+ return
+
+ prevObj = None
+ for relation in lastPos[0].getRelationSet():
+ if relation.getRelationType() == pyatspi.RELATION_FLOWS_FROM:
+ prevObj = relation.getTarget(0)
+
+ if not self.isSameObject(prevObj, obj):
+ return
+
+ endOffset = obj.queryText().characterCount
+ self.speakTextSelectionState(obj, startOffset, endOffset)
+
def onSelectionChanged(self, event):
"""Called when an object's selection changes.
@@ -6810,14 +6945,15 @@
self.pointOfReference["spokenTextRange"] = [startOffset, endOffset]
- def _saveLastCursorPosition(self, text):
+ def _saveLastCursorPosition(self, obj, caretOffset):
"""Save away the current text cursor position for next time.
Arguments:
- - text: the text object.
+ - obj: the current accessible
+ - caretOffset: the cursor position within this object
"""
- self.pointOfReference["lastCursorPosition"] = text.caretOffset
+ self.pointOfReference["lastCursorPosition"] = [obj, caretOffset]
def _saveLastTextSelections(self, text):
"""Save away the list of text selections for next time.
@@ -6848,8 +6984,13 @@
# Handle special cases.
#
- # Shift-Page-Down: speak "page <state> from cursor position".
- # Shift-Page-Up: speak "page <state> to cursor position".
+ # Control-Shift-Page_Down:
+ # speak "line selected to end from previous cursor position".
+ # Control-Shift-Page_Up:
+ # speak "line selected from start to previous cursor position".
+ #
+ # Shift-Page_Down: speak "page <state> from cursor position".
+ # Shift-Page_Up: speak "page <state> to cursor position".
#
# Control-Shift-Down: speak "line <state> down from cursor position".
# Control-Shift-Up: speak "line <state> up from cursor position".
@@ -6874,7 +7015,23 @@
selectedText = (text.getNSelections() != 0)
specialCaseFound = False
- if (eventStr == "Page_Down") and isShiftKey and not isControlKey:
+ if (eventStr == "Page_Down") and isShiftKey and isControlKey:
+ specialCaseFound = True
+ # Translators: when the user selects (highlights) text in
+ # a document, Orca will speak information about what they
+ # have selected.
+ #
+ line = _("line selected to end from previous cursor position")
+
+ elif (eventStr == "Page_Up") and isShiftKey and isControlKey:
+ specialCaseFound = True
+ # Translators: when the user selects (highlights) text in
+ # a document, Orca will speak information about what they
+ # have selected.
+ #
+ line = _("line selected from start to previous cursor position")
+
+ elif (eventStr == "Page_Down") and isShiftKey and not isControlKey:
specialCaseFound = True
if selectedText:
# Translators: when the user selects (highlights) text in
@@ -6977,6 +7134,8 @@
if specialCaseFound:
speech.speak(line, None, False)
return
+ elif startOffset == endOffset:
+ return
try:
# If we are selecting by word, then there possibly will be
@@ -7007,6 +7166,7 @@
startOffset += 1
else:
break
+
except:
debug.printException(debug.LEVEL_FINEST)
@@ -7017,23 +7177,14 @@
# ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
#
speech.speak(Q_("text|selected"), None, False)
- else:
- if self.pointOfReference.has_key("lastSelections"):
- for i in xrange(len(self.pointOfReference["lastSelections"])):
- startSelOffset = \
- self.pointOfReference["lastSelections"][0][0]
- endSelOffset = \
- self.pointOfReference["lastSelections"][0][1]
- if (startOffset >= startSelOffset) \
- and (endOffset <= endSelOffset):
- # Translators: when the user unselects
- # (unhighlights) text in a document, Orca lets
- # them know this.
- #
- # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
- #
- speech.speak(Q_("text|unselected"), None, False)
- break
+ elif len(text.getText(startOffset, endOffset)):
+ # Translators: when the user unselects
+ # (unhighlights) text in a document, Orca lets
+ # them know this.
+ #
+ # ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+ #
+ speech.speak(Q_("text|unselected"), None, False)
self._saveLastTextSelections(text)
Modified: trunk/src/orca/scripts/apps/gedit/script.py
==============================================================================
--- trunk/src/orca/scripts/apps/gedit/script.py (original)
+++ trunk/src/orca/scripts/apps/gedit/script.py Tue May 20 20:27:27 2008
@@ -291,6 +291,9 @@
"""
obj = orca_state.locusOfFocus
+ if not obj:
+ return False
+
rolesList1 = [pyatspi.ROLE_PUSH_BUTTON,
pyatspi.ROLE_FILLER,
pyatspi.ROLE_FILLER,
Modified: trunk/src/orca/scripts/apps/soffice/script.py
==============================================================================
--- trunk/src/orca/scripts/apps/soffice/script.py (original)
+++ trunk/src/orca/scripts/apps/soffice/script.py Tue May 20 20:27:27 2008
@@ -1848,6 +1848,11 @@
- event: the Event
"""
+ # If the object is losing focus, then just ignore this event.
+ #
+ if event.detail1 == -1:
+ return
+
if orca_state.lastNonModifierKeyEvent:
event_string = orca_state.lastNonModifierKeyEvent.event_string
isShiftKey = orca_state.lastNonModifierKeyEvent.modifiers \
@@ -1921,10 +1926,6 @@
if (event_string == "Up" or event_string == "Down") and not isShiftKey:
speech.stop()
- # Speak a newline, if appropriate.
- if self.speakNewLine(event.source):
- speech.speakCharacter("\n", None)
-
# Speak a blank line, if appropriate.
if self.speakBlankLine(event.source):
# Translators: "blank" is a short word to mean the
@@ -1934,63 +1935,6 @@
default.Script.onCaretMoved(self, event)
- def speakNewLine(self, obj):
- """Returns True if a newline should be spoken.
- Otherwise, returns False.
- """
-
- # Get the the AccessibleText interface.
- try:
- text = obj.queryText()
- except NotImplementedError:
- return False
-
- # Was a left or right-arrow key pressed?
- if not (orca_state.lastInputEvent and \
- orca_state.lastInputEvent.__dict__.has_key("event_string")):
- return False
-
- lastKey = orca_state.lastNonModifierKeyEvent.event_string
- if lastKey != "Left" and lastKey != "Right":
- return False
-
- # Was a control key pressed?
- mods = orca_state.lastInputEvent.modifiers
- isControlKey = mods & (1 << pyatspi.MODIFIER_CONTROL)
-
- # Get the line containing the caret
- caretOffset = text.caretOffset
- line = text.getTextAtOffset(caretOffset, \
- pyatspi.TEXT_BOUNDARY_LINE_START)
- lineStart = line[1]
- lineEnd = line[2]
-
- if isControlKey: # control-right-arrow or control-left-arrow
-
- # Get the word containing the caret.
- word = text.getTextAtOffset(caretOffset, \
- pyatspi.TEXT_BOUNDARY_WORD_START)
- wordStart = word[1]
- wordEnd = word[2]
-
- if lastKey == "Right":
- if wordStart == lineStart:
- return True
- else:
- if wordEnd == lineEnd:
- return True
-
- else: # right arrow or left arrow
-
- if lastKey == "Right":
- if caretOffset == lineStart:
- return True
- else:
- if caretOffset == lineEnd:
- return True
-
- return False
-
def speakBlankLine(self, obj):
"""Returns True if a blank line should be spoken.
Otherwise, returns False.
Modified: trunk/src/orca/where_am_I.py
==============================================================================
--- trunk/src/orca/where_am_I.py (original)
+++ trunk/src/orca/where_am_I.py Tue May 20 20:27:27 2008
@@ -1267,7 +1267,7 @@
return text
- def _getTextSelection(self, obj):
+ def getTextSelection(self, obj):
"""Get the text selection for the given object.
Arguments:
@@ -1284,12 +1284,12 @@
[startOffset, endOffset] = textObj.getSelection(i)
debug.println(self._debugLevel,
- "_getTextSelection: selection start=%d, end=%d" % \
+ "getTextSelection: selection start=%d, end=%d" % \
(startOffset, endOffset))
selectedText = textObj.getText(startOffset, endOffset)
debug.println(self._debugLevel,
- "_getTextSelection: selected text=<%s>" % selectedText)
+ "getTextSelection: selected text=<%s>" % selectedText)
if i > 0:
textContents += " "
@@ -1317,7 +1317,7 @@
text = obj.queryText()
if text.getNSelections() > 0:
[textContents, startOffset, endOffset] = \
- self._getTextSelection(obj)
+ self.getTextSelection(obj)
if not basicOnly:
current = obj
@@ -1331,7 +1331,7 @@
prevObjText = prevObj.queryText()
if prevObjText.getNSelections() > 0:
[newTextContents, start, end] = \
- self._getTextSelection(prevObj)
+ self.getTextSelection(prevObj)
textContents = newTextContents + " " + textContents
current = prevObj
morePossibleSelections = True
@@ -1353,7 +1353,7 @@
nextObjText = nextObj.queryText()
if nextObjText.getNSelections() > 0:
[newTextContents, start, end] = \
- self._getTextSelection(nextObj)
+ self.getTextSelection(nextObj)
textContents += " " + newTextContents
current = nextObj
morePossibleSelections = True
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]