Bug 930094 - [Australis] Browser windows sometimes have the nav-bar drawn in the titlebar. r=dao, Gijs.
authorMike Conley <mconley@mozilla.com>
Tue, 04 Feb 2014 16:17:00 -0500
changeset 166819 8a56937c985b8525ca5e32c5a08318cf12ad5f6d
parent 166818 a77d5593a3fc7744a82928d0394ab78187b2aa93
child 166820 f1156ec42c25e1a4b1fd684f7ee5c5d2eeaca39e
child 166954 579cf46bc21ebb2232813c8be9f572d40f018e52
push id4840
push usermconley@mozilla.com
push dateWed, 05 Feb 2014 00:19:25 +0000
treeherderfx-team@8a56937c985b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, Gijs
bugs930094
milestone30.0a1
Bug 930094 - [Australis] Browser windows sometimes have the nav-bar drawn in the titlebar. r=dao, Gijs. * * * Fix for 930094 * * * Fix because WTF
browser/base/content/browser.css
browser/base/content/browser.js
browser/base/content/test/general/browser.ini
browser/themes/osx/browser.css
toolkit/modules/LightweightThemeConsumer.jsm
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -168,16 +168,17 @@ toolbar[overflowable] > .customization-t
 }
 
 toolbar:not([overflowing]) > .overflow-button,
 toolbar[customizing] > .overflow-button {
   display: none;
 }
 
 %ifdef CAN_DRAW_IN_TITLEBAR
