Bug 1399909 - Prevent the inspector resizing its left pane during load. r=gl
authorAlexandre Poirot <poirot.alex@gmail.com>
Mon, 18 Sep 2017 18:07:24 +0200
changeset 381645 930533fdd67daea94a1d192defe4c52e8fcef2a5
parent 381644 f4714012ceb4294af938d48a557c394cf7e57358
child 381646 f28b312705df90d41bf211916e2417d4aafcc32e
push id32535
push userkwierso@gmail.com
push dateTue, 19 Sep 2017 21:06:08 +0000
treeherdermozilla-central@c0d1f9eb2a40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1399909
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1399909 - Prevent the inspector resizing its left pane during load. r=gl Today, inspector startup is clunky and is made is many steps in which the left pane with the markup view is loaded full width before the rule view is opened. It blinks and resize things. * display the left pane (inspector-main-content) only when the size of panels is set by the splitter. * fix markupbox hidding while loading as "collapsed" wasn't working * setup the splitter with the right size immediately * prevent unnecessary renders in split-box MozReview-Commit-ID: HvTnmzKpbjy
devtools/client/inspector/inspector.js
devtools/client/inspector/inspector.xhtml
devtools/client/shared/components/splitter/split-box.js
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -273,16 +273,26 @@ Inspector.prototype = {
       this._toolbox.on("select", this.updateDebuggerPausedWarning);
       this.updateDebuggerPausedWarning();
     }
 
     this._initMarkup();
     this.isReady = false;
 
     this.setupSearchBox();
