DevTools [Layers]: Adding paint profiler link for sidepanel nodes
Re-upload of https://chromium-review.googlesource.com/c/chromium/src/+/1626027 to new repository
Issue:
- Paint profiler link is only available when selecting a node on the 3D canvas
- 3D canvas is only cursor accessible
Changes:
- Made Paint Profile tab keyboard accessible (via link and sidebar context menu)
Changing PaintProfilerLink from padding to margin (focus indicator):
https://imgur.com/a/B6kATQS
Bug: 963183
Change-Id: I79498b210539f9c2c8a114ef323f66f8baf61b92
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1872877
Reviewed-by: Benedikt Meurer <[email protected]>
Commit-Queue: Michael Liao <[email protected]>
diff --git a/front_end/layer_viewer/LayerDetailsView.js b/front_end/layer_viewer/LayerDetailsView.js
index 268a15e..8c8fb09 100644
--- a/front_end/layer_viewer/LayerDetailsView.js
+++ b/front_end/layer_viewer/LayerDetailsView.js
@@ -41,6 +41,7 @@
this._layerViewHost = layerViewHost;
this._layerViewHost.registerView(this);
this._emptyWidget = new UI.EmptyWidget(Common.UIString('Select a layer to see its details'));
+ this._layerSnapshotMap = this._layerViewHost.getLayerSnapshotMap();
this._buildContent();
}
@@ -88,9 +89,12 @@
this._layerViewHost.selectObject(new LayerViewer.LayerView.ScrollRectSelection(this._selection.layer(), index));
}
- _onPaintProfilerButtonClicked() {
- if (this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot || this._selection.layer()) {
- this.dispatchEventToListeners(LayerViewer.LayerDetailsView.Events.PaintProfilerRequested, this._selection);
+ _invokeProfilerLink() {
+ const snapshotSelection = this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot ?
+ this._selection :
+ this._layerSnapshotMap.get(this._selection.layer());
+ if (snapshotSelection) {
+ this.dispatchEventToListeners(LayerViewer.LayerDetailsView.Events.PaintProfilerRequested, snapshotSelection);
}
}
@@ -173,13 +177,13 @@
const layer = this._selection && this._selection.layer();
if (!layer) {
this._tableElement.remove();
- this._paintProfilerButton.remove();
+ this._paintProfilerLink.remove();
this._emptyWidget.show(this.contentElement);
return;
}
this._emptyWidget.detach();
this.contentElement.appendChild(this._tableElement);
- this.contentElement.appendChild(this._paintProfilerButton);
+ this.contentElement.appendChild(this._paintProfilerLink);
this._sizeCell.textContent =
Common.UIString('%d × %d (at %d,%d)', layer.width(), layer.height(), layer.offsetX(), layer.offsetY());
this._paintCountCell.parentElement.classList.toggle('hidden', !layer.paintCount());
@@ -192,7 +196,8 @@
const snapshot = this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot ?
/** @type {!LayerViewer.LayerView.SnapshotSelection} */ (this._selection).snapshot() :
null;
- this._paintProfilerButton.classList.toggle('hidden', !snapshot);
+
+ this._paintProfilerLink.classList.toggle('hidden', !(this._layerSnapshotMap.has(layer) || snapshot));
}
_buildContent() {
@@ -204,9 +209,20 @@
this._paintCountCell = this._createRow(Common.UIString('Paint count'));
this._scrollRectsCell = this._createRow(Common.UIString('Slow scroll regions'));
this._stickyPositionConstraintCell = this._createRow(Common.UIString('Sticky position constraint'));
- this._paintProfilerButton = this.contentElement.createChild('a', 'hidden link');
- this._paintProfilerButton.textContent = Common.UIString('Paint Profiler');
- this._paintProfilerButton.addEventListener('click', this._onPaintProfilerButtonClicked.bind(this));
+ this._paintProfilerLink = this.contentElement.createChild('span', 'hidden devtools-link link-margin');
+ UI.ARIAUtils.markAsLink(this._paintProfilerLink);
+ this._paintProfilerLink.textContent = ls`Paint Profiler`;
+ this._paintProfilerLink.tabIndex = 0;
+ this._paintProfilerLink.addEventListener('click', e => {
+ e.consume(true);
+ this._invokeProfilerLink();
+ });
+ this._paintProfilerLink.addEventListener('keydown', event => {
+ if (isEnterKey(event)) {
+ event.consume();
+ this._invokeProfilerLink();
+ }
+ });
}
/**
diff --git a/front_end/layer_viewer/LayerTreeOutline.js b/front_end/layer_viewer/LayerTreeOutline.js
index 5d88ddf..8abedba 100644
--- a/front_end/layer_viewer/LayerTreeOutline.js
+++ b/front_end/layer_viewer/LayerTreeOutline.js
@@ -45,6 +45,7 @@
this._treeOutline.element.addEventListener('mousemove', this._onMouseMove.bind(this), false);
this._treeOutline.element.addEventListener('mouseout', this._onMouseMove.bind(this), false);
this._treeOutline.element.addEventListener('contextmenu', this._onContextMenu.bind(this), true);
+ UI.ARIAUtils.setAccessibleName(this._treeOutline.contentElement, ls`Layers Tree Pane`);
this._lastHoveredNode = null;
this.element = this._treeOutline.element;
@@ -205,6 +206,17 @@
_onContextMenu(event) {
const selection = this._selectionForNode(this._treeOutline.treeElementFromEvent(event));
const contextMenu = new UI.ContextMenu(event);
+ const layer = selection && selection.layer();
+ if (layer) {
+ this._layerSnapshotMap = this._layerViewHost.getLayerSnapshotMap();
+ if (this._layerSnapshotMap.has(layer)) {
+ contextMenu.defaultSection().appendItem(
+ ls`Show Paint Profiler`,
+ this.dispatchEventToListeners.bind(
+ this, LayerViewer.LayerTreeOutline.Events.PaintProfilerRequested, selection),
+ false);
+ }
+ }
this._layerViewHost.showContextMenu(contextMenu, selection);
}
@@ -218,6 +230,13 @@
};
/**
+ * @enum {symbol}
+ */
+LayerViewer.LayerTreeOutline.Events = {
+ PaintProfilerRequested: Symbol('PaintProfilerRequested')
+};
+
+/**
* @unrestricted
*/
LayerViewer.LayerTreeElement = class extends UI.TreeElement {
diff --git a/front_end/layer_viewer/LayerViewHost.js b/front_end/layer_viewer/LayerViewHost.js
index f92b464..40e0bee 100644
--- a/front_end/layer_viewer/LayerViewHost.js
+++ b/front_end/layer_viewer/LayerViewHost.js
@@ -177,6 +177,20 @@
}
/**
+ * @param {!Map<!SDK.Layer, !LayerViewer.LayerView.SnapshotSelection>} snapshotLayers
+ */
+ setLayerSnapshotMap(snapshotLayers) {
+ this._snapshotLayers = snapshotLayers;
+ }
+
+ /**
+ * @return {!Map<!SDK.Layer, !LayerViewer.LayerView.SnapshotSelection>}
+ */
+ getLayerSnapshotMap() {
+ return this._snapshotLayers;
+ }
+
+ /**
* @param {?SDK.LayerTreeBase} layerTree
*/
setLayerTree(layerTree) {
diff --git a/front_end/layer_viewer/Layers3DView.js b/front_end/layer_viewer/Layers3DView.js
index b68f022..ff80a5e 100644
--- a/front_end/layer_viewer/Layers3DView.js
+++ b/front_end/layer_viewer/Layers3DView.js
@@ -69,6 +69,10 @@
this._chromeTextures = [];
this._rects = [];
+ /** @type Map<SDK.Layer, LayerViewer.LayerView.SnapshotSelection> */
+ this._snapshotLayers = new Map();
+ this._layerViewHost.setLayerSnapshotMap(this._snapshotLayers);
+
this._layerViewHost.showInternalLayersSetting().addChangeListener(this._update, this);
}
@@ -462,6 +466,10 @@
}
const selection = new LayerViewer.LayerView.SnapshotSelection(layer, {rect: tile.rect, snapshot: tile.snapshot});
const rect = new LayerViewer.Layers3DView.Rectangle(selection);
+ if (!this._snapshotLayers.has(layer)) {
+ this._snapshotLayers.set(layer, selection);
+ }
+
rect.calculateVerticesFromRect(layer, tile.rect, this._depthForLayer(layer) + 1);
rect.texture = tile.texture;
this._appendRect(rect);
@@ -470,6 +478,7 @@
_calculateRects() {
this._rects = [];
+ this._snapshotLayers.clear();
this._dimensionsForAutoscale = {width: 0, height: 0};
this._layerTree.forEachLayer(this._calculateLayerRect.bind(this));
diff --git a/front_end/layer_viewer/layerDetailsView.css b/front_end/layer_viewer/layerDetailsView.css
index 2e620dd..57c2d03 100644
--- a/front_end/layer_viewer/layerDetailsView.css
+++ b/front_end/layer_viewer/layerDetailsView.css
@@ -23,7 +23,7 @@
margin-block-end: 0;
}
-a {
- padding: 8px;
- display: block;
+.devtools-link.link-margin {
+ margin: 8px;
+ display: inline-block;
}
diff --git a/front_end/layer_viewer/layer_viewer_strings.grdp b/front_end/layer_viewer/layer_viewer_strings.grdp
index b110d59..d79a639 100644
--- a/front_end/layer_viewer/layer_viewer_strings.grdp
+++ b/front_end/layer_viewer/layer_viewer_strings.grdp
@@ -93,6 +93,9 @@
<message name="IDS_DEVTOOLS_c634209b1884c963528d21a21cb64ac8" desc="Text in Layer Details View of the Layers panel">
Nearest Layer Shifting Containing Block
</message>
+ <message name="IDS_DEVTOOLS_c874f8e5eb4a8b49e80cc524acde3f23" desc="Label for layers sidepanel tree">
+ Layers Tree Pane
+ </message>
<message name="IDS_DEVTOOLS_cd5be434fea99c341680590738e3b6d5" desc="Text in DView of the Layers panel">
WebGL support is disabled in your browser.
</message>
diff --git a/front_end/layers/LayersPanel.js b/front_end/layers/LayersPanel.js
index c40ea5c..337c441 100644
--- a/front_end/layers/LayersPanel.js
+++ b/front_end/layers/LayersPanel.js
@@ -41,6 +41,8 @@
SDK.targetManager.observeTargets(this);
this._layerViewHost = new LayerViewer.LayerViewHost();
this._layerTreeOutline = new LayerViewer.LayerTreeOutline(this._layerViewHost);
+ this._layerTreeOutline.addEventListener(
+ LayerViewer.LayerTreeOutline.Events.PaintProfilerRequested, this._onPaintProfileRequested, this);
this.panelSidebarElement().appendChild(this._layerTreeOutline.element);
this.setDefaultFocusedElement(this._layerTreeOutline.element);