From 5c83fadc37c6968b4256d729337e04a2728b86bd Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Mon, 2 Oct 2023 16:54:27 +0100 Subject: [PATCH] soffice: Announce actually deleted text on Ctrl+backspace ### Link to issue number: Fixes #15436 ### Summary of the issue: The base class implementation `EditableText#_backspaceScriptHelper` for handling the Ctrl+Backspace keyboard shortcut retrieves the text to announce as deleted by expanding the text info to the corresponding text unit and then retrieving the text. This gives an incorrect result in at least Libreoffice Writer, where that would return a string just containing the space character when removing a word followed by a space using the Ctrl+backspace keyboard shortcut. (Writer's `IAccessibleText::textAtOffset` implementation that gets used in `IA2TextTextInfo#_getWordOffsets` handles the space as a separate word, but Ctrl+backspace removes both, the actual word and following whitespace.) ### Description of user facing changes When removing a word followed by whitespace in Libreoffice Writer, the actually removed text is announced. ### Description of development approach Instead of separately retrieving the text for a word, override the default implementation in the LibreOffice app module and announce the actually removed text when handling Ctrl+backspace. Use the caret position before and after the text has been removed to identify what the removed text is. ### Testing strategy: Test the scenario as described in issue #15436: 1) start LibreOffice Writer 2) type "NVDA is a free screen reader." 3) press Ctrl+backspace 7 times 4) verify that the actually removed text is annonced by NVDA. ### Known issues with pull request: None ### 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. --- source/appModules/soffice.py | 35 +++++++++++++++++++++++++++++++++++ user_docs/en/changes.t2t | 1 + 2 files changed, 36 insertions(+) diff --git a/source/appModules/soffice.py b/source/appModules/soffice.py index c1332da45e8..979accf9ead 100755 --- a/source/appModules/soffice.py +++ b/source/appModules/soffice.py @@ -25,6 +25,7 @@ import speech import api import braille +import inputCore import languageHandler import vision @@ -318,6 +319,40 @@ def _get_locationText(self): class SymphonyDocument(CompoundDocument): TextInfo = SymphonyDocumentTextInfo + # override base class implementation because that one assumes + # that the text retrieved from the text info for the text unit + # is the same as the text that actually gets removed, which at + # least isn't true for Writer paragraphs when removing a word + # followed by whitespace using Ctrl+Backspace + def _backspaceScriptHelper(self, unit: str, gesture: inputCore.InputGesture): + try: + oldInfo = self.makeTextInfo(textInfos.POSITION_CARET) + ia2TextObj = oldInfo._start.obj.IAccessibleTextObject + oldCaretOffset = ia2TextObj.caretOffset + oldText = ia2TextObj.text(0, ia2TextObj.nCharacters) + except NotImplementedError: + gesture.send() + return + + gesture.send() + + newInfo = self.makeTextInfo(textInfos.POSITION_CARET) + ia2TextObj = newInfo._start.obj.IAccessibleTextObject + newCaretOffset = ia2TextObj.caretOffset + newText = ia2TextObj.text(0, ia2TextObj.nCharacters) + + # double-check check that text between previous and current + # caret position was deleted and announce it + deletedText = oldText[newCaretOffset:oldCaretOffset] + if newText == oldText[0:newCaretOffset] + oldText[oldCaretOffset:]: + if len(deletedText) > 1: + speech.speakMessage(deletedText) + else: + speech.speakSpelling(deletedText) + self._caretScriptPostMovedHelper(None, gesture, newInfo) + else: + log.warning('Backspace did not remove text as expected.') + class AppModule(appModuleHandler.AppModule): diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 17c25a8ed34..d9522298257 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -21,6 +21,7 @@ This option now announces additional relevant information about an object when t == Bug Fixes == - Reporting of object shortcut keys has been improved. (#10807) - The SAPI4 synthesizer now properly supports volume, rate and pitch changes embedded in speech. (#15271) +- 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) - == Changes for Developers ==