Commit 0abb1953 authored by David Tseng's avatar David Tseng Committed by Commit Bot

Improve initial window announcements and learn mode

- chrome.tabs.create is unavailable when all windows are closed. Use
  chrome.windows.create instaed
- open learn mode in a panel window (e.g. no address bar)

- detect when a load complete fires with focus on an ancestor window
  such as when the learn mode window appears. This interrupts ChromeVox
  from reading the entire url of the root web area on initial showing of
  the root which happens before load complete. Since the window never
  explicitly places focus on the root web area, ChromeVox never reads
  the title or triggers focus recovery.

that a friendly (non-url) title gets read in both cases.

Test: launch both options page and learn mode from empty desktop. Verify
Bug: 
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Ia5f564cbaa2dedb07c50878368a371b54bf1ac2a
Reviewed-on: https://chromium-review.googlesource.com/825629
Commit-Queue: David Tseng <dtseng@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524580}
parent 9a6d07a3
......@@ -696,18 +696,22 @@ TEST_F('BackgroundTest', 'ForwardObjectNavigationThroughIframes', function() {
return;
running = true;
var suppressFocusActionOutput = function() {
DesktopAutomationHandler.announceActions = false;
};
var beforeButton = rootNode.find({role: RoleType.BUTTON,
name: 'Before'});
beforeButton.focus();
mockFeedback.expectSpeech('Before', 'Button');
mockFeedback.call(doCmd('nextObject'))
mockFeedback.call(beforeButton.focus.bind(beforeButton))
.expectSpeech('Before', 'Button')
.call(suppressFocusActionOutput)
.call(doCmd('nextObject'))
.expectSpeech('Inside', 'Button');
mockFeedback.call(doCmd('nextObject'))
.expectSpeech('Inside', 'Heading 1');
mockFeedback.call(doCmd('nextObject'))
.expectSpeech('After', 'Button');
mockFeedback.call(doCmd('previousObject'))
.expectSpeech('Heading 1', 'Inside');
.expectSpeech('Inside', 'Heading 1');
mockFeedback.call(doCmd('previousObject'))
.expectSpeech('Inside', 'Button');
mockFeedback.call(doCmd('previousObject'))
......
......@@ -100,8 +100,11 @@ CommandHandler.onCommand = function(command) {
Msgs.getMsg('pass_through_key'), cvox.QueueMode.QUEUE);
return true;
case 'showKbExplorerPage':
var explorerPage = {url: 'chromevox/background/kbexplorer.html'};
chrome.tabs.create(explorerPage);
var explorerPage = {
url: 'chromevox/background/kbexplorer.html',
type: 'panel'
};
chrome.windows.create(explorerPage);
break;
case 'decreaseTtsRate':
CommandHandler.increaseOrDecreaseSpeechProperty_(
......
......@@ -285,7 +285,8 @@ DesktopAutomationHandler.prototype = {
*/
onFocus: function(evt) {
if (evt.target.role == RoleType.ROOT_WEB_AREA) {
this.maybeRecoverFocusAndOutput_(evt);
chrome.automation.getFocus(
this.maybeRecoverFocusAndOutput_.bind(this, evt));
return;
}
......@@ -320,9 +321,20 @@ DesktopAutomationHandler.prototype = {
onLoadComplete: function(evt) {
this.lastRootUrl_ = '';
chrome.automation.getFocus(function(focus) {
if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target))
// In some situations, ancestor windows get focused before a descendant
// webView/rootWebArea. In particular, a window that gets opened but no
// inner focus gets set. We catch this generically by re-targetting focus
// if focus is the ancestor of the load complete target (below).
var focusIsAncestor = AutomationUtil.isDescendantOf(evt.target, focus);
var focusIsDescendant = AutomationUtil.isDescendantOf(focus, evt.target);
if (!focus || (!focusIsAncestor && !focusIsDescendant))
return;
if (focusIsAncestor) {
focus = evt.target;
Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
}
// Create text edit handler, if needed, now in order not to miss initial
// value change if text field has already been focused when initializing
// ChromeVox.
......@@ -339,7 +351,7 @@ DesktopAutomationHandler.prototype = {
return;
}
this.maybeRecoverFocusAndOutput_(evt);
this.maybeRecoverFocusAndOutput_(evt, focus);
}.bind(this));
},
......@@ -544,48 +556,46 @@ DesktopAutomationHandler.prototype = {
* @param {AutomationEvent} evt
* @private
*/
maybeRecoverFocusAndOutput_: function(evt) {
chrome.automation.getFocus(function(focus) {
var focusedRoot = AutomationUtil.getTopLevelRoot(focus);
if (!focusedRoot)
return;
maybeRecoverFocusAndOutput_: function(evt, focus) {
var focusedRoot = AutomationUtil.getTopLevelRoot(focus);
if (!focusedRoot)
return;
var curRoot;
if (ChromeVoxState.instance.currentRange) {
curRoot = AutomationUtil.getTopLevelRoot(
ChromeVoxState.instance.currentRange.start.node);
}
var curRoot;
if (ChromeVoxState.instance.currentRange) {
curRoot = AutomationUtil.getTopLevelRoot(
ChromeVoxState.instance.currentRange.start.node);
}
// If initial focus was already placed inside this page (e.g. if a user
// starts tabbing before load complete), then don't move ChromeVox's
// position on the page.
if (curRoot && focusedRoot == curRoot &&
this.lastRootUrl_ == focusedRoot.docUrl)
return;
// If initial focus was already placed inside this page (e.g. if a user
// starts tabbing before load complete), then don't move ChromeVox's
// position on the page.
if (curRoot && focusedRoot == curRoot &&
this.lastRootUrl_ == focusedRoot.docUrl)
return;
this.lastRootUrl_ = focusedRoot.docUrl || '';
var o = new Output();
// Restore to previous position.
var url = focusedRoot.docUrl;
url = url.substring(0, url.indexOf('#')) || url;
var pos = cvox.ChromeVox.position[url];
if (pos) {
focus = AutomationUtil.hitTest(focusedRoot, pos) || focus;
if (focus != focusedRoot)
o.format('$name', focusedRoot);
} else {
// This catches initial focus (i.e. on startup).
if (!curRoot && focus != focusedRoot)
o.format('$name', focusedRoot);
}
this.lastRootUrl_ = focusedRoot.docUrl || '';
var o = new Output();
// Restore to previous position.
var url = focusedRoot.docUrl;
url = url.substring(0, url.indexOf('#')) || url;
var pos = cvox.ChromeVox.position[url];
if (pos) {
focus = AutomationUtil.hitTest(focusedRoot, pos) || focus;
if (focus != focusedRoot)
o.format('$name', focusedRoot);
} else {
// This catches initial focus (i.e. on startup).
if (!curRoot && focus != focusedRoot)
o.format('$name', focusedRoot);
}
ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus));
ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus));
Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
o.withRichSpeechAndBraille(
ChromeVoxState.instance.currentRange, null, evt.type)
.go();
}.bind(this));
Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH);
o.withRichSpeechAndBraille(
ChromeVoxState.instance.currentRange, null, evt.type)
.go();
}
};
......
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