Better handling of sound only setting.

This commit is contained in:
Storm Dragon
2025-12-30 07:04:16 -05:00
parent b0375faa45
commit e059063115
2 changed files with 89 additions and 0 deletions
@@ -375,6 +375,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
if self._script.utilities.shouldVerbalizeAllPunctuation(obj): if self._script.utilities.shouldVerbalizeAllPunctuation(obj):
name = self._script.utilities.verbalizeAllPunctuation(name) name = self._script.utilities.verbalizeAllPunctuation(name)
name = self._stripRoleFromNameIfNeeded(obj, name, role)
result = [name] result = [name]
result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args))
return result return result
@@ -423,6 +424,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
name = AXObject.get_name(obj) name = AXObject.get_name(obj)
if not self._script.utilities.hasExplicitName(obj): if not self._script.utilities.hasExplicitName(obj):
name = name.strip() name = name.strip()
name = self._stripRoleFromNameIfNeeded(obj, name, role)
result = [name] result = [name]
result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args))
@@ -439,6 +441,8 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
label, objects = self._script.utilities.inferLabelFor(obj) label, objects = self._script.utilities.inferLabelFor(obj)
if label: if label:
role = args.get('role', AXObject.get_role(obj))
label = self._stripRoleFromNameIfNeeded(obj, label, role)
result = [label] result = [label]
result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args))
return result return result
+85
View File
@@ -169,6 +169,8 @@ class SpeechGenerator(generator.Generator):
result = generator.Generator._generateName(self, obj, **args) result = generator.Generator._generateName(self, obj, **args)
if result: if result:
if isinstance(result[0], str):
result[0] = self._stripRoleFromNameIfNeeded(obj, result[0], role)
if role == Atspi.Role.LAYERED_PANE: if role == Atspi.Role.LAYERED_PANE:
result.extend(self.voice(SYSTEM, obj=obj, **args)) result.extend(self.voice(SYSTEM, obj=obj, **args))
else: else:
@@ -185,6 +187,9 @@ class SpeechGenerator(generator.Generator):
result = generator.Generator._generateLabel(self, obj, **args) result = generator.Generator._generateLabel(self, obj, **args)
if result: if result:
role = args.get('role', AXObject.get_role(obj))
if isinstance(result[0], str):
result[0] = self._stripRoleFromNameIfNeeded(obj, result[0], role)
result.extend(self.voice(DEFAULT, obj=obj, **args)) result.extend(self.voice(DEFAULT, obj=obj, **args))
return result return result
@@ -205,6 +210,7 @@ class SpeechGenerator(generator.Generator):
if not result: if not result:
name = AXObject.get_name(obj) name = AXObject.get_name(obj)
if name: if name:
name = self._stripRoleFromNameIfNeeded(obj, name, role)
result.append(name) result.append(name)
result.extend(self.voice(DEFAULT, obj=obj, **args)) result.extend(self.voice(DEFAULT, obj=obj, **args))
if result: if result:
@@ -216,6 +222,85 @@ class SpeechGenerator(generator.Generator):
return result return result
def _stripRoleFromNameIfNeeded(self, obj, name, role=None):
if not name:
return name
roleSoundPresentation = _settingsManager.getSetting('roleSoundPresentation')
if roleSoundPresentation != settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY:
return name
if not _settingsManager.getSetting('enableSound'):
return name
if not self._shouldStripRoleFromName(obj):
return name
candidates = self._getRoleNameStripCandidates(obj, role)
if not candidates:
return name
strippedName = name.strip()
strippedNameLower = strippedName.casefold()
for candidate in candidates:
candidate = candidate.strip()
if not candidate:
continue
candidateLower = candidate.casefold()
if strippedNameLower == candidateLower:
continue
suffix = f" {candidateLower}"
if strippedNameLower.endswith(suffix):
return strippedName[:-(len(candidateLower) + 1)].rstrip()
suffix = f" ({candidateLower})"
if strippedNameLower.endswith(suffix):
return strippedName[:-(len(candidateLower) + 3)].rstrip()
return name
def _shouldStripRoleFromName(self, obj):
return AXUtilities.is_check_box(obj) \
or AXUtilities.is_check_menu_item(obj) \
or AXUtilities.is_combo_box(obj) \
or AXUtilities.is_push_button(obj) \
or AXUtilities.is_radio_button(obj) \
or AXUtilities.is_radio_menu_item(obj) \
or AXUtilities.is_toggle_button(obj) \
or AXUtilities.is_switch(obj)
def _getRoleNameStripCandidates(self, obj, role=None):
normalizedRole = role
if isinstance(normalizedRole, str):
if normalizedRole == "ROLE_SWITCH":
normalizedRole = Atspi.Role.SWITCH
else:
normalizedRole = None
candidates = []
if normalizedRole is None and isinstance(role, str):
localizedRoleName = self.getLocalizedRoleName(obj)
else:
localizedRoleName = self.getLocalizedRoleName(obj, role=normalizedRole or role)
if localizedRoleName:
candidates.append(localizedRoleName)
if " " in localizedRoleName:
candidates.append(localizedRoleName.replace(" ", ""))
if normalizedRole is not None and not isinstance(normalizedRole, str):
roleName = Atspi.role_get_name(normalizedRole)
if roleName:
candidates.append(roleName)
if " " in roleName:
candidates.append(roleName.replace(" ", ""))
if AXUtilities.is_push_button(obj):
candidates.append("button")
return list(dict.fromkeys(candidates))
def _generatePlaceholderText(self, obj, **args): def _generatePlaceholderText(self, obj, **args):
"""Returns an array of strings for use by speech and braille that """Returns an array of strings for use by speech and braille that
represent the 'placeholder' text. This is typically text that represent the 'placeholder' text. This is typically text that