diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 8419aec5de4..163a5eff4ae 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -412,10 +412,10 @@ pref("browser.tabs.loadBookmarksInBackground", false);
pref("browser.tabs.tabClipWidth", 140);
pref("browser.tabs.animate", true);
pref("browser.tabs.onTop", true);
-#ifdef XP_WIN
-pref("browser.tabs.drawInTitlebar", true);
-#else
+#ifdef UNIX_BUT_NOT_MAC
pref("browser.tabs.drawInTitlebar", false);
+#else
+pref("browser.tabs.drawInTitlebar", true);
#endif
// Where to show tab close buttons:
diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js
index b638f31f9ea..c63fea50b88 100644
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -415,3 +415,58 @@ var LightWeightThemeWebInstaller = {
node.baseURI);
}
}
+
+/*
+ * Listen for Lightweight Theme styling changes and update the browser's theme accordingly.
+ */
+let LightweightThemeListener = {
+ _modifiedStyles: [],
+
+ init: function () {
+ XPCOMUtils.defineLazyGetter(this, "styleSheet", function() {
+ for (let i = document.styleSheets.length - 1; i >= 0; i--) {
+ let sheet = document.styleSheets[i];
+ if (sheet.href == "chrome://browser/skin/browser-lightweightTheme.css")
+ return sheet;
+ }
+ });
+
+ Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
+ if (document.documentElement.hasAttribute("lwtheme"))
+ this.updateStyleSheet(document.documentElement.style.backgroundImage);
+ },
+
+ uninit: function () {
+ Services.obs.removeObserver(this, "lightweight-theme-styling-update");
+ },
+
+ /**
+ * Append the headerImage to the background-image property of all rulesets in
+ * browser-lightweightTheme.css.
+ *
+ * @param headerImage - a string containing a CSS image for the lightweight theme header.
+ */
+ updateStyleSheet: function(headerImage) {
+ if (!this.styleSheet)
+ return;
+ for (let i = 0; i < this.styleSheet.cssRules.length; i++) {
+ let rule = this.styleSheet.cssRules[i];
+ if (!rule.style.backgroundImage)
+ continue;
+
+ if (!this._modifiedStyles[i])
+ this._modifiedStyles[i] = { backgroundImage: rule.style.backgroundImage };
+
+ rule.style.backgroundImage = this._modifiedStyles[i].backgroundImage + ", " + headerImage;
+ }
+ },
+
+ // nsIObserver
+ observe: function (aSubject, aTopic, aData) {
+ if (aTopic != "lightweight-theme-styling-update" || !this.styleSheet)
+ return;
+
+ let themeData = JSON.parse(aData);
+ this.updateStyleSheet("url(" + themeData.headerURL + ")");
+ },
+};
diff --git a/browser/base/content/browser-appmenu.inc b/browser/base/content/browser-appmenu.inc
deleted file mode 100644
index f6cd13d40eb..00000000000
--- a/browser/base/content/browser-appmenu.inc
+++ /dev/null
@@ -1,400 +0,0 @@
-# -*- Mode: HTML -*-
-# 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/.
-
-
diff --git a/browser/base/content/browser-customization.js b/browser/base/content/browser-customization.js
new file mode 100644
index 00000000000..ac8f3ca3db2
--- /dev/null
+++ b/browser/base/content/browser-customization.js
@@ -0,0 +1,102 @@
+# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+# 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/.
+
+/**
+ * Customization handler prepares this browser window for entering and exiting
+ * customization mode by handling CustomizationStart and CustomizationEnd
+ * events.
+ */
+let CustomizationHandler = {
+ handleEvent: function(aEvent) {
+ switch(aEvent.type) {
+ case "CustomizationStart":
+ this._customizationStart();
+ break;
+ case "CustomizationEnd":
+ this._customizationEnd(aEvent.detail);
+ break;
+ }
+ },
+
+ _customizationStart: function() {
+ // Disable the toolbar context menu items
+ let menubar = document.getElementById("main-menubar");
+ for (let childNode of menubar.childNodes)
+ childNode.setAttribute("disabled", true);
+
+ let cmd = document.getElementById("cmd_CustomizeToolbars");
+ cmd.setAttribute("disabled", "true");
+
+ let splitter = document.getElementById("urlbar-search-splitter");
+ if (splitter) {
+ splitter.parentNode.removeChild(splitter);
+ }
+
+ CombinedStopReload.uninit();
+ PlacesToolbarHelper.customizeStart();
+ BookmarksMenuButton.customizeStart();
+ DownloadsButton.customizeStart();
+ TabsInTitlebar.allowedBy("customizing-toolbars", false);
+ },
+
+ _customizationEnd: function(aDetails) {
+ // Update global UI elements that may have been added or removed
+ if (aDetails.changed) {
+ gURLBar = document.getElementById("urlbar");
+
+ gProxyFavIcon = document.getElementById("page-proxy-favicon");
+ gHomeButton.updateTooltip();
+ gIdentityHandler._cacheElements();
+ XULBrowserWindow.init();
+
+#ifndef XP_MACOSX
+ updateEditUIVisibility();
+#endif
+
+ // Hacky: update the PopupNotifications' object's reference to the iconBox,
+ // if it already exists, since it may have changed if the URL bar was
+ // added/removed.
+ if (!window.__lookupGetter__("PopupNotifications")) {
+ PopupNotifications.iconBox =
+ document.getElementById("notification-popup-box");
+ }
+
+ }
+
+ PlacesToolbarHelper.customizeDone();
+ BookmarksMenuButton.customizeDone();
+ DownloadsButton.customizeDone();
+
+ // The url bar splitter state is dependent on whether stop/reload
+ // and the location bar are combined, so we need this ordering
+ CombinedStopReload.init();
+ UpdateUrlbarSearchSplitterState();
+ setUrlAndSearchBarWidthForConditionalForwardButton();
+
+ // Update the urlbar
+ if (gURLBar) {
+ URLBarSetURI();
+ XULBrowserWindow.asyncUpdateUI();
+ BookmarksMenuButton.updateStarState();
+ SocialMark.updateMarkState();
+ }
+
+ TabsInTitlebar.allowedBy("customizing-toolbars", true);
+
+ // Re-enable parts of the UI we disabled during the dialog
+ let menubar = document.getElementById("main-menubar");
+ for (let childNode of menubar.childNodes)
+ childNode.setAttribute("disabled", false);
+ let cmd = document.getElementById("cmd_CustomizeToolbars");
+ cmd.removeAttribute("disabled");
+
+ // make sure to re-enable click-and-hold
+ if (!getBoolPref("ui.click_hold_context_menus", false)) {
+ SetClickAndHoldHandlers();
+ }
+
+ gBrowser.selectedBrowser.focus();
+ }
+}
diff --git a/browser/base/content/browser-fullScreen.js b/browser/base/content/browser-fullScreen.js
index 0fa92a55f9f..f2ff7274b29 100644
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -17,7 +17,7 @@ var FullScreen = {
enterFS = !enterFS;
// Toggle the View:FullScreen command, which controls elements like the
- // fullscreen menuitem, menubars, and the appmenu.
+ // fullscreen menuitem, and menubars.
document.getElementById("View:FullScreen").setAttribute("checked", enterFS);
#ifdef XP_MACOSX
diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index 579546d4353..c01af1690a4 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -13,6 +13,20 @@ browser[remote="true"] {
-moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
}
+toolbar[customizable="true"] {
+ -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar");
+}
+
+%ifdef XP_MACOSX
+toolbar[customizable="true"]:not([nowindowdrag="true"]) {
+ -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
+}
+%endif
+
+#toolbar-menubar[autohide="true"] {
+ -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-autohide");
+}
+
tabbrowser {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
}
@@ -39,11 +53,11 @@ tabbrowser {
.tabbrowser-tab:not([pinned]) {
-moz-box-flex: 100;
- max-width: 250px;
+ max-width: 180px;
min-width: 100px;
width: 0;
transition: min-width 200ms ease-out,
- max-width 250ms ease-out,
+ max-width 230ms ease-out,
opacity 50ms ease-out 20ms /* hide the tab for the first 20ms of the max-width transition */;
}
@@ -52,8 +66,8 @@ tabbrowser {
min-width: 0.1px;
opacity: 0 !important;
transition: min-width 200ms ease-out,
- max-width 250ms ease-out,
- opacity 50ms ease-out 180ms /* hide the tab for the last 20ms of the max-width transition */;
+ max-width 230ms ease-out,
+ opacity 50ms ease-out 160ms /* hide the tab for the last 20ms of the max-width transition */;
}
.tab-throbber:not([fadein]):not([pinned]),
@@ -117,10 +131,26 @@ toolbar[printpreview="true"] {
pointer-events: none;
}
-#main-window[tabsintitlebar] #appmenu-button-container,
#main-window[tabsintitlebar] #titlebar-buttonbox {
position: relative;
}
+
+#titlebar-buttonbox {
+ -moz-appearance: -moz-window-button-box;
+}
+
+%ifdef XP_MACOSX
+#titlebar-fullscreen-button {
+ -moz-appearance: -moz-mac-fullscreen-button;
+}
+%endif
+
+%ifdef XP_WIN
+#main-window[sizemode="maximized"] #titlebar-buttonbox {
+ -moz-appearance: -moz-window-button-box-maximized;
+}
+%endif
+
%endif
.bookmarks-toolbar-customize,
@@ -140,11 +170,10 @@ toolbar[printpreview="true"] {
#urlbar-container:not([combined]) > #urlbar > toolbarbutton,
#urlbar-container[combined] + #reload-button + #stop-button,
#urlbar-container[combined] + #reload-button,
-toolbar:not([mode="icons"]) > #urlbar-container > #urlbar > toolbarbutton,
-toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
-toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button[displaystop],
-toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button,
-toolbar[mode="icons"] > #reload-button[displaystop] {
+#urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
+#urlbar-reload-button[displaystop],
+#reload-button:not([displaystop]) + #stop-button,
+#reload-button[displaystop] {
visibility: collapse;
}
@@ -172,27 +201,6 @@ toolbar[mode="icons"] > #reload-button[displaystop] {
background-position: bottom left;
}
-splitmenu {
- -moz-binding: url("chrome://browser/content/urlbarBindings.xml#splitmenu");
-}
-
-.splitmenu-menuitem {
- -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem");
- list-style-image: inherit;
- -moz-image-region: inherit;
-}
-
-.splitmenu-menuitem[iconic="true"] {
- -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
-}
-
-.splitmenu-menu > .menu-text,
-:-moz-any(.splitmenu-menu, .splitmenu-menuitem) > .menu-accel-container,
-#appmenu-editmenu > .menu-text,
-#appmenu-editmenu > .menu-accel-container {
- display: none;
-}
-
.menuitem-tooltip {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-tooltip");
}
@@ -203,18 +211,6 @@ splitmenu {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-iconic-tooltip");
}
-%ifdef MENUBAR_CAN_AUTOHIDE
-%ifndef CAN_DRAW_IN_TITLEBAR
-#appmenu-toolbar-button > .toolbarbutton-text {
- display: -moz-box;
-}
-%endif
-
-#appmenu_offlineModeRecovery:not([checked=true]) {
- display: none;
-}
-%endif
-
/* Hide menu elements intended for keyboard access support */
#main-menubar[openedwithkey=false] .show-only-for-keyboard {
display: none;
@@ -439,14 +435,6 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
min-width: 1px;
}
-#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon {
- display: -moz-box;
-}
-
-#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
- display: none;
-}
-
/* ::::: Ctrl-Tab Panel ::::: */
.ctrlTab-preview > html|img,
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index a33971fc6cb..1a8f9a61e18 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -91,6 +91,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
"resource:///modules/AboutHomeUtils.jsm");
+XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
+ let scope = {};
+ Cu.import("resource:///modules/CustomizeMode.jsm", scope);
+ return new scope.CustomizeMode(window);
+});
+
#ifdef MOZ_SERVICES_SYNC
XPCOMUtils.defineLazyModuleGetter(this, "Weave",
"resource://services-sync/main.js");
@@ -147,6 +153,7 @@ let gInitialPages = [
];
#include browser-addons.js
+#include browser-customization.js
#include browser-feeds.js
#include browser-fullScreen.js
#include browser-fullZoom.js
@@ -936,8 +943,8 @@ var gBrowserInit = {
goSetCommandEnabled("cmd_newNavigatorTab", false);
}
-#ifdef MENUBAR_CAN_AUTOHIDE
- updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+ updateTitlebarDisplay();
#endif
// Misc. inits.
@@ -1031,7 +1038,9 @@ var gBrowserInit = {
OfflineApps.init();
IndexedDBPromptHelper.init();
gFormSubmitObserver.init();
+ PanelUI.init();
SocialUI.init();
+ LightweightThemeListener.init();
AddonManager.addAddonListener(AddonsMgrListener);
WebrtcIndicator.init();
@@ -1226,15 +1235,6 @@ var gBrowserInit = {
cmd.removeAttribute("hidden");
}
-#ifdef MENUBAR_CAN_AUTOHIDE
- // If the user (or the locale) hasn't enabled the top-level "Character
- // Encoding" menu via the "browser.menu.showCharacterEncoding" preference,
- // hide it.
- if ("true" != gPrefService.getComplexValue("browser.menu.showCharacterEncoding",
- Ci.nsIPrefLocalizedString).data)
- document.getElementById("appmenu_charsetMenu").hidden = true;
-#endif
-
// Enable Responsive UI?
let responsiveUIEnabled = gPrefService.getBoolPref("devtools.responsiveUI.enabled");
if (responsiveUIEnabled) {
@@ -1246,26 +1246,14 @@ var gBrowserInit = {
// Add Devtools menuitems and listeners
gDevToolsBrowser.registerBrowserWindow(window);
- let appMenuButton = document.getElementById("appmenu-button");
- let appMenuPopup = document.getElementById("appmenu-popup");
- if (appMenuButton && appMenuPopup) {
- let appMenuOpening = null;
- appMenuButton.addEventListener("mousedown", function(event) {
- if (event.button == 0)
- appMenuOpening = new Date();
- }, false);
- appMenuPopup.addEventListener("popupshown", function(event) {
- if (event.target != appMenuPopup || !appMenuOpening)
- return;
- let duration = new Date() - appMenuOpening;
- appMenuOpening = null;
- Services.telemetry.getHistogramById("FX_APP_MENU_OPEN_MS").add(duration);
- }, false);
- }
-
window.addEventListener("mousemove", MousePosTracker, false);
window.addEventListener("dragover", MousePosTracker, false);
+ window.addEventListener("CustomizationStart", CustomizationHandler, false);
+ window.addEventListener("CustomizationEnd", CustomizationHandler, false);
+
+ gCustomizeMode.init();
+
// End startup crash tracking after a delay to catch crashes while restoring
// tabs and to postpone saving the pref to disk.
try {
@@ -1361,6 +1349,9 @@ var gBrowserInit = {
IndexedDBPromptHelper.uninit();
AddonManager.removeAddonListener(AddonsMgrListener);
SocialUI.uninit();
+ LightweightThemeListener.uninit();
+ gCustomizeMode.uninit();
+ PanelUI.uninit();
}
// Final window teardown, do this last.
@@ -2644,8 +2635,8 @@ var PrintPreviewListener = {
if (this._chromeState.sidebarOpen)
toggleSidebar(this._sidebarCommand);
-#ifdef MENUBAR_CAN_AUTOHIDE
- updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+ updateTitlebarDisplay();
#endif
},
_hideChrome: function () {
@@ -3310,118 +3301,13 @@ function OpenBrowserWindow(options)
return win;
}
-var gCustomizeSheet = false;
+//XXXunf Are these still useful to keep around?
function BrowserCustomizeToolbar() {
- // Disable the toolbar context menu items
- var menubar = document.getElementById("main-menubar");
- for (let childNode of menubar.childNodes)
- childNode.setAttribute("disabled", true);
-
- var cmd = document.getElementById("cmd_CustomizeToolbars");
- cmd.setAttribute("disabled", "true");
-
- var splitter = document.getElementById("urlbar-search-splitter");
- if (splitter)
- splitter.parentNode.removeChild(splitter);
-
- CombinedStopReload.uninit();
-
- PlacesToolbarHelper.customizeStart();
- BookmarksMenuButton.customizeStart();
- DownloadsButton.customizeStart();
-
- TabsInTitlebar.allowedBy("customizing-toolbars", false);
-
- var customizeURL = "chrome://global/content/customizeToolbar.xul";
- gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
-
- if (gCustomizeSheet) {
- let sheetFrame = document.createElement("iframe");
- let panel = document.getElementById("customizeToolbarSheetPopup");
- sheetFrame.id = "customizeToolbarSheetIFrame";
- sheetFrame.toolbox = gNavToolbox;
- sheetFrame.panel = panel;
- sheetFrame.setAttribute("style", panel.getAttribute("sheetstyle"));
- panel.appendChild(sheetFrame);
-
- // Open the panel, but make it invisible until the iframe has loaded so
- // that the user doesn't see a white flash.
- panel.style.visibility = "hidden";
- gNavToolbox.addEventListener("beforecustomization", function onBeforeCustomization() {
- gNavToolbox.removeEventListener("beforecustomization", onBeforeCustomization, false);
- panel.style.removeProperty("visibility");
- }, false);
-
- sheetFrame.setAttribute("src", customizeURL);
-
- panel.openPopup(gNavToolbox, "after_start", 0, 0);
- } else {
- window.openDialog(customizeURL,
- "CustomizeToolbar",
- "chrome,titlebar,toolbar,location,resizable,dependent",
- gNavToolbox);
- }
+ gCustomizeMode.enter();
}
function BrowserToolboxCustomizeDone(aToolboxChanged) {
- if (gCustomizeSheet) {
- document.getElementById("customizeToolbarSheetPopup").hidePopup();
- let iframe = document.getElementById("customizeToolbarSheetIFrame");
- iframe.parentNode.removeChild(iframe);
- }
-
- // Update global UI elements that may have been added or removed
- if (aToolboxChanged) {
- gURLBar = document.getElementById("urlbar");
-
- gProxyFavIcon = document.getElementById("page-proxy-favicon");
- gHomeButton.updateTooltip();
- gIdentityHandler._cacheElements();
- window.XULBrowserWindow.init();
-
-#ifndef XP_MACOSX
- updateEditUIVisibility();
-#endif
-
- // Hacky: update the PopupNotifications' object's reference to the iconBox,
- // if it already exists, since it may have changed if the URL bar was
- // added/removed.
- if (!window.__lookupGetter__("PopupNotifications"))
- PopupNotifications.iconBox = document.getElementById("notification-popup-box");
- }
-
- PlacesToolbarHelper.customizeDone();
- BookmarksMenuButton.customizeDone();
- DownloadsButton.customizeDone();
-
- // The url bar splitter state is dependent on whether stop/reload
- // and the location bar are combined, so we need this ordering
- CombinedStopReload.init();
- UpdateUrlbarSearchSplitterState();
- setUrlAndSearchBarWidthForConditionalForwardButton();
-
- // Update the urlbar
- if (gURLBar) {
- URLBarSetURI();
- XULBrowserWindow.asyncUpdateUI();
- BookmarksMenuButton.updateStarState();
- SocialMark.updateMarkState();
- }
-
- TabsInTitlebar.allowedBy("customizing-toolbars", true);
-
- // Re-enable parts of the UI we disabled during the dialog
- var menubar = document.getElementById("main-menubar");
- for (let childNode of menubar.childNodes)
- childNode.setAttribute("disabled", false);
- var cmd = document.getElementById("cmd_CustomizeToolbars");
- cmd.removeAttribute("disabled");
-
- // make sure to re-enable click-and-hold
- if (!getBoolPref("ui.click_hold_context_menus", false))
- SetClickAndHoldHandlers();
-
- gBrowser.selectedBrowser.focus();
+ gCustomizeMode.exit(aToolboxChanged);
}
function BrowserToolboxCustomizeChange(aType) {
@@ -3485,9 +3371,6 @@ function updateEditUIVisibility()
let editMenuPopupState = document.getElementById("menu_EditPopup").state;
let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
let placesContextMenuPopupState = document.getElementById("placesContext").state;
-#ifdef MENUBAR_CAN_AUTOHIDE
- let appMenuPopupState = document.getElementById("appmenu-popup").state;
-#endif
// The UI is visible if the Edit menu is opening or open, if the context menu
// is open, or if the toolbar has been customized to include the Cut, Copy,
@@ -3498,10 +3381,6 @@ function updateEditUIVisibility()
contextMenuPopupState == "open" ||
placesContextMenuPopupState == "showing" ||
placesContextMenuPopupState == "open" ||
-#ifdef MENUBAR_CAN_AUTOHIDE
- appMenuPopupState == "showing" ||
- appMenuPopupState == "open" ||
-#endif
document.getElementById("cut-button") ||
document.getElementById("copy-button") ||
document.getElementById("paste-button") ? true : false;
@@ -3534,9 +3413,6 @@ function updateEditUIVisibility()
function updateCharacterEncodingMenuState()
{
let charsetMenu = document.getElementById("charsetMenu");
- let appCharsetMenu = document.getElementById("appmenu_charsetMenu");
- let appDevCharsetMenu =
- document.getElementById("appmenu_developer_charsetMenu");
// gBrowser is null on Mac when the menubar shows in the context of
// non-browser windows. The above elements may be null depending on
// what parts of the menubar are present. E.g. no app menu on Mac.
@@ -3546,22 +3422,10 @@ function updateCharacterEncodingMenuState()
if (charsetMenu) {
charsetMenu.removeAttribute("disabled");
}
- if (appCharsetMenu) {
- appCharsetMenu.removeAttribute("disabled");
- }
- if (appDevCharsetMenu) {
- appDevCharsetMenu.removeAttribute("disabled");
- }
} else {
if (charsetMenu) {
charsetMenu.setAttribute("disabled", "true");
}
- if (appCharsetMenu) {
- appCharsetMenu.setAttribute("disabled", "true");
- }
- if (appDevCharsetMenu) {
- appDevCharsetMenu.setAttribute("disabled", "true");
- }
}
}
@@ -3592,6 +3456,9 @@ var XULBrowserWindow = {
startTime: 0,
statusText: "",
isBusy: false,
+ // The pages in this array should be kept in sync with what pages that
+ // panelUIOverlay.xul is set to overlay in
+ // browser/components/customizableui/content/jar.mn
inContentWhitelist: ["about:addons", "about:downloads", "about:permissions",
"about:sync-progress", "about:preferences"],
@@ -4143,8 +4010,7 @@ var CombinedStopReload = {
var stop = document.getElementById("stop-button");
if (urlbar) {
- if (urlbar.parentNode.getAttribute("mode") != "icons" ||
- !reload || urlbar.nextSibling != reload ||
+ if (!reload || urlbar.nextSibling != reload ||
!stop || reload.nextSibling != stop)
urlbar.removeAttribute("combined");
else {
@@ -4469,8 +4335,6 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
menuItem.setAttribute("type", "checkbox");
menuItem.setAttribute("label", toolbarName);
menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute) != "true");
- if (popup.id != "appmenu_customizeMenu")
- menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
if (popup.id != "toolbar-context-menu")
menuItem.setAttribute("key", toolbar.getAttribute("key"));
@@ -4499,8 +4363,8 @@ function setToolbarVisibility(toolbar, isVisible) {
BookmarksMenuButton.onToolbarVisibilityChange();
gBrowser.updateWindowResizers();
-#ifdef MENUBAR_CAN_AUTOHIDE
- updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+ updateTitlebarDisplay();
#endif
}
@@ -4561,10 +4425,19 @@ var TabsInTitlebar = {
this._readPref();
Services.prefs.addObserver(this._prefName, this, false);
- // Don't trust the initial value of the sizemode attribute; wait for
- // the resize event (handled in tabbrowser.xml).
- this.allowedBy("sizemode", false);
-
+ // We need to update the appearance of the titlebar when the menu changes
+ // from the active to the inactive state. We can't, however, rely on
+ // DOMMenuBarInactive, because the menu fires this event and then removes
+ // the inactive attribute after an event-loop spin.
+ //
+ // Because updating the appearance involves sampling the heights and margins
+ // of various elements, it's important that the layout be more or less
+ // settled before updating the titlebar. So instead of listening to
+ // DOMMenuBarActive and DOMMenuBarInactive, we use a MutationObserver to
+ // watch the "invalid" attribute directly.
+ let menu = document.getElementById("toolbar-menubar");
+ this._menuObserver = new MutationObserver(this._onMenuMutate);
+ this._menuObserver.observe(menu, {attributes: true});
this._initialized = true;
#endif
},
@@ -4574,17 +4447,23 @@ var TabsInTitlebar = {
if (allow) {
if (condition in this._disallowed) {
delete this._disallowed[condition];
- this._update();
+ this._update(true);
}
} else {
if (!(condition in this._disallowed)) {
this._disallowed[condition] = null;
- this._update();
+ this._update(true);
}
}
#endif
},
+ updateAppearance: function updateAppearance(aForce) {
+#ifdef CAN_DRAW_IN_TITLEBAR
+ this._update(aForce);
+#endif
+ },
+
get enabled() {
return document.documentElement.getAttribute("tabsintitlebar") == "true";
},
@@ -4595,62 +4474,132 @@ var TabsInTitlebar = {
this._readPref();
},
+ _onMenuMutate: function (aMutations) {
+ // We don't care about restored windows, since the menu shouldn't be
+ // pushing the tab-strip down.
+ if (document.documentElement.getAttribute("sizemode") == "normal") {
+ return;
+ }
+
+ for (let mutation of aMutations) {
+ if (mutation.attributeName == "inactive" ||
+ mutation.attributeName == "autohide") {
+ TabsInTitlebar._update(true);
+ return;
+ }
+ }
+ },
+
_initialized: false,
_disallowed: {},
_prefName: "browser.tabs.drawInTitlebar",
+ _lastSizeMode: null,
_readPref: function () {
this.allowedBy("pref",
Services.prefs.getBoolPref(this._prefName));
},
- _update: function () {
+ _update: function (aForce=false) {
if (!this._initialized || window.fullScreen)
return;
let allowed = true;
+
+ if (!aForce) {
+ // _update is called on resize events, because the window is not ready
+ // after sizemode events. However, we only care about the event when the
+ // sizemode is different from the last time we updated the appearance of
+ // the tabs in the titlebar.
+ let sizemode = document.documentElement.getAttribute("sizemode");
+ if (this._lastSizeMode == sizemode) {
+ return;
+ }
+ this._lastSizeMode = sizemode;
+ }
+
for (let something in this._disallowed) {
allowed = false;
break;
}
- if (allowed == this.enabled)
- return;
-
function $(id) document.getElementById(id);
+
let titlebar = $("titlebar");
+ let titlebarContent = $("titlebar-content");
+ let menubar = $("toolbar-menubar");
+
+ // Reset the margins and padding that _update modifies so that we can take
+ // accurate measurements.
+ titlebarContent.style.marginBottom = "";
+ titlebar.style.marginBottom = "";
+ menubar.style.paddingBottom = "";
if (allowed) {
- function rect(ele) ele.getBoundingClientRect();
-
- let tabsToolbar = $("TabsToolbar");
-
-#ifdef MENUBAR_CAN_AUTOHIDE
- let appmenuButtonBox = $("appmenu-button-container");
- this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
-#endif
- let captionButtonsBox = $("titlebar-buttonbox");
- this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
-
- let tabsToolbarRect = rect(tabsToolbar);
- let titlebarTop = rect($("titlebar-content")).top;
- titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop,
- tabsToolbarRect.height) + "px";
-
+ // We set the tabsintitlebar attribute first so that our CSS for
+ // tabsintitlebar manifests before we do our measurements.
document.documentElement.setAttribute("tabsintitlebar", "true");
- if (!this._draghandle) {
+ function rect(ele) ele.getBoundingClientRect();
+
+ let captionButtonsBox = $("titlebar-buttonbox");
+ this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
+#ifdef XP_MACOSX
+ let fullscreenButton = $("titlebar-fullscreen-button");
+ this._sizePlaceholder("fullscreen-button", rect(fullscreenButton).width);
+#endif
+ let titlebarContentHeight = rect(titlebarContent).height;
+ let menuHeight = this._outerHeight(menubar);
+
+ // If the titlebar is taller than the menubar, add more padding to the
+ // bottom of the menubar so that it matches.
+ if (menuHeight && titlebarContentHeight > menuHeight) {
+ let menuTitlebarDelta = titlebarContentHeight - menuHeight;
+ menubar.style.paddingBottom = menuTitlebarDelta + "px";
+ menuHeight += menuTitlebarDelta;
+ }
+
+ // Next, we calculate how much we need to stretch the titlebar down to
+ // go all the way to the bottom of the tab strip.
+ let tabsToolbar = $("TabsToolbar");
+ let tabAndMenuHeight = this._outerHeight(tabsToolbar) + menuHeight;
+ titlebarContent.style.marginBottom = tabAndMenuHeight + "px";
+
+ // Finally, we have to determine how much to bring up the elements below
+ // the titlebar. We start with a baseHeight of tabAndMenuHeight, to offset
+ // the amount we added to the titlebar content. Then, we have two cases:
+ //
+ // 1) The titlebar is larger than the tabAndMenuHeight. This can happen in
+ // large font mode with the menu autohidden. In this case, we want to
+ // add tabAndMenuHeight, since this should line up the bottom of the
+ // tabstrip with the bottom of the titlebar.
+ //
+ // 2) The titlebar is equal to or smaller than the tabAndMenuHeight. This
+ // is the more common case, and occurs with normal font sizes. In this
+ // case, we want to bring the menu and tabstrip right up to the top of
+ // the titlebar, so we add the titlebarContentHeight to the baseHeight.
+ let baseHeight = tabAndMenuHeight;
+ baseHeight += (titlebarContentHeight > tabAndMenuHeight) ? tabAndMenuHeight
+ : titlebarContentHeight;
+ titlebar.style.marginBottom = "-" + baseHeight + "px";
+
+ if (!this._draghandles) {
+ this._draghandles = {};
let tmp = {};
Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
- this._draghandle = new tmp.WindowDraggingElement(tabsToolbar);
- this._draghandle.mouseDownCheck = function () {
+
+ let mouseDownCheck = function () {
return !this._dragBindingAlive && TabsInTitlebar.enabled;
};
+
+ this._draghandles.tabsToolbar = new tmp.WindowDraggingElement(tabsToolbar);
+ this._draghandles.tabsToolbar.mouseDownCheck = mouseDownCheck;
+
+ this._draghandles.navToolbox = new tmp.WindowDraggingElement(gNavToolbox);
+ this._draghandles.navToolbox.mouseDownCheck = mouseDownCheck;
}
} else {
document.documentElement.removeAttribute("tabsintitlebar");
-
- titlebar.style.marginBottom = "";
}
},
@@ -4658,36 +4607,44 @@ var TabsInTitlebar = {
Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
function (node) { node.width = width; });
},
+
+ /**
+ * Retrieve the height of an element, including its top and bottom
+ * margins.
+ *
+ * @param ele
+ * The element to measure.
+ * @return
+ * The height and margins as an integer. If the height of the element
+ * is 0, then this returns 0, regardless of what the margins are.
+ */
+ _outerHeight: function (ele) {
+ let cstyle = document.defaultView.getComputedStyle(ele);
+ let margins = parseInt(cstyle.marginTop) + parseInt(cstyle.marginBottom);
+ let height = ele.getBoundingClientRect().height;
+ return height > 0 ? Math.abs(height + margins) : 0;
+ },
#endif
uninit: function () {
#ifdef CAN_DRAW_IN_TITLEBAR
this._initialized = false;
Services.prefs.removeObserver(this._prefName, this);
+ this._menuObserver.disconnect();
#endif
}
};
-#ifdef MENUBAR_CAN_AUTOHIDE
-function updateAppButtonDisplay() {
- var displayAppButton =
- !gInPrintPreviewMode &&
- window.menubar.visible &&
- document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
-
#ifdef CAN_DRAW_IN_TITLEBAR
- document.getElementById("titlebar").hidden = !displayAppButton;
+function updateTitlebarDisplay() {
+ document.getElementById("titlebar").hidden = gInPrintPreviewMode;
- if (displayAppButton)
+ if (!gInPrintPreviewMode)
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
else
document.documentElement.removeAttribute("chromemargin");
- TabsInTitlebar.allowedBy("drawing-in-titlebar", displayAppButton);
-#else
- document.getElementById("appmenu-toolbar-button").hidden =
- !displayAppButton;
-#endif
+ TabsInTitlebar.allowedBy("drawing-in-titlebar", !gInPrintPreviewMode);
}
#endif
@@ -6724,12 +6681,6 @@ let gPrivateBrowsingUI = {
document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
if (window.location.href == getBrowserURL()) {
-#ifdef XP_MACOSX
- if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
- document.documentElement.setAttribute("drawintitlebar", true);
- }
-#endif
-
// Adjust the window's title
let docElement = document.documentElement;
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
@@ -6746,7 +6697,6 @@ let gPrivateBrowsingUI = {
// Adjust the New Window menu entries
[
{ normal: "menu_newNavigator", private: "menu_newPrivateWindow" },
- { normal: "appmenu_newNavigator", private: "appmenu_newPrivateWindow" },
].forEach(function(menu) {
let newWindow = document.getElementById(menu.normal);
let newPrivateWindow = document.getElementById(menu.private);
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index 098870f2420..668171ac9da 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -9,7 +9,9 @@
+
+
@@ -22,6 +24,7 @@
+#include ../../components/customizableui/content/panelUI.inc.xul
#ifdef CAN_DRAW_IN_TITLEBAR
-#ifdef MENUBAR_CAN_AUTOHIDE
-
-#endif
-
+
+#ifdef XP_MACOSX
+
+#endif
#endif
@@ -468,8 +470,17 @@
#ifdef CAN_DRAW_IN_TITLEBAR
-
-
+
+
+#ifdef XP_MACOSX
+
+#endif
#endif
@@ -478,127 +489,349 @@
fullscreentoolbar="true" mode="icons" customizable="true"
iconsize="large"
defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,webrtc-status-button,bookmarks-menu-button,downloads-button,home-button,window-controls"
+ customizationtarget="nav-bar-customizationtarget"
context="toolbar-context-menu">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+ tooltip="back-button-tooltip"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef CAN_DRAW_IN_TITLEBAR
+
+
+#ifdef XP_MACOSX
+
+#endif
+#endif
+
+
+
+
+# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
+# or removing default items with the toolbarbutton-1 class.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-#ifndef CAN_DRAW_IN_TITLEBAR
-#define APPMENU_ON_TABBAR
-#endif
-#endif
-
-
-
-
-#ifdef APPMENU_ON_TABBAR
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef CAN_DRAW_IN_TITLEBAR
-
-
-#endif
-
-
-
-
-# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
-# or removing default items with the toolbarbutton-1 class.
-
@@ -1017,45 +1031,49 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+#include ../../components/customizableui/content/customizeMode.inc.xul
+
@@ -1116,7 +1134,6 @@
mode="icons" iconsize="small" defaulticonsize="small"
lockiconsize="true"
defaultset="addonbar-closebutton,spring,status-bar"
- customizable="true"
key="key_toggleAddonBar">
-#ifndef XP_UNIX
+
+
+
+
+
+
+
+
+
+
+#ifndef XP_UNIX
-
#endif
#ifdef XP_MACOSX
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#endif
+
#