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/. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define ID_PREFIX appmenu_developer_ -#define OMIT_ACCESSKEYS -#include browser-charsetmenu.inc -#undef ID_PREFIX -#undef OMIT_ACCESSKEYS - - - - -#define ID_PREFIX appmenu_ -#define OMIT_ACCESSKEYS -#include browser-charsetmenu.inc -#undef ID_PREFIX -#undef OMIT_ACCESSKEYS - -#ifdef MOZ_SERVICES_SYNC - - - -#endif - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef MOZ_SERVICES_SYNC - -#endif - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef MOZ_SERVICES_HEALTHREPORT - -#endif - - - - - - - - - - - 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 - -#include browser-appmenu.inc - -#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 +