Bug 969914 - Make developer toolbar match the light devtools theme when applied;r=jwalker,r=pbrosset
authorBrian Grinstead <bgrinstead@mozilla.com>
Wed, 15 Apr 2015 08:12:49 -0700
changeset 239277 848604d33facee4e37d89e44d72f47c165f7c97b
parent 239276 8d585806822feed8855b6c9f13516dfe84dd92c6
child 239278 fd1fddc74fe82cdb2dde47400243a9403aadf37b
push id12388
push userbgrinstead@mozilla.com
push dateWed, 15 Apr 2015 15:12:58 +0000
treeherderfx-team@848604d33fac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalker, pbrosset
bugs969914
milestone40.0a1
Bug 969914 - Make developer toolbar match the light devtools theme when applied;r=jwalker,r=pbrosset
browser/devtools/shared/DeveloperToolbar.jsm
browser/devtools/shared/test/browser_toolbar_tooltip.js
browser/themes/shared/devtools/commandline.css
browser/themes/shared/devtools/commandline.inc.css
browser/themes/shared/devtools/dark-theme.css
browser/themes/shared/devtools/light-theme.css
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -830,32 +830,43 @@ OutputPanel.prototype._init = function(d
   this._update = this._update.bind(this);
 
   // Wire up the element from the iframe, and resolve the promise
   let deferred = promise.defer();
   let onload = () => {
     this._frame.removeEventListener("load", onload, true);
 
     this.document = this._frame.contentDocument;
+    this._copyTheme();
 
     this._div = this.document.getElementById("gcli-output-root");
     this._div.classList.add('gcli-row-out');
     this._div.setAttribute('aria-live', 'assertive');
 
     let styles = this._toolbar.ownerDocument.defaultView
                     .getComputedStyle(this._toolbar);
     this._div.setAttribute("dir", styles.direction);
 
     deferred.resolve(this);
   };
   this._frame.addEventListener("load", onload, true);
 
   return deferred.promise;
 }
 