+#main-window:not([chromemargin]) > #titlebar,
 #main-window[inFullscreen] > #titlebar,
 #main-window[inFullscreen] .titlebar-placeholder,
 #main-window:not([tabsintitlebar]) .titlebar-placeholder {
   display: none;
 }
 
 #titlebar {
   -moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4476,54 +4476,45 @@ var TabsInTitlebar = {
       // We set the tabsintitlebar attribute first so that our CSS for
       // tabsintitlebar manifests before we do our measurements.
       document.documentElement.setAttribute("tabsintitlebar", "true");
       updateTitlebarDisplay();
 
       // Try to avoid reflows in this code by calculating dimensions first and
       // then later set the properties affecting layout together in a batch.
 
+      // Get the full height of the tabs toolbar:
+      let tabsToolbar = $("TabsToolbar");
+      let fullTabsHeight = rect(tabsToolbar).height;
       // Buttons first:
       let captionButtonsBoxWidth = rect($("titlebar-buttonbox")).width;
 #ifdef XP_MACOSX
       let fullscreenButtonWidth = rect($("titlebar-fullscreen-button")).width;
       // No need to look up the menubar stuff on OS X:
       let menuHeight = 0;
       let fullMenuHeight = 0;
       // Instead, look up the titlebar padding:
       let titlebarPadding = parseInt(window.getComputedStyle(titlebar).paddingTop, 10);
 #else
       // Otherwise, get the height and margins separately for the menubar
       let menuHeight = rect(menubar).height;
       let menuStyles = window.getComputedStyle(menubar);
       let fullMenuHeight = verticalMargins(menuStyles) + menuHeight;
+      let tabsStyles = window.getComputedStyle(tabsToolbar);
+      fullTabsHeight += verticalMargins(tabsStyles);
 #endif
-      // Get the full height of the tabs toolbar:
-      let tabsToolbar = $("TabsToolbar");
-      let tabsStyles = window.getComputedStyle(tabsToolbar);
-      let fullTabsHeight = rect(tabsToolbar).height + verticalMargins(tabsStyles);
 
       // If the navbar overlaps the tabbar using negative margins, we need to take those into
       // account so we don't overlap it
       let navbarMarginTop = parseFloat(window.getComputedStyle($("nav-bar")).marginTop);
       navbarMarginTop = Math.min(navbarMarginTop, 0);
 
       // And get the height of what's in the titlebar:
       let titlebarContentHeight = rect(titlebarContent).height;
 
-      // Padding surrounds the tab-view-deck when we are in customization mode,
-      // so take that into account:
-      let areCustomizing = document.documentElement.hasAttribute("customizing") ||
-                           document.documentElement.hasAttribute("customize-exiting");
-      let customizePadding = 0;
-      if (areCustomizing) {
-        let deckStyle = window.getComputedStyle($("tab-view-deck"));
-        customizePadding = parseFloat(deckStyle.paddingTop);
-      }
-
       // Begin setting CSS properties which will cause a reflow
 
       // If the menubar is around (menuHeight is non-zero), try to adjust
       // its full height (i.e. including margins) to match the titlebar,
       // by changing the menubar's bottom padding
       if (menuHeight) {
         // Calculate the difference between the titlebar's height and that of the menubar
         let menuTitlebarDelta = titlebarContentHeight - fullMenuHeight;
@@ -4546,37 +4537,27 @@ var TabsInTitlebar = {
           // We've changed the menu height now:
           fullMenuHeight += desiredPadding - existingPadding;
         }
       }
 
       // Next, we calculate how much we need to stretch the titlebar down to
       // go all the way to the bottom of the tab strip, if necessary.
       let tabAndMenuHeight = fullTabsHeight + fullMenuHeight;
-      // Oh, and don't forget customization mode:
-      if (areCustomizing) {
-        tabAndMenuHeight += customizePadding;
-      }
 
       if (tabAndMenuHeight > titlebarContentHeight) {
         // We need to increase the titlebar content's outer height (ie including margins)
         // to match the tab and menu height:
         let extraMargin = tabAndMenuHeight - titlebarContentHeight;
         // We need to reduce the height by the amount of navbar overlap
         // (this value is 0 or negative):
         extraMargin += navbarMarginTop;
         // On non-OSX, we can just use bottom margin:
 #ifndef XP_MACOSX
         titlebarContent.style.marginBottom = extraMargin + "px";
-#else
-        // Otherwise, center the content. This means taking the titlebar's
-        // padding into account:
-        let halfMargin = (extraMargin - titlebarPadding) / 2;
-        titlebarContent.style.marginTop =  halfMargin + "px";
-        titlebarContent.style.marginBottom =  (titlebarPadding + halfMargin) + "px";
 #endif
         titlebarContentHeight += extraMargin;
       }
 
       // Then we bring up the titlebar by the same amount, but we add any negative margin:
       titlebar.style.marginBottom = "-" + titlebarContentHeight + "px";
 
 
@@ -4601,16 +4582,17 @@ var TabsInTitlebar = {
         this._draghandles.navToolbox = new tmp.WindowDraggingElement(gNavToolbox);
         this._draghandles.navToolbox.mouseDownCheck = mouseDownCheck;
       }
     } else {
       document.documentElement.removeAttribute("tabsintitlebar");
       updateTitlebarDisplay();
 
       // Reset the margins and padding that might have been modified:
+      titlebarContent.style.marginTop = "";
       titlebarContent.style.marginBottom = "";
       titlebar.style.marginBottom = "";
       menubar.style.paddingBottom = "";
     }
   },
 
   _sizePlaceholder: function (type, width) {
     Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
@@ -4625,26 +4607,47 @@ var TabsInTitlebar = {
     this._menuObserver.disconnect();
     CustomizableUI.removeListener(this);
 #endif
   }
 };
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 function updateTitlebarDisplay() {
-  document.getElementById("titlebar").hidden = !TabsInTitlebar.enabled;
+
+#ifdef XP_MACOSX
+  // OS X and the other platforms differ enough to necessitate this kind of
+  // special-casing. Like the other platforms where we CAN_DRAW_IN_TITLEBAR,
+  // we draw in the OS X titlebar when putting the tabs up there. However, OS X
+  // also draws in the titlebar when a lightweight theme is applied, regardless
+  // of whether or not the tabs are drawn in the titlebar.
+  if (TabsInTitlebar.enabled) {
+    document.documentElement.setAttribute("chromemargin-nonlwtheme", "0,-1,-1,-1");
+    document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
+    document.documentElement.removeAttribute("drawtitle");
+  } else {
+    // We set chromemargin-nonlwtheme to "" instead of removing it as a way of
+    // making sure that LightweightThemeConsumer doesn't take it upon itself to
+    // detect this value again if and when we do a lwtheme state change.
+    document.documentElement.setAttribute("chromemargin-nonlwtheme", "");
+    let isCustomizing = document.documentElement.hasAttribute("customizing");
+    let hasLWTheme = document.documentElement.hasAttribute("lwtheme");
+    if (!hasLWTheme || isCustomizing) {
+      document.documentElement.removeAttribute("chromemargin");
+    }
+    document.documentElement.setAttribute("drawtitle", "true");
+  }
+
+#else
 
   if (TabsInTitlebar.enabled)
-#ifdef XP_WIN
     document.documentElement.setAttribute("chromemargin", "0,2,2,2");
-#else
-    document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
-#endif
   else
     document.documentElement.removeAttribute("chromemargin");
+#endif
 }
 #endif
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 function onTitlebarMaxClick() {
   if (window.windowState == window.STATE_MAXIMIZED)
     window.restore();
   else
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -308,17 +308,18 @@ skip-if = true  # disabled until the tre
 [browser_scope.js]
 [browser_selectTabAtIndex.js]
 [browser_tabDrop.js]
 [browser_tabMatchesInAwesomebar_perwindowpb.js]
 [browser_tab_drag_drop_perwindow.js]
 [browser_tab_dragdrop.js]
 [browser_tab_dragdrop2.js]
 [browser_tabbar_big_widgets.js]
-skip-if = os == "linux" # No tabs in titlebar on linux
+skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
+                                       # Disabled on OS X because of bug 967917
 [browser_tabfocus.js]
 [browser_tabopen_reflows.js]
 [browser_tabs_isActive.js]
 [browser_tabs_owner.js]
 [browser_typeAheadFind.js]
 [browser_unloaddialogs.js]
 [browser_urlHighlight.js]
 [browser_urlbarAutoFillTrimURLs.js]
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -54,17 +54,17 @@
 
 @media (-moz-mac-lion-theme) {
   .titlebar-placeholder[type="fullscreen-button"],
   #titlebar-fullscreen-button {
     margin-right: 7px;
   }
 }
 
