Backed out changeset e8de82ab570d (bug 1260552)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 17 Sep 2016 20:07:57 +0200
changeset 314261 65f32c651eb766d3e6be7e55aafe42c2f8a47305
parent 314260 8dc7461d078ee8681c0a751ea02a69611fff1954
child 314262 8d211b6a94f603ef81ffcdee3a2b484c2ecd21cd
push id30716
push userarchaeopteryx@coole-files.de
push dateSat, 17 Sep 2016 18:09:28 +0000
treeherdermozilla-central@8d211b6a94f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1260552
milestone51.0a1
backs oute8de82ab570d878051233aef77271e693d362c78
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
Backed out changeset e8de82ab570d (bug 1260552) MozReview-Commit-ID: B8xetPlNaN2
devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
devtools/client/framework/test/browser_toolbox_window_reload_target.js
devtools/client/framework/test/shared-head.js
devtools/client/inspector/components/inspector-tab-panel.js
devtools/client/inspector/inspector-panel.js
devtools/client/inspector/inspector.xul
devtools/client/inspector/rules/test/browser_rules_authored_color.js
devtools/client/inspector/rules/test/browser_rules_colorUnit.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
devtools/client/inspector/rules/test/head.js
devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js
devtools/client/inspector/test/browser_inspector_pane-toggle-02.js
devtools/client/inspector/test/browser_inspector_pane-toggle-03.js
devtools/client/inspector/test/browser_inspector_pane-toggle-04.js
devtools/client/inspector/test/browser_inspector_pane-toggle-05.js
devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
devtools/client/inspector/toolsidebar.js
devtools/client/shared/components/test/mochitest/test_tabs_accessibility.html
devtools/client/themes/inspector.css
--- a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
+++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
@@ -4,40 +4,34 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const URL = "data:text/html;charset=utf8,test for textbox context menu";
 
 add_task(function* () {
   let toolbox = yield openNewTabAndToolbox(URL, "inspector");
   let textboxContextMenu = toolbox.textboxContextMenuPopup;
 
-  // Make sure the focus is predictable.
-  let inspector = toolbox.getPanel("inspector");
-  inspector.searchBox.focus();
-
   ok(textboxContextMenu, "The textbox context menu is loaded in the toolbox");
 
-  emptyClipboard();
-
   let cmdUndo = textboxContextMenu.querySelector("[command=cmd_undo]");
   let cmdDelete = textboxContextMenu.querySelector("[command=cmd_delete]");
   let cmdSelectAll = textboxContextMenu.querySelector("[command=cmd_selectAll]");
   let cmdCut = textboxContextMenu.querySelector("[command=cmd_cut]");
   let cmdCopy = textboxContextMenu.querySelector("[command=cmd_copy]");
   let cmdPaste = textboxContextMenu.querySelector("[command=cmd_paste]");
 
   info("Opening context menu");
 
   let onContextMenuPopup = once(textboxContextMenu, "popupshowing");
   textboxContextMenu.openPopupAtScreen(0, 0, true);
   yield onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
-  is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
+  is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
   is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
   is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
   is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
 
   yield cleanup(toolbox);
 });
 
 function* cleanup(toolbox) {
--- a/devtools/client/framework/test/browser_toolbox_window_reload_target.js
+++ b/devtools/client/framework/test/browser_toolbox_window_reload_target.js
@@ -79,17 +79,16 @@ function testReload(shortcut, docked, to
   let complete = () => {
     gBrowser.selectedBrowser.messageManager.removeMessageListener("devtools:test:load", complete);
     return callback();
   };
   gBrowser.selectedBrowser.messageManager.addMessageListener("devtools:test:load", complete);
 
   description = docked + " devtools with tool " + toolID + ", shortcut #" + shortcut;
   info("Testing reload in " + description);
-  toolbox.win.focus();
   synthesizeKeyShortcut(L10N.getStr(shortcut), toolbox.win);
   reloadsSent++;
 }
 
 function finishUp() {
   toolbox.destroy().then(() => {
     gBrowser.removeCurrentTab();
 
--- a/devtools/client/framework/test/shared-head.js
+++ b/devtools/client/framework/test/shared-head.js
@@ -554,17 +554,8 @@ function loadTelemetryAndRecordLogs() {
 function stopRecordingTelemetryLogs(Telemetry) {
   info("Stopping Telemetry");
   Telemetry.prototype.log = Telemetry.prototype._oldlog;
   Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed;
   delete Telemetry.prototype._oldlog;
   delete Telemetry.prototype._oldlogKeyed;
   delete Telemetry.prototype.telemetryInfo;
 }
-
-/**
- * Clean the OS clipboard content.
- */
-function emptyClipboard() {
-  let clipboard = Cc["@mozilla.org/widget/clipboard;1"]
-    .getService(SpecialPowers.Ci.nsIClipboard);
-  clipboard.emptyClipboard(1);
-}
--- a/devtools/client/inspector/components/inspector-tab-panel.js
+++ b/devtools/client/inspector/components/inspector-tab-panel.js
@@ -7,41 +7,29 @@
 "use strict";
 
 const { DOM, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
 
 // Shortcuts
 const { div } = DOM;
 
 /**
- * Helper panel component that is using an existing DOM node
- * as the content. It's used by Sidebar as well as SplitBox
- * components.
+ * Side panel for the Inspector panel.
+ * This side panel is using an existing DOM node as a content.
  */
 var InspectorTabPanel = createClass({
   displayName: "InspectorTabPanel",
 
   propTypes: {
-    // ID of the node that should be rendered as the content.
-    id: PropTypes.string.isRequired,
-    // Optional prefix for panel IDs.
-    idPrefix: PropTypes.string,
-    // Optional mount callback
     onMount: PropTypes.func,
   },
 
-  getDefaultProps: function () {
-    return {
-      idPrefix: "",
-    };
-  },
-
   componentDidMount: function () {
     let doc = this.refs.content.ownerDocument;
-    let panel = doc.getElementById(this.props.idPrefix + this.props.id);
+    let panel = doc.getElementById("sidebar-panel-" + this.props.id);
 
     // Append existing DOM node into panel's content.
     this.refs.content.appendChild(panel);
 
     if (this.props.onMount) {
       this.props.onMount(this.refs.content, this.props);
     }
   },
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -30,24 +30,16 @@ const {RuleViewTool} = require("devtools
 const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const INSPECTOR_L10N = new LocalizationHelper("devtools/locale/inspector.properties");
 const TOOLBOX_L10N = new LocalizationHelper("devtools/locale/toolbox.properties");
 
-// Sidebar dimensions
-const INITIAL_SIDEBAR_SIZE = 350;
-const MIN_SIDEBAR_SIZE = 50;
-
-// If the toolbox width is smaller than given amount of pixels,
-// the sidebar automatically switches from 'landscape' to 'portrait' mode.
-const PORTRAIT_MODE_WIDTH = 700;
-
 /**
  * Represents an open instance of the Inspector for a tab.
  * The inspector controls the breadcrumbs, the markup view, and the sidebar
  * (computed view, rule view, font view and layout view).
  *
  * Events:
  * - ready
  *      Fired when the inspector panel is opened for the first time and ready to
@@ -97,19 +89,16 @@ function InspectorPanel(iframeWindow, to
   this.onNewRoot = this.onNewRoot.bind(this);
   this._onContextMenu = this._onContextMenu.bind(this);
   this._updateSearchResultsLabel = this._updateSearchResultsLabel.bind(this);
   this.onNewSelection = this.onNewSelection.bind(this);
   this.onBeforeNewSelection = this.onBeforeNewSelection.bind(this);
   this.onDetached = this.onDetached.bind(this);
   this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
   this._onMarkupFrameLoad = this._onMarkupFrameLoad.bind(this);
-  this.onPanelWindowResize = this.onPanelWindowResize.bind(this);
-  this.onSidebarShown = this.onSidebarShown.bind(this);
-  this.onSidebarHidden = this.onSidebarHidden.bind(this);
 
   this._target.on("will-navigate", this._onBeforeNavigate);
   this._detectingActorFeatures = this._detectActorFeatures();
 
   EventEmitter.decorate(this);
 }
 
 exports.InspectorPanel = InspectorPanel;
@@ -406,108 +395,16 @@ InspectorPanel.prototype = {
   get ReactDOM() {
     return this._toolbox.ReactDOM;
   },
 
   get browserRequire() {
     return this._toolbox.browserRequire;
   },
 
-  get InspectorTabPanel() {
-    if (!this._InspectorTabPanel) {
-      this._InspectorTabPanel =
-        this.React.createFactory(this.browserRequire(
-        "devtools/client/inspector/components/inspector-tab-panel"));
-    }
-    return this._InspectorTabPanel;
-  },
-
-  /**
-   * 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);
-
-    let splitter = SplitBox({
-      className: "inspector-sidebar-splitter",
-      initialWidth: INITIAL_SIDEBAR_SIZE,
-      initialHeight: INITIAL_SIDEBAR_SIZE,
-      minSize: MIN_SIDEBAR_SIZE,
-      splitterSize: 1,
-      endPanelControl: true,
-      startPanel: this.InspectorTabPanel({
-        id: "inspector-main-content"
-      }),
-      endPanel: this.InspectorTabPanel({
-        id: "inspector-sidebar-container"
-      })
-    });
-
-    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);
-    this.sidebar.on("destroy", this.onSidebarHidden);
-  },
-
-  /**
-   * Splitter clean up.
-   */
-  teardownSplitter: function () {
-    this.panelWin.removeEventListener("resize", this.onPanelWindowResize, true);
-
-    this.sidebar.off("show", this.onSidebarShown);
-    this.sidebar.off("hide", this.onSidebarHidden);
-    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)
-    });
-  },
-
-  onSidebarShown: 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;
-    }
-
-    this._splitter.setState({width, height});
-  },
-
-  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);
-  },
-
   /**
    * Build the sidebar.
    */
   setupSidebar: function () {
     let tabbox = this.panelDoc.querySelector("#inspector-sidebar");
     this.sidebar = new ToolSidebar(tabbox, this, "inspector", {
       showAllTabsMenu: true
     });
@@ -553,23 +450,66 @@ InspectorPanel.prototype = {
         "fontinspector",
         INSPECTOR_L10N.getStr("inspector.sidebar.fontInspectorTitle"),
         defaultTab == "fontinspector");
 
       this.fontInspector = new FontInspector(this, this.panelWin);
       this.sidebar.toggleTab(true, "fontinspector");
     }
 
-    // Setup the splitter before the sidebar is displayed so,
-    // we don't miss any events.
-    this.setupSplitter();
+    this.setupSidebarSize();
 
     this.sidebar.show(defaultTab);
   },
 
+  /**
+   * Sidebar size is currently driven by vbox.inspector-sidebar-container
+   * element, which is located at the left/bottom side of the side bar splitter.
+   * Its size is changed by the splitter and stored into preferences.
+   * As soon as bug 1260552 is fixed and new HTML based splitter in place
+   * the size can be driven by div.inspector-sidebar element. This element
+   * represents the ToolSidebar and so, the entire logic related to size
+   * persistence can be done inside the ToolSidebar.
+   */
+  setupSidebarSize: function () {
+    let sidePaneContainer = this.panelDoc.querySelector(
+      "#inspector-sidebar-container");
+
+    this.sidebar.on("show", () => {
+      try {
+        sidePaneContainer.width = Services.prefs.getIntPref(
+          "devtools.toolsidebar-width.inspector");
+        sidePaneContainer.height = Services.prefs.getIntPref(
+          "devtools.toolsidebar-height.inspector");
+      } catch (e) {
+        // The default width is the min-width set in CSS
+        // for #inspector-sidebar-container
+        // Set width and height of the sidebar container. Only one
+        // value is really useful at a time depending on the current
+        // toolbox orientation and having both doesn't break anything.
+        sidePaneContainer.width = 450;
+        sidePaneContainer.height = 450;
+      }
+    });
+
+    this.sidebar.on("hide", () => {
+      Services.prefs.setIntPref("devtools.toolsidebar-width.inspector",
+        sidePaneContainer.width);
+      Services.prefs.setIntPref("devtools.toolsidebar-height.inspector",
+        sidePaneContainer.height);
+    });
+
+    this.sidebar.on("destroy", () => {
+      Services.prefs.setIntPref("devtools.toolsidebar-width.inspector",
+        sidePaneContainer.width);
+      Services.prefs.setIntPref("devtools.toolsidebar-height.inspector",
+        sidePaneContainer.height);
+    });
+  },
+
   setupToolbar: function () {
     this.teardownToolbar();
 
     // Setup the sidebar toggle button.
     let SidebarToggle = this.React.createFactory(this.browserRequire(
       "devtools/client/shared/components/sidebar-toggle"));
 
     let sidebarToggle = SidebarToggle({
@@ -853,19 +793,16 @@ InspectorPanel.prototype = {
     let cssPropertiesDestroyer = this._cssPropertiesLoaded.then(({front}) => {
       if (front) {
         front.destroy();
       }
     });
 
     this.sidebar.off("select", this._setDefaultSidebar);
     let sidebarDestroyer = this.sidebar.destroy();
-
-    this.teardownSplitter();
-
     this.sidebar = null;
 
     this.teardownToolbar();
     this.breadcrumbs.destroy();
     this.selection.off("new-node-front", this.onNewSelection);
     this.selection.off("before-new-node-front", this.onBeforeNewSelection);
     this.selection.off("detached-front", this.onDetached);
     let markupDestroyer = this._destroyMarkup();
@@ -1309,18 +1246,17 @@ InspectorPanel.prototype = {
     return destroyPromise;
   },
 
   /**
    * When the pane toggle button is clicked or pressed, toggle the pane, change the button
    * state and tooltip.
    */
   onPaneToggleButtonClicked: function (e) {
-    let sidePaneContainer = this.panelDoc.querySelector(
-      "#inspector-splitter-box .controlled");
+    let sidePaneContainer = this.panelDoc.querySelector("#inspector-sidebar-container");
     let isVisible = !this._sidebarToggle.state.collapsed;
 
     // Make sure the sidebar has width and height attributes before collapsing
     // because ViewHelpers needs it.
     if (isVisible) {
       let rect = sidePaneContainer.getBoundingClientRect();
       if (!sidePaneContainer.hasAttribute("width")) {
         sidePaneContainer.setAttribute("width", rect.width);
--- a/devtools/client/inspector/inspector.xul
+++ b/devtools/client/inspector/inspector.xul
@@ -11,35 +11,32 @@
 <?xml-stylesheet href="chrome://devtools/skin/fonts.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/layout.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/animationinspector.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/shared/components/sidebar-toggle.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/shared/components/tabs/tabs.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/shared/components/tabs/tabbar.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/inspector/components/side-panel.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/inspector/components/inspector-tab-panel.css" type="text/css"?>
-<?xml-stylesheet href="resource://devtools/client/shared/components/splitter/split-box.css" type="text/css"?>
 
 <!DOCTYPE window [
   <!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/inspector.dtd"> %inspectorDTD;
   <!ENTITY % styleinspectorDTD SYSTEM "chrome://devtools/locale/styleinspector.dtd"> %styleinspectorDTD;
   <!ENTITY % fontinspectorDTD SYSTEM "chrome://devtools/locale/font-inspector.dtd"> %fontinspectorDTD;
   <!ENTITY % layoutviewDTD SYSTEM "chrome://devtools/locale/layoutview.dtd"> %layoutviewDTD;
 ]>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml">
 
   <script type="application/javascript;version=1.8"
           src="chrome://devtools/content/shared/theme-switching.js"/>
 
-  <html:div class="inspector-responsive-container theme-body inspector">
-
-    <!-- Main Panel Content -->
-    <html:div id="inspector-main-content" class="devtools-main-content">
+  <box flex="1" class="devtools-responsive-container theme-body">
+    <vbox flex="1" class="devtools-main-content">
       <html:div id="inspector-toolbar"
         class="devtools-toolbar"
         nowindowdrag="true">
         <html:button id="inspector-element-add-button"
           title="&inspectorAddNode.label;"
           class="devtools-button" />
         <html:div class="devtools-toolbar-spacer" />
         <html:span id="inspector-searchlabel" />
@@ -47,41 +44,37 @@
           <html:input id="inspector-searchbox" class="devtools-searchinput"
                       type="search"
                       placeholder="&inspectorSearchHTML.label3;"/>
           <html:button id="inspector-searchinput-clear" class="devtools-searchinput-clear" tabindex="-1"></html:button>
         </html:div>
         <html:button id="inspector-eyedropper-toggle"
                      title="&inspectorEyeDropper.label;"
                      class="devtools-button command-button-invertable" />
-        <html:div id="inspector-sidebar-toggle-box" />
+        <div xmlns="http://www.w3.org/1999/xhtml"
+          id="inspector-sidebar-toggle-box" />
       </html:div>
-      <html:div id="markup-box" />
+      <vbox flex="1" id="markup-box">
+      </vbox>
       <html:div id="inspector-breadcrumbs-toolbar" class="devtools-toolbar">
         <html:div id="inspector-breadcrumbs" class="breadcrumbs-widget-container"
                   role="group" aria-label="&inspectorBreadcrumbsGroup;" tabindex="0" />
       </html:div>
-    </html:div>
-
-    <!-- Splitter -->
-    <html:div
-      xmlns="http://www.w3.org/1999/xhtml"
-      id="inspector-splitter-box">
-    </html:div>
-
-    <!-- Sidebar Container -->
-    <html:div id="inspector-sidebar-container">
-      <html:div
-        xmlns="http://www.w3.org/1999/xhtml"
-        id="inspector-sidebar"
-        hidden="true" />
-    </html:div>
+    </vbox>
+    <splitter class="devtools-side-splitter"/>
+    <vbox id="inspector-sidebar-container">
+      <!-- Specify the XHTML namespace explicitly
+        otherwise the layout is broken. -->
+      <div xmlns="http://www.w3.org/1999/xhtml"
+           id="inspector-sidebar"
+           hidden="true" />
+    </vbox>
 
     <!-- Sidebar panel definitions -->
-    <html:div id="tabpanels" style="visibility:collapse">
+    <html:div xmlns="http://www.w3.org/1999/xhtml" id="tabpanels" style="visibility:collapse">
       <html:div id="sidebar-panel-ruleview" class="devtools-monospace theme-sidebar inspector-tabpanel">
         <html:div id="ruleview-toolbar-container" class="devtools-toolbar">
           <html:div id="ruleview-toolbar">
             <html:div class="devtools-searchbox has-clear-btn">
               <html:input id="ruleview-searchbox"
                           class="devtools-filterinput devtools-rule-searchbox"
                           type="search"
                           placeholder="&filterStylesPlaceholder;"/>
@@ -220,10 +213,10 @@
         </html:div>
       </html:div>
 
       <html:div id="sidebar-panel-animationinspector" class="devtools-monospace theme-sidebar inspector-tabpanel">
         <html:iframe class="devtools-inspector-tab-frame" />
       </html:div>
     </html:div>
 
-  </html:div>
+  </box>
 </window>
--- a/devtools/client/inspector/rules/test/browser_rules_authored_color.js
+++ b/devtools/client/inspector/rules/test/browser_rules_authored_color.js
@@ -46,17 +46,17 @@ add_task(function* () {
       name: "color",
       value: "rgb(0, 255, 0)"
     });
 
     let spectrum = cPicker.spectrum;
     let onHidden = cPicker.tooltip.once("hidden");
     // Validating the color change ends up updating the rule view twice
     let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
-    focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
+    EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
     yield onHidden;
     yield onRuleViewChanged;
 
     is(getRuleViewPropertyValue(view, "#testid", "color"), color.result,
        "changing the color preserved the unit for " + color.name);
 
     let target = TargetFactory.forTab(tab);
     yield gDevTools.closeToolbox(target);
--- a/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorUnit.js
@@ -51,15 +51,15 @@ function* basicTest(view, name, result) 
     name: "color",
     value: "rgb(0, 255, 0)"
   });
 
   let spectrum = cPicker.spectrum;
   let onHidden = cPicker.tooltip.once("hidden");
   // Validating the color change ends up updating the rule view twice
   let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
-  focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
   yield onRuleViewChanged;
 
   is(getRuleViewPropertyValue(view, "#testid", "color"), result,
      "changing the color used the " + name + " unit");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_01.js
@@ -43,17 +43,17 @@ function* testImageTooltipAfterColorChan
     selector: "body",
     name: "background-image",
     value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'
   });
 
   let spectrum = picker.spectrum;
   let onHidden = picker.tooltip.once("hidden");
   let onModifications = ruleView.once("ruleview-changed");
-  focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
   yield onModifications;
 
   info("Verify again that the image preview tooltip works");
   // After a color change, the property is re-populated, we need to get the new
   // dom node
   url = getRuleViewProperty(ruleView, "body", "background").valueSpan
     .querySelector(".theme-link");
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-and-image-tooltip_02.js
@@ -41,17 +41,17 @@ function* testColorChangeIsntRevertedWhe
     name: "background-color",
     value: "rgb(0, 0, 0)"
   });
 
   let spectrum = picker.spectrum;
 
   let onModifications = waitForNEvents(ruleView, "ruleview-changed", 2);
   let onHidden = picker.tooltip.once("hidden");
-  focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
   yield onModifications;
 
   info("Open the image preview tooltip");
   let value = getRuleViewProperty(ruleView, "body", "background").valueSpan;
   let url = value.querySelector(".theme-link");
   let onShown = ruleView.tooltips.previewTooltip.once("shown");
   let anchor = yield isHoverTooltipTarget(ruleView.tooltips.previewTooltip, url);
--- a/devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
+++ b/devtools/client/inspector/rules/test/browser_rules_colorpicker-commit-on-ENTER.js
@@ -42,17 +42,17 @@ function* testPressingEnterCommitsChange
     "The color swatch's background was updated");
   is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
     "2em solid rgba(0, 255, 0, 0.5)",
     "The text of the border css property was updated");
 
   let onModified = ruleView.once("ruleview-changed");
   let spectrum = cPicker.spectrum;
   let onHidden = cPicker.tooltip.once("hidden");
