Major sound fixes and more added. Fixed a bug where switch items were being silently ignored.
This commit is contained in:
@@ -1035,23 +1035,6 @@
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="enableModeChangeSoundCheckButton">
|
||||
<property name="label" translatable="yes" comments="Translators: If this checkbox is checked, Cthulhu will play sounds when switching between browse mode and focus mode in web content.">Play sounds when switching between _browse and focus modes</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="enableModeChangeSoundCheckButtonToggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="soundThemeHBox">
|
||||
<property name="visible">True</property>
|
||||
@@ -1094,7 +1077,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@@ -1139,7 +1122,7 @@
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@@ -2004,15 +2004,9 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
|
||||
prefs = self.prefsDict
|
||||
|
||||
# Get widget references
|
||||
self.enableModeChangeSoundCheckButton = self.get_widget(
|
||||
"enableModeChangeSoundCheckButton")
|
||||
self.soundThemeCombo = self.get_widget("soundThemeCombo")
|
||||
self.roleSoundPresentationCombo = self.get_widget("roleSoundPresentationCombo")
|
||||
|
||||
# Set enable mode change sound checkbox
|
||||
enabled = prefs.get("enableModeChangeSound", settings.enableModeChangeSound)
|
||||
self.enableModeChangeSoundCheckButton.set_active(enabled)
|
||||
|
||||
# Populate sound theme combo box
|
||||
themeManager = sound_theme_manager.getManager()
|
||||
availableThemes = themeManager.getAvailableThemes()
|
||||
@@ -2055,19 +2049,6 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper):
|
||||
break
|
||||
self.roleSoundPresentationCombo.set_active(presentationIndex)
|
||||
|
||||
# Update sensitivity based on checkbox
|
||||
self._updateSoundThemeWidgetSensitivity()
|
||||
|
||||
def _updateSoundThemeWidgetSensitivity(self):
|
||||
"""Update sound theme combo sensitivity based on enable checkbox."""
|
||||
enabled = self.enableModeChangeSoundCheckButton.get_active()
|
||||
self.soundThemeCombo.set_sensitive(enabled)
|
||||
|
||||
def enableModeChangeSoundCheckButtonToggled(self, widget):
|
||||
"""Signal handler for the enable mode change sound checkbox."""
|
||||
self.prefsDict["enableModeChangeSound"] = widget.get_active()
|
||||
self._updateSoundThemeWidgetSensitivity()
|
||||
|
||||
def soundThemeComboChanged(self, widget):
|
||||
"""Signal handler for the sound theme combo box."""
|
||||
activeText = widget.get_active_text()
|
||||
|
||||
@@ -915,11 +915,11 @@ formatting = {
|
||||
},
|
||||
Atspi.Role.CHECK_BOX: {
|
||||
'focused': 'checkedState',
|
||||
'unfocused': 'roleName + checkedState + required + invalid + availability',
|
||||
'unfocused': 'checkedState + required + invalid + availability',
|
||||
},
|
||||
Atspi.Role.CHECK_MENU_ITEM: {
|
||||
'focused': 'checkedState',
|
||||
'unfocused': 'roleName + checkedState + availability + positionInSet',
|
||||
'unfocused': 'checkedState + availability + positionInSet',
|
||||
},
|
||||
Atspi.Role.COMBO_BOX: {
|
||||
'focused': 'expandableState',
|
||||
@@ -970,11 +970,11 @@ formatting = {
|
||||
},
|
||||
Atspi.Role.RADIO_BUTTON: {
|
||||
'focused': 'radioState',
|
||||
'unfocused': 'roleName + radioState + availability + positionInSet',
|
||||
'unfocused': 'radioState + availability + positionInSet',
|
||||
},
|
||||
Atspi.Role.RADIO_MENU_ITEM: {
|
||||
'focused': 'radioState',
|
||||
'unfocused': 'roleName + checkedState + availability + positionInSet',
|
||||
'unfocused': 'checkedState + availability + positionInSet',
|
||||
},
|
||||
Atspi.Role.SCROLL_BAR: {
|
||||
'focused': 'percentage',
|
||||
@@ -994,7 +994,7 @@ formatting = {
|
||||
},
|
||||
'ROLE_SWITCH': {
|
||||
'focused': 'switchState',
|
||||
'unfocused': 'roleName + switchState + availability',
|
||||
'unfocused': 'switchState + availability',
|
||||
},
|
||||
Atspi.Role.TABLE_CELL: {
|
||||
'focused': 'expandableState',
|
||||
@@ -1008,7 +1008,7 @@ formatting = {
|
||||
},
|
||||
Atspi.Role.TOGGLE_BUTTON: {
|
||||
'focused': 'expandableState or toggleState',
|
||||
'unfocused': 'roleName + (expandableState or toggleState) + availability',
|
||||
'unfocused': '(expandableState or toggleState) + availability',
|
||||
},
|
||||
Atspi.Role.TREE_ITEM: {
|
||||
'focused': 'expandableState',
|
||||
|
||||
@@ -929,11 +929,6 @@ USE_CARET_NAVIGATION = _("Control caret navigation")
|
||||
# of a checkbox in which users can indicate their default preference.
|
||||
USE_STRUCTURAL_NAVIGATION = _("Enable _structural navigation")
|
||||
|
||||
# Translators: This is the label for a checkbox in the preferences dialog.
|
||||
# When enabled, Cthulhu will play sounds when switching between browse mode
|
||||
# and focus mode in web content.
|
||||
ENABLE_MODE_CHANGE_SOUND = _("Play sounds when switching between _browse and focus modes")
|
||||
|
||||
# Translators: This is the label for a combo box in the preferences dialog
|
||||
# where users can select a sound theme. A sound theme is a collection of
|
||||
# audio files that Cthulhu plays for various events.
|
||||
|
||||
@@ -1429,6 +1429,8 @@ class Script(default.Script):
|
||||
return None
|
||||
|
||||
role = AXObject.get_role(obj)
|
||||
if self.utilities.isSwitch(obj):
|
||||
role = Atspi.Role.SWITCH
|
||||
manager = sound_theme_manager.getManager()
|
||||
icon = manager.getRoleSoundIcon(role)
|
||||
if icon:
|
||||
|
||||
@@ -4009,6 +4009,9 @@ class Utilities(script_utilities.Utilities):
|
||||
if not (obj and self.inDocumentContent(obj)):
|
||||
return super().isSwitch(obj)
|
||||
|
||||
if AXObject.get_role(obj) == Atspi.Role.SWITCH:
|
||||
return True
|
||||
|
||||
return 'switch' in self._getXMLRoles(obj)
|
||||
|
||||
def isNonNavigableEmbeddedDocument(self, obj):
|
||||
|
||||
@@ -553,6 +553,16 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
|
||||
result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args))
|
||||
|
||||
role = args.get('role', AXObject.get_role(obj))
|
||||
roleSoundPresentation = _settingsManager.getSetting('roleSoundPresentation')
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY \
|
||||
and _settingsManager.getSetting('enableSound'):
|
||||
if AXUtilities.is_check_box(obj) \
|
||||
or AXUtilities.is_check_menu_item(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):
|
||||
return []
|
||||
enabled, disabled = self._getEnabledAndDisabledContextRoles()
|
||||
if role in disabled:
|
||||
return []
|
||||
@@ -659,19 +669,18 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
|
||||
if not result:
|
||||
return result
|
||||
|
||||
roleSoundPresentation = _settingsManager.getSetting('roleSoundPresentation')
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SPEECH_ONLY:
|
||||
return result
|
||||
if not _settingsManager.getSetting('enableSound'):
|
||||
return result
|
||||
|
||||
roleSoundIcon = sound_theme_manager.getManager().getRoleSoundIcon(role)
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY:
|
||||
return [roleSoundIcon] if roleSoundIcon else []
|
||||
|
||||
if not roleSoundIcon:
|
||||
return result
|
||||
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY:
|
||||
return [roleSoundIcon]
|
||||
|
||||
return [roleSoundIcon] + result
|
||||
|
||||
def _generatePageSummary(self, obj, **args):
|
||||
|
||||
@@ -80,7 +80,6 @@ userCustomizableSettings = [
|
||||
"playSoundForValue",
|
||||
"roleSoundPresentation",
|
||||
"soundTheme",
|
||||
"enableModeChangeSound",
|
||||
"verbalizePunctuationStyle",
|
||||
"presentToolTips",
|
||||
"sayAllStyle",
|
||||
@@ -322,7 +321,6 @@ playSoundForPositionInSet = False
|
||||
playSoundForValue = False
|
||||
roleSoundPresentation = ROLE_SOUND_PRESENTATION_SOUND_AND_SPEECH
|
||||
soundTheme = "default"
|
||||
enableModeChangeSound = True
|
||||
|
||||
# Keyboard and Echo
|
||||
keyboardLayout = GENERAL_KEYBOARD_LAYOUT_DESKTOP
|
||||
|
||||
@@ -371,6 +371,11 @@ class SoundGenerator(generator.Generator):
|
||||
return []
|
||||
|
||||
role = args.get('role', AXObject.get_role(obj))
|
||||
if isinstance(role, str):
|
||||
if role == "ROLE_SWITCH":
|
||||
role = Atspi.Role.SWITCH
|
||||
else:
|
||||
return []
|
||||
filename = Atspi.role_get_name(role).replace(' ', '_')
|
||||
result = self._convertFilenameToIcon(filename)
|
||||
if result:
|
||||
|
||||
@@ -172,6 +172,9 @@ class SoundThemeManager:
|
||||
|
||||
def _getRoleSoundCandidates(self, role):
|
||||
"""Return candidate sound names for a given role."""
|
||||
role = self._normalizeRole(role)
|
||||
if role is None:
|
||||
return []
|
||||
candidates = ROLE_SOUND_ALIASES.get(role, [])
|
||||
if candidates:
|
||||
return candidates
|
||||
@@ -182,8 +185,18 @@ class SoundThemeManager:
|
||||
|
||||
return []
|
||||
|
||||
def _normalizeRole(self, role):
|
||||
if isinstance(role, str):
|
||||
if role == "ROLE_SWITCH":
|
||||
return Atspi.Role.SWITCH
|
||||
return None
|
||||
return role
|
||||
|
||||
def _getRoleStateSoundCandidates(self, role, stateKey):
|
||||
"""Return candidate sound names for a given role/state pair."""
|
||||
role = self._normalizeRole(role)
|
||||
if role is None:
|
||||
return []
|
||||
bases = ROLE_STATE_SOUND_BASES.get(role, [])
|
||||
if not bases:
|
||||
return []
|
||||
@@ -225,21 +238,18 @@ class SoundThemeManager:
|
||||
return None
|
||||
|
||||
def _playThemeSound(self, soundName, interrupt=True, wait=False,
|
||||
requireModeChangeSetting=False, requireSoundSetting=False):
|
||||
requireSoundSetting=False):
|
||||
"""Play a themed sound with optional gating and blocking.
|
||||
|
||||
Args:
|
||||
soundName: The name of the sound file (without extension)
|
||||
interrupt: Whether to interrupt currently playing sounds
|
||||
wait: Whether to block until the sound finishes playing
|
||||
requireModeChangeSetting: Honor enableModeChangeSound setting
|
||||
requireSoundSetting: Honor enableSound setting
|
||||
|
||||
Returns:
|
||||
True if sound was played, False otherwise
|
||||
"""
|
||||
if requireModeChangeSetting and not _settingsManager.getSetting('enableModeChangeSound'):
|
||||
return False
|
||||
if requireSoundSetting and not _settingsManager.getSetting('enableSound'):
|
||||
return False
|
||||
|
||||
@@ -285,8 +295,7 @@ class SoundThemeManager:
|
||||
return self._playThemeSound(
|
||||
soundName,
|
||||
interrupt=interrupt,
|
||||
wait=wait,
|
||||
requireModeChangeSetting=True
|
||||
wait=wait
|
||||
)
|
||||
|
||||
def playFocusModeSound(self):
|
||||
|
||||
@@ -581,6 +581,15 @@ class SpeechGenerator(generator.Generator):
|
||||
result = []
|
||||
role = args.get('role', AXObject.get_role(obj))
|
||||
roleSoundPresentation = _settingsManager.getSetting('roleSoundPresentation')
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY \
|
||||
and _settingsManager.getSetting('enableSound'):
|
||||
if AXUtilities.is_check_box(obj) \
|
||||
or AXUtilities.is_check_menu_item(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):
|
||||
return []
|
||||
roleSoundIcon = None
|
||||
if roleSoundPresentation != settings.ROLE_SOUND_PRESENTATION_SPEECH_ONLY \
|
||||
and _settingsManager.getSetting('enableSound'):
|
||||
@@ -627,9 +636,10 @@ class SpeechGenerator(generator.Generator):
|
||||
result.append(self.getLocalizedRoleName(obj, **args))
|
||||
result.extend(self.voice(SYSTEM, obj=obj, **args))
|
||||
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY:
|
||||
return [roleSoundIcon] if roleSoundIcon else []
|
||||
|
||||
if result and roleSoundIcon:
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_ONLY:
|
||||
return [roleSoundIcon]
|
||||
if roleSoundPresentation == settings.ROLE_SOUND_PRESENTATION_SOUND_AND_SPEECH:
|
||||
return [roleSoundIcon] + result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user