+/* Copy the current devtools theme attribute into the iframe,
+   so it can be styled correctly. */
+OutputPanel.prototype._copyTheme = function() {
+  if (this.document) {
+    let theme =
+      this._devtoolbar._doc.documentElement.getAttribute("devtoolstheme");
+    this.document.documentElement.setAttribute("devtoolstheme", theme);
+  }
+};
+
 /**
  * Prevent the popup from hiding if it is not permitted via this.canHide.
  */
 OutputPanel.prototype._onpopuphiding = function(ev) {
   // TODO: When we switch back from tooltip to panel we can remove this hack:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
   if (isLinux && !this.canHide) {
     ev.preventDefault();
@@ -870,16 +881,17 @@ OutputPanel.prototype.show = function() 
     this.canHide = false;
   }
 
   // We need to reset the iframe size in order for future size calculations to
   // be correct
   this._frame.style.minHeight = this._frame.style.maxHeight = 0;
   this._frame.style.minWidth = 0;
 
+  this._copyTheme();
   this._panel.openPopup(this._input, "before_start", 0, 0, false, false, null);
   this._resize();
 
   this._input.focus();
 };
 
 /**
  * Internal helper to set the height of the output panel to fit the available
@@ -1085,16 +1097,17 @@ TooltipPanel.create = function(devtoolba
 
 /**
  * @private See TooltipPanel.create
  */
 TooltipPanel.prototype._init = function(devtoolbar) {
   let deferred = promise.defer();
 
   let chromeDocument = devtoolbar._doc;
+  this._devtoolbar = devtoolbar;
   this._input = devtoolbar._doc.querySelector(".gclitoolbar-input-node");
   this._toolbar = devtoolbar._doc.querySelector("#developer-toolbar");
   this._dimensions = { start: 0, end: 0 };
 
   /*
   <tooltip|panel id="gcli-tooltip"
          type="arrow"
          noautofocus="true"
@@ -1141,29 +1154,40 @@ TooltipPanel.prototype._init = function(
 
   /**
    * Wire up the element from the iframe, and resolve the promise.
    */
   let onload = () => {
     this._frame.removeEventListener("load", onload, true);
 
     this.document = this._frame.contentDocument;
+    this._copyTheme();
     this.hintElement = this.document.getElementById("gcli-tooltip-root");
     this._connector = this.document.getElementById("gcli-tooltip-connector");
 
     let styles = this._toolbar.ownerDocument.defaultView
                     .getComputedStyle(this._toolbar);
     this.hintElement.setAttribute("dir", styles.direction);
 
     deferred.resolve(this);
   };
   this._frame.addEventListener("load", onload, true);
 
   return deferred.promise;
-}
+};
+
+/* Copy the current devtools theme attribute into the iframe,
+   so it can be styled correctly. */
+TooltipPanel.prototype._copyTheme = function() {
+  if (this.document) {
+    let theme =
+      this._devtoolbar._doc.documentElement.getAttribute("devtoolstheme");
+    this.document.documentElement.setAttribute("devtoolstheme", theme);
+  }
+};
 
 /**
  * Prevent the popup from hiding if it is not permitted via this.canHide.
  */
 TooltipPanel.prototype._onpopuphiding = function(ev) {
   // TODO: When we switch back from tooltip to panel we can remove this hack:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
   if (isLinux && !this.canHide) {
@@ -1186,16 +1210,17 @@ TooltipPanel.prototype.show = function(d
   this._panel.ownerDocument.defaultView.setTimeout(() => {
     this._resize();
   }, 0);
 
   if (isLinux) {
     this.canHide = false;
   }
 
+  this._copyTheme();
   this._resize();
   this._panel.openPopup(this._input, "before_start", dimensions.start * 10, 0,
                         false, false, null);
   this._input.focus();
 };
 
 /**
  * One option is to spend lots of time taking an average width of characters
--- a/browser/devtools/shared/test/browser_toolbar_tooltip.js
+++ b/browser/devtools/shared/test/browser_toolbar_tooltip.js
@@ -6,35 +6,36 @@
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed.
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Protocol error (unknownError): Error: Got an invalid root window in DocumentWalker");
 
 const TEST_URI = "data:text/html;charset=utf-8,<p>Tooltip Tests</p>";
+const PREF_DEVTOOLS_THEME = "devtools.theme";
 
-function test() {
-  addTab(TEST_URI, function() {
-    Task.spawn(runTest).catch(err => {
-      ok(false, ex);
-      console.error(ex);
-    }).then(finish);
-  });
-}
+registerCleanupFunction(() => {
+  // Set preferences back to their original values
+  Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME);
+});
 
-function* runTest() {
+add_task(function* showToolbar() {
+  yield promiseTab(TEST_URI);
+
   info("Starting browser_toolbar_tooltip.js");
 
   ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in runTest");
 
   let showPromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.SHOW);
   document.getElementById("Tools:DevToolbar").doCommand();
   yield showPromise;
+});
 
+add_task(function* testDimensions() {
   let tooltipPanel = DeveloperToolbar.tooltipPanel;
 
   DeveloperToolbar.display.focusManager.helpRequest();
   yield DeveloperToolbar.display.inputter.setInput('help help');
 
   DeveloperToolbar.display.inputter.setCursor({ start: 'help help'.length });
   is(tooltipPanel._dimensions.start, 'help '.length,
           'search param start, when cursor at end');
@@ -49,17 +50,36 @@ function* runTest() {
   is(tooltipPanel._dimensions.start, 'help '.length,
           'search param start, when cursor at penultimate position');
   ok(getLeftMargin() > 30, 'tooltip offset, when cursor at penultimate position')
 
   DeveloperToolbar.display.inputter.setCursor({ start: 0 });
   is(tooltipPanel._dimensions.start, 0,
           'search param start, when cursor at start');
   ok(getLeftMargin() > 9, 'tooltip offset, when cursor at start')
-}
+});
+
+add_task(function* testThemes() {
+  let tooltipPanel = DeveloperToolbar.tooltipPanel;
+  ok(tooltipPanel.document, "Tooltip panel is initialized");
+
+  Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
+
+  yield DeveloperToolbar.display.inputter.setInput("");
+  yield DeveloperToolbar.display.inputter.setInput("help help");
+  is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
+     "dark", "Tooltip panel has correct theme");
+
+  Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
+
+  yield DeveloperToolbar.display.inputter.setInput("");
+  yield DeveloperToolbar.display.inputter.setInput("help help");
+  is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
+     "light", "Tooltip panel has correct theme");
+});
 
 function getLeftMargin() {
   let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
   return parseInt(style.slice(0, -2), 10);
 }
 
 function observeOnce(topic, ownsWeak=false) {
   return new Promise(function(resolve, reject) {
--- a/browser/themes/shared/devtools/commandline.css
+++ b/browser/themes/shared/devtools/commandline.css
@@ -1,24 +1,42 @@
 /* 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/. */
 
+
+/* NOTE: THESE NEED TO STAY IN SYNC WITH LIGHT-THEME.CSS AND DARK-THEME.CSS.
+   We are copy/pasting variables from light-theme and dark-theme,
+   since they aren't loaded in this context (within commandlineoutput.xhtml
+   and commandlinetooltip.xhtml). */
+:root[devtoolstheme="light"] {
+  --gcli-background-color: #ebeced; /* --theme-tab-toolbar-background */
+  --gcli-input-focused-background: #f7f7f7; /* --theme-sidebar-background */
+  --gcli-input-color: #18191a; /* --theme-body-color */
+  --gcli-border-color: #aaaaaa; /* --theme-splitter-color */
+}
+
+:root[devtoolstheme="dark"] {
+  --gcli-background-color: #343c45; /* --theme-toolbar-background */
+  --gcli-input-focused-background: #252c33; /* --theme-tab-toolbar-background */
+  --gcli-input-color: #b6babf; /* --theme-body-color-alt */
+  --gcli-border-color: black; /* --theme-splitter-color */
+}
+
 .gcli-body {
   margin: 0;
   font: message-box;
-  color: hsl(210,30%,85%);
+  color: var(--gcli-input-color);
 }
 
 #gcli-output-root,
 #gcli-tooltip-root {
-  border: 1px solid hsl(206,37%,4%);
-  box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
-  background-image: linear-gradient(hsla(209,18%,18%,0.9), hsl(209,23%,18%));
+  border: 1px solid var(--gcli-border-color);
   border-radius: 3px;
+  background-color: var(--gcli-background-color);
 }
 
 #gcli-output-root {
   padding: 5px 10px;
   border-bottom-left-radius: 0;
   border-bottom-right-radius: 0;
   border-bottom: 0;
 }
