diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py index 5db71848e5b..daeedd82fb9 100644 --- a/source/NVDAObjects/UIA/__init__.py +++ b/source/NVDAObjects/UIA/__init__.py @@ -221,7 +221,7 @@ def _getFormatFieldAtRange( # noqa: C901 IDs.add(UIAHandler.UIA_FontNameAttributeId) if formatConfig["reportFontSize"]: IDs.add(UIAHandler.UIA_FontSizeAttributeId) - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: IDs.update( { UIAHandler.UIA_FontWeightAttributeId, @@ -265,7 +265,7 @@ def _getFormatFieldAtRange( # noqa: C901 if isinstance(val, numbers.Number): # Translators: Abbreviation for points, a measurement of font size. formatField["font-size"] = pgettext("font size", "%s pt") % float(val) - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: val = fetcher.getValue(UIAHandler.UIA_FontWeightAttributeId, ignoreMixedValues=ignoreMixedValues) if isinstance(val, int): formatField["bold"] = val >= 700 diff --git a/source/NVDAObjects/window/edit.py b/source/NVDAObjects/window/edit.py index bd6091ed347..e8d3f49be23 100644 --- a/source/NVDAObjects/window/edit.py +++ b/source/NVDAObjects/window/edit.py @@ -343,7 +343,7 @@ def _getFormatFieldAndOffsets(self, offset, formatConfig, calculateOffsets=True) fontSize = charFormat.yHeight // 20 # Translators: Abbreviation for points, a measurement of font size. formatField["font-size"] = pgettext("font size", "%s pt") % fontSize - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: if charFormat is None: charFormat = self._getCharFormat(offset) # noqa: E701 formatField["bold"] = bool(charFormat.dwEffects & CFE_BOLD) @@ -712,7 +712,7 @@ def _getFormatFieldAtRange(self, textRange, formatConfig): # noqa: C901 fontObj = textRange.font # Translators: Abbreviation for points, a measurement of font size. formatField["font-size"] = pgettext("font size", "%s pt") % fontObj.size - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: if not fontObj: fontObj = textRange.font formatField["bold"] = bool(fontObj.bold) diff --git a/source/NVDAObjects/window/excel.py b/source/NVDAObjects/window/excel.py index 0b56291c61e..b8d239a8c80 100755 --- a/source/NVDAObjects/window/excel.py +++ b/source/NVDAObjects/window/excel.py @@ -1297,7 +1297,7 @@ def _getFormatFieldAndOffsets(self, offset, formatConfig, calculateOffsets=True) if formatConfig["reportFontSize"]: # Translators: Abbreviation for points, a measurement of font size. formatField["font-size"] = pgettext("font size", "%s pt") % fontObj.size - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: formatField["bold"] = fontObj.bold formatField["italic"] = fontObj.italic underline = fontObj.underline diff --git a/source/NVDAObjects/window/scintilla.py b/source/NVDAObjects/window/scintilla.py index e6f9502cf65..bf5f732d96a 100755 --- a/source/NVDAObjects/window/scintilla.py +++ b/source/NVDAObjects/window/scintilla.py @@ -154,7 +154,7 @@ def _getFormatFieldAndOffsets(self, offset, formatConfig, calculateOffsets=True) formatField["font-size"] = pgettext("font size", "%s pt") % fontSize if formatConfig["reportLineNumber"]: formatField["line-number"] = self._getLineNumFromOffset(offset) + 1 - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: formatField["bold"] = bool( watchdog.cancellableSendMessage(self.obj.windowHandle, SCI_STYLEGETBOLD, style, 0), ) diff --git a/source/NVDAObjects/window/winword.py b/source/NVDAObjects/window/winword.py index cf42e3dd3f2..f113f8cd60e 100755 --- a/source/NVDAObjects/window/winword.py +++ b/source/NVDAObjects/window/winword.py @@ -362,7 +362,7 @@ class WinWordColor(IntEnum): formatConfigFlagsMap = { "reportFontName": 0x1, "reportFontSize": 0x2, - "reportFontAttributes": 0x4, + "fontAttributeReporting": 0x4, "reportColor": 0x8, "reportAlignment": 0x10, "reportStyle": 0x20, diff --git a/source/appModules/powerpnt.py b/source/appModules/powerpnt.py index 21f5895a9bb..4b99dc5c9c6 100644 --- a/source/appModules/powerpnt.py +++ b/source/appModules/powerpnt.py @@ -1111,7 +1111,7 @@ def _getFormatFieldAndOffsets(self, offset, formatConfig, calculateOffsets=True) if formatConfig["reportFontSize"]: # Translators: Abbreviation for points, a measurement of font size. formatField["font-size"] = pgettext("font size", "%s pt") % font.size - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"]: formatField["bold"] = bool(font.bold) formatField["italic"] = bool(font.italic) formatField["underline"] = bool(font.underline) diff --git a/source/braille.py b/source/braille.py index 92abf904047..2a1757ed578 100644 --- a/source/braille.py +++ b/source/braille.py @@ -44,6 +44,7 @@ TetherTo, BrailleMode, ReportTableHeaders, + OutputMode, ) from config.featureFlagEnums import ReviewRoutingMovesSystemCaretFlag from logHandler import log @@ -1173,7 +1174,7 @@ def _setCursor(self, info: textInfos.TextInfo): def _getTypeformFromFormatField(self, field, formatConfig): typeform = louis.plain_text - if not formatConfig["reportFontAttributes"]: + if not (formatConfig["fontAttributeReporting"] & OutputMode.BRAILLE): return typeform if field.get("bold", False): typeform |= louis.bold diff --git a/source/browseMode.py b/source/browseMode.py index 721a8575883..711cc521e30 100644 --- a/source/browseMode.py +++ b/source/browseMode.py @@ -2399,7 +2399,7 @@ def _extractStyles( reportFormattingOptions = ( "reportFontName", "reportFontSize", - "reportFontAttributes", + "fontAttributeReporting", "reportSuperscriptsAndSubscripts", "reportHighlight", "reportColor", diff --git a/source/config/__init__.py b/source/config/__init__.py index 769ad024646..37bfb397320 100644 --- a/source/config/__init__.py +++ b/source/config/__init__.py @@ -36,6 +36,7 @@ from . import profileUpgrader from . import aggregatedSection from .configSpec import confspec +from .configFlags import OutputMode from .featureFlag import ( _transformSpec_AddFeatureFlagDefault, _validateConfig_featureFlag, @@ -51,7 +52,7 @@ ) import NVDAState from NVDAState import WritePaths - +from buildVersion import version_year #: True if NVDA is running as a Windows Store Desktop Bridge application isAppX = False @@ -1304,6 +1305,56 @@ def __setitem__( self.manager._markWriteProfileDirty() self._cache[key] = val + # Alias [documentFormatting][reportFontAttributes] for backwards compatibility. + # TODO: Comment out in 2025.1. + if version_year < 2025 and NVDAState._allowDeprecatedAPI(): + self._linkDeprecatedValues(key, val) + + def _linkDeprecatedValues(self, key: aggregatedSection._cacheKeyT, val: aggregatedSection._cacheValueT): + """Link deprecated config keys and values to their replacements. + + Args: + key: The configuration key to link to its new or old counterpart. + val: The value associated with the configuration key. + + postconditions: + - If self.path is "documentFormatting": + - If key is "reportFontAttributes": + - If val is True, "documentFormatting.fontAttributeReporting" is set to OutputMode.SPEECH_AND_BRAILLE, otherwise, it is set to OutputMode.OFF. + - If key is "fontAttributeReporting": + - if val is OutputMode.OFF, "documentFormatting.reportFontAttributes" is set to False, otherwise, it is set to True. + """ + match self.path: + case ("documentFormatting",): + match key: + case "fontAttributeReporting": + # Alias documentFormatting.fontAttributeReporting to documentFormatting.reportFontAttributes for backwards compatibility. + key = "reportFontAttributes" + val = bool(val) + + case "reportFontAttributes": + # Alias documentFormatting.reportFontAttributes to documentFormatting.fontAttributeReporting for forwards compatibility. + log.warning( + "documentFormatting.reportFontAttributes is deprecated. Use documentFormatting.fontAttributeReporting instead.", + # Include stack info so testers can report warning to add-on author. + stack_info=True, + ) + key = "fontAttributeReporting" + val = OutputMode.SPEECH_AND_BRAILLE if val else OutputMode.OFF + + case _: + # We don't care about other keys in this section. + return + + case _: + # We don't care about other sections. + return + + # Update the value in the most recently activated profile. + # If we have reached this point, we must have a new key and value to set. + self._getUpdateSection()[key] = val + self._cache[key] = val + def _getUpdateSection(self): profile = self.profiles[-1] if profile is not None: diff --git a/source/config/configFlags.py b/source/config/configFlags.py index 7bf2afda8af..21354abcca6 100644 --- a/source/config/configFlags.py +++ b/source/config/configFlags.py @@ -225,3 +225,29 @@ def _displayStringLabels(self): # Translators: This is a label for the automatic update behaviour for add-ons. self.DISABLED: _("Disabled"), } + + +@unique +class OutputMode(DisplayStringIntFlag): + """Enumeration for ways to output information, such as formatting. + Use OutputMode.MEMBER.value to compare with the config; + use OutputMode.MEMBER.displayString in the UI for a translatable description of this member. + """ + + OFF = 0b0 + SPEECH = 0b01 + BRAILLE = 0b10 + SPEECH_AND_BRAILLE = SPEECH | BRAILLE + + @property + def _displayStringLabels(self): + return { + # Translators: A label for an option to choose a method of reporting information, e.g. font attributes. + self.OFF: _("Off"), + # Translators: A label for an option to choose a method of reporting information, e.g. font attributes. + self.SPEECH: _("Speech"), + # Translators: A label for an option to choose a method of reporting information, e.g. font attributes. + self.BRAILLE: _("Braille"), + # Translators: A label for an option to choose a method of reporting information, e.g. font attributes. + self.SPEECH_AND_BRAILLE: _("Speech and braille"), + } diff --git a/source/config/configSpec.py b/source/config/configSpec.py index 91eec72866e..82a5de7eabf 100644 --- a/source/config/configSpec.py +++ b/source/config/configSpec.py @@ -13,7 +13,7 @@ #: provide an upgrade step (@see profileUpgradeSteps.py). An upgrade step does not need to be added when #: just adding a new element to (or removing from) the schema, only when old versions of the config #: (conforming to old schema versions) will not work correctly with the new schema. -latestSchemaVersion = 11 +latestSchemaVersion = 12 #: The configuration specification string #: @type: String @@ -205,7 +205,10 @@ detectFormatAfterCursor = boolean(default=false) reportFontName = boolean(default=false) reportFontSize = boolean(default=false) - reportFontAttributes = boolean(default=false) + # Deprecated in 2025.1 + reportFontAttributes = boolean(default=false) + # 0: Off, 1: Speech, 2: Braille, 3: Speech and Braille + fontAttributeReporting = integer(0, 3, default=0) reportRevisions = boolean(default=true) reportEmphasis = boolean(default=false) reportHighlight = boolean(default=true) diff --git a/source/config/profileUpgradeSteps.py b/source/config/profileUpgradeSteps.py index 38b394fd816..f98fe167d29 100644 --- a/source/config/profileUpgradeSteps.py +++ b/source/config/profileUpgradeSteps.py @@ -22,6 +22,7 @@ ReportLineIndentation, ReportTableHeaders, ReportCellBorders, + OutputMode, ) import configobj.validate from configobj import ConfigObj @@ -377,3 +378,21 @@ def upgradeConfigFrom_10_to_11(profile: ConfigObj) -> None: "hidBrailleStandard added to braille display auto detection excluded displays. " f"List is now: {profile['braille']['auto']['excludedDisplays']}", ) + + +def upgradeConfigFrom_11_to_12(profile: ConfigObj) -> None: + """Add a new key, documentFormatting.fontAttributeReporting, which allows users to select between speech and/or braille, and base it on documentFormatting.reportFontAttributes.""" + try: + reportFontAttributes: bool = profile["documentFormatting"].as_bool("reportFontAttributes") + except KeyError: + log.debug("reportFontAttributes not present in config, no action taken.") + return + except ValueError: + log.error("reportFontAttributes is not a boolean, no action taken.") + return + profile["documentFormatting"]["fontAttributeReporting"] = ( + OutputMode.SPEECH_AND_BRAILLE if reportFontAttributes else OutputMode.OFF + ) + log.debug( + f"documentFormatting.fontAttributeReporting added with value {profile['documentFormatting']['fontAttributeReporting']}." + ) diff --git a/source/globalCommands.py b/source/globalCommands.py index 340c3383579..5241d175ebd 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -43,6 +43,7 @@ TetherTo, ShowMessages, BrailleMode, + OutputMode, ) from config.featureFlag import FeatureFlag from config.featureFlagEnums import BoolFlag @@ -573,20 +574,30 @@ def script_toggleReportFontSize(self, gesture): ui.message(state) @script( - # Translators: Input help mode message for toggle report font attributes command. - description=_("Toggles on and off the reporting of font attributes"), + description=_( + # Translators: Input help mode message for toggle report font attributes command. + "Cycles font attribute reporting between speech, braille, speech and braille, and off." + ), category=SCRCAT_DOCUMENTFORMATTING, ) - def script_toggleReportFontAttributes(self, gesture): - if config.conf["documentFormatting"]["reportFontAttributes"]: - # Translators: The message announced when toggling the report font attributes document formatting setting. - state = _("report font attributes off") - config.conf["documentFormatting"]["reportFontAttributes"] = False - else: - # Translators: The message announced when toggling the report font attributes document formatting setting. - state = _("report font attributes on") - config.conf["documentFormatting"]["reportFontAttributes"] = True - ui.message(state) + def script_toggleReportFontAttributes(self, gesture: "inputCore.InputGesture"): + currentValue = config.conf["documentFormatting"]["fontAttributeReporting"] + nextValue = OutputMode((currentValue + 1) % len(OutputMode.__members__)) + match nextValue: + case OutputMode.OFF: + # Translators: A state in which font attributes are not reported. + status = _("Do not report font attributes") + case OutputMode.SPEECH: + # Translators: A state in which font attributes are only spoken. + status = _("Speak font attributes") + case OutputMode.BRAILLE: + # Translators: A state in which font attributes are only brailled. + status = _("Braille font attributes") + case OutputMode.SPEECH_AND_BRAILLE: + # Translators: A state in which font attributes are both spoken and brailled. + status = _("Speak and braille font attributes") + config.conf["documentFormatting"]["fontAttributeReporting"] = nextValue + ui.message(status) @script( # Translators: Input help mode message for toggle superscripts and subscripts command. @@ -2366,7 +2377,7 @@ def _reportFormattingHelper(self, info, browseable=False): reportFormattingOptions = ( "reportFontName", "reportFontSize", - "reportFontAttributes", + "fontAttributeReporting", "reportSuperscriptsAndSubscripts", "reportHighlight", "reportColor", diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index d28cb6415d8..9e762329a35 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -34,6 +34,7 @@ ReportLineIndentation, ReportTableHeaders, ReportCellBorders, + OutputMode, ) import languageHandler import speech @@ -2572,8 +2573,12 @@ def makeSettings(self, settingsSizer): # Translators: This is the label for a checkbox in the # document formatting settings panel. fontAttributesText = _("Font attrib&utes") - self.fontAttrsCheckBox = fontGroup.addItem(wx.CheckBox(fontGroupBox, label=fontAttributesText)) - self.fontAttrsCheckBox.SetValue(config.conf["documentFormatting"]["reportFontAttributes"]) + fontAttributesOptions = [i.displayString for i in OutputMode.__members__.values()] + self.fontAttrsList = fontGroup.addLabeledControl( + fontAttributesText, wx.Choice, choices=fontAttributesOptions + ) + self.bindHelpEvent("DocumentFormattingFontAttributes", self.fontAttrsList) + self.fontAttrsList.SetSelection(config.conf["documentFormatting"]["fontAttributeReporting"]) # Translators: This is the label for a checkbox in the # document formatting settings panel. @@ -2844,7 +2849,7 @@ def onSave(self): ) config.conf["documentFormatting"]["reportFontName"] = self.fontNameCheckBox.IsChecked() config.conf["documentFormatting"]["reportFontSize"] = self.fontSizeCheckBox.IsChecked() - config.conf["documentFormatting"]["reportFontAttributes"] = self.fontAttrsCheckBox.IsChecked() + config.conf["documentFormatting"]["fontAttributeReporting"] = self.fontAttrsList.GetSelection() config.conf["documentFormatting"]["reportSuperscriptsAndSubscripts"] = ( self.superscriptsAndSubscriptsCheckBox.IsChecked() ) diff --git a/source/speech/speech.py b/source/speech/speech.py index 95f42ebd913..d910f866339 100644 --- a/source/speech/speech.py +++ b/source/speech/speech.py @@ -66,6 +66,7 @@ ReportLineIndentation, ReportTableHeaders, ReportCellBorders, + OutputMode, ) import aria from .priorities import Spri @@ -2781,12 +2782,12 @@ def getFormatFieldSpeech( # noqa: C901 else _("not emphasised") ) textList.append(text) - if formatConfig["reportFontAttributes"]: + if formatConfig["fontAttributeReporting"] & OutputMode.SPEECH: bold = attrs.get("bold") oldBold = attrsCache.get("bold") if attrsCache is not None else None if (bold or oldBold is not None) and bold != oldBold: - # Translators: Reported when text is bolded. text = ( + # Translators: Reported when text is bolded. _("bold") if bold # Translators: Reported when text is not bolded. diff --git a/source/winConsoleHandler.py b/source/winConsoleHandler.py index 31967ae3260..cd14e152a3f 100755 --- a/source/winConsoleHandler.py +++ b/source/winConsoleHandler.py @@ -287,7 +287,7 @@ def getTextWithFields(self, formatConfig: Optional[Dict] = None) -> textInfos.Te if formatConfig["reportColor"]: formatField["color"] = CONSOLE_COLORS_TO_RGB[c.Attributes & 0x0F] formatField["background-color"] = CONSOLE_COLORS_TO_RGB[(c.Attributes >> 4) & 0x0F] - if formatConfig["reportFontAttributes"] and c.Attributes & COMMON_LVB_UNDERSCORE: + if formatConfig["fontAttributeReporting"] and c.Attributes & COMMON_LVB_UNDERSCORE: formatField["underline"] = True if formatField: if lastText: diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 6fd6241c9e8..e16e207c248 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -29,6 +29,7 @@ _upgradeConfigFrom_8_to_9_showMessages, _upgradeConfigFrom_8_to_9_tetherTo, upgradeConfigFrom_9_to_10, + upgradeConfigFrom_11_to_12, ) from config.configFlags import ( NVDAKey, @@ -36,6 +37,7 @@ ReportLineIndentation, ReportCellBorders, TetherTo, + OutputMode, ) from utils.displayString import ( DisplayStringEnum, @@ -784,6 +786,95 @@ def test_ManualProfile_setNumpadInsertFalseExtendedInsertFalse(self): ) +class Config_upgradeProfileSteps_upgradeProfileFrom_11_to_12(unittest.TestCase): + def test_DefaultProfile_Unmodified(self): + """reportFontAttributes unmodified.""" + configString = "[documentFormatting]" + profile = _loadProfile(configString) + upgradeConfigFrom_11_to_12(profile) + with self.assertRaises(KeyError): + profile["documentFormatting"]["reportFontAttributes"] + with self.assertRaises(KeyError): + profile["documentFormatting"]["fontAttributeReporting"] + + def test_defaultProfile_reportFontAttributes_false(self): + """reportFontAttributes set to False.""" + configString = """ + [documentFormatting] + reportFontAttributes = False + """ + profile = _loadProfile(configString) + upgradeConfigFrom_11_to_12(profile) + self.assertEqual(profile["documentFormatting"]["reportFontAttributes"], "False") + self.assertEqual(profile["documentFormatting"]["fontAttributeReporting"], OutputMode.OFF.value) + + def test_defaultProfile_reportFontAttributes_true(self): + """reportFontAttributes set to True.""" + configString = """ + [documentFormatting] + reportFontAttributes = True + """ + profile = _loadProfile(configString) + upgradeConfigFrom_11_to_12(profile) + self.assertEqual(profile["documentFormatting"]["reportFontAttributes"], "True") + self.assertEqual( + profile["documentFormatting"]["fontAttributeReporting"], OutputMode.SPEECH_AND_BRAILLE.value + ) + + def test_defaultProfile_reportFontAttributes_invalid(self): + """reportFontAttributes set to a non-boolean value.""" + configString = """ + [documentFormatting] + reportFontAttributes = notABool + """ + profile = _loadProfile(configString) + upgradeConfigFrom_11_to_12(profile) + self.assertEqual(profile["documentFormatting"]["reportFontAttributes"], "notABool") + with self.assertRaises(KeyError): + profile["documentFormatting"]["fontAttributeReporting"] + + +class Config_getitem_alias(unittest.TestCase): + def setUp(self): + self.config = ConfigManager()["documentFormatting"] + + def test_set_reportFontAttributes_false(self): + config = self.config + config["reportFontAttributes"] = False + self.assertEqual(config["reportFontAttributes"], False) + self.assertEqual(config["fontAttributeReporting"], OutputMode.OFF) + + def test_set_reportFontAttributes_true(self): + config = self.config + config["reportFontAttributes"] = True + self.assertEqual(config["reportFontAttributes"], True) + self.assertEqual(config["fontAttributeReporting"], OutputMode.SPEECH_AND_BRAILLE) + + def test_set_fontAttributeReporting_off(self): + config = self.config + config["fontAttributeReporting"] = OutputMode.OFF + self.assertEqual(config["fontAttributeReporting"], OutputMode.OFF) + self.assertEqual(config["reportFontAttributes"], False) + + def test_set_fontAttributeReporting_speech(self): + config = self.config + config["fontAttributeReporting"] = OutputMode.SPEECH + self.assertEqual(config["fontAttributeReporting"], OutputMode.SPEECH) + self.assertEqual(config["reportFontAttributes"], True) + + def test_set_fontAttributeReporting_braille(self): + config = self.config + config["fontAttributeReporting"] = OutputMode.BRAILLE + self.assertEqual(config["fontAttributeReporting"], OutputMode.BRAILLE) + self.assertEqual(config["reportFontAttributes"], True) + + def test_set_fontAttributeReporting_speechAndBraille(self): + config = self.config + config["fontAttributeReporting"] = OutputMode.SPEECH_AND_BRAILLE + self.assertEqual(config["fontAttributeReporting"], OutputMode.SPEECH_AND_BRAILLE) + self.assertEqual(config["reportFontAttributes"], True) + + class Config_AggregatedSection_getitem(unittest.TestCase): def setUp(self): manager = MagicMock(ConfigManager()) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index e26865f9883..8517edb5f77 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -6,6 +6,8 @@ ### New Features +* NVDA can now be configured to report font attributes in speech and braille separately. (#16755) + ### Bug Fixes * NVDA once again relies on UIA events for caret movement in XAML and WPF text controls, rather than only on manual querying of the caret position. (#16817, @LeonarddeR) @@ -18,6 +20,10 @@ Please refer to [the developer guide](https://www.nvaccess.org/files/nvda/docume #### Deprecations +* The `bool` configuration key `[documentFormatting][reportFontAttributes]` is deprecated for removal in 2025.1, instead use `[fontAttributeReporting]`. (#16748) + * The new key has an `int` value matching an `OutputMode` `enum` with options for speech, braille, speech and braille and off. + * API consumers can use the `bool` value as previously, or check the `OutputMode` if handling speech or braille specifically. + * These keys are currently synchronized until 2025.1. * `NVDAObjects.UIA.InaccurateTextChangeEventEmittingEditableText` is deprecated with no replacement. (#16817, @LeonarddeR) ## 2024.3 diff --git a/user_docs/en/userGuide.md b/user_docs/en/userGuide.md index 22c73eb4e8d..16d8b158909 100644 --- a/user_docs/en/userGuide.md +++ b/user_docs/en/userGuide.md @@ -2841,7 +2841,7 @@ You can configure reporting of: * Font * Font name * Font size - * Font attributes + * Font attributes [(Off, Speech, Braille, Speech and braille)](#DocumentFormattingFontAttributes) * Superscripts and subscripts * Emphasis * Highlighted (Marked) text @@ -2880,6 +2880,18 @@ You can configure reporting of: To toggle these settings from anywhere, please assign custom gestures using the [Input Gestures dialog](#InputGestures). +##### Font attributes {#DocumentFormattingFontAttributes} + +This option allows you to select how certain font attributes, such as bold, italics, underline and strikethrough are reported. +The font attributes combo box has four options: + +* Off: NVDA will not report these font attributes. +* Speech: NVDA will announce when these font attributes change. +* Braille: NVDA will display bold, italic, and underlines in braille. +Note that your chosen braille table must support displaying these attributes. +Exactly how these attributes are displayed varies between tables. +* Speech and braille: NVDA will report font attributes using both of the above methods. + ##### Report formatting changes after the cursor {#DocumentFormattingDetectFormatAfterCursor} If enabled, this setting tells NVDA to try and detect all the formatting changes on a line as it reports it, even if doing this may slow down NVDA's performance.