Home | History | Annotate | Download | only in layers
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @extends {WebInspector.VBox}
     34  */
     35 WebInspector.LayerDetailsView = function()
     36 {
     37     WebInspector.VBox.call(this);
     38     this.element.classList.add("layer-details-view");
     39     this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("Select a layer to see its details"));
     40     this._createTable();
     41 }
     42 
     43 /**
     44  * @enum {string}
     45  */
     46 WebInspector.LayerDetailsView.Events = {
     47     ObjectSelected: "ObjectSelected"
     48 }
     49 
     50 /**
     51  * @type {!Object.<string, string>}
     52  */
     53 WebInspector.LayerDetailsView.CompositingReasonDetail = {
     54     "transform3D": WebInspector.UIString("Composition due to association with an element with a CSS 3D transform."),
     55     "video": WebInspector.UIString("Composition due to association with a <video> element."),
     56     "canvas": WebInspector.UIString("Composition due to the element being a <canvas> element."),
     57     "plugin": WebInspector.UIString("Composition due to association with a plugin."),
     58     "iFrame": WebInspector.UIString("Composition due to association with an <iframe> element."),
     59     "backfaceVisibilityHidden": WebInspector.UIString("Composition due to association with an element with a \"backface-visibility: hidden\" style."),
     60     "animation": WebInspector.UIString("Composition due to association with an animated element."),
     61     "filters": WebInspector.UIString("Composition due to association with an element with CSS filters applied."),
     62     "positionFixed": WebInspector.UIString("Composition due to association with an element with a \"position: fixed\" style."),
     63     // FIXME: Can we remove this entry now that position: sticky has been removed?
     64     "positionSticky": WebInspector.UIString("Composition due to association with an element with a \"position: sticky\" style."),
     65     "overflowScrollingTouch": WebInspector.UIString("Composition due to association with an element with a \"overflow-scrolling: touch\" style."),
     66     "blending": WebInspector.UIString("Composition due to association with an element that has blend mode other than \"normal\"."),
     67     "assumedOverlap": WebInspector.UIString("Composition due to association with an element that may overlap other composited elements."),
     68     "overlap": WebInspector.UIString("Composition due to association with an element overlapping other composited elements."),
     69     "negativeZIndexChildren": WebInspector.UIString("Composition due to association with an element with descendants that have a negative z-index."),
     70     "transformWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with composited descendants."),
     71     "opacityWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with opacity applied and composited descendants."),
     72     "maskWithCompositedDescendants": WebInspector.UIString("Composition due to association with a masked element and composited descendants."),
     73     "reflectionWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with a reflection and composited descendants."),
     74     "filterWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with CSS filters applied and composited descendants."),
     75     "blendingWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with CSS blending applied and composited descendants."),
     76     "clipsCompositingDescendants": WebInspector.UIString("Composition due to association with an element clipping compositing descendants."),
     77     "perspective": WebInspector.UIString("Composition due to association with an element with perspective applied."),
     78     "preserve3D": WebInspector.UIString("Composition due to association with an element with a \"transform-style: preserve-3d\" style."),
     79     "root": WebInspector.UIString("Root layer."),
     80     "layerForClip": WebInspector.UIString("Layer for clip."),
     81     "layerForScrollbar": WebInspector.UIString("Layer for scrollbar."),
     82     "layerForScrollingContainer": WebInspector.UIString("Layer for scrolling container."),
     83     "layerForForeground": WebInspector.UIString("Layer for foreground."),
     84     "layerForBackground": WebInspector.UIString("Layer for background."),
     85     "layerForMask": WebInspector.UIString("Layer for mask."),
     86     "layerForVideoOverlay": WebInspector.UIString("Layer for video overlay.")
     87 };
     88 
     89 WebInspector.LayerDetailsView.prototype = {
     90     /**
     91      * @param {!WebInspector.Layers3DView.ActiveObject} activeObject
     92      */
     93     setObject: function(activeObject)
     94     {
     95         this._layer = activeObject ? activeObject.layer : null;
     96         this._scrollRectIndex = activeObject ? activeObject.scrollRectIndex : null;
     97         if (this.isShowing())
     98             this.update();
     99     },
    100 
    101     wasShown: function()
    102     {
    103         WebInspector.View.prototype.wasShown.call(this);
    104         this.update();
    105     },
    106 
    107     /**
    108      * @param {number} index
    109      * @param {!Event} event
    110      */
    111     _onScrollRectClicked: function(index, event)
    112     {
    113         if (event.which !== 1)
    114             return;
    115         this.dispatchEventToListeners(WebInspector.LayerDetailsView.Events.ObjectSelected, {layer: this._layer, scrollRectIndex: index});
    116     },
    117 
    118     /**
    119      * @param {!LayerTreeAgent.ScrollRect} scrollRect
    120      * @param {number} index
    121      */
    122     _createScrollRectElement: function(scrollRect, index)
    123     {
    124         if (index)
    125             this._scrollRectsCell.createTextChild(", ");
    126         var element = this._scrollRectsCell.createChild("span");
    127         element.className = index === this._scrollRectIndex ? "scroll-rect active" : "scroll-rect";
    128         element.textContent = WebInspector.LayerTreeModel.ScrollRectType[scrollRect.type].description + " (" + scrollRect.rect.x + ", " + scrollRect.rect.y +
    129             ", " + scrollRect.rect.width + ", " + scrollRect.rect.height + ")";
    130         element.addEventListener("click", this._onScrollRectClicked.bind(this, index), false);
    131     },
    132 
    133     update: function()
    134     {
    135         if (!this._layer) {
    136             this._tableElement.remove();
    137             this._emptyView.show(this.element);
    138             return;
    139         }
    140         this._emptyView.detach();
    141         this.element.appendChild(this._tableElement);
    142         this._positionCell.textContent = WebInspector.UIString("%d,%d", this._layer.offsetX(), this._layer.offsetY());
    143         this._sizeCell.textContent = WebInspector.UIString("%d  %d", this._layer.width(), this._layer.height());
    144         this._paintCountCell.textContent = this._layer.paintCount();
    145         const bytesPerPixel = 4;
    146         this._memoryEstimateCell.textContent = Number.bytesToString(this._layer.invisible() ? 0 : this._layer.width() * this._layer.height() * bytesPerPixel);
    147         this._layer.requestCompositingReasons(this._updateCompositingReasons.bind(this));
    148         this._scrollRectsCell.removeChildren();
    149         this._layer.scrollRects().forEach(this._createScrollRectElement.bind(this));
    150     },
    151 
    152     _createTable: function()
    153     {
    154         this._tableElement = this.element.createChild("table");
    155         this._tbodyElement = this._tableElement.createChild("tbody");
    156         this._positionCell = this._createRow(WebInspector.UIString("Position in parent:"));
    157         this._sizeCell = this._createRow(WebInspector.UIString("Size:"));
    158         this._compositingReasonsCell = this._createRow(WebInspector.UIString("Compositing Reasons:"));
    159         this._memoryEstimateCell = this._createRow(WebInspector.UIString("Memory estimate:"));
    160         this._paintCountCell = this._createRow(WebInspector.UIString("Paint count:"));
    161         this._scrollRectsCell = this._createRow(WebInspector.UIString("Slow scroll regions:"));
    162     },
    163 
    164     /**
    165      * @param {string} title
    166      */
    167     _createRow: function(title)
    168     {
    169         var tr = this._tbodyElement.createChild("tr");
    170         var titleCell = tr.createChild("td");
    171         titleCell.textContent = title;
    172         return tr.createChild("td");
    173     },
    174 
    175     /**
    176      * @param {!Array.<string>} compositingReasons
    177      */
    178     _updateCompositingReasons: function(compositingReasons)
    179     {
    180         if (!compositingReasons || !compositingReasons.length) {
    181             this._compositingReasonsCell.textContent = "n/a";
    182             return;
    183         }
    184         var fragment = document.createDocumentFragment();
    185         for (var i = 0; i < compositingReasons.length; ++i) {
    186             if (i)
    187                 fragment.createTextChild(",");
    188             var span = document.createElement("span");
    189             span.title = WebInspector.LayerDetailsView.CompositingReasonDetail[compositingReasons[i]] || "";
    190             span.textContent = compositingReasons[i];
    191             fragment.appendChild(span);
    192         }
    193         this._compositingReasonsCell.removeChildren();
    194         this._compositingReasonsCell.appendChild(fragment);
    195     },
    196 
    197     __proto__: WebInspector.VBox.prototype
    198 }
    199