-  focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
   yield onModified;
 
   is((yield getComputedStyleProperty("body", null, "border-left-color")),
     "rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
   is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
     "The color swatch's background was kept after RETURN");
   is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
--- a/devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
+++ b/devtools/client/inspector/rules/test/browser_rules_cubicbezier-commit-on-ENTER.js
@@ -48,17 +48,17 @@ function* testPressingEnterCommitsChange
   ok(getRuleViewProperty(ruleView, "body", "transition").valueSpan.textContent
     .indexOf("cubic-bezier(") !== -1,
     "The text of the timing-function was updated");
 
   info("Sending RETURN key within the tooltip document");
   // Pressing RETURN ends up doing 2 rule-view updates, one for the preview and
   // one for the commit when the tooltip closes.
   let onRuleViewChanged = waitForNEvents(ruleView, "ruleview-changed", 2);
-  focusAndSendKey(widget.parent.ownerDocument.defaultView, "RETURN");
+  EventUtils.sendKey("RETURN", widget.parent.ownerDocument.defaultView);
   yield onRuleViewChanged;
 
   let style = yield getComputedStyleProperty("body", null,
                                              "transition-timing-function");
   is(style, expected, "The element's timing-function was kept after RETURN");
 
   let ruleViewStyle = getRuleViewProperty(ruleView, "body", "transition")
                       .valueSpan.textContent.indexOf("cubic-bezier(") !== -1;
