Bug 1258114 - use invisible borders to drag devtools splitters on both sides;r=bgrins
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 15 Apr 2016 12:36:17 +0200
changeset 331496 98b97a7844ccbfa9ca5bb72053ac824cfd4e76b0
parent 331495 23fdf133c101347ef6a01f1cabc1f6238567d7e8
child 331497 54303363802794f3c7fbc23d886965f5c5495335
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1258114
milestone48.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 1258114 - use invisible borders to drag devtools splitters on both sides;r=bgrins Devtools splitters now have a clickable area on both sides of the splitter. The previous layout provided a 3px clickable area (2px empty content + 1px visible border). The new layout uses invisible borders on both sides and a visible (clipped) content. New draggable areas: - side splitters : 1px left + 1px splitter + 4px right - horizontal splitters : 2 px top + 1px splitter + 2px bottom Variables are defined in splitters.css to adjust these settings. Modified two test helpers opening context menus: the click should be performed with a slight offset in order to avoid clicking on the splitter. MozReview-Commit-ID: 94uFZoIBL7B
devtools/client/inspector/rules/test/browser_rules_edit-selector-click.js
devtools/client/shared/components/h-split-box.js
devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
devtools/client/storage/test/head.js
devtools/client/themes/components-h-split-box.css
devtools/client/themes/splitters.css
devtools/client/themes/toolbars.css
devtools/client/themes/widgets.css
devtools/client/webconsole/test/head.js
--- a/devtools/client/inspector/rules/test/browser_rules_edit-selector-click.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-selector-click.js
@@ -31,25 +31,25 @@ function* testClickOnSelectorEditorInput
   info("Focusing an existing selector name in the rule-view");
   let editor = yield focusEditableField(view, ruleEditor.selectorText);
   let editorInput = editor.input;
   is(inplaceEditor(ruleEditor.selectorText), editor,
     "The selector editor got focused");
 
   info("Click inside the editor input");
   let onClick = once(editorInput, "click");
-  EventUtils.synthesizeMouse(editor.input, 1, 1, {}, view.styleWindow);
+  EventUtils.synthesizeMouse(editor.input, 2, 1, {}, view.styleWindow);
   yield onClick;
   is(editor.input, view.styleDocument.activeElement,
     "The editor input should still be focused");
   ok(!ruleEditor.newPropSpan, "No newProperty editor was created");
 
   info("Doubleclick inside the editor input");
   let onDoubleClick = once(editorInput, "dblclick");
