From fd24d8186d296ac7eb782a4784fa257ed071dea7 Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Mon, 29 Oct 2018 13:48:35 +1000 Subject: [PATCH] Ensure that labels explicitly set on divs and spans are reported in braille and speech (#8886) * Ensure that labels explicitly set by the web author on nodes such as divs and spans (that don't usually get reported) are shown in browseMode in both speech and braille. * Update what's new. --- source/braille.py | 8 +++++++- source/browseMode.py | 4 ++++ source/speech.py | 12 +++++++++--- user_docs/en/changes.t2t | 1 + 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/source/braille.py b/source/braille.py index 1070a4dc821..5344862cf1e 100644 --- a/source/braille.py +++ b/source/braille.py @@ -660,10 +660,16 @@ def getControlFieldBraille(info, field, ancestors, reportStart, formatConfig): current=field.get('current', None) placeholder=field.get('placeholder', None) roleText=field.get('roleText') + name=field.get('name') + alwaysReportName=field.get('alwaysReportName') if presCat == field.PRESCAT_LAYOUT: text = [] - # The only item we report for these fields is clickable, if present. + # Always braille the name of a field if it is forced. + # This is for the fallback case where a div or a span (which has no other presentation) has its name reported if explicitly set by the author using aria-label etc. + if alwaysReportName and name and field.get("_startOfNode"): + text.append(name) + # report clickable if present. if controlTypes.STATE_CLICKABLE in states: text.append(getBrailleTextForProperties(states={controlTypes.STATE_CLICKABLE})) if current: diff --git a/source/browseMode.py b/source/browseMode.py index 877a647aacc..2c026f1bba7 100644 --- a/source/browseMode.py +++ b/source/browseMode.py @@ -1067,6 +1067,8 @@ def getControlFieldSpeech(self, attrs, ancestorAttrs, fieldType, formatConfig=No name=attrs.get('name') if name and attrs.getPresentationCategory(ancestorAttrs,formatConfig,reason) is None: textList.append(name) + # As the name is being explicitly reported along with the landmark, we must ensure that it is not reported again generically + attrs['alwaysReportName']=False if landmark == "region": # The word landmark is superfluous for regions. textList.append(aria.landmarkRoles[landmark]) @@ -1082,6 +1084,8 @@ def getControlFieldBraille(self, field, ancestors, reportStart, formatConfig): # Ensure that the name of the field gets presented even if normally it wouldn't. name=field.get('name') if name and field.getPresentationCategory(ancestors,formatConfig) is None: + # As the name is being explicitly reported along with the landmark, we must ensure that it is not reported again generically + field['alwaysReportName']=False textList.append(name) if landmark == "region": # The word landmark is superfluous for regions. diff --git a/source/speech.py b/source/speech.py index 32d96b88515..571ca79bb4b 100755 --- a/source/speech.py +++ b/source/speech.py @@ -1109,7 +1109,10 @@ def getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD presCat=attrs.getPresentationCategory(ancestorAttrs,formatConfig, reason=reason) childControlCount=int(attrs.get('_childcontrolcount',"0")) - if reason==controlTypes.REASON_FOCUS or attrs.get('alwaysReportName',False): + alwaysReportName=attrs.get('alwaysReportName',False) + alwaysReportDescription=attrs.get('alwaysReportDescription',False) + isBlock=attrs.get('_isBlock',False) + if reason==controlTypes.REASON_FOCUS or alwaysReportName: name=attrs.get('name',"") else: name="" @@ -1225,14 +1228,17 @@ def getControlFieldSpeech(attrs,ancestorAttrs,fieldType,formatConfig=None,extraD # Special cases elif not speakEntry and fieldType in ("start_addedToControlFieldStack","start_relative"): out = [] + # Always speak the name of a field if it is forced. + # This is for the fallback case where a div or a span (which has no other presentation) has its name announced if explicitly set by the author using aria-label etc. + if alwaysReportName and nameText: + out.append(nameText) if not extraDetail and controlTypes.STATE_CLICKABLE in states: # Clickable. out.append(getSpeechTextForProperties(states=set([controlTypes.STATE_CLICKABLE]))) if ariaCurrent: out.append(ariaCurrentText) return CHUNK_SEPARATOR.join(out) - else: - return "" + return "" def getFormatFieldSpeech(attrs,attrsCache=None,formatConfig=None,reason=None,unit=None,extraDetail=False , initialFormat=False, separator=CHUNK_SEPARATOR): if not formatConfig: diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 8769ab868b1..0c8a8a461c7 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -30,6 +30,7 @@ What's New in NVDA - NVDA no longer fails to track focus in File Explorer and other applications using UI Automation when another app is busy (such as batch processing audio). (#7345) - In ARIA menus on the web, the Escape key will now be passed through to the menu and no longer turn off focus mode unconditionally. (#3215) - NVDA no longer refuses to report the focus on web pages where the new focus replaces a control that no longer exists. (#6606, #8341) +- In BrowseMode, NVDA will now always report labels on divs and spans explicitly set by the web author. (#8886) == Changes for Developers ==