+
+    // Setup the splitter before the sidebar is displayed so,
+    // we don't miss any events.
+    this.setupSplitter();
+
+    // We can display right panel with: tab bar, markup view and breadbrumb. Right after
+    // the splitter set the right and left panel sizes, in order to avoid resizing it
+    // during load of the inspector.
+    this.panelDoc.getElementById("inspector-main-content").style.visibility = "visible";
+
     this.setupSidebar();
     this.setupExtensionSidebars();
 
     await this.once("markuploaded");
     this.isReady = true;
 
     // All the components are initialized. Let's select a node.
     if (defaultSelection) {
@@ -472,40 +482,36 @@ Inspector.prototype = {
   /**
    * Build Splitter located between the main and side area of
    * the Inspector panel.
    */
   setupSplitter: function () {
     let SplitBox = this.React.createFactory(this.browserRequire(
       "devtools/client/shared/components/splitter/split-box"));
 
+    let { width, height } = this.getSidebarSize();
     let splitter = SplitBox({
       className: "inspector-sidebar-splitter",
-      initialWidth: INITIAL_SIDEBAR_SIZE,
-      initialHeight: INITIAL_SIDEBAR_SIZE,
+      initialWidth: width,
+      initialHeight: height,
       splitterSize: 1,
       endPanelControl: true,
       startPanel: this.InspectorTabPanel({
         id: "inspector-main-content"
       }),
       endPanel: this.InspectorTabPanel({
         id: "inspector-sidebar-container"
       }),
       vert: this.useLandscapeMode(),
     });
 
     this._splitter = this.ReactDOM.render(splitter,
       this.panelDoc.getElementById("inspector-splitter-box"));
 
     this.panelWin.addEventListener("resize", this.onPanelWindowResize, true);
-
-    // Persist splitter state in preferences.
-    this.sidebar.on("show", this.onSidebarShown);
-    this.sidebar.on("hide", this.onSidebarHidden);
-    this.sidebar.on("destroy", this.onSidebarHidden);
   },
 
   /**
    * Splitter clean up.
    */
   teardownSplitter: function () {
     this.panelWin.removeEventListener("resize", this.onPanelWindowResize, true);
 
@@ -519,34 +525,37 @@ Inspector.prototype = {
    * to `horizontal` to support portrait view.
    */
   onPanelWindowResize: function () {
     this._splitter.setState({
       vert: this.useLandscapeMode(),
     });
   },
 
-  onSidebarShown: function () {
+  getSidebarSize: function () {
     let width;
     let height;
 
     // Initialize splitter size from preferences.
     try {
       width = Services.prefs.getIntPref("devtools.toolsidebar-width.inspector");
       height = Services.prefs.getIntPref("devtools.toolsidebar-height.inspector");
     } catch (e) {
       // Set width and height of the splitter. Only one
       // value is really useful at a time depending on the current
       // orientation (vertical/horizontal).
       // Having both is supported by the splitter component.
       width = INITIAL_SIDEBAR_SIZE;
       height = INITIAL_SIDEBAR_SIZE;
     }
+    return { width, height };
+  },
 
-    this._splitter.setState({width, height});
+  onSidebarShown: function () {
+    this._splitter.setState(this.getSidebarSize());
   },
 
   onSidebarHidden: function () {
     // Store the current splitter size to preferences.
     let state = this._splitter.state;
     Services.prefs.setIntPref("devtools.toolsidebar-width.inspector", state.width);
     Services.prefs.setIntPref("devtools.toolsidebar-height.inspector", state.height);
   },
@@ -661,19 +670,20 @@ Inspector.prototype = {
         this.canGetUsedFontFaces) {
       const FontInspector = this.browserRequire("devtools/client/inspector/fonts/fonts");
       this.fontinspector = new FontInspector(this, this.panelWin);
       this.fontinspector.init();
 
       this.sidebar.toggleTab(true, "fontinspector");
     }
 
-    // Setup the splitter before the sidebar is displayed so,
-    // we don't miss any events.
-    this.setupSplitter();
+    // Persist splitter state in preferences.
+    this.sidebar.on("show", this.onSidebarShown);
+    this.sidebar.on("hide", this.onSidebarHidden);
+    this.sidebar.on("destroy", this.onSidebarHidden);
 
     this.sidebar.show(defaultTab);
   },
 
   /**
    * Setup any extension sidebar already registered to the toolbox when the inspector.
    * has been created for the first time.
    */
@@ -1513,34 +1523,33 @@ Inspector.prototype = {
 
     // create tool iframe
     this._markupFrame = doc.createElement("iframe");
     this._markupFrame.setAttribute("flex", "1");
     // This is needed to enable tooltips inside the iframe document.
     this._markupFrame.setAttribute("tooltip", "aHTMLTooltip");
     this._markupFrame.addEventListener("contextmenu", this._onContextMenu);
 
-    this._markupBox.setAttribute("collapsed", true);
+    this._markupBox.style.visibility = "hidden";
     this._markupBox.appendChild(this._markupFrame);
 
     this._markupFrame.addEventListener("load", this._onMarkupFrameLoad, true);
     this._markupFrame.setAttribute("src", "markup/markup.xhtml");
     this._markupFrame.setAttribute("aria-label",
       INSPECTOR_L10N.getStr("inspector.panelLabel.markupView"));
   },
 
   _onMarkupFrameLoad: function () {
     this._markupFrame.removeEventListener("load", this._onMarkupFrameLoad, true);
 
     this._markupFrame.contentWindow.focus();
 
-    this._markupBox.removeAttribute("collapsed");
-
     this.markup = new MarkupView(this, this._markupFrame, this._toolbox.win);
 
+    this._markupBox.style.visibility = "visible";
     this.emit("markuploaded");
   },
 
   _destroyMarkup: function () {
     let destroyPromise;
 
     if (this._markupFrame) {
       this._markupFrame.removeEventListener("load", this._onMarkupFrameLoad, true);
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -40,17 +40,17 @@
 
   <!-- in content, inspector.js is mapped to the dynamically generated webpack bundle -->
   <script type="application/javascript" src="inspector.js" defer="true"></script>
 </head>
 <body class="theme-body" role="application">
   <div class="inspector-responsive-container theme-body inspector">
 
     <!-- Main Panel Content -->
-    <div id="inspector-main-content" class="devtools-main-content">
+    <div id="inspector-main-content" class="devtools-main-content" style="visibility: hidden;">
       <div id="inspector-toolbar" class="devtools-toolbar" nowindowdrag="true"
            data-localization-bundle="devtools/client/locales/inspector.properties">
         <button id="inspector-element-add-button" class="devtools-button"
                 data-localization="title=inspectorAddNode.label"></button>
         <div class="devtools-toolbar-spacer"></div>
         <span id="inspector-searchlabel"></span>
         <div id="inspector-search" class="devtools-searchbox has-clear-btn">
           <input id="inspector-searchbox" class="devtools-searchinput"
--- a/devtools/client/shared/components/splitter/split-box.js
+++ b/devtools/client/shared/components/splitter/split-box.js
@@ -67,16 +67,28 @@ const SplitBox = React.createClass({
   componentWillReceiveProps(nextProps) {
     let { vert } = nextProps;
 
     if (vert !== this.props.vert) {
       this.setState({ vert });
     }
   },
 
+  shouldComponentUpdate(nextProps, nextState) {
+    return nextState.width != this.state.width ||
+      nextState.height != this.state.height ||
+      nextState.vert != this.state.vert ||
+      nextProps.startPanel != this.props.startPanel ||
+      nextProps.endPanel != this.props.endPanel ||
+      nextProps.endPanelControl != this.props.endPanelControl ||
+      nextProps.minSize != this.props.minSize ||
+      nextProps.maxSize != this.props.maxSize ||
+      nextProps.splitterSize != this.props.splitterSize;
+  },
+
   // Dragging Events
 
   /**
    * Set 'resizing' cursor on entire document during splitter dragging.
    * This avoids cursor-flickering that happens when the mouse leaves
    * the splitter bar area (happens frequently).
    */
   onStartMove() {