зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1650835 - Use a "button-and-view" widget for the profiler button. r=florian
Differential Revision: https://phabricator.services.mozilla.com/D98217
This commit is contained in:
Родитель
097973bc25
Коммит
c66257367b
|
@ -294,11 +294,13 @@ toolbarpaletteitem > #search-container > #searchbar > .searchbar-textbox {
|
||||||
|
|
||||||
/* Squeeze together the multi-button toolbarpaletteitems: */
|
/* Squeeze together the multi-button toolbarpaletteitems: */
|
||||||
#wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-out-button,
|
#wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-out-button,
|
||||||
#wrapper-edit-controls[place="palette"] > #edit-controls > #cut-button {
|
#wrapper-edit-controls[place="palette"] > #edit-controls > #cut-button,
|
||||||
|
#wrapper-profiler-button[place="palette"] > #profiler-button > #profiler-button-button {
|
||||||
-moz-box-align: end;
|
-moz-box-align: end;
|
||||||
}
|
}
|
||||||
#wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-in-button,
|
#wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-in-button,
|
||||||
#wrapper-edit-controls[place="palette"] > #edit-controls > #paste-button {
|
#wrapper-edit-controls[place="palette"] > #edit-controls > #paste-button,
|
||||||
|
#wrapper-profiler-button[place="palette"] > #profiler-button > #profiler-button-dropmarker {
|
||||||
-moz-box-align: start;
|
-moz-box-align: start;
|
||||||
}
|
}
|
||||||
#wrapper-edit-controls[place="palette"] > #edit-controls > #copy-button {
|
#wrapper-edit-controls[place="palette"] > #edit-controls > #copy-button {
|
||||||
|
|
|
@ -256,41 +256,28 @@ toolbar[brighttext] {
|
||||||
list-style-image: url("chrome://browser/skin/developer.svg");
|
list-style-image: url("chrome://browser/skin/developer.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button > .toolbarbutton-icon {
|
#profiler-button-button > .toolbarbutton-icon {
|
||||||
list-style-image: url("chrome://devtools/skin/images/tool-profiler.svg");
|
list-style-image: url("chrome://devtools/skin/images/tool-profiler.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button:not(.profiler-active) > image {
|
#profiler-button-button:not(.profiler-active) > image {
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button.profiler-active > image {
|
#profiler-button-button.profiler-active > image {
|
||||||
fill: #0060df;
|
fill: #0060df;
|
||||||
fill-opacity: 1;
|
fill-opacity: 1;
|
||||||
background-color: #0060df33;
|
background-color: #0060df33;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button.profiler-active:hover > image {
|
#profiler-button-button.profiler-active:hover > image {
|
||||||
background-color: #0060df22;
|
background-color: #0060df22;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button.profiler-paused > image {
|
#profiler-button-button.profiler-paused > image {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
#profiler-button > .toolbarbutton-menu-dropmarker {
|
|
||||||
/* Inherit the fill and fill-opacity values from the toolbarbutton
|
|
||||||
instead of using the values from .toolbarbutton-menu-dropmarker */
|
|
||||||
-moz-context-properties: fill, fill-opacity;
|
|
||||||
fill: inherit;
|
|
||||||
fill-opacity: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget-overflow-list #profiler-button > .toolbarbutton-menu-dropmarker,
|
|
||||||
#customization-palette #profiler-button > .toolbarbutton-menu-dropmarker {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#preferences-button {
|
#preferences-button {
|
||||||
list-style-image: url("chrome://global/skin/icons/settings.svg");
|
list-style-image: url("chrome://global/skin/icons/settings.svg");
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ function initialize(toggleProfilerKeyShortcuts) {
|
||||||
|
|
||||||
const item = {
|
const item = {
|
||||||
id: WIDGET_ID,
|
id: WIDGET_ID,
|
||||||
type: "view",
|
type: "button-and-view",
|
||||||
viewId,
|
viewId,
|
||||||
tooltiptext: "profiler-button.tooltiptext",
|
tooltiptext: "profiler-button.tooltiptext",
|
||||||
|
|
||||||
|
@ -229,32 +229,34 @@ function initialize(toggleProfilerKeyShortcuts) {
|
||||||
* This method is used when we need to operate upon the button element itself.
|
* This method is used when we need to operate upon the button element itself.
|
||||||
* This is called once per browser window.
|
* This is called once per browser window.
|
||||||
*
|
*
|
||||||
* @type {(buttonElement: HTMLElement) => void}
|
* @type {(node: HTMLElement) => void}
|
||||||
*/
|
*/
|
||||||
onCreated: buttonElement => {
|
onCreated: node => {
|
||||||
const window = buttonElement?.ownerDocument?.defaultView;
|
const window = node.ownerDocument?.defaultView;
|
||||||
if (!window) {
|
if (!window) {
|
||||||
console.error(
|
console.error(
|
||||||
"Unable to find the window of the profiler button element."
|
"Unable to find the window of the profiler toolbar item."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const firstButton = node.firstElementChild;
|
||||||
|
if (!firstButton) {
|
||||||
|
console.error(
|
||||||
|
"Unable to find the button element inside the profiler toolbar item."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign the null-checked button element to a new variable so that
|
||||||
|
// TypeScript doesn't require additional null checks in the functions
|
||||||
|
// below.
|
||||||
|
const buttonElement = firstButton;
|
||||||
|
|
||||||
// This class is needed to show the subview arrow when our button
|
// This class is needed to show the subview arrow when our button
|
||||||
// is in the overflow menu.
|
// is in the overflow menu.
|
||||||
buttonElement.classList.add("subviewbutton-nav");
|
buttonElement.classList.add("subviewbutton-nav");
|
||||||
|
|
||||||
// Our buttons has 2 targets: the icon which starts the profiler or
|
|
||||||
// captures the profile, and the dropmarker which opens the popup.
|
|
||||||
// To have this behavior, we need to enable showing the dropmarker...
|
|
||||||
buttonElement.setAttribute("wantdropmarker", "true");
|
|
||||||
// ... and to implement our custom click and keyboard event handling
|
|
||||||
// to decide which of the 2 behaviors should be triggered.
|
|
||||||
buttonElement.addEventListener("click", item);
|
|
||||||
// This would be better as a keypress handler, but CustomizableUI's
|
|
||||||
// keypress handler runs before keypress handlers we could add here.
|
|
||||||
buttonElement.addEventListener("keydown", item);
|
|
||||||
|
|
||||||
function setButtonActive() {
|
function setButtonActive() {
|
||||||
buttonElement.setAttribute(
|
buttonElement.setAttribute(
|
||||||
"tooltiptext",
|
"tooltiptext",
|
||||||
|
@ -295,14 +297,11 @@ function initialize(toggleProfilerKeyShortcuts) {
|
||||||
Services.obs.removeObserver(setButtonActive, "profiler-started");
|
Services.obs.removeObserver(setButtonActive, "profiler-started");
|
||||||
Services.obs.removeObserver(setButtonInactive, "profiler-stopped");
|
Services.obs.removeObserver(setButtonInactive, "profiler-stopped");
|
||||||
Services.obs.removeObserver(setButtonPaused, "profiler-paused");
|
Services.obs.removeObserver(setButtonPaused, "profiler-paused");
|
||||||
buttonElement.removeEventListener("click", item);
|
|
||||||
buttonElement.removeEventListener("keydown", item);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// @ts-ignore - Bug 1674368
|
// @ts-ignore - Bug 1674368
|
||||||
handleEvent: event => {
|
onCommand: event => {
|
||||||
function startOrCapture() {
|
|
||||||
if (Services.profiler.IsPaused()) {
|
if (Services.profiler.IsPaused()) {
|
||||||
// A profile is already being captured, ignore this event.
|
// A profile is already being captured, ignore this event.
|
||||||
return;
|
return;
|
||||||
|
@ -313,62 +312,6 @@ function initialize(toggleProfilerKeyShortcuts) {
|
||||||
} else {
|
} else {
|
||||||
startProfiler("aboutprofiling");
|
startProfiler("aboutprofiling");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (event.type == "click") {
|
|
||||||
// Only handle clicks on the left button.
|
|
||||||
if (event.button != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const button = event.target;
|
|
||||||
|
|
||||||
// Ignore the click event while in the overflow menu
|
|
||||||
if (button.getAttribute("cui-anchorid") == "nav-bar-overflow-button") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are within the area of the icon, handle the event.
|
|
||||||
// Otherwise we are on the dropmarker and CustomizableUI will take
|
|
||||||
// care of opening the panel.
|
|
||||||
const win = button.ownerGlobal;
|
|
||||||
const iconBounds = win.windowUtils.getBoundsWithoutFlushing(
|
|
||||||
button.icon
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
win.RTL_UI ? event.x >= iconBounds.left : event.x <= iconBounds.right
|
|
||||||
) {
|
|
||||||
startOrCapture();
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
} else if (event.type == "keydown") {
|
|
||||||
if (event.key == " " || event.key == "Enter") {
|
|
||||||
startOrCapture();
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (event.key == "ArrowDown") {
|
|
||||||
// Trigger a "command" event that CustomizableUI will handle.
|
|
||||||
const button = event.target;
|
|
||||||
const cmdEvent = button.ownerDocument.createEvent("xulcommandevent");
|
|
||||||
cmdEvent.initCommandEvent(
|
|
||||||
"command",
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
button.ownerGlobal,
|
|
||||||
0,
|
|
||||||
event.ctrlKey,
|
|
||||||
event.altKey,
|
|
||||||
event.shiftKey,
|
|
||||||
event.metaKey,
|
|
||||||
null,
|
|
||||||
event.mozInputSource
|
|
||||||
);
|
|
||||||
event.currentTarget.dispatchEvent(cmdEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ add_task(async function test() {
|
||||||
|
|
||||||
const getRecordingButton = () =>
|
const getRecordingButton = () =>
|
||||||
getElementByLabel(document, "Start Recording");
|
getElementByLabel(document, "Start Recording");
|
||||||
|
|
||||||
const getDisabledMessage = () =>
|
const getDisabledMessage = () =>
|
||||||
getElementFromDocumentByText(
|
getElementFromDocumentByText(
|
||||||
document,
|
document,
|
||||||
|
|
|
@ -17,7 +17,7 @@ add_task(async function test() {
|
||||||
"resource://devtools/client/performance-new/popup/background.jsm.js"
|
"resource://devtools/client/performance-new/popup/background.jsm.js"
|
||||||
);
|
);
|
||||||
|
|
||||||
const button = document.getElementById("profiler-button");
|
const button = document.getElementById("profiler-button-button");
|
||||||
if (!button) {
|
if (!button) {
|
||||||
throw new Error("Could not find the profiler button.");
|
throw new Error("Could not find the profiler button.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ async function waitForProfileAndCloseTab() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var button;
|
var button;
|
||||||
|
var dropmarker;
|
||||||
|
|
||||||
add_task(async function setup() {
|
add_task(async function setup() {
|
||||||
info(
|
info(
|
||||||
|
@ -43,34 +44,35 @@ add_task(async function setup() {
|
||||||
"http://example.com/browser/devtools/client/performance-new/test/browser/fake-frontend.html"
|
"http://example.com/browser/devtools/client/performance-new/test/browser/fake-frontend.html"
|
||||||
);
|
);
|
||||||
await makeSureProfilerPopupIsEnabled();
|
await makeSureProfilerPopupIsEnabled();
|
||||||
button = document.getElementById("profiler-button");
|
button = document.getElementById("profiler-button-button");
|
||||||
|
dropmarker = document.getElementById("profiler-button-dropmarker");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function click_icon() {
|
add_task(async function click_icon() {
|
||||||
info("Test that the profiler icon starts and captures a profile.");
|
info("Test that the profiler icon starts and captures a profile.");
|
||||||
|
|
||||||
ok(!button.hasAttribute("open"), "should start with the panel closed");
|
ok(!dropmarker.hasAttribute("open"), "should start with the panel closed");
|
||||||
ok(!isActive(), "should start with the profiler inactive");
|
ok(!isActive(), "should start with the profiler inactive");
|
||||||
|
|
||||||
await EventUtils.synthesizeMouseAtCenter(button.icon, {});
|
button.click();
|
||||||
ok(isActive(), "should have started the profiler");
|
ok(isActive(), "should have started the profiler");
|
||||||
|
|
||||||
await EventUtils.synthesizeMouseAtCenter(button.icon, {});
|
button.click();
|
||||||
await waitForProfileAndCloseTab();
|
await waitForProfileAndCloseTab();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function click_dropmarker() {
|
add_task(async function click_dropmarker() {
|
||||||
info("Test that the profiler icon dropmarker opens the panel.");
|
info("Test that the profiler icon dropmarker opens the panel.");
|
||||||
|
|
||||||
ok(!button.hasAttribute("open"), "should start with the panel closed");
|
ok(!dropmarker.hasAttribute("open"), "should start with the panel closed");
|
||||||
ok(!isActive(), "should start with the profiler inactive");
|
ok(!isActive(), "should start with the profiler inactive");
|
||||||
|
|
||||||
const popupShownPromise = waitForProfilerPopupEvent("popupshown");
|
const popupShownPromise = waitForProfilerPopupEvent("popupshown");
|
||||||
await EventUtils.synthesizeMouseAtCenter(button.dropmarker, {});
|
dropmarker.click();
|
||||||
await popupShownPromise;
|
await popupShownPromise;
|
||||||
|
|
||||||
info("Ensure the panel is open and the profiler still inactive.");
|
info("Ensure the panel is open and the profiler still inactive.");
|
||||||
ok(button.getAttribute("open") == "true", "panel should be open");
|
ok(dropmarker.getAttribute("open") == "true", "panel should be open");
|
||||||
ok(!isActive(), "profiler should still be inactive");
|
ok(!isActive(), "profiler should still be inactive");
|
||||||
await getElementByLabel(document, "Start Recording");
|
await getElementByLabel(document, "Start Recording");
|
||||||
|
|
||||||
|
@ -78,13 +80,13 @@ add_task(async function click_dropmarker() {
|
||||||
const popupHiddenPromise = waitForProfilerPopupEvent("popuphidden");
|
const popupHiddenPromise = waitForProfilerPopupEvent("popuphidden");
|
||||||
EventUtils.synthesizeKey("KEY_Escape");
|
EventUtils.synthesizeKey("KEY_Escape");
|
||||||
await popupHiddenPromise;
|
await popupHiddenPromise;
|
||||||
ok(!button.hasAttribute("open"), "panel should be closed");
|
ok(!dropmarker.hasAttribute("open"), "panel should be closed");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function space_key() {
|
add_task(async function space_key() {
|
||||||
info("Test that the Space key starts and captures a profile.");
|
info("Test that the Space key starts and captures a profile.");
|
||||||
|
|
||||||
ok(!button.hasAttribute("open"), "should start with the panel closed");
|
ok(!dropmarker.hasAttribute("open"), "should start with the panel closed");
|
||||||
ok(!isActive(), "should start with the profiler inactive");
|
ok(!isActive(), "should start with the profiler inactive");
|
||||||
forceFocus(button);
|
forceFocus(button);
|
||||||
|
|
||||||
|
@ -100,10 +102,17 @@ add_task(async function space_key() {
|
||||||
add_task(async function enter_key() {
|
add_task(async function enter_key() {
|
||||||
info("Test that the Enter key starts and captures a profile.");
|
info("Test that the Enter key starts and captures a profile.");
|
||||||
|
|
||||||
ok(!button.hasAttribute("open"), "should start with the panel closed");
|
ok(!dropmarker.hasAttribute("open"), "should start with the panel closed");
|
||||||
ok(!isActive(), "should start with the profiler inactive");
|
ok(!isActive(), "should start with the profiler inactive");
|
||||||
forceFocus(button);
|
forceFocus(button);
|
||||||
|
|
||||||
|
const isMacOS = Services.appinfo.OS === "Darwin";
|
||||||
|
if (isMacOS) {
|
||||||
|
// On macOS, pressing Enter on a focused toolbarbutton does not fire a
|
||||||
|
// command event, so we do not expect Enter to start the profiler.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
info("Pressing Enter should start the profiler.");
|
info("Pressing Enter should start the profiler.");
|
||||||
EventUtils.synthesizeKey("KEY_Enter");
|
EventUtils.synthesizeKey("KEY_Enter");
|
||||||
ok(isActive(), "should have started the profiler");
|
ok(isActive(), "should have started the profiler");
|
||||||
|
@ -112,24 +121,3 @@ add_task(async function enter_key() {
|
||||||
EventUtils.synthesizeKey("KEY_Enter");
|
EventUtils.synthesizeKey("KEY_Enter");
|
||||||
await waitForProfileAndCloseTab();
|
await waitForProfileAndCloseTab();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function arrowDown_key() {
|
|
||||||
info("Test that ArrowDown key dropmarker opens the panel.");
|
|
||||||
|
|
||||||
ok(!button.hasAttribute("open"), "should start with the panel closed");
|
|
||||||
ok(!isActive(), "should start with the profiler inactive");
|
|
||||||
forceFocus(button);
|
|
||||||
|
|
||||||
info("Pressing the down arrow should open the panel.");
|
|
||||||
const popupShownPromise = waitForProfilerPopupEvent("popupshown");
|
|
||||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
|
||||||
await popupShownPromise;
|
|
||||||
ok(!isActive(), "profiler should still be inactive");
|
|
||||||
ok(button.getAttribute("open") == "true", "panel should be open");
|
|
||||||
|
|
||||||
info("Press Escape to close the panel.");
|
|
||||||
const popupHiddenPromise = waitForProfilerPopupEvent("popuphidden");
|
|
||||||
EventUtils.synthesizeKey("KEY_Escape");
|
|
||||||
await popupHiddenPromise;
|
|
||||||
ok(!button.hasAttribute("open"), "panel should be closed");
|
|
||||||
});
|
|
||||||
|
|
|
@ -233,17 +233,21 @@ async function _toggleOpenProfilerPopup(window) {
|
||||||
info("Toggle open the profiler popup.");
|
info("Toggle open the profiler popup.");
|
||||||
|
|
||||||
info("> Find the profiler menu button.");
|
info("> Find the profiler menu button.");
|
||||||
const profilerButton = document.getElementById("profiler-button");
|
const profilerDropmarker = document.getElementById(
|
||||||
if (!profilerButton) {
|
"profiler-button-dropmarker"
|
||||||
throw new Error("Could not find the profiler button in the menu.");
|
);
|
||||||
|
if (!profilerDropmarker) {
|
||||||
|
throw new Error(
|
||||||
|
"Could not find the profiler button dropmarker in the toolbar."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const popupShown = waitForProfilerPopupEvent("popupshown");
|
const popupShown = waitForProfilerPopupEvent("popupshown");
|
||||||
|
|
||||||
info("> Trigger a click on the profiler button dropmarker.");
|
info("> Trigger a click on the profiler button dropmarker.");
|
||||||
await EventUtils.synthesizeMouseAtCenter(profilerButton.dropmarker, {});
|
await EventUtils.synthesizeMouseAtCenter(profilerDropmarker, {});
|
||||||
|
|
||||||
if (profilerButton.getAttribute("open") !== "true") {
|
if (profilerDropmarker.getAttribute("open") !== "true") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"This test assumes that the button will have an open=true attribute after clicking it."
|
"This test assumes that the button will have an open=true attribute after clicking it."
|
||||||
);
|
);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче