Bug 1304701 - initialize splitter in horizontal mode if inspector starts in portrait mode;r=Honza draft
authorJulian Descottes <jdescottes@mozilla.com>
Thu, 22 Sep 2016 16:06:26 +0200
changeset 416629 bc74c77b190a90f79f062271b664bb0d35acd700
parent 416562 f0e6cc6360213ba21fd98c887b55fce5c680df68
child 531897 e6e8e7dd15cc67136c48d9c9c4d3c3c0c6e28765
push id30191
push userjdescottes@mozilla.com
push dateThu, 22 Sep 2016 16:06:19 +0000
reviewersHonza
bugs1304701
milestone52.0a1
Bug 1304701 - initialize splitter in horizontal mode if inspector starts in portrait mode;r=Honza MozReview-Commit-ID: 60vAM9qfW09
devtools/client/inspector/inspector-panel.js
devtools/client/inspector/test/browser.ini
devtools/client/inspector/test/browser_inspector_portrait_mode.js
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -419,16 +419,26 @@ InspectorPanel.prototype = {
       this._InspectorTabPanel =
         this.React.createFactory(this.browserRequire(
         "devtools/client/inspector/components/inspector-tab-panel"));
     }
     return this._InspectorTabPanel;
   },
 
   /**
+   * Check if the inspector should use the landscape mode.
+   *
+   * @return {Boolean} true if the inspector should be in landscape mode.
+   */
+  useLandscapeMode: function () {
+    let { clientWidth } = this.panelDoc.getElementById("inspector-splitter-box");
+    return clientWidth > PORTRAIT_MODE_WIDTH;
+  },
+
+  /**
    * 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"));
 
     this.panelWin.addEventListener("resize", this.onPanelWindowResize, true);
@@ -440,17 +450,18 @@ InspectorPanel.prototype = {
       minSize: MIN_SIDEBAR_SIZE,
       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"));
 
     // Persist splitter state in preferences.
     this.sidebar.on("show", this.onSidebarShown);
     this.sidebar.on("hide", this.onSidebarHidden);
@@ -468,19 +479,18 @@ InspectorPanel.prototype = {
     this.sidebar.off("destroy", this.onSidebarHidden);
   },
 
   /**
    * If Toolbox width is less than 600 px, the splitter changes its mode
    * to `horizontal` to support portrait view.
    */
   onPanelWindowResize: function () {
-    let box = this.panelDoc.getElementById("inspector-splitter-box");
     this._splitter.setState({
-      vert: (box.clientWidth > PORTRAIT_MODE_WIDTH)
+      vert: this.useLandscapeMode(),
     });
   },
 
   onSidebarShown: function () {
     let width;
     let height;
 
     // Initialize splitter size from preferences.
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -129,16 +129,17 @@ subsuite = clipboard
 [browser_inspector_navigation.js]
 [browser_inspector_pane-toggle-01.js]
 [browser_inspector_pane-toggle-02.js]
 [browser_inspector_pane-toggle-03.js]
 [browser_inspector_pane-toggle-05.js]
 skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard
 [browser_inspector_picker-stop-on-destroy.js]
 [browser_inspector_picker-stop-on-tool-change.js]
+[browser_inspector_portrait_mode.js]
 [browser_inspector_pseudoclass-lock.js]
 [browser_inspector_pseudoclass-menu.js]
 [browser_inspector_reload-01.js]
 [browser_inspector_reload-02.js]
 [browser_inspector_remove-iframe-during-load.js]
 [browser_inspector_search-01.js]
 [browser_inspector_search-02.js]
 [browser_inspector_search-03.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_portrait_mode.js
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+// Test that the inspector splitter is properly initialized in horizontal mode if the
+// inspector starts in portrait mode.
+
+add_task(function* () {
+  let { inspector, toolbox } = yield openInspectorForURL(
+    "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>", "window");
+
+  let hostWindow = toolbox._host._window;
+  let originalWidth = hostWindow.outerWidth;
+  let originalHeight = hostWindow.outerHeight;
+
+  info("Resize toolbox window to force inspector to landscape mode");
+  hostWindow.resizeTo(800, 500);
+
+  let splitter = inspector.panelDoc.querySelector(".inspector-sidebar-splitter");
+  ok(splitter.classList.contains("vert"), "Splitter is in vertical mode");
+
+  info("Resize toolbox window to force inspector to portrait mode");
+  let onClassnameMutation = waitForClassMutation(splitter);
+  hostWindow.resizeTo(500, 500);
+  yield onClassnameMutation;
+
+  ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode");
+
+  info("Close the inspector");
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  yield gDevTools.closeToolbox(target);
+
+  info("Reopen inspector");
+  ({ inspector, toolbox } = yield openInspector("window"));
+
+  // Devtools window should still be 500px * 500px, inspector should still be in portrait.
+  splitter = inspector.panelDoc.querySelector(".inspector-sidebar-splitter");
+  ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode");
+
+  info("Restore original window size");
+  toolbox._host._window.resizeTo(originalWidth, originalHeight);
+});
+
+/**
+ * Helper waiting for a class attribute mutation on the provided target. Returns a
+ * promise.
+ *
+ * @param {Node} target
+ *        Node to observe
+ * @return {Promise} promise that will resolve upon receiving a mutation for the class
+ *         attribute on the target.
+ */
+function waitForClassMutation(target) {
+  return new Promise(resolve => {
+    let observer = new MutationObserver((mutations) => {
+      for (let mutation of mutations) {
+        if (mutation.attributeName === "class") {
+          observer.disconnect();
+          resolve();
+          return;
+        }
+      }
+    });
+    observer.observe(target, { attributes: true });
+  });
+}
+
+registerCleanupFunction(function () {
+  // Restore the host type for other tests.
+  Services.prefs.clearUserPref("devtools.toolbox.host");
+});