Bug 1448555 - Make devtools flexible so that it doesn't stretch the window. r?jryans draft
authorXidorn Quan <me@upsuper.org>
Sun, 25 Mar 2018 02:14:33 +1100
changeset 772119 57e3a61e3b88842f3cc6e2e4a8ab6357539b45cc
parent 771944 d7b0d0e7228da9d690df6f105b865db973789c34
push id103853
push userxquan@mozilla.com
push dateSat, 24 Mar 2018 23:56:56 +0000
reviewersjryans
bugs1448555
milestone61.0a1
Bug 1448555 - Make devtools flexible so that it doesn't stretch the window. r?jryans MozReview-Commit-ID: 74EdTp9EvAf
devtools/client/framework/toolbox-hosts.js
--- a/devtools/client/framework/toolbox-hosts.js
+++ b/devtools/client/framework/toolbox-hosts.js
@@ -16,16 +16,52 @@ loader.lazyRequireGetter(this, "AppConst
 loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
 
 /* A host should always allow this much space for the page to be displayed.
  * There is also a min-height on the browser, but we still don't want to set
  * frame.height to be larger than that, since it can cause problems with
  * resizing the toolbox and panel layout. */
 const MIN_PAGE_SIZE = 25;
 
+function capitalize(s) {
+  return s[0].toUpperCase() + s.substring(1);
+}
+
+/**
+ * Size the frame before appending it into the container.
+ *
+ * This also explicitly sizes previous flex siblings in the container
+ * to prevent frame from being expanded after appended.
+ */
+function sizeFrameBeforeAppend(container, frame, prop, pref) {
+  frame.setAttribute("flex", "1");
+  frame[prop] = Math.min(
+    Services.prefs.getIntPref(pref),
+    container["client" + capitalize(prop)] - MIN_PAGE_SIZE
+  );
+  // Size previous flex siblings explicitly so that when we insert the
+  // frame with flex, its size wouldn't be expanded unexpectedly. Among
+  // the previous flex siblings, the last one would be resized to to
+  // reserve room for the frame.
+  let foundLastFlex = false;
+  for (let child = container.lastElementChild; child;
+       child = child.previousElementSibling) {
+    if (child.getClientRects().length > 0 &&
+        parseInt(child.getAttribute("flex"), 10) > 0) {
+      let childRect = child.getBoundingClientRect();
+      if (!foundLastFlex) {
+        foundLastFlex = true;
+        child[prop] = childRect[prop] - frame[prop];
+      } else {
+        child[prop] = childRect[prop];
+      }
+    }
+  }
+}
+
 /**
  * A toolbox host represents an object that contains a toolbox (e.g. the
  * sidebar or a separate window). Any host object should implement the
  * following functions:
  *
  * create() - create the UI and emit a 'ready' event when the UI is ready to use
  * destroy() - destroy the host's UI
  */
@@ -63,20 +99,17 @@ BottomHost.prototype = {
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-horizontal-splitter");
     // Avoid resizing notification containers
     this._splitter.setAttribute("resizebefore", "flex");
 
     this.frame = ownerDocument.createElement("iframe");
     this.frame.className = "devtools-toolbox-bottom-iframe";
-    this.frame.height = Math.min(
-      Services.prefs.getIntPref(this.heightPref),
-      this._nbox.clientHeight - MIN_PAGE_SIZE
-    );
+    sizeFrameBeforeAppend(this._nbox, this.frame, "height", this.heightPref);
 
     this._nbox.appendChild(this._splitter);
     this._nbox.appendChild(this.frame);
 
     this.frame.tooltip = "aHTMLTooltip";
 
     // we have to load something so we can switch documents if we have to
     this.frame.setAttribute("src", "about:blank");
@@ -207,21 +240,17 @@ SidebarHost.prototype = {
     let ownerDocument = gBrowser.ownerDocument;
     this._sidebar = gBrowser.getSidebarContainer(this.hostTab.linkedBrowser);
 
     this._splitter = ownerDocument.createElement("splitter");
     this._splitter.setAttribute("class", "devtools-side-splitter");
 
     this.frame = ownerDocument.createElement("iframe");
     this.frame.className = "devtools-toolbox-side-iframe";
-
-    this.frame.width = Math.min(
-      Services.prefs.getIntPref(this.widthPref),
-      this._sidebar.clientWidth - MIN_PAGE_SIZE
-    );
+    sizeFrameBeforeAppend(this._sidebar, this.frame, "width", this.widthPref);
 
     this._sidebar.appendChild(this._splitter);
     this._sidebar.appendChild(this.frame);
 
     this.frame.tooltip = "aHTMLTooltip";
     this.frame.setAttribute("src", "about:blank");
 
     let frame = await new Promise(resolve => {