Bug 1273211 - Add side panel enter and return controls, added keyboard space selection for controls in netmonitor and console key. r=pbro

MozReview-Commit-ID: HGGTeshLBDs

--HG--
extra : transplant_source : e%0A%19%0B%96%8F%11%8B%E8%3A%DA%7B%06%C0n%9C%09-TU
This commit is contained in:
Nancy Pang 2016-07-12 14:10:57 -04:00
parent 3a79cf448f
commit 6c2a980a72
10 changed files with 151 additions and 10 deletions

View File

@ -284,6 +284,8 @@ skip-if = e10s && debug
skip-if = e10s # TODO
[browser_dbg_instruments-pane-collapse.js]
skip-if = e10s && debug
[browser_dbg_instruments-pane-collapse_keyboard.js]
skip-if = (os == 'mac' && e10s && debug) # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control
[browser_dbg_interrupts.js]
skip-if = e10s && debug
[browser_dbg_listaddons.js]

View File

@ -0,0 +1,40 @@
/* -*- 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/ */
/**
* Tests that the debugger panes collapse properly.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
function test() {
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
Task.spawn(function* () {
let doc = aPanel.panelWin.document;
let panel = doc.getElementById("instruments-pane");
let button = doc.getElementById("instruments-pane-toggle");
ok(panel.classList.contains("pane-collapsed"),
"The instruments panel is initially in collapsed state");
yield togglePane(button, "Press on the toggle button to expand", panel, "VK_RETURN");
ok(!panel.classList.contains("pane-collapsed"),
"The instruments panel is in the expanded state");
yield togglePane(button, "Press on the toggle button to collapse", panel, "VK_SPACE");
ok(panel.classList.contains("pane-collapsed"),
"The instruments panel is in the collapsed state");
closeDebuggerAndFinish(aPanel);
});
});
}
function* togglePane(button, message, pane, keycode) {
let onTransitionEnd = once(pane, "transitionend");
info(message);
button.focus();
EventUtils.synthesizeKey(keycode, {});
yield onTransitionEnd;
}

View File

@ -21,6 +21,7 @@ function ToolbarView(DebuggerController, DebuggerView) {
this.DebuggerController = DebuggerController;
this.DebuggerView = DebuggerView;
this._onTogglePanesActivated = this._onTogglePanesActivated.bind(this);
this._onTogglePanesPressed = this._onTogglePanesPressed.bind(this);
this._onResumePressed = this._onResumePressed.bind(this);
this._onStepOverPressed = this._onStepOverPressed.bind(this);
@ -62,7 +63,10 @@ ToolbarView.prototype = {
this._stepInTooltip = L10N.getFormatStr("stepInTooltip", stepInKey);
this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", stepOutKey);
this._instrumentsPaneToggleButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
this._instrumentsPaneToggleButton.addEventListener("mousedown",
this._onTogglePanesActivated, false);
this._instrumentsPaneToggleButton.addEventListener("keydown",
this._onTogglePanesPressed, false);
this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.addEventListener("mousedown", this._onStepOverPressed, false);
this._stepInButton.addEventListener("mousedown", this._onStepInPressed, false);
@ -82,7 +86,10 @@ ToolbarView.prototype = {
destroy: function () {
dumpn("Destroying the ToolbarView");
this._instrumentsPaneToggleButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
this._instrumentsPaneToggleButton.removeEventListener("mousedown",
this._onTogglePanesActivated, false);
this._instrumentsPaneToggleButton.removeEventListener("keydown",
this._onTogglePanesPressed, false);
this._resumeButton.removeEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.removeEventListener("mousedown", this._onStepOverPressed, false);
this._stepInButton.removeEventListener("mousedown", this._onStepInPressed, false);
@ -168,10 +175,19 @@ ToolbarView.prototype = {
}
},
/**
* Listener handling the toggle button space and return key event.
*/
_onTogglePanesPressed: function (event) {
if (ViewHelpers.isSpaceOrReturn(event)) {
this._onTogglePanesActivated();
}
},
/**
* Listener handling the toggle button click event.
*/
_onTogglePanesPressed: function () {
_onTogglePanesActivated: function() {
DebuggerView.toggleInstrumentsPane({
visible: DebuggerView.instrumentsPaneHidden,
animated: true,

View File

@ -99,7 +99,8 @@ function InspectorPanel(iframeWindow, toolbox) {
this.onNewSelection = this.onNewSelection.bind(this);
this.onBeforeNewSelection = this.onBeforeNewSelection.bind(this);
this.onDetached = this.onDetached.bind(this);
this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
this.onPaneToggleButtonActivated = this.onPaneToggleButtonActivated.bind(this);
this.onPaneToggleButtonPressed = this.onPaneToggleButtonPressed.bind(this);
this._onMarkupFrameLoad = this._onMarkupFrameLoad.bind(this);
let doc = this.panelDoc;
@ -447,7 +448,8 @@ InspectorPanel.prototype = {
"devtools/client/shared/components/sidebar-toggle"));
let sidebarToggle = SidebarToggle({
onClick: this.onPaneToggleButtonClicked,
onClick: this.onPaneToggleButtonActivated,
onKeyDown: this.onPaneToggleButtonPressed,
collapsed: false,
expandPaneTitle: strings.GetStringFromName("inspector.expandPane"),
collapsePaneTitle: strings.GetStringFromName("inspector.collapsePane"),
@ -1153,11 +1155,21 @@ InspectorPanel.prototype = {
return destroyPromise;
},
/**
* When the pane toggle button is pressed with space and return keys toggle
* the pane, change the button state and tooltip.
*/
onPaneToggleButtonPressed: function (event) {
if (ViewHelpers.isSpaceOrReturn(event)) {
this.onPaneToggleButtonActivated(event);
}
},
/**
* When the pane toggle button is clicked, toggle the pane, change the button
* state and tooltip.
*/
onPaneToggleButtonClicked: function (e) {
onPaneToggleButtonActivated: function (e) {
let sidePane = this.panelDoc.querySelector("#inspector-sidebar");
let isVisible = !this._sidebarToggle.state.collapsed;

View File

@ -114,6 +114,8 @@ subsuite = clipboard
[browser_inspector_pane-toggle-02.js]
[browser_inspector_pane-toggle-03.js]
[browser_inspector_pane-toggle-04.js]
[browser_inspector_pane-toggle-05.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
[browser_inspector_picker-stop-on-destroy.js]
[browser_inspector_picker-stop-on-tool-change.js]
[browser_inspector_pseudoclass-lock.js]

View File

@ -0,0 +1,32 @@
/* 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";
/**
* Test the keyboard navigation for the pane toggle using
* space and enter
*/
add_task(function* () {
let {inspector} = yield openInspectorForURL("about:blank", "side");
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
yield togglePane(button, "Press on the toggle button", panel, "VK_RETURN");
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
yield togglePane(button, "Press on the toggle button to expand the panel again",
panel, "VK_SPACE");
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
});
function* togglePane(button, message, panel, keycode) {
let onTransitionEnd = once(panel, "transitionend");
info(message);
button.focus();
EventUtils.synthesizeKey(keycode, {});
yield onTransitionEnd;
}

View File

@ -493,7 +493,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
window.addEventListener("resize", this._onResize, false);
this.requestsMenuSortEvent = getKeyWithEvent(this.sortBy.bind(this));
this.requestsMenuSortKeyboardEvent = getKeyWithEvent(this.sortBy.bind(this), true);
this.requestsMenuFilterEvent = getKeyWithEvent(this.filterOn.bind(this));
this.requestsMenuFilterKeyboardEvent = getKeyWithEvent(
this.filterOn.bind(this), true);
this.reqeustsMenuClearEvent = this.clear.bind(this);
this._onContextShowing = this._onContextShowing.bind(this);
this._onContextNewTabCommand = this.openRequestInTab.bind(this);
@ -525,8 +528,12 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#toolbar-labels").addEventListener("click",
this.requestsMenuSortEvent, false);
$("#toolbar-labels").addEventListener("keydown",
this.requestsMenuSortKeyboardEvent, false);
$("#requests-menu-filter-buttons").addEventListener("click",
this.requestsMenuFilterEvent, false);
$("#requests-menu-filter-buttons").addEventListener("keydown",
this.requestsMenuFilterKeyboardEvent, false);
$("#requests-menu-clear-button").addEventListener("click",
this.reqeustsMenuClearEvent, false);
$("#network-request-popup").addEventListener("popupshowing",
@ -605,8 +612,12 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#toolbar-labels").removeEventListener("click",
this.requestsMenuSortEvent, false);
$("#toolbar-labels").removeEventListener("keydown",
this.requestsMenuSortKeyboardEvent, false);
$("#requests-menu-filter-buttons").removeEventListener("click",
this.requestsMenuFilterEvent, false);
$("#requests-menu-filter-buttons").removeEventListener("keydown",
this.requestsMenuFilterKeyboardEvent, false);
$("#requests-menu-clear-button").removeEventListener("click",
this.reqeustsMenuClearEvent, false);
this.freetextFilterBox.removeEventListener("input",
@ -4017,13 +4028,19 @@ function responseIsFresh({ responseHeaders, status }) {
* @param function callback
* Function to execute execute when data-key
* is present in event.target.
* @param bool onlySpaceOrReturn
* Flag to indicate if callback should only be called
when the space or return button is pressed
* @return function
* Wrapped function with the target data-key as the first argument.
* Wrapped function with the target data-key as the first argument
* and the event as the second argument.
*/
function getKeyWithEvent(callback) {
function getKeyWithEvent(callback, onlySpaceOrReturn) {
return function (event) {
let key = event.target.getAttribute("data-key");
if (key) {
let filterKeyboardEvent = onlySpaceOrReturn
? ViewHelpers.isSpaceOrReturn(event) : true;
if (key && filterKeyboardEvent) {
callback.call(null, key);
}
};

View File

@ -10,6 +10,7 @@ const defer = require("devtools/shared/defer");
const Services = require("Services");
const { TargetFactory } = require("devtools/client/framework/target");
const Telemetry = require("devtools/client/shared/telemetry");
const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
const NS_XHTML = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -109,6 +110,13 @@ var CommandUtils = {
requisition.updateExec(typed);
}, false);
button.addEventListener("keypress", (event) => {
if (ViewHelpers.isSpaceOrReturn(event)) {
event.preventDefault();
requisition.updateExec(typed);
}
}, false);
// Allow the command button to be toggleable
if (command.state) {
button.setAttribute("autocheck", false);

View File

@ -218,6 +218,17 @@ const ViewHelpers = exports.ViewHelpers = {
}
},
/**
* Check if the enter key or space was pressed
*
* @param event event
* The event triggered by a keypress on an element
*/
isSpaceOrReturn: function (event) {
return event.keyCode === event.DOM_VK_SPACE ||
event.keyCode === event.DOM_VK_RETURN;
},
/**
* Sets a toggled pane hidden or visible. The pane can either be displayed on
* the side (right or left depending on the locale) or at the bottom.

View File

@ -79,9 +79,10 @@
}
/* Add element toolbar button */
#inspector-element-add-button::before {
background-image: url("chrome://devtools/skin/images/add.svg");
list-style-image: url("chrome://devtools/skin/images/add.svg");
-moz-user-focus: normal;
}
/* "no results" warning message displayed in the ruleview and in the computed view */