Commit 48c27836 authored by Akihiro Ota's avatar Akihiro Ota Committed by Commit Bot

ChromeVox: Add hotkey to announce phonetic disambiguation.

This change adds a hotkey in ChromeVox that allows the user to get
the phonetic disambiguation for the current word in the node's name.
If the user is on a node, then we speak the first word in the node's
name. Upon activation, ChromeVox speaks each character in the word,
followed by its phonetic disambiguation.

Change-Id: I1a88c3256cf1084a971f6fc7fc47d5bfe847ab11
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1811988Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Commit-Queue: Akihiro Ota <akihiroota@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699057}
parent c4193280
......@@ -1014,6 +1014,15 @@
"keyCode": [65, 70]
}
}
},
{
"command": "readPhoneticPronunciation",
"sequence": {
"cvoxModifier": true,
"keys": {
"keyCode": [65, 67]
}
}
}
]
}
......@@ -132,11 +132,8 @@ cvox.CommandStore.commandsForCategory = function(category) {
* false.
*/
cvox.CommandStore.CMD_WHITELIST = {
'toggleStickyMode': {
announce: false,
msgId: 'toggle_sticky_mode',
category: 'modifier_keys'
},
'toggleStickyMode':
{announce: false, msgId: 'toggle_sticky_mode', category: 'modifier_keys'},
'passThroughMode': {
announce: false,
msgId: 'pass_through_key_description',
......@@ -819,6 +816,12 @@ cvox.CommandStore.CMD_WHITELIST = {
'pauseAllMedia':
{announce: false, msgId: 'pause_all_media', category: 'information'},
'readPhoneticPronunciation': {
announce: true,
msgId: 'read_phonetic_pronunciation',
category: 'information'
},
// Scrolling actions.
'scrollBackward': {msgId: 'action_scroll_backward_description'},
'scrollForward': {msgId: 'action_scroll_forward_description'},
......
......@@ -1990,7 +1990,6 @@ TEST_F('ChromeVoxBackgroundTest', 'DISABLED_PopUpButtonSetSize', function() {
var button = document.getElementById('button');
var expanded = false;
button.addEventListener('click', function(e) {
console.error('Heelooo');
if (expanded)
button.setAttribute('aria-expanded', false);
else
......@@ -2018,3 +2017,47 @@ TEST_F('ChromeVoxBackgroundTest', 'DISABLED_PopUpButtonSetSize', function() {
.replay();
});
});
TEST_F('ChromeVoxBackgroundTest', 'ReadPhoneticPronunciationTest', function() {
var mockFeedback = this.createMockFeedback();
this.runWithLoadedTree(function() {/*!
<button>This is a button</button>
<input type="text"></input>
*/}, function(root) {
root.find({role: RoleType.BUTTON}).focus();
mockFeedback.call(doCmd('readPhoneticPronunciation'))
.expectSpeech('T')
.expectSpeech('tango')
.expectSpeech('h')
.expectSpeech('hotel')
.expectSpeech('i')
.expectSpeech('india')
.expectSpeech('s')
.expectSpeech('sierra')
.call(doCmd('nextWord'))
.call(doCmd('readPhoneticPronunciation'))
.expectSpeech('i')
.expectSpeech('india')
.expectSpeech('s')
.expectSpeech('sierra')
.call(doCmd('nextWord'))
.call(doCmd('nextWord'))
.call(doCmd('readPhoneticPronunciation'))
.expectSpeech('b')
.expectSpeech('bravo')
.expectSpeech('u')
.expectSpeech('uniform')
.expectSpeech('t')
.expectSpeech('tango')
.expectSpeech('t')
.expectSpeech('tango')
.expectSpeech('o')
.expectSpeech('oscar')
.expectSpeech('n')
.expectSpeech('november')
.call(doCmd('nextEditText'))
.call(doCmd('readPhoneticPronunciation'))
.expectSpeech('No available text for this item');
mockFeedback.replay();
});
});
......@@ -9,15 +9,16 @@
goog.provide('CommandHandler');
goog.require('ChromeVoxState');
goog.require('Color');
goog.require('CustomAutomationEvent');
goog.require('LogStore');
goog.require('Output');
goog.require('PhoneticData');
goog.require('TreeDumper');
goog.require('cvox.ChromeVoxBackground');
goog.require('cvox.ChromeVoxKbHandler');
goog.require('cvox.ChromeVoxPrefs');
goog.require('cvox.CommandStore');
goog.require('Color');
goog.scope(function() {
var AutomationEvent = chrome.automation.AutomationEvent;
......@@ -896,6 +897,65 @@ CommandHandler.onCommand = function(command) {
.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH)
.go();
return false;
case 'readPhoneticPronunciation':
// Get node info.
var node = ChromeVoxState.instance.currentRange.start.node;
var index = ChromeVoxState.instance.currentRange.start.index;
var text = node.name;
// If there is no text to speak, inform the user and return early.
if (!text) {
new Output()
.withString(Msgs.getMsg('empty_name'))
.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH)
.go();
return false;
}
// Get word start and end indices.
var wordStarts, wordEnds;
if (node.role == RoleType.INLINE_TEXT_BOX) {
wordStarts = node.wordStarts;
wordEnds = node.wordEnds;
} else {
wordStarts = node.nonInlineTextWordStarts;
wordEnds = node.nonInlineTextWordEnds;
}
// Find the word we want to speak phonetically. If index === -1, then the
// index represents an entire node. If that is the case, we want to find
// the first word in the node's name. We do this by setting index to 0.
if (index === -1)
index = 0;
var word = '';
for (var z = 0; z < wordStarts.length; ++z) {
if (wordStarts[z] <= index && wordEnds[z] >= index) {
word = text.substring(wordStarts[z], wordEnds[z]);
break;
}
}
// Get unicode-aware array of characters.
var characterArray = [...word];
// We currently only load phonetic data for the browser UI language.
var language = chrome.i18n.getUILanguage();
for (var i = 0; i < characterArray.length; ++i) {
var character = characterArray[i];
var phoneticText =
PhoneticData.getPhoneticDisambiguation(language, character);
// Speak the character followed by its phonetic disambiguation, if it
// was found.
new Output()
.withString(character)
.withQueueMode(
i === 0 ? cvox.QueueMode.CATEGORY_FLUSH : cvox.QueueMode.QUEUE)
.go();
if (phoneticText) {
new Output()
.withString(phoneticText)
.withQueueMode(cvox.QueueMode.QUEUE)
.go();
}
}
return false;
default:
return true;
}
......
......@@ -49,9 +49,10 @@ PhoneticData.init = function() {
* @return {string}
*/
PhoneticData.getPhoneticDisambiguation = function(language, character) {
if (!language)
if (!language || !character)
return '';
language = language.toLowerCase();
character = character.toLowerCase();
// If language isn't in the map, try stripping extra information, such as the
// country and/or script codes (e.g. "en-us" or "zh-hant-hk") and use only the
// language code to do a lookup.
......
......@@ -3709,6 +3709,12 @@ If you're done with the tutorial, use ChromeVox to navigate to the Close button
<message desc="Appends language in front of content." name="IDS_CHROMEVOX_LANGUAGE_SWITCH">
<ph name="language">$1<ex>English</ex></ph>: <ph name="content">$2<ex>This is example content</ex></ph>
</message>
<message desc="The description of the readPhoneticPronunciation key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_READ_PHONETIC_PRONUNCIATION">
Announce phonetic pronunciation for word
</message>
<message desc="Spoken to inform the user that the node's name is empty" name="IDS_CHROMEVOX_EMPTY_NAME">
No available text for this item
</message>
</messages>
</release>
</grit>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment