Fix some interruption issues in discord.
This commit is contained in:
@@ -1083,7 +1083,7 @@ class Script(default.Script):
|
|||||||
"""Speaks the specified contents."""
|
"""Speaks the specified contents."""
|
||||||
|
|
||||||
utterances = self.speechGenerator.generateContents(contents, **args)
|
utterances = self.speechGenerator.generateContents(contents, **args)
|
||||||
speech.speak(utterances)
|
speech.speak(utterances, interrupt=args.get("interrupt", True))
|
||||||
|
|
||||||
def sayCharacter(self, obj):
|
def sayCharacter(self, obj):
|
||||||
"""Speaks the character at the current caret position."""
|
"""Speaks the character at the current caret position."""
|
||||||
@@ -1874,11 +1874,15 @@ class Script(default.Script):
|
|||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if self.utilities.shouldInterruptForLocusOfFocusChange(oldFocus, newFocus, event):
|
||||||
|
self.presentationInterrupt()
|
||||||
|
|
||||||
|
args["interrupt"] = False
|
||||||
if contents:
|
if contents:
|
||||||
self.speakContents(contents, **args)
|
self.speakContents(contents, **args)
|
||||||
else:
|
else:
|
||||||
utterances = self.speechGenerator.generateSpeech(newFocus, **args)
|
utterances = self.speechGenerator.generateSpeech(newFocus, **args)
|
||||||
speech.speak(utterances)
|
speech.speak(utterances, interrupt=False)
|
||||||
|
|
||||||
self._saveFocusedObjectInfo(newFocus)
|
self._saveFocusedObjectInfo(newFocus)
|
||||||
|
|
||||||
@@ -2650,6 +2654,44 @@ class Script(default.Script):
|
|||||||
self._lastCommandWasMouseButton = True
|
self._lastCommandWasMouseButton = True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def onDescriptionChanged(self, event):
|
||||||
|
"""Callback for object:property-change:accessible-description events."""
|
||||||
|
|
||||||
|
if self.utilities.eventIsBrowserUINoise(event):
|
||||||
|
msg = "WEB: Ignoring event believed to be browser UI noise"
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
obj = event.source
|
||||||
|
if not self.utilities.inDocumentContent(obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
descriptions = self.pointOfReference.get('descriptions', {})
|
||||||
|
oldDescription = descriptions.get(hash(obj))
|
||||||
|
if oldDescription == event.any_data:
|
||||||
|
tokens = ["WEB: Old description (", oldDescription, ") is the same as new one"]
|
||||||
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
descriptions[hash(obj)] = event.any_data
|
||||||
|
self.pointOfReference['descriptions'] = descriptions
|
||||||
|
if obj != cthulhu_state.locusOfFocus:
|
||||||
|
msg = "WEB: Description change is for object other than locusOfFocus"
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not event.any_data:
|
||||||
|
return True
|
||||||
|
|
||||||
|
name = AXObject.get_name(obj)
|
||||||
|
if self.utilities.stringsAreRedundant(name, event.any_data):
|
||||||
|
tokens = ["WEB: Description change is redundant with name for", obj]
|
||||||
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.presentMessage(event.any_data, interrupt=False)
|
||||||
|
return True
|
||||||
|
|
||||||
def onNameChanged(self, event):
|
def onNameChanged(self, event):
|
||||||
"""Callback for object:property-change:accessible-name events."""
|
"""Callback for object:property-change:accessible-name events."""
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,104 @@ class WebPresentationModeSpeechRegressionTests(unittest.TestCase):
|
|||||||
testScript.presentMessage.assert_called_once_with(messages.MODE_FOCUS, interrupt=True)
|
testScript.presentMessage.assert_called_once_with(messages.MODE_FOCUS, interrupt=True)
|
||||||
|
|
||||||
|
|
||||||
|
class WebFocusSpeechInterruptionRegressionTests(unittest.TestCase):
|
||||||
|
def _make_script(self):
|
||||||
|
testScript = web_script.Script.__new__(web_script.Script)
|
||||||
|
testScript._navSuspended = False
|
||||||
|
testScript._lastCommandWasCaretNav = False
|
||||||
|
testScript._lastCommandWasStructNav = False
|
||||||
|
testScript._lastCommandWasMouseButton = False
|
||||||
|
testScript._inFocusMode = True
|
||||||
|
testScript._focusModeIsSticky = True
|
||||||
|
testScript._browseModeIsSticky = False
|
||||||
|
testScript.flatReviewPresenter = mock.Mock()
|
||||||
|
testScript.flatReviewPresenter.is_active.return_value = False
|
||||||
|
testScript.utilities = mock.Mock()
|
||||||
|
testScript.utilities.isZombie.return_value = False
|
||||||
|
testScript.utilities.isDocument.return_value = False
|
||||||
|
testScript.utilities.getTopLevelDocumentForObject.return_value = "document"
|
||||||
|
testScript.utilities.inFindContainer.return_value = False
|
||||||
|
testScript.utilities.queryNonEmptyText.return_value = None
|
||||||
|
testScript.utilities.isContentEditableWithEmbeddedObjects.return_value = False
|
||||||
|
testScript.utilities.isAnchor.return_value = False
|
||||||
|
testScript.utilities.lastInputEventWasPageNav.return_value = False
|
||||||
|
testScript.utilities.isFocusedWithMathChild.return_value = False
|
||||||
|
testScript.utilities.caretMovedToSamePageFragment.return_value = False
|
||||||
|
testScript.utilities.lastInputEventWasLineNav.return_value = False
|
||||||
|
testScript.utilities.inDocumentContent.return_value = True
|
||||||
|
testScript.utilities.shouldInterruptForLocusOfFocusChange.return_value = True
|
||||||
|
testScript.speechGenerator = mock.Mock()
|
||||||
|
testScript.speechGenerator.generateSpeech.return_value = ["focus speech"]
|
||||||
|
testScript.updateBraille = mock.Mock()
|
||||||
|
testScript.presentationInterrupt = mock.Mock()
|
||||||
|
testScript._saveFocusedObjectInfo = mock.Mock()
|
||||||
|
testScript.refreshKeyGrabs = mock.Mock()
|
||||||
|
return testScript
|
||||||
|
|
||||||
|
def test_focus_generated_speech_uses_explicit_interrupt_then_appends(self):
|
||||||
|
testScript = self._make_script()
|
||||||
|
oldFocus = object()
|
||||||
|
newFocus = object()
|
||||||
|
event = mock.Mock(type="object:state-changed:focused", source=newFocus)
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(web_script.AXObject, "is_dead", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_unknown_or_redundant", return_value=False),
|
||||||
|
mock.patch.object(web_script.AXUtilities, "is_heading", return_value=False),
|
||||||
|
mock.patch.object(web_script.speech, "speak") as speak,
|
||||||
|
mock.patch.object(web_script.cthulhu, "emitRegionChanged"),
|
||||||
|
):
|
||||||
|
result = web_script.Script.locus_of_focus_changed(
|
||||||
|
testScript, event, oldFocus, newFocus
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(result)
|
||||||
|
testScript.presentationInterrupt.assert_called_once_with()
|
||||||
|
speak.assert_called_once_with(["focus speech"], interrupt=False)
|
||||||
|
|
||||||
|
|
||||||
|
class WebDescriptionChangeRegressionTests(unittest.TestCase):
|
||||||
|
def _make_script(self):
|
||||||
|
testScript = web_script.Script.__new__(web_script.Script)
|
||||||
|
testScript.pointOfReference = {}
|
||||||
|
testScript.utilities = mock.Mock()
|
||||||
|
testScript.utilities.eventIsBrowserUINoise.return_value = False
|
||||||
|
testScript.utilities.inDocumentContent.return_value = True
|
||||||
|
testScript.utilities.stringsAreRedundant.side_effect = (
|
||||||
|
lambda first, second: first == second
|
||||||
|
)
|
||||||
|
testScript.presentMessage = mock.Mock()
|
||||||
|
return testScript
|
||||||
|
|
||||||
|
def test_document_description_change_matching_name_is_ignored(self):
|
||||||
|
testScript = self._make_script()
|
||||||
|
source = object()
|
||||||
|
event = mock.Mock(source=source, any_data="More")
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(web_script.cthulhu_state, "locusOfFocus", source),
|
||||||
|
mock.patch.object(web_script.AXObject, "get_name", return_value="More"),
|
||||||
|
):
|
||||||
|
result = web_script.Script.onDescriptionChanged(testScript, event)
|
||||||
|
|
||||||
|
self.assertTrue(result)
|
||||||
|
testScript.presentMessage.assert_not_called()
|
||||||
|
|
||||||
|
def test_document_description_change_appends_to_focus_presentation(self):
|
||||||
|
testScript = self._make_script()
|
||||||
|
source = object()
|
||||||
|
event = mock.Mock(source=source, any_data="Helpful tooltip")
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(web_script.cthulhu_state, "locusOfFocus", source),
|
||||||
|
mock.patch.object(web_script.AXObject, "get_name", return_value="Button"),
|
||||||
|
):
|
||||||
|
result = web_script.Script.onDescriptionChanged(testScript, event)
|
||||||
|
|
||||||
|
self.assertTrue(result)
|
||||||
|
testScript.presentMessage.assert_called_once_with("Helpful tooltip", interrupt=False)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user