diff options
author | dtseng <dtseng@chromium.org> | 2015-06-26 10:58:46 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-26 17:59:14 +0000 |
commit | 911ea803dbd347a95ca49f4d46ad4c2e1ab06ac1 (patch) | |
tree | e1f7825d144bbc9f8230d3f89f643512328850fa | |
parent | d3639a0b90860d03afa59a06c6635d7af23111d1 (diff) | |
download | chromium_src-911ea803dbd347a95ca49f4d46ad4c2e1ab06ac1.zip chromium_src-911ea803dbd347a95ca49f4d46ad4c2e1ab06ac1.tar.gz chromium_src-911ea803dbd347a95ca49f4d46ad4c2e1ab06ac1.tar.bz2 |
Reland: Support Compat mode inside of the desktop tree.
Originalcommit:
https://crrev.com/e7b1c72c03dcf636e50917b2c8122e5d0ef884b6
TEST=interactive_ui_tests --gtest_filter=SpokenFeedbackTest.*
TBR=dtseng@chromium.org
Review URL: https://codereview.chromium.org/1214503003
Cr-Commit-Position: refs/heads/master@{#336406}
7 files changed, 107 insertions, 88 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 6eb68a3..8f1d947 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -79,37 +79,6 @@ namespace { using base::UserMetricsAction; -bool CanHandleAccessibleFocusCycle() { - if (!Shell::GetInstance()->accessibility_delegate()-> - IsSpokenFeedbackEnabled()) { - return false; - } - aura::Window* active_window = ash::wm::GetActiveWindow(); - if (!active_window) - return false; - views::Widget* widget = - views::Widget::GetWidgetForNativeWindow(active_window); - if (!widget) - return false; - views::FocusManager* focus_manager = widget->GetFocusManager(); - if (!focus_manager) - return false; - views::View* view = focus_manager->GetFocusedView(); - return view && strcmp(view->GetClassName(), views::WebView::kViewClassName); -} - -void HandleAccessibleFocusCycle(bool reverse) { - if (reverse) - base::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Previous")); - else - base::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Next")); - - aura::Window* active_window = ash::wm::GetActiveWindow(); - views::Widget* widget = - views::Widget::GetWidgetForNativeWindow(active_window); - widget->GetFocusManager()->AdvanceFocus(reverse); -} - void HandleCycleBackwardMRU(const ui::Accelerator& accelerator) { if (accelerator.key_code() == ui::VKEY_TAB) base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab")); @@ -880,9 +849,6 @@ bool AcceleratorController::CanPerformAction( // false should be returned to give the web contents a chance at handling the // accelerator. switch (action) { - case ACCESSIBLE_FOCUS_NEXT: - case ACCESSIBLE_FOCUS_PREVIOUS: - return CanHandleAccessibleFocusCycle(); case DEBUG_PRINT_LAYER_HIERARCHY: case DEBUG_PRINT_VIEW_HIERARCHY: case DEBUG_PRINT_WINDOW_HIERARCHY: @@ -1013,12 +979,6 @@ void AcceleratorController::PerformAction(AcceleratorAction action, // implement it in your module's controller code (like TOGGLE_MIRROR_MODE // below) or pull it into a HandleFoo() function above. switch (action) { - case ACCESSIBLE_FOCUS_NEXT: - HandleAccessibleFocusCycle(false); - break; - case ACCESSIBLE_FOCUS_PREVIOUS: - HandleAccessibleFocusCycle(true); - break; case CYCLE_BACKWARD_MRU: HandleCycleBackwardMRU(accelerator); break; diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index 93ddb01..446819c 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc @@ -171,11 +171,6 @@ const AcceleratorData kAcceleratorData[] = { { true, ui::VKEY_U, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN, PRINT_UI_HIERARCHIES }, - { false, ui::VKEY_HOME, ui::EF_SHIFT_DOWN, ACCESSIBLE_FOCUS_PREVIOUS}, - { false, ui::VKEY_PRIOR, ui::EF_SHIFT_DOWN, ACCESSIBLE_FOCUS_PREVIOUS}, - { false, ui::VKEY_END, ui::EF_SHIFT_DOWN, ACCESSIBLE_FOCUS_NEXT}, - { false, ui::VKEY_NEXT, ui::EF_SHIFT_DOWN, ACCESSIBLE_FOCUS_NEXT}, - // TODO(yusukes): Handle VKEY_MEDIA_STOP, and // VKEY_MEDIA_LAUNCH_MAIL. }; @@ -408,8 +403,6 @@ const size_t kActionsAllowedInAppModeLength = arraysize(kActionsAllowedInAppMode); const AcceleratorAction kActionsNeedingWindow[] = { - ACCESSIBLE_FOCUS_NEXT, - ACCESSIBLE_FOCUS_PREVIOUS, CYCLE_BACKWARD_MRU, CYCLE_FORWARD_MRU, TOGGLE_OVERVIEW, diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h index 1d478a0..86ec318 100644 --- a/ash/accelerators/accelerator_table.h +++ b/ash/accelerators/accelerator_table.h @@ -51,8 +51,6 @@ namespace ash { // Please put if/def sections at the end of the bare section and keep the list // within each section in alphabetical order. enum AcceleratorAction { - ACCESSIBLE_FOCUS_NEXT, - ACCESSIBLE_FOCUS_PREVIOUS, CYCLE_BACKWARD_MRU, CYCLE_FORWARD_MRU, DEBUG_PRINT_LAYER_HIERARCHY, diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index 9fb3b46..942f257 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc @@ -355,6 +355,21 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, NavigateSystemTray) { break; } + SendKeyPress(ui::VKEY_TAB); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*")); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "Button")); + + // Compat next element. + SendKeyPressWithSearchAndShift(ui::VKEY_RIGHT); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*")); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "Button")); + + // Compat next button. + SendKeyPressWithSearchAndShift(ui::VKEY_N); + SendKeyPressWithSearchAndShift(ui::VKEY_B); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*")); + EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "Button")); + // Navigate to Bluetooth sub-menu and open it. while (true) { SendKeyPress(ui::VKEY_TAB); diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index 8d988b5..59b90f3 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js @@ -61,7 +61,7 @@ Background = function() { this.mode_ = ChromeVoxMode.CLASSIC; /** @type {!ClassicCompatibility} @private */ - this.compat_ = new ClassicCompatibility(this.mode_ === ChromeVoxMode.COMPAT); + this.compat_ = new ClassicCompatibility(); // Manually bind all functions to |this|. for (var func in this) { @@ -86,8 +86,6 @@ Background = function() { valueChanged: this.onValueChanged }; - // Register listeners for ... - // Desktop. chrome.automation.getDesktop(this.onGotDesktop); }; @@ -127,18 +125,15 @@ Background.prototype = { * @param {string} command * @param {boolean=} opt_skipCompat Whether to skip compatibility checks. */ - onGotCommand: function(command, opt_skipCompat) { + onGotCommand: function(command, opt_skipCompat) { if (!this.currentRange_) return; - if (!opt_skipCompat) { + if (!opt_skipCompat && this.mode_ === ChromeVoxMode.COMPAT) { if (this.compat_.onGotCommand(command)) return; } - if (this.mode_ === ChromeVoxMode.CLASSIC) - return; - var current = this.currentRange_; var dir = Dir.FORWARD; var pred = null; @@ -328,10 +323,14 @@ Background.prototype = { if (current) { // TODO(dtseng): Figure out what it means to focus a range. - current.getStart().getNode().focus(); + var actionNode = current.getStart().getNode(); + if (actionNode.role == chrome.automation.RoleType.inlineTextBox) + actionNode = actionNode.parent; + actionNode.focus(); var prevRange = this.currentRange_; this.currentRange_ = current; + new Output().withSpeechAndBraille( this.currentRange_, prevRange, Output.EventType.NAVIGATE) .go(); @@ -352,10 +351,12 @@ Background.prototype = { this.currentRange_ = cursors.Range.fromNode(node); - // Check to see if we've crossed roots. Only care about focused roots. - if (!prevRange || + // Check to see if we've crossed roots. Continue if we've crossed roots or + // are not within web content. + if (node.root.role == 'desktop' || + !prevRange || (prevRange.getStart().getNode().root != node.root && - node.root.focused)) + node.state.focused)) this.setupChromeVoxVariants_(node.root.docUrl || ''); // Don't process nodes inside of web content if ChromeVox Next is inactive. @@ -365,6 +366,12 @@ Background.prototype = { return; } + // Don't output if focused node hasn't changed. + if (prevRange && + evt.type == 'focus' && + this.currentRange_.equals(prevRange)) + return; + new Output().withSpeechAndBraille( this.currentRange_, prevRange, evt.type) .go(); @@ -512,7 +519,7 @@ Background.prototype = { * @private */ isWhitelistedForCompat_: function(url) { - return url.indexOf('chrome://md-settings') != -1; + return url.indexOf('chrome://md-settings') != -1 || url === ''; }, /** @@ -532,14 +539,15 @@ Background.prototype = { * @private */ setupChromeVoxVariants_: function(url) { - this.compat_.active = this.isWhitelistedForCompat_(url); var mode = this.mode_; - if (this.compat_.active) - mode = ChromeVoxMode.COMPAT; - else if (this.isWhitelistedForNext_(url)) - mode = ChromeVoxMode.NEXT; - else if (mode != ChromeVoxMode.FORCE_NEXT) - mode = ChromeVoxMode.CLASSIC; + if (mode != ChromeVoxMode.FORCE_NEXT) { + if (this.isWhitelistedForCompat_(url)) + mode = ChromeVoxMode.COMPAT; + else if (this.isWhitelistedForNext_(url)) + mode = ChromeVoxMode.NEXT; + else + mode = ChromeVoxMode.CLASSIC; + } this.setChromeVoxMode(mode); }, @@ -577,13 +585,17 @@ Background.prototype = { // for tabs, re-enable. // cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); } else { + // When in compat mode, if the focus is within the desktop tree proper, + // then do not disable content scripts. + if (this.currentRange_.getStart().getNode().root.role == 'desktop') + return; + tabs.forEach(function(tab) { this.disableClassicChromeVox_(tab.id); }.bind(this)); } }.bind(this)); - this.compat_.active = mode === ChromeVoxMode.COMPAT; this.mode_ = mode; } }; diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/classic_compatibility.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/classic_compatibility.js index dae832c..a5a063e 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/classic_compatibility.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/classic_compatibility.js @@ -9,19 +9,16 @@ goog.provide('ClassicCompatibility'); +goog.require('cvox.ExtensionBridge'); goog.require('cvox.KeyMap'); goog.require('cvox.KeySequence'); goog.require('cvox.KeyUtil'); goog.require('cvox.SimpleKeyEvent'); /** - * @param {boolean=} opt_active Whether compatibility is currently active. * @constructor */ -var ClassicCompatibility = function(opt_active) { - /** @type {boolean} */ - this.active = !!opt_active; - +var ClassicCompatibility = function() { /** * @type {!Array<{description: string, name: string, shortcut: string}>} * @private @@ -31,9 +28,15 @@ var ClassicCompatibility = function(opt_active) { /** @type {!cvox.KeyMap} */ this.keyMap = cvox.KeyMap.fromCurrentKeyMap(); - chrome.commands.getAll(function(commands) { - this.commands_ = commands; - }.bind(this)); + // We grab the list of commands from the manifest because + // chrome.commands.getAll is buggy. + /** @type {!Object} */ + var commands = chrome.runtime.getManifest()['commands']; + for (var key in commands) { + /** @type {{suggested_key: {chromeos: string}}} */ + var command = commands[key]; + this.commands_.push({name: key, shortcut: command.suggested_key.chromeos}); + } }; ClassicCompatibility.prototype = { @@ -43,25 +46,45 @@ ClassicCompatibility.prototype = { * @return {boolean} Whether the command was successfully processed. */ onGotCommand: function(command) { - if (!this.active) + var evt = this.buildKeyEvent_(command); + if (!evt) + return false; + this.simulateKeyDownNext_(evt); + return true; + }, + + /** + * Processes a ChromeVox Next command while in CLASSIC mode. + * @param {string} command + * @return {boolean} Whether the command was successfully processed. + */ + onGotClassicCommand: function(command) { + var evt = this.buildKeyEvent_(command); + if (!evt) return false; + this.simulateKeyDownClassic_(evt); + return true; + }, + /** + * @param {string} command + * @return {cvox.SimpleKeyEvent?} + */ + buildKeyEvent_: function(command) { var commandInfo = this.commands_.filter(function(c) { return c.name == command; }.bind(this))[0]; if (!commandInfo) - return false; + return null; var shortcut = commandInfo.shortcut; - var evt = this.convertCommandShortcutToKeyEvent_(shortcut); - this.simulateKeyDown_(evt); - return true; + return this.convertCommandShortcutToKeyEvent_(shortcut); }, /** * @param {cvox.SimpleKeyEvent} evt * @private */ - simulateKeyDown_: function(evt) { + simulateKeyDownNext_: function(evt) { var keySequence = cvox.KeyUtil.keyEventToKeySequence(evt); var classicCommand = this.keyMap.commandForKey(keySequence); if (classicCommand) { @@ -72,6 +95,21 @@ ClassicCompatibility.prototype = { }, /** + * @param {cvox.SimpleKeyEvent} evt + * @private + */ + simulateKeyDownClassic_: function(evt) { + var keySequence = cvox.KeyUtil.keyEventToKeySequence(evt); + var classicCommand = this.keyMap.commandForKey(keySequence); + if (classicCommand) { + cvox.ExtensionBridge.send({ + 'message': 'USER_COMMAND', + 'command': classicCommand + }); + } + }, + + /** * @param {string} shortcut * @return {cvox.SimpleKeyEvent} * @private @@ -96,16 +134,16 @@ ClassicCompatibility.prototype = { case 'Space': evt.keyCode = 32; break; - case 'Left Arrow': + case 'Left': evt.keyCode = 37; break; - case 'Up Arrow': + case 'Up': evt.keyCode = 38; break; - case 'Right Arrow': + case 'Right': evt.keyCode = 39; break; - case 'Down Arrow': + case 'Down': evt.keyCode = 40; break; default: diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/host.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/host.js index 19cdfb7..7fbe95b 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/host.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/host.js @@ -125,6 +125,9 @@ cvox.ChromeHost.prototype.init = function() { var message = msg['message']; if (message == 'USER_COMMAND') { var cmd = msg['command']; + if (cmd != 'toggleChromeVox' && !cvox.ChromeVox.documentHasFocus()) { + return; + } cvox.ChromeVoxUserCommands.commands[cmd](msg); } }); |