--- a/devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
+++ b/devtools/client/inspector/rules/test/browser_rules_cubicbezier-revert-on-ESC.js
@@ -89,12 +89,12 @@ function* getRulePropertyValue(name) {
 
 function* escapeTooltip(view) {
   info("Pressing ESCAPE to close the tooltip");
 
   let bezierTooltip = view.tooltips.cubicBezier;
   let widget = yield bezierTooltip.widget;
   let onHidden = bezierTooltip.tooltip.once("hidden");
   let onModifications = view.once("ruleview-changed");
-  focusAndSendKey(widget.parent.ownerDocument.defaultView, "ESCAPE");
+  EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
   yield onHidden;
   yield onModifications;
 }
--- a/devtools/client/inspector/rules/test/head.js
+++ b/devtools/client/inspector/rules/test/head.js
@@ -809,18 +809,8 @@ function waitForStyleModification(inspec
           resolve();
           return;
         }
       }
     }
     inspector.on("markupmutation", checkForStyleModification);
   });
 }
-
-/**
- * Make sure window is properly focused before sending a key event.
- * @param {Window} win
- * @param {Event} key
- */
-function focusAndSendKey(win, key) {
-  win.document.documentElement.focus();
-  EventUtils.sendKey(key, win);
-}
--- a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js
+++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js
@@ -27,20 +27,16 @@ const NODES = [
   { action: "end", title: NODE_TWO },
   { action: "end", title: NODE_THREE },
   { action: "end", title: NODE_FOUR },
   { action: "end", title: NODE_FIVE },
   { action: "end", title: NODE_SIX }
 ];
 
 add_task(function* () {
-  // This test needs specific initial size of the sidebar.
-  yield pushPref("devtools.toolsidebar-width.inspector", 350);
-  yield pushPref("devtools.toolsidebar-height.inspector", 150);
-
   let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
 
   // No way to wait for scrolling to end (Bug 1172171)
   // Rather than wait a max time; limit test to instant scroll behavior
   inspector.breadcrumbs.arrowScrollBox.scrollBehavior = "instant";
 
   yield toolbox.switchHost(Toolbox.HostType.WINDOW);
   let hostWindow = toolbox._host._window;
--- a/devtools/client/inspector/test/browser_inspector_pane-toggle-02.js
+++ b/devtools/client/inspector/test/browser_inspector_pane-toggle-02.js
@@ -6,18 +6,17 @@
 // Test that the inspector toggled panel is visible by default, is hidden after
 // clicking on the toggle button and remains expanded/collapsed when switching
 // hosts.
 
 add_task(function* () {
   info("Open the inspector in a side toolbox host");
   let {toolbox, inspector} = yield openInspectorForURL("about:blank", "side");
 
-  let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
-
+  let panel = inspector.panelDoc.querySelector("#inspector-sidebar-container");
   let button = inspector.panelDoc.querySelector(".sidebar-toggle");
   ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
 
   info("Listen to the end of the animation on the sidebar panel");
   let onTransitionEnd = once(panel, "transitionend");
 
   info("Click on the toggle button");
   EventUtils.synthesizeMouseAtCenter(button, {},
--- a/devtools/client/inspector/test/browser_inspector_pane-toggle-03.js
+++ b/devtools/client/inspector/test/browser_inspector_pane-toggle-03.js
@@ -5,17 +5,17 @@
 
 // Test that the toggle button can collapse and expand the inspector side/bottom
 // panel, and that the appropriate attributes are updated in the process.
 
 add_task(function* () {
   let {inspector} = yield openInspectorForURL("about:blank");
 
   let button = inspector.panelDoc.querySelector(".sidebar-toggle");
-  let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
+  let panel = inspector.panelDoc.querySelector("#inspector-sidebar-container");
 
   ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
 
   info("Listen to the end of the animation on the sidebar panel");
   let onTransitionEnd = once(panel, "transitionend");
 
   info("Click on the toggle button");
   EventUtils.synthesizeMouseAtCenter(button, {},
--- a/devtools/client/inspector/test/browser_inspector_pane-toggle-04.js
+++ b/devtools/client/inspector/test/browser_inspector_pane-toggle-04.js
@@ -15,17 +15,17 @@ add_task(function* () {
     let options = {"set": [
       ["devtools.toolsidebar-width.inspector", 200]
     ]};
     SpecialPowers.pushPrefEnv(options, resolve);
   });
 
   let { inspector, toolbox } = yield openInspectorForURL("about:blank");
   let button = inspector.panelDoc.querySelector(".sidebar-toggle");
-  let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
+  let panel = inspector.panelDoc.querySelector("#inspector-sidebar-container");
 
   info("Changing toolbox host to a window.");
   yield toolbox.switchHost(Toolbox.HostType.WINDOW);
 
   let hostWindow = toolbox._host._window;
   let originalWidth = hostWindow.outerWidth;
   let originalHeight = hostWindow.outerHeight;
 
--- a/devtools/client/inspector/test/browser_inspector_pane-toggle-05.js
+++ b/devtools/client/inspector/test/browser_inspector_pane-toggle-05.js
@@ -5,18 +5,17 @@
 
 /**
 * Test the keyboard navigation for the pane toggle using
 * space and enter
 */
 
 add_task(function* () {
   let {inspector} = yield openInspectorForURL("about:blank", "side");
-  let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
-
+  let panel = inspector.panelDoc.querySelector("#inspector-sidebar-container");
   let button = inspector.panelDoc.querySelector(".sidebar-toggle");
 
   ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
 
   yield togglePane(button, "Press on the toggle button", panel, "VK_RETURN");
   ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
 
   yield togglePane(button, "Press on the toggle button to expand the panel again",
--- a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
@@ -14,48 +14,44 @@ add_task(function* () {
   let {searchBox} = inspector;
   yield selectNode("h1", inspector);
 
   let win = inspector.panelWin;
   let searchContextMenu = toolbox.textboxContextMenuPopup;
   ok(searchContextMenu,
     "The search filter context menu is loaded in the inspector");
 
-  emptyClipboard();
-
   let cmdUndo = searchContextMenu.querySelector("[command=cmd_undo]");
   let cmdDelete = searchContextMenu.querySelector("[command=cmd_delete]");
   let cmdSelectAll = searchContextMenu.querySelector("[command=cmd_selectAll]");
   let cmdCut = searchContextMenu.querySelector("[command=cmd_cut]");
   let cmdCopy = searchContextMenu.querySelector("[command=cmd_copy]");
   let cmdPaste = searchContextMenu.querySelector("[command=cmd_paste]");
 
   info("Opening context menu");
-  searchBox.focus();
   let onContextMenuPopup = once(searchContextMenu, "popupshowing");
   EventUtils.synthesizeMouse(searchBox, 2, 2,
     {type: "contextmenu", button: 2}, win);
   yield onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
-  is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
+  is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
   is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
   is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
   is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
 
   info("Closing context menu");
   let onContextMenuHidden = once(searchContextMenu, "popuphidden");
   searchContextMenu.hidePopup();
   yield onContextMenuHidden;
 
   info("Copy text in search field using the context menu");
   searchBox.value = TEST_INPUT;
   searchBox.select();
-  searchBox.focus();
   EventUtils.synthesizeMouse(searchBox, 2, 2,
     {type: "contextmenu", button: 2}, win);
   yield onContextMenuPopup;
   yield waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
   searchContextMenu.hidePopup();
   yield onContextMenuHidden;
 
   info("Reopen context menu and check command properties");
--- a/devtools/client/inspector/toolsidebar.js
+++ b/devtools/client/inspector/toolsidebar.js
@@ -61,17 +61,22 @@ ToolSidebar.prototype = {
     return this._toolPanel.ReactDOM;
   },
 
   get browserRequire() {
     return this._toolPanel.browserRequire;
   },
 
   get InspectorTabPanel() {
-    return this._toolPanel.InspectorTabPanel;
+    if (!this._InspectorTabPanel) {
+      this._InspectorTabPanel =
+        this.React.createFactory(this.browserRequire(
+        "devtools/client/inspector/components/inspector-tab-panel"));
+    }
+    return this._InspectorTabPanel;
   },
 
   // Rendering
 
   render: function () {
     let Tabbar = this.React.createFactory(this.browserRequire(
       "devtools/client/shared/components/tabs/tabbar"));
 
@@ -80,39 +85,31 @@ ToolSidebar.prototype = {
       showAllTabsMenu: true,
       onSelect: this.handleSelectionChange.bind(this),
     });
 
     this._tabbar = this.ReactDOM.render(sidebar, this._tabbox);
   },
 
   addExistingTab: function (id, title, selected) {
-    let panel = this.InspectorTabPanel({
-      id: id,
-      idPrefix: this.TABPANEL_ID_PREFIX,
-      key: id,
-      title: title,
-    });
-
-    this._tabbar.addTab(id, title, selected, panel);
+    this._tabbar.addTab(id, title, selected, this.InspectorTabPanel);
 
     this.emit("new-tab-registered", id);
   },
 
   /**
    * Register a tab. A tab is a document.
    * The document must have a title, which will be used as the name of the tab.
    *
    * @param {string} tab uniq id
    * @param {string} url
    */
   addFrameTab: function (id, title, url, selected) {
     let panel = this.InspectorTabPanel({
       id: id,
-      idPrefix: this.TABPANEL_ID_PREFIX,
       key: id,
       title: title,
       url: url,
       onMount: this.onSidePanelMounted.bind(this),
     });
 
     this._tabbar.addTab(id, title, selected, panel);
 
--- a/devtools/client/shared/components/test/mochitest/test_tabs_accessibility.html
+++ b/devtools/client/shared/components/test/mochitest/test_tabs_accessibility.html
@@ -52,21 +52,17 @@ window.onload = Task.async(function* () 
 
     function addTabWithPanel(tabId) {
       // Setup for InspectorTabPanel
       let panel = document.createElement("div");
       panel.id = `sidebar-panel-${tabId}`;
       document.body.appendChild(panel);
 
       return setState(tabbarReact, Object.assign({}, tabbarReact.state, {
-        tabs: tabbarReact.state.tabs.concat({
-          id: `sidebar-panel-${tabId}`,
-          title: `tab-${tabId}`,
-          panel: InspectorTabPanel
-        }),
+        tabs: tabbarReact.state.tabs.concat({id: `${tabId}`, title: `tab-${tabId}`, panel: InspectorTabPanel}),
       }));
     }
   } catch(e) {
     ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
   } finally {
     SimpleTest.finish();
   }
 });
--- a/devtools/client/themes/inspector.css
+++ b/devtools/client/themes/inspector.css
@@ -6,57 +6,19 @@
 :root {
   --eyedropper-image: url(images/command-eyedropper.svg);
 }
 
 .theme-firebug {
   --eyedropper-image: url(images/firebug/command-eyedropper.svg);
 }
 
-/* Make sure to hide scroll bars for the parent window */
-window {
-  overflow: hidden;
-}
-
-/* The main Inspector panel container. */
-.inspector-responsive-container {
-  height: 100vh;
-}
-
-/* The main panel layout. This area consists of a toolbar, markup view
-  and breadcrumbs bar. */
-.devtools-main-content {
-  /* Subtract 1 pixel from the panel height. It's puzzling why this
-    is needed, but if not presented the entire Inspector panel
-    content jumps 1 pixel up when the Toolbox is opened. */
-  height: calc(100% - 1px);
-  display: flex;
-  flex-direction: column;
-  flex: 1 1 auto;
-}
-
-/* Inspector Panel Splitter */
-
-#inspector-splitter-box {
-  height: 100vh;
-  width: 100%;
-}
-
-/* Minimum width for the Inspector main (uncontrolled) area. */
-#inspector-splitter-box .uncontrolled {
-  min-width: 275px;
-}
-
-#inspector-splitter-box .controlled.pane-collapsed {
-  visibility: collapse;
-}
-
 /* Use flex layout for the Inspector toolbar. For now, it's done
    specifically for the Inspector toolbar since general rule applied
-   on .devtools-toolbar breaks breadcrumbs and also toolbars in other
+   on .devtools-toolbar breaks breadcrubs and also toolbars in other
    panels (e.g. webconsole, debugger), these are not ready for HTML
    layout yet. */
 #inspector-toolbar.devtools-toolbar {
   display: flex;
 }
 
 #inspector-toolbar.devtools-toolbar .devtools-toolbar-spacer {
   flex-grow: 1;
@@ -157,19 +119,18 @@ window {
   font: message-box;
 }
 
 /* Set the minimum width for the side bar so, all tabs are
   properly visible. The value can be decreased when bug 1281789
   is fixed and the all-tabs-menu is available again. */
 #inspector-sidebar-container {
   overflow: hidden;
-  min-width: 50px;
+  min-width: 300px;
   position: relative;
-  height: 100%;
 }
 
 #inspector-sidebar {
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
@@ -183,21 +144,8 @@ window {
 /* "no results" warning message displayed in the ruleview and in the computed view */
 
 #ruleview-no-results,
 #computedview-no-results {
   color: var(--theme-body-color-inactive);
   text-align: center;
   margin: 5px;
 }
-
-/* Markup Box */
-
-#markup-box {
-  width: 100%;
-  flex: 1 1 auto;
-}
-
-#markup-box > iframe {
-  height: 100%;
-  width: 100%;
-}
-