Skip to content

Commit

Permalink
soffice: Support text attrs according to IA2 spec
Browse files Browse the repository at this point in the history
 ### Link to issue number:

Fixes nvaccess#15648

 ### Summary of the issue:

So far, LibreOffice was using custom attribute and value
names for reporting text attributes. Spelling errors were
not reported via any attribute. NVDA was using the presence
of a specific underline as heuristic to detect and report
spelling errors.
This works for some cases, but e.g. does not cause misspelled
words on a line being annonced as such when reading a
line in LibreOffice Writer (issue nvaccess#15648).

 ### Description of user facing changes

Announcement of text attributes also works with
LibreOffice version 24.2 and above.
When announcing a line in LibreOffice Writer, misspelled
words are announced as such with LibreOffice version 24.2
and above.

 ### Description of development approach

Switch LibreOffice from using custom text attribute names
and values to using attributes according to the IAccessible2
text attributes specification
( https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes )
instead and implement reporting of the "invalid:spelling;"
attribute for misspelled words:

https://gerrit.libreoffice.org/c/core/+/157804
https://gerrit.libreoffice.org/c/core/+/157845
https://gerrit.libreoffice.org/c/core/+/157867
https://gerrit.libreoffice.org/c/core/+/157939
https://gerrit.libreoffice.org/c/core/+/158088
https://gerrit.libreoffice.org/c/core/+/158089
https://gerrit.libreoffice.org/c/core/+/158090

These changes are contained in LibreOffice >= 24.2.

Adapt NVDA to evaluate those text attributes by
using the already existing implementation from
the `IA2TextTextInfo` base class in
`SymphonyTextInfo._getFormatFieldAndOffsets`.

For backwards-compatibility with LibreOffice
versions <= 7.6, keep support for the legacy
attributes and move the handling for that into
a new helper method
`SymphonyTextInfo_getFormatFieldFromLegacyAttributesString`.

For the case where the legacy attributes are used,
the text attribute string starts with "Version:1;"
(s. the LibreOffice code dropped in
https://gerrit.libreoffice.org/c/core/+/158090 ),
so use that as a criterion what code path to take.

Address some of the pre-existing lint issues, but silence
the C901 ones
("'SymphonyTextInfo._getFormatFieldFromLegacyAttributesString' is too complex (27)",
same for "_SymphonyTextInfo._getFormatFieldAndOffsets").
Each one of them is at least already less complex than the single
one was before, now that it has been split into two methods.

 ### Testing strategy:

Test that incorrect spelling in the middle of a line in LibreOffice
Writer gets announced when testing the scenario described in
issue nvaccess#15648 with both, the LibreOffice and the NVDA changes
in place.

Test that the character attributes from the sample document
attached to
https://bugs.documentfoundation.org/show_bug.cgi?id=157696
works with these changes in NVDA in place, and *both*,

* a current LibreOffice development version containing
  the above-mentioned LibreOffice changes
* LibreOffice 7.6.2 which does not contain the above-mentioned
  changes and therefore triggers the "legacy" code path.

 ### Known issues with pull request:

Requires the above-mentioned LibreOffice changes in addition
to actually make the scenario described in issue nvaccess#15648
work.

 ### Code Review Checklist:

- [x] Documentation:
  - Change log entry
  - User Documentation
  - Developer / Technical Documentation
  - Context sensitive help for GUI changes
- [x] Testing:
  - Unit tests
  - System (end to end) tests
  - Manual testing
- [x] UX of all users considered:
  - Speech
  - Braille
  - Low Vision
  - Different web browsers
  - Localization in other languages / culture than English
- [x] API is compatible with existing add-ons.
- [x] Security precautions taken.
  • Loading branch information
michaelweghorn committed Oct 19, 2023
1 parent 9878248 commit 0492878
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 21 deletions.
77 changes: 58 additions & 19 deletions source/appModules/soffice.py
Expand Up @@ -31,20 +31,24 @@


class SymphonyTextInfo(IA2TextTextInfo):

def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
obj = self.obj
try:
startOffset,endOffset,attribsString=obj.IAccessibleTextObject.attributes(offset)
except COMError:
log.debugWarning("could not get attributes",exc_info=True)
return textInfos.FormatField(),(self._startOffset,self._endOffset)
def _getFormatFieldFromLegacyAttributesString( # noqa: C901
self,
attribsString: str,
offset: int
) -> textInfos.FormatField:

"""Get format field with information retrieved from a text
attributes string containing LibreOffice's legacy custom text
attributes (used by LibreOffice <= 7.6), instead of attributes
according to the IAccessible2 text attributes specification
(used by LibreOffice >= 24.2).
:param attribsString: Legacy text attributes string.
:param offset: Character offset for which the attributes are
retrieved.
:return: Format field containing the text attribute information.
"""
formatField=textInfos.FormatField()
if not attribsString and offset>0:
try:
attribsString=obj.IAccessibleTextObject.attributes(offset-1)[2]
except COMError:
pass
if attribsString:
formatField.update(splitIA2Attribs(attribsString))

Expand Down Expand Up @@ -101,6 +105,47 @@ def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
if backgroundColor:
formatField['background-color']=colors.RGB.fromString(backgroundColor)

if offset == 0:
# Only include the list item prefix on the first line of the paragraph.
numbering = formatField.get("Numbering")
if numbering:
formatField["line-prefix"] = numbering.get("NumberingPrefix") or numbering.get("BulletChar")

return formatField

def _getFormatFieldAndOffsets( # noqa: C901
self,
offset: int,
formatConfig: Optional[dict],
calculateOffsets: bool = True
) -> tuple[textInfos.FormatField, tuple[int, int]]:
obj = self.obj
try:
startOffset, endOffset, attribsString = obj.IAccessibleTextObject.attributes(offset)
except COMError:
log.debugWarning("could not get attributes", exc_info=True)
return textInfos.FormatField(), (self._startOffset, self._endOffset)

if not attribsString and offset > 0:
try:
attribsString = obj.IAccessibleTextObject.attributes(offset - 1)[2]
except COMError:
pass

# LibreOffice >= 24.2 uses IAccessible2 text attributes, earlier versions use
# custom attributes, with the attributes string starting with "Version:1;"
if attribsString and attribsString.startswith('Version:1;'):
formatField = self._getFormatFieldFromLegacyAttributesString(
attribsString,
offset
)
else:
formatField, (startOffset, endOffset) = super()._getFormatFieldAndOffsets(
offset,
formatConfig,
calculateOffsets
)

# optimisation: Assume a hyperlink occupies a full attribute run.
try:
if obj.IAccessibleTextObject.QueryInterface(
Expand All @@ -110,12 +155,6 @@ def _getFormatFieldAndOffsets(self,offset,formatConfig,calculateOffsets=True):
except COMError:
pass

if offset == 0:
# Only include the list item prefix on the first line of the paragraph.
numbering = formatField.get("Numbering")
if numbering:
formatField["line-prefix"] = numbering.get("NumberingPrefix") or numbering.get("BulletChar")

if obj.hasFocus:
# Symphony exposes some information for the caret position as attributes on the document object.
# optimisation: Use the tree interceptor to get the document.
Expand Down
5 changes: 3 additions & 2 deletions user_docs/en/changes.t2t
Expand Up @@ -30,8 +30,9 @@ This option now announces additional relevant information about an object when t
- Reporting of object shortcut keys has been improved. (#10807, @CyrilleB79)
- The SAPI4 synthesizer now properly supports volume, rate and pitch changes embedded in speech. (#15271, @LeonarddeR)
- Multi line state is now correctly reported in applications using Java Access Bridge. (#14609)
- In LibreOffice, words deleted using the ``control+backspace`` keyboard shortcut are now also properly announced when the deleted word is followed by whitespace (like spaces and tabs). (#15436)
- In LibreOffice, announcement of the status bar using the ``NVDA+end`` keyboard shortcut now also works for dialogs in LibreOffice version 24.2 and newer. (#15591)
- In LibreOffice, words deleted using the ``control+backspace`` keyboard shortcut are now also properly announced when the deleted word is followed by whitespace (like spaces and tabs). (#15436, @michaelweghorn)
- In LibreOffice, announcement of the status bar using the ``NVDA+end`` keyboard shortcut now also works for dialogs in LibreOffice version 24.2 and newer. (#15591, @michaelweghorn)
- In LibreOffice, text attributes according to the [IAccessible2 text attributes specification https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes] are supported, which is required to support announcement of text attributes in LibreOffice versions 24.2 and above and makes the announcement of spelling errors work when announcing a line in Writer. (#15648, @michaelweghorn)
- In Microsoft Excel with UIA disabled, braille is updated, and the active cell content is spoken, when ``control+y``, ``control+z`` or ``alt+backspace`` is pressed. (15547)
-

Expand Down

0 comments on commit 0492878

Please sign in to comment.