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