-#main-window[chromehidden~="toolbar"] > #titlebar {
+#main-window[chromehidden~="toolbar"]:not(:-moz-lwtheme) > #titlebar {
   padding-top: 22px;
 }
 
 #main-window:not(:-moz-lwtheme):not([privatebrowsingmode=temporary]) > #titlebar {
   -moz-appearance: -moz-window-titlebar;
 }
 
 #main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
@@ -2653,17 +2653,17 @@ toolbarbutton.chevron > .toolbarbutton-m
   border: solid transparent;
   border-width: 0 11px;
 }
 
 .tabbrowser-tab:focus > .tab-stack > .tab-content > .tab-label {
   box-shadow: @focusRingShadow@;
 }
 
-#titlebar {
+#main-window:not(:-moz-lwtheme) > #titlebar {
   padding-top: @spaceAboveTabbar@;
   min-height: @tabHeight@;
 }
 
 #main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing])) #navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before,
 #main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing],[tabsintitlebar])) #navigator-toolbox:not(:-moz-lwtheme)::before {
   /* We want the titlebar to be unified, but we still want to be able
    * to give #TabsToolbar a background. So we can't set -moz-appearance:
@@ -4088,23 +4088,36 @@ window > chatbox {
   border-bottom-left-radius: @toolbarbuttonCornerRadius@;
   border-bottom-right-radius: @toolbarbuttonCornerRadius@;
 }
 
 /* Customization mode */
 
 %include ../shared/customizableui/customizeMode.inc.css
 
-#main-window[customize-entered] #titlebar {
+#main-window[customize-entered] > #titlebar {
   padding-top: 0;
 }
 
-#main-window[tabsintitlebar][customize-entered] #titlebar-content {
-  margin-bottom: 0px !important;
-  margin-top: 11px !important;
+#main-window[tabsintitlebar]:not([customizing]):not(:-moz-lwtheme) > #titlebar > #titlebar-content,
+#main-window[tabsintitlebar][customize-entering] > #titlebar > #titlebar-content,
+#main-window[tabsintitlebar][customize-exiting] > #titlebar > #titlebar-content {
+  margin-top: 2px;
+  margin-bottom: 11px;
+}
+
+#main-window[tabsintitlebar][customize-entered] > #titlebar > #titlebar-content,
+#main-window:not([tabsintitlebar]):not(:-moz-lwtheme) > #titlebar > #titlebar-content {
+  margin-top: 11px;
+  margin-bottom: 0px;
+}
+
+#main-window[tabsintitlebar]:-moz-lwtheme > #titlebar > #titlebar-content {
+  margin-top: 11px;
+  margin-bottom: 11px;
 }
 
 #main-window[customize-entered] #tab-view-deck {
   background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
                     url("chrome://browser/skin/customizableui/background-noise-toolbar.png"),
                     linear-gradient(to bottom, rgb(233,233,233), rgb(178,178,178) 21px);
   background-attachment: fixed;
 }
@@ -4119,18 +4132,21 @@ window > chatbox {
   -moz-border-bottom-colors: hsla(0,0%,0%,.05) hsla(0,0%,0%,.1) hsla(0,0%,0%,.2);
   -moz-border-left-colors: hsla(0,0%,0%,.05) hsla(0,0%,0%,.1) hsla(0,0%,0%,.2);
 }
 
 #main-window[customize-entered] #navigator-toolbox > toolbar:not(#TabsToolbar) {
   border-bottom-width: 0;
 }
 