@@ -27,32 +45,32 @@
   padding: 5px 0px;
 }
 
 #gcli-tooltip-connector {
   margin-top: -1px;
   margin-left: 8px;
   width: 20px;
   height: 10px;
-  border-left: 1px solid hsl(206,37%,4%);
-  border-right: 1px solid hsl(206,37%,4%);
-  background-color: hsl(209,23%,18%);
+  border-left: 1px solid var(--gcli-border-color);
+  border-right: 1px solid var(--gcli-border-color);
+  background-color: var(--gcli-background-color);
 }
 
 .gcli-tt-description,
 .gcli-tt-error {
   padding: 0 10px;
 }
 
 .gcli-row-out {
   padding: 0 5px;
   line-height: 1.2em;
   border-top: none;
   border-bottom: none;
-  color: hsl(210,30%,85%);
+  color: var(--gcli-input-color);
 }
 
 .gcli-row-out p,
 .gcli-row-out h1,
 .gcli-row-out h2,
 .gcli-row-out h3 {
   margin: 5px 0;
 }
@@ -60,17 +78,17 @@
 .gcli-row-out h1,
 .gcli-row-out h2,
 .gcli-row-out h3,
 .gcli-row-out h4,
 .gcli-row-out h5,
 .gcli-row-out th,
 .gcli-row-out strong,
 .gcli-row-out pre {
-  color: hsl(210,30%,95%);
+  color: var(--gcli-input-color);
 }
 
 .gcli-row-out pre {
   font-size: 80%;
 }
 
 .gcli-row-out td {
   white-space: nowrap;
@@ -78,23 +96,23 @@
 
 .gcli-out-shortcut,
 .gcli-help-synopsis {
   padding: 0 3px;
   margin: 0 4px;
   font-weight: normal;
   font-size: 90%;
   border-radius: 3px;
-  background-color: hsl(209,23%,18%);
-  border: 1px solid hsl(206,37%,4%);
+  background-color: var(--gcli-background-color);
+  border: 1px solid var(--gcli-border-color);
 }
 
 .gcli-out-shortcut:before,
 .gcli-help-synopsis:before {
-  color: hsl(210,30%,85%);
+  color: var(--gcli-input-color);
   -moz-padding-end: 2px;
 }
 
 .gcli-help-arrow {
   color: #666;
 }
 
 .gcli-help-description {
@@ -112,22 +130,22 @@
 }
 
 .gcli-menu-name {
   -moz-padding-start: 8px;
 }
 
 .gcli-menu-desc {
   -moz-padding-end: 8px;
-  color: hsl(210,30%,75%);
+  color: var(--gcli-input-color);
 }
 
 .gcli-menu-name:hover,
 .gcli-menu-desc:hover {
-  background-color: hsla(0,0%,0%,.3);
+  background-color: var(--gcli-input-focused-background);
 }
 
 .gcli-menu-highlight,
 .gcli-menu-highlight:hover {
   background-color: hsla(0,100%,100%,.1);
 }
 
 .gcli-menu-typed {
--- a/browser/themes/shared/devtools/commandline.inc.css
+++ b/browser/themes/shared/devtools/commandline.inc.css
@@ -1,38 +1,65 @@
 %if 0
 /* 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/. */
 %endif
 
 /* Developer toolbar */
 
+/* NOTE: THESE NEED TO STAY IN SYNC WITH LIGHT-THEME.CSS AND DARK-THEME.CSS.
+   We are copy/pasting variables from light-theme and dark-theme,
+   since they aren't loaded in this context (within browser.css). */
+:root[devtoolstheme="light"] #developer-toolbar {
+  --gcli-background-color: #ebeced; /* --theme-tab-toolbar-background */
+  --gcli-input-background: #f0f1f2; /* --theme-toolbar-background */
+  --gcli-input-focused-background: #f7f7f7; /* --theme-sidebar-background */
+  --gcli-input-color: #18191a; /* --theme-body-color */
+  --gcli-border-color: #aaaaaa; /* --theme-splitter-color */
+  --selection-background: #4c9ed9; /* --theme-selection-background */
+  --selection-color: #f5f7fa; /* --theme-selection-color */
+}
+
+:root[devtoolstheme="dark"] #developer-toolbar {
+  --gcli-background-color: #343c45; /* --theme-toolbar-background */
+  --gcli-input-background: rgba(37, 44, 51, .6); /* --theme-tab-toolbar-background */
+  --gcli-input-focused-background: #252c33; /* --theme-tab-toolbar-background */
+  --gcli-input-color: #b6babf; /* --theme-body-color-alt */
+  --gcli-border-color: black; /* --theme-splitter-color */
+  --selection-background: #1d4f73; /* --theme-selection-background */
+  --selection-color: #f5f7fa; /* --theme-selection-color */
+}
+
 #developer-toolbar {
   -moz-appearance: none;
   padding: 0;
   min-height: 32px;
