From 7ef680d9c6b2cb40203108705fa97e132ba16faf Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Mon, 15 Jul 2024 11:22:17 +1000 Subject: [PATCH 1/4] ia2TextMozilla: expose name as content for any non-contenteditable within a contenteditable. Required to report addresses in outlook.com / Modern Outlook To/CC/BCC fields. --- source/NVDAObjects/IAccessible/ia2TextMozilla.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/NVDAObjects/IAccessible/ia2TextMozilla.py b/source/NVDAObjects/IAccessible/ia2TextMozilla.py index 9ed7c673115..f25b96e0017 100644 --- a/source/NVDAObjects/IAccessible/ia2TextMozilla.py +++ b/source/NVDAObjects/IAccessible/ia2TextMozilla.py @@ -24,6 +24,7 @@ from compoundDocuments import CompoundTextInfo import locationHelper from logHandler import log +import controlTypes class FakeEmbeddingTextInfo(offsets.OffsetsTextInfo): @@ -80,6 +81,16 @@ def _getControlFieldForObject(self, obj, ignoreEditableText=True): uniqueID = obj.IA2UniqueID if uniqueID is not None: controlField["uniqueID"] = uniqueID + # #16631: Outlook.com /modern Outlook represent addresses in To/CC/BCC fields as labelled buttons. + # These buttons are non-contenteditable within a parent contenteditable. + # Ensure their label (name) is reported as the content + # as the caret cannot move through them. + if ( + controlTypes.state.State.EDITABLE not in obj.states + and obj.parent + and controlTypes.state.State.EDITABLE in obj.parent.states + ): + controlField['content'] = obj.name return controlField def _isCaretAtEndOfLine(self, caretObj: IAccessible) -> bool: From 17f9440915c2a83c4745e658291a9dcce891e17d Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Mon, 15 Jul 2024 11:43:31 +1000 Subject: [PATCH 2/4] Update what's new --- user_docs/en/changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 30f8053d4c6..dfe0e9add1a 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -81,6 +81,7 @@ A warning message will inform you if you try writing to a non-empty directory. ( * Speech is no longer silent after disconnecting from and reconnecting to a Remote Desktop session. (#16722, @jcsteh) * Support added for text review commands for an object's name in Visual Studio Code. (#16248, @Cary-Rowen) * Playing NVDA sounds no longer fails on a mono audio device. (#16770, @jcsteh) +* NVDA will report addresses when arrowing through To/CC/BCC fields in outlook.com / Modern Outlook. (#16856) ### Changes for Developers From 5d78b61239ffbf14ebb6f93b5467d6c0ada48527 Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Mon, 15 Jul 2024 11:50:00 +1000 Subject: [PATCH 3/4] Remove redundant import --- source/NVDAObjects/IAccessible/ia2TextMozilla.py | 1 - 1 file changed, 1 deletion(-) diff --git a/source/NVDAObjects/IAccessible/ia2TextMozilla.py b/source/NVDAObjects/IAccessible/ia2TextMozilla.py index f25b96e0017..6dbe8ec072f 100644 --- a/source/NVDAObjects/IAccessible/ia2TextMozilla.py +++ b/source/NVDAObjects/IAccessible/ia2TextMozilla.py @@ -24,7 +24,6 @@ from compoundDocuments import CompoundTextInfo import locationHelper from logHandler import log -import controlTypes class FakeEmbeddingTextInfo(offsets.OffsetsTextInfo): From b0b20c5a2e2972894053f7addbbf6c1e34523902 Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Wed, 17 Jul 2024 07:40:59 +1000 Subject: [PATCH 4/4] ia2TextMozilla: tighten labelling of non-contenteditables to just buttons as links actually don't get the editable state. --- source/NVDAObjects/IAccessible/ia2TextMozilla.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/NVDAObjects/IAccessible/ia2TextMozilla.py b/source/NVDAObjects/IAccessible/ia2TextMozilla.py index 6dbe8ec072f..96c83da63ae 100644 --- a/source/NVDAObjects/IAccessible/ia2TextMozilla.py +++ b/source/NVDAObjects/IAccessible/ia2TextMozilla.py @@ -85,7 +85,8 @@ def _getControlFieldForObject(self, obj, ignoreEditableText=True): # Ensure their label (name) is reported as the content # as the caret cannot move through them. if ( - controlTypes.state.State.EDITABLE not in obj.states + obj.role == controlTypes.role.Role.BUTTON + and controlTypes.state.State.EDITABLE not in obj.states and obj.parent and controlTypes.state.State.EDITABLE in obj.parent.states ):