-  EventUtils.synthesizeMouse(editor.input, 1, 1, { clickCount: 2 },
+  EventUtils.synthesizeMouse(editor.input, 2, 1, { clickCount: 2 },
     view.styleWindow);
   yield onDoubleClick;
   is(editor.input, view.styleDocument.activeElement,
     "The editor input should still be focused");
   ok(!ruleEditor.newPropSpan, "No newProperty editor was created");
 
   info("Click outside the editor input");
   let onBlur = once(editorInput, "blur");
--- a/devtools/client/shared/components/h-split-box.js
+++ b/devtools/client/shared/components/h-split-box.js
@@ -125,17 +125,17 @@ module.exports = createClass({
         {
           className: "h-split-box-pane",
           style: { flex: startWidth, minWidth: minStartWidth },
         },
         start
       ),
 
       dom.div({
-        className: "h-split-box-splitter",
+        className: "devtools-side-splitter",
         onMouseDown: this._onMouseDown,
       }),
 
       dom.div(
         {
           className: "h-split-box-pane",
           style: { flex: 1 - startWidth, minWidth: minEndWidth },
         },
--- a/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
+++ b/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
@@ -4,16 +4,17 @@
 Basic tests for the HSplitBox component.
 -->
 <head>
   <meta charset="utf-8">
   <title>Tree component test</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript "src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+  <link rel="stylesheet" href="chrome://devtools/skin/splitters.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/components-h-split-box.css" type="text/css"/>
   <style>
     html {
       --theme-splitter-color: black;
     }
   </style>
 </head>
 <body>
@@ -72,17 +73,17 @@ window.onload = Task.async(function* () 
     const threeQuarters = left + 3 * width / 4;
 
     synthesizeMouse(container, middle, top, { type: "mousemove" }, window);
     is(newSizes.length, 0, "Mouse moves without dragging the splitter should have no effect");
 
     // Send a mouse down on the splitter, and then move the mouse a couple
     // times. Now we should get resizes.
 
-    const splitter = document.querySelector(".h-split-box-splitter");
+    const splitter = document.querySelector(".devtools-side-splitter");
     ok(splitter, "Should get our splitter");
 
     synthesizeMouseAtCenter(splitter, { button: 0, type: "mousedown" }, window);
 
     function mouseMove(clientX) {
       const event = new MouseEvent("mousemove", { clientX });
       document.defaultView.top.dispatchEvent(event);
     }
--- a/devtools/client/storage/test/head.js
+++ b/devtools/client/storage/test/head.js
@@ -838,17 +838,17 @@ function waitForContextMenu(popup, butto
     deferred.resolve(popup);
   }
 
   popup.addEventListener("popupshown", onPopupShown);
 
   info("wait for the context menu to open");
   button.scrollIntoView();
   let eventDetails = {type: "contextmenu", button: 2};
-  EventUtils.synthesizeMouse(button, 2, 2, eventDetails,
+  EventUtils.synthesizeMouse(button, 5, 2, eventDetails,
                              button.ownerDocument.defaultView);
   return deferred.promise;
 }
 
 /**
  * Verify the storage inspector state: check that given type/host exists
  * in the tree, and that the table contains rows with specified names.
  *
--- a/devtools/client/themes/components-h-split-box.css
+++ b/devtools/client/themes/components-h-split-box.css
@@ -17,15 +17,8 @@
   height: 100%;
 }
 
 .h-split-box {
   display: flex;
   flex-direction: row;
   flex: 1;
 }
-
-.h-split-box-splitter {
-  -moz-border-end: 1px solid var(--theme-splitter-color);
-  cursor: ew-resize;
-  width: 3px;
-  -moz-margin-start: -3px;
-}
--- a/devtools/client/themes/splitters.css
+++ b/devtools/client/themes/splitters.css
@@ -1,43 +1,79 @@
 /* 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/. */
 
+/* This file is loaded by both browser.xul and toolbox.xul. Therefore, rules
+   defined here can not rely on toolbox.xul variables. */
+
 /* Splitters */
+
+:root {
+  /* Define the widths of the draggable areas on each side of a splitter. top
+     and bottom widths are used for horizontal splitters, inline-start and
+     inline-end for side splitters.*/
+
+  --devtools-splitter-top-width: 2px;
+  --devtools-splitter-bottom-width: 2px;
+
+  /* Small draggable area on inline-start to avoid overlaps on scrollbars.*/
+  --devtools-splitter-inline-start-width: 1px;
+  --devtools-splitter-inline-end-width: 4px;
+}
+
 :root[devtoolstheme="light"] {
   /* These variables are used in browser.xul but inside the toolbox they are overridden by --theme-splitter-color */
   --devtools-splitter-color: #dde1e4;
 }
 
 :root[devtoolstheme="dark"] {
   --devtools-splitter-color: #42484f;
 }
 
-.devtools-horizontal-splitter {
+.devtools-horizontal-splitter,
+.devtools-side-splitter {
   -moz-appearance: none;
   background-image: none;
-  background-color: transparent;
   border: 0;
-  border-bottom: 1px solid var(--devtools-splitter-color);
-  min-height: 3px;
-  height: 3px;
-  margin-top: -3px;
+  border-style: solid;
+  border-color: transparent;
+  background-color: var(--devtools-splitter-color);
+  background-clip: content-box;
   position: relative;
+
+  box-sizing: border-box;
+
+  /* Positive z-index positions the splitter on top of its siblings and makes
+     it clickable on both sides. */
+  z-index: 1;
+}
+
+.devtools-horizontal-splitter {
+  min-height: calc(var(--devtools-splitter-top-width) +
+    var(--devtools-splitter-bottom-width) + 1px);
+
+  border-top-width: var(--devtools-splitter-top-width);
+  border-bottom-width: var(--devtools-splitter-bottom-width);
+
+  margin-top: calc(-1 * var(--devtools-splitter-top-width) - 1px);
+  margin-bottom: calc(-1 * var(--devtools-splitter-bottom-width));
+
+  cursor: n-resize;
 }
 
 .devtools-side-splitter {
-  -moz-appearance: none;
-  background-image: none;
-  background-color: transparent;
-  border: 0;
-  -moz-border-end: 1px solid var(--devtools-splitter-color);
-  min-width: 3px;
-  width: 3px;
-  -moz-margin-start: -3px;
-  position: relative;
+  min-width: calc(var(--devtools-splitter-inline-start-width) +
+    var(--devtools-splitter-inline-end-width) + 1px);
+
+  border-inline-start-width: var(--devtools-splitter-inline-start-width);
+  border-inline-end-width: var(--devtools-splitter-inline-end-width);
+
+  margin-inline-start: calc(-1 * var(--devtools-splitter-inline-start-width) - 1px);
+  margin-inline-end: calc(-1 * var(--devtools-splitter-inline-end-width));
+
   cursor: e-resize;
 }
 
 .devtools-horizontal-splitter.disabled,
 .devtools-side-splitter.disabled {
   pointer-events: none;
 }
--- a/devtools/client/themes/toolbars.css
+++ b/devtools/client/themes/toolbars.css
@@ -975,26 +975,24 @@
 
 .hidden-labels-box:not(.visible) > label,
 .hidden-labels-box.visible ~ .hidden-labels-box > label:last-child {
   display: none;
 }
 
 .devtools-invisible-splitter {
   border-color: transparent;
+  background-color: transparent;
 }
 
-.devtools-horizontal-splitter {
-  border-bottom: 1px solid var(--theme-splitter-color);
+.devtools-horizontal-splitter,
+.devtools-side-splitter {
+  background-color: var(--theme-splitter-color);
 }
 
-.devtools-side-splitter {
-  -moz-border-end: 1px solid var(--theme-splitter-color);
-  border-color: var(--theme-splitter-color); /* Needed for responsive container at low width. */
-}
 
 /* Throbbers */
 .devtools-throbber::before {
   content: "";
   display: inline-block;
   vertical-align: bottom;
   -moz-margin-end: 0.5em;
   width: 1em;
--- a/devtools/client/themes/widgets.css
+++ b/devtools/client/themes/widgets.css
@@ -59,27 +59,29 @@
 @media (max-width: 700px) {
   .devtools-responsive-container {
     -moz-box-orient: vertical;
   }
 
   .devtools-responsive-container > .devtools-side-splitter {
     /* This is a normally vertical splitter, but we have turned it horizontal
        due to the smaller resolution */
-    min-height: 3px;
-    height: 3px;
-    margin-top: -3px;
+    min-height: calc(var(--devtools-splitter-top-width) +
+    var(--devtools-splitter-bottom-width) + 1px);
+    border-top-width: var(--devtools-splitter-top-width);
+    border-bottom-width: var(--devtools-splitter-bottom-width);
+    margin-top: calc(-1 * var(--devtools-splitter-top-width) - 1px);
+    margin-bottom: calc(-1 * var(--devtools-splitter-bottom-width));
 
     /* Reset the vertical splitter styles */
-    border-width: 0;
-    border-bottom-width: 1px;
-    border-bottom-style: solid;
-    -moz-margin-start: 0;
-    width: auto;
     min-width: 0;
+    border-inline-end-width: 0;
+    border-inline-start-width: 0;
+    margin-inline-end: 0;
+    margin-inline-start: 0;
 
     /* In some edge case the cursor is not changed to n-resize */
     cursor: n-resize;
   }
 
   .devtools-responsive-container > .devtools-sidebar-tabs:not([pane-collapsed]) {
     /* When the panel is collapsed min/max height should not be applied because
        collapsing relies on negative margins, which implies constant height. */
@@ -1118,17 +1120,17 @@
   color: var(--theme-body-color);
 }
 
 /* Table Widget */
 
 /* Table body */
 
 .table-widget-body > .devtools-side-splitter {
-  border: none;
+  background-color: transparent;
 }
 
 .table-widget-body {
   overflow: auto;
 }
 
 .table-widget-body,
 .table-widget-empty-text {
--- a/devtools/client/webconsole/test/head.js
+++ b/devtools/client/webconsole/test/head.js
@@ -278,17 +278,17 @@ function waitForContextMenu(popup, butto
 
     deferred.resolve(popup);
   }
 
   popup.addEventListener("popupshown", onPopupShown);
 
   info("wait for the context menu to open");
   let eventDetails = {type: "contextmenu", button: 2};
-  EventUtils.synthesizeMouse(button, 2, 2, eventDetails,
+  EventUtils.synthesizeMouse(button, 5, 2, eventDetails,
                              button.ownerDocument.defaultView);
   return deferred.promise;
 }
 
 /**
  * Listen for a new tab to open and return a promise that resolves when one
  * does and completes the load event.
  * @return a promise that resolves to the tab object