-  background-color: #343C45; /* Toolbars */
-  border-top: 1px solid #060a0d;
-  box-shadow: 0 1px 0 hsla(204,45%,98%,.05) inset, 0 -1px 0 hsla(206,37%,4%,.1) inset;
+  background-color: var(--gcli-background-color);
+  border-top: 1px solid var(--gcli-border-color);
 }
 
 #developer-toolbar > toolbarbutton {
   -moz-appearance: none;
   border: none;
   background: transparent;
   margin: 0;
   padding: 0 10px;
   width: 32px;
 }
 
 .developer-toolbar-button > image {
   margin: auto 10px;
 }
 
+:root[devtoolstheme="light"] #developer-toolbar > toolbarbutton:not([checked=true]) > image,
+:root[devtoolstheme="light"] .gclitoolbar-input-node:not([focused=true])::before  {
+  filter: url("chrome://browser/skin/devtools/filters.svg#invert");
+}
+
 .developer-toolbar-button > .toolbarbutton-icon,
 #developer-toolbar-closebutton > .toolbarbutton-icon {
   width: 16px;
   height: 16px;
 }
 
 #developer-toolbar-toolbox-button {
   list-style-image: url("chrome://browser/skin/devtools/toggle-tools.png");
@@ -130,34 +157,35 @@ html|*#gcli-output-frame {
   -moz-box-align: center;
   padding-top: 0;
   padding-bottom: 0;
   padding-right: 8px;
   text-shadow: none;
   box-shadow: none;
   border-width: 0;
   background-color: transparent;