+#main-window[tabsintitlebar][customize-entered] #TabsToolbar {
+  margin-top: 9px;
+}
+
 #main-window[customize-entered] #TabsToolbar {
-  margin-top: 9px;
   background-clip: padding-box;
   border-right: 3px solid transparent;
   border-left: 3px solid transparent;
 }
 
 @media (min-resolution: 2dppx) {
   #customization-titlebar-visibility-button {
     list-style-image: url("chrome://browser/skin/customizableui/customize-titleBar-toggle@2x.png");
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -37,19 +37,17 @@ this.LightweightThemeConsumer =
   this._win.addEventListener("resize", this);
 }
 
 LightweightThemeConsumer.prototype = {
   _lastData: null,
   _lastScreenWidth: null,
   _lastScreenHeight: null,
   _enabled: true,
-#ifdef XP_MACOSX
-  _chromemarginDefault: undefined,
-#endif
+  _active: false,
 
   enable: function() {
     this._enabled = true;
     this._update(this._lastData);
   },
 
   disable: function() {
     // Dance to keep the data, but reset the applied styles:
@@ -95,59 +93,68 @@ LightweightThemeConsumer.prototype = {
       this._lastData = aData;
     } else {
       this._lastData = aData;
       aData = LightweightThemeImageOptimizer.optimize(aData, this._win.screen);
     }
     if (!this._enabled)
       return;
 
-    var root = this._doc.documentElement;
-    var active = !!aData.headerURL;
+    let root = this._doc.documentElement;
+    let active = !!aData.headerURL;
+    let stateChanging = (active != this._active);
 
     if (active) {
       root.style.color = aData.textcolor || "black";
       root.style.backgroundColor = aData.accentcolor || "white";
       let [r, g, b] = _parseRGB(this._doc.defaultView.getComputedStyle(root, "").color);
       let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
       root.setAttribute("lwthemetextcolor", luminance <= 110 ? "dark" : "bright");
       root.setAttribute("lwtheme", "true");
     } else {
       root.style.color = "";
       root.style.backgroundColor = "";
       root.removeAttribute("lwthemetextcolor");
       root.removeAttribute("lwtheme");
     }
 
+    this._active = active;
+
     _setImage(root, active, aData.headerURL);
     if (this._footerId) {
       let footer = this._doc.getElementById(this._footerId);
       footer.style.backgroundColor = active ? aData.accentcolor || "white" : "";
       _setImage(footer, active, aData.footerURL);
       if (active && aData.footerURL)
         footer.setAttribute("lwthemefooter", "true");
       else
         footer.removeAttribute("lwthemefooter");
     }
 
 #ifdef XP_MACOSX
-    // Sample whether or not we draw in the titlebar by default the first time we update.
-    // If the root has no chromemargin attribute, getAttribute will return null, and
-    // we'll remove the attribute when the lw-theme is deactivated.
-    if (this._chromemarginDefault === undefined)
-      this._chromemarginDefault = root.getAttribute("chromemargin");
+    // On OS X, we extend the lightweight theme into the titlebar, which means setting
+    // the chromemargin attribute. Some XUL applications already draw in the titlebar,
+    // so we need to save the chromemargin value before we overwrite it with the value
+    // that lets us draw in the titlebar. We stash this value on the root attribute so
+    // that XUL applications have the ability to invalidate the saved value.
+    if (stateChanging) {
+      if (!root.hasAttribute("chromemargin-nonlwtheme")) {
+        root.setAttribute("chromemargin-nonlwtheme", root.getAttribute("chromemargin"));
+      }
 
-    if (active) {
-      root.setAttribute("chromemargin", "0,-1,-1,-1");
-    }
-    else {
-      if (this._chromemarginDefault)
-        root.setAttribute("chromemargin", this._chromemarginDefault);
-      else
-        root.removeAttribute("chromemargin");
+      if (active) {
+        root.setAttribute("chromemargin", "0,-1,-1,-1");
+      } else {
+        let defaultChromemargin = root.getAttribute("chromemargin-nonlwtheme");
+        if (defaultChromemargin) {
+          root.setAttribute("chromemargin", defaultChromemargin);
+        } else {
+          root.removeAttribute("chromemargin");
+        }
+      }
     }
 #endif
   }
 }
 
 function _setImage(aElement, aActive, aURL) {
   aElement.style.backgroundImage =
     (aActive && aURL) ? 'url("' + aURL.replace(/"/g, '\\"') + '")' : "";