зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1242852 - (part 1) making top dev tools toolbar keyboard accessible. r=bgrins
MozReview-Commit-ID: MPMzYnbZOM --- devtools/client/framework/test/browser.ini | 2 + .../test/browser_toolbox_keyboard_navigation.js | 88 ++++++++++++++++++++++ devtools/client/framework/toolbox.js | 67 ++++++++++++++++ devtools/client/themes/toolbars.css | 3 + 4 files changed, 160 insertions(+) create mode 100644 devtools/client/framework/test/browser_toolbox_keyboard_navigation.js --HG-- extra : rebase_source : d26a1dc86672a77b095e212ed658ab3fd89c0af2
This commit is contained in:
Родитель
d7620bcfda
Коммит
428478e041
|
@ -41,6 +41,8 @@ support-files =
|
|||
[browser_toolbox_highlight.js]
|
||||
[browser_toolbox_hosts.js]
|
||||
[browser_toolbox_hosts_size.js]
|
||||
[browser_toolbox_keyboard_navigation.js]
|
||||
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
|
||||
[browser_toolbox_minimize.js]
|
||||
skip-if = true # Bug 1177463 - Temporarily hide the minimize button
|
||||
[browser_toolbox_options.js]
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests keyboard navigation of devtools tabbar.
|
||||
|
||||
const TEST_URL =
|
||||
"data:text/html;charset=utf8,test page for toolbar keyboard navigation";
|
||||
|
||||
function containsFocus(aDoc, aElm) {
|
||||
let elm = aDoc.activeElement;
|
||||
while (elm) {
|
||||
if (elm === aElm) { return true; }
|
||||
elm = elm.parentNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function testFocus(aDoc, aToolbar, aElm) {
|
||||
let id = aElm.id;
|
||||
is(aToolbar.getAttribute("aria-activedescendant"), id,
|
||||
`Active descendant is set to a new control: ${id}`);
|
||||
is(aDoc.activeElement.id, id, "New control is focused");
|
||||
}
|
||||
|
||||
add_task(function*() {
|
||||
info("Create a test tab and open the toolbox");
|
||||
let toolbox = yield openNewTabAndToolbox(TEST_URL, "webconsole");
|
||||
let doc = toolbox.doc;
|
||||
|
||||
let toolbar = doc.querySelector(".devtools-tabbar");
|
||||
let toolbarControls = [...toolbar.querySelectorAll(
|
||||
".devtools-tab, toolbarbutton")].filter(elm =>
|
||||
!elm.hidden && doc.defaultView.getComputedStyle(elm).getPropertyValue(
|
||||
"display") !== "none");
|
||||
|
||||
// Put the keyboard focus onto the first toolbar control.
|
||||
toolbarControls[0].focus();
|
||||
ok(containsFocus(doc, toolbar), "Focus is within the toolbar");
|
||||
|
||||
// Move the focus away from toolbar to a next focusable element.
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
ok(!containsFocus(doc, toolbar), "Focus is outside of the toolbar");
|
||||
|
||||
// Move the focus back to the toolbar.
|
||||
EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
|
||||
ok(containsFocus(doc, toolbar), "Focus is within the toolbar again");
|
||||
|
||||
// Move through the toolbar forward using the right arrow key.
|
||||
for (let i = 0; i < toolbarControls.length; ++i) {
|
||||
testFocus(doc, toolbar, toolbarControls[i]);
|
||||
if (i < toolbarControls.length - 1) {
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {});
|
||||
}
|
||||
}
|
||||
|
||||
// Move the focus away from toolbar to a next focusable element.
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
ok(!containsFocus(doc, toolbar), "Focus is outside of the toolbar");
|
||||
|
||||
// Move the focus back to the toolbar.
|
||||
EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
|
||||
ok(containsFocus(doc, toolbar), "Focus is within the toolbar again");
|
||||
|
||||
// Move through the toolbar backward using the left arrow key.
|
||||
for (let i = toolbarControls.length - 1; i >= 0; --i) {
|
||||
testFocus(doc, toolbar, toolbarControls[i]);
|
||||
if (i > 0) { EventUtils.synthesizeKey("VK_LEFT", {}); }
|
||||
}
|
||||
|
||||
// Move focus to the 3rd (non-first) toolbar control.
|
||||
let expectedFocusedControl = toolbarControls[2];
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {});
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {});
|
||||
testFocus(doc, toolbar, expectedFocusedControl);
|
||||
|
||||
// Move the focus away from toolbar to a next focusable element.
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
ok(!containsFocus(doc, toolbar), "Focus is outside of the toolbar");
|
||||
|
||||
// Move the focus back to the toolbar, ensure we land on the last active
|
||||
// descendant control.
|
||||
EventUtils.synthesizeKey("VK_TAB", { shiftKey: true });
|
||||
testFocus(doc, toolbar, expectedFocusedControl);
|
||||
});
|
|
@ -413,6 +413,7 @@ Toolbox.prototype = {
|
|||
this._addZoomKeys();
|
||||
this._loadInitialZoom();
|
||||
}
|
||||
this._setToolbarKeyboardNavigation();
|
||||
|
||||
this.webconsolePanel = this.doc.querySelector("#toolbox-panel-webconsole");
|
||||
this.webconsolePanel.height = Services.prefs.getIntPref(SPLITCONSOLE_HEIGHT_PREF);
|
||||
|
@ -906,6 +907,72 @@ Toolbox.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up keyboard navigation with and within the dev tools toolbar.
|
||||
*/
|
||||
_setToolbarKeyboardNavigation() {
|
||||
let toolbar = this.doc.querySelector(".devtools-tabbar");
|
||||
// Set and track aria-activedescendant to indicate which control is
|
||||
// currently focused within the toolbar (for accessibility purposes).
|
||||
toolbar.addEventListener("focus", event => {
|
||||
let { target, rangeParent } = event;
|
||||
let control, controlID = toolbar.getAttribute("aria-activedescendant");
|
||||
|
||||
if (controlID) {
|
||||
control = this.doc.getElementById(controlID);
|
||||
}
|
||||
if (rangeParent || !control) {
|
||||
// If range parent is present, the focused is moved within the toolbar,
|
||||
// simply updating aria-activedescendant. Or if aria-activedescendant is
|
||||
// not available, set it to target.
|
||||
toolbar.setAttribute("aria-activedescendant", target.id);
|
||||
} else {
|
||||
// When range parent is not present, we focused into the toolbar, move
|
||||
// focus to current aria-activedescendant.
|
||||
event.preventDefault();
|
||||
control.focus();
|
||||
}
|
||||
}, true)
|
||||
|
||||
toolbar.addEventListener("keypress", event => {
|
||||
let { key, target } = event;
|
||||
let win = this.doc.defaultView;
|
||||
let elm, type;
|
||||
if (key === "Tab") {
|
||||
// Tabbing when toolbar or its contents are focused should move focus to
|
||||
// next/previous focusable element relative to toolbar itself.
|
||||
if (event.shiftKey) {
|
||||
elm = toolbar;
|
||||
type = Services.focus.MOVEFOCUS_BACKWARD;
|
||||
} else {
|
||||
// To move focus to next element following the toolbar, relative
|
||||
// element needs to be the last element in its subtree.
|
||||
let last = toolbar.lastChild;
|
||||
while (last && last.lastChild) {
|
||||
last = last.lastChild;
|
||||
}
|
||||
elm = last;
|
||||
type = Services.focus.MOVEFOCUS_FORWARD;
|
||||
}
|
||||
} else if (key === "ArrowLeft") {
|
||||
// Using left arrow key inside toolbar should move focus to previous
|
||||
// toolbar control.
|
||||
elm = target;
|
||||
type = Services.focus.MOVEFOCUS_BACKWARD;
|
||||
} else if (key === "ArrowRight") {
|
||||
// Using right arrow key inside toolbar should move focus to next
|
||||
// toolbar control.
|
||||
elm = target;
|
||||
type = Services.focus.MOVEFOCUS_FORWARD;
|
||||
} else {
|
||||
// Ignore all other keys.
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
Services.focus.moveFocus(win, elm, type, 0);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Add buttons to the UI as specified in the devtools.toolbox.toolbarSpec pref
|
||||
*/
|
||||
|
|
|
@ -605,6 +605,7 @@
|
|||
#toolbox-controls > toolbarbutton,
|
||||
#toolbox-dock-buttons > toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
-moz-user-focus: normal;
|
||||
border: none;
|
||||
margin: 0 4px;
|
||||
min-width: 16px;
|
||||
|
@ -691,6 +692,7 @@
|
|||
margin: 0;
|
||||
width: 32px;
|
||||
position: relative;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.command-button:hover {
|
||||
|
@ -812,6 +814,7 @@
|
|||
border-width: 0;
|
||||
-moz-border-start-width: 1px;
|
||||
-moz-box-align: center;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
.theme-dark .devtools-tab {
|
||||
|
|
Загрузка…
Ссылка в новой задаче