+  border-radius: 0;
 }
 
 .gclitoolbar-input-node {
   -moz-appearance: none;
-  color: hsl(210,30%,85%);
-  background-color: #242b33;
+  color: var(--gcli-input-color);
+  background-color: var(--gcli-input-background);
   background-repeat: no-repeat;
   background-position: 4px center;
-  box-shadow: 0 1px 1px hsla(206,37%,4%,.2) inset,
-              1px 0 0 hsla(206,37%,4%,.2) inset,
-              -1px 0 0 hsla(206,37%,4%,.2) inset;
+  box-shadow: 1px 0 0 var(--gcli-border-color) inset,
+              -1px 0 0 var(--gcli-border-color) inset;
+
   line-height: 32px;
   outline-style: none;
   padding: 0;
 }
 
 .gclitoolbar-input-node[focused="true"] {
-  background-color: #232e38;
+  background-color: var(--gcli-input-focused-background);
 }
 
 .gclitoolbar-input-node::before {
   content: "";
   display: inline-block;
   -moz-box-ordinal-group: 0;
   width: 16px;
   height: 16px;
@@ -173,18 +201,18 @@ html|*#gcli-output-frame {
 
 @media (min-resolution: 2dppx) {
   .gclitoolbar-input-node::before {
     background-image: url("chrome://browser/skin/devtools/commandline-icon@2x.png");
   }
 }
 
 .gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {
-  background-color: hsl(210,30%,85%);
-  color: hsl(210,24%,16%);
+  background-color: var(--selection-background);
+  color: var(--selection-color);
   text-shadow: none;
 }
 
 .gclitoolbar-complete-node {
   padding-left: 21px;
   background-color: transparent;
   color: transparent;
   z-index: 100;
--- a/browser/themes/shared/devtools/dark-theme.css
+++ b/browser/themes/shared/devtools/dark-theme.css
@@ -1,18 +1,18 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
 /* Colors are taken from:
- * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
+ * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors.
+ * Changes should be kept in sync with commandline.css and commandline.inc.css.
  */
 :root {
-
   --theme-body-background: #14171a;
   --theme-sidebar-background: #181d20;
   --theme-contrast-background: #b28025;
 
   --theme-tab-toolbar-background: #252c33;
   --theme-toolbar-background: #343c45;
   --theme-selection-background: #1d4f73;
   --theme-selection-background-semitransparent: rgba(29, 79, 115, .5);
--- a/browser/themes/shared/devtools/light-theme.css
+++ b/browser/themes/shared/devtools/light-theme.css
@@ -1,15 +1,16 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
 /* Colors are taken from:
- * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
+ * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors.
+ * Changes should be kept in sync with commandline.css and commandline.inc.css.
  */
 :root {
   --theme-body-background: #fcfcfc;
   --theme-sidebar-background: #f7f7f7;
   --theme-contrast-background: #e6b064;
 
   --theme-tab-toolbar-background: #ebeced;
   --theme-toolbar-background: #f0f1f2;