author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Thu, 24 Apr 2014 11:39:30 +0200 | |
changeset 179853 | c8055a00235db1ddadfdd74e1d8181537117c23c |
parent 179839 | 6965a913e858b6feb2944649940a646f40eb4037 (current diff) |
parent 179852 | 3544b8716eb11f273ac2c3be1cb192aa62a6e613 (diff) |
child 179879 | 9d3da41ad0b6ef945bd06c680a9e23fcfc1fa406 |
push id | 26646 |
push user | cbook@mozilla.com |
push date | Thu, 24 Apr 2014 09:40:22 +0000 |
treeherder | mozilla-central@c8055a00235d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 31.0a1 |
first release with | nightly linux32
c8055a00235d
/
31.0a1
/
20140424030204
/
files
nightly linux64
c8055a00235d
/
31.0a1
/
20140424030204
/
files
nightly mac
c8055a00235d
/
31.0a1
/
20140424030204
/
files
nightly win32
c8055a00235d
/
31.0a1
/
20140424030204
/
files
nightly win64
c8055a00235d
/
31.0a1
/
20140424030204
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
31.0a1
/
20140424030204
/
pushlog to previous
nightly linux64
31.0a1
/
20140424030204
/
pushlog to previous
nightly mac
31.0a1
/
20140424030204
/
pushlog to previous
nightly win32
31.0a1
/
20140424030204
/
pushlog to previous
nightly win64
31.0a1
/
20140424030204
/
pushlog to previous
|
--- a/browser/base/content/browser-customization.js +++ b/browser/base/content/browser-customization.js @@ -34,17 +34,16 @@ let CustomizationHandler = { childNode.setAttribute("disabled", true); let cmd = document.getElementById("cmd_CustomizeToolbars"); cmd.setAttribute("disabled", "true"); UpdateUrlbarSearchSplitterState(); CombinedStopReload.uninit(); - CombinedBackForward.uninit(); PlacesToolbarHelper.customizeStart(); DownloadsButton.customizeStart(); // The additional padding on the sides of the browser // can cause the customize tab to get clipped. let tabContainer = gBrowser.tabContainer; if (tabContainer.getAttribute("overflow") == "true") { let tabstrip = tabContainer.mTabstrip; @@ -82,17 +81,16 @@ let CustomizationHandler = { } PlacesToolbarHelper.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(); - CombinedBackForward.init(); UpdateUrlbarSearchSplitterState(); // Update the urlbar if (gURLBar) { URLBarSetURI(); XULBrowserWindow.asyncUpdateUI(); }
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -255,25 +255,17 @@ function UpdateBackForwardCommands(aWebN var forwardDisabled = forwardBroadcaster.hasAttribute("disabled"); if (backDisabled == aWebNavigation.canGoBack) { if (backDisabled) backBroadcaster.removeAttribute("disabled"); else backBroadcaster.setAttribute("disabled", true); } - let canGoForward = aWebNavigation.canGoForward; - if (forwardDisabled) { - // Force the button to either be hidden (if we are already disabled, - // and should be), or to show if we're about to un-disable it: - // otherwise no transition will occur and it'll never show: - CombinedBackForward.setForwardButtonOcclusion(!canGoForward); - } - - if (forwardDisabled == canGoForward) { + if (forwardDisabled == aWebNavigation.canGoForward) { if (forwardDisabled) forwardBroadcaster.removeAttribute("disabled"); else forwardBroadcaster.setAttribute("disabled", true); } } /** @@ -915,17 +907,16 @@ var gBrowserInit = { gURLBar.setAttribute("readonly", "true"); gURLBar.setAttribute("enablehistory", "false"); } goSetCommandEnabled("cmd_newNavigatorTab", false); } // Misc. inits. CombinedStopReload.init(); - CombinedBackForward.init(); gPrivateBrowsingUI.init(); TabsInTitlebar.init(); // Wait until chrome is painted before executing code not critical to making the window visible this._boundDelayedStartup = this._delayedStartup.bind(this, mustLoadSidebar); window.addEventListener("MozAfterPaint", this._boundDelayedStartup); this._loadHandled = true; @@ -1262,17 +1253,16 @@ var gBrowserInit = { if (desc && !desc.get) { DeveloperToolbar.destroy(); } // First clean up services initialized in gBrowserInit.onLoad (or those whose // uninit methods don't depend on the services having been initialized). CombinedStopReload.uninit(); - CombinedBackForward.uninit(); gGestureSupport.init(false); gHistorySwipeAnimation.uninit(); FullScreen.cleanup(); #ifdef MOZ_SERVICES_SYNC @@ -3794,17 +3784,16 @@ var XULBrowserWindow = { } catch (e) {} gIdentityHandler.checkIdentity(this._state, uri); }, // simulate all change notifications after switching tabs onUpdateCurrentBrowser: function XWB_onUpdateCurrentBrowser(aStateFlags, aStatus, aMessage, aTotalProgress) { if (FullZoom.updateBackgroundTabs) FullZoom.onLocationChange(gBrowser.currentURI, true); - CombinedBackForward.setForwardButtonOcclusion(!gBrowser.webProgress.canGoForward); var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP; // use a pseudo-object instead of a (potentially nonexistent) channel for getting // a correct error message - and make sure that the UI is always either in // loading (STATE_START) or done (STATE_STOP) mode this.onStateChange( gBrowser.webProgress, { URI: gBrowser.currentURI }, @@ -3869,53 +3858,16 @@ var LinkTargetDisplay = { _hide: function () { clearTimeout(this._timer); XULBrowserWindow.updateStatusField(); } }; -let CombinedBackForward = { - init: function() { - this.forwardButton = document.getElementById("forward-button"); - // Add a transition listener to the url bar to hide the forward button - // when necessary - if (gURLBar) - gURLBar.addEventListener("transitionend", this); - // On startup, or if the user customizes, our listener isn't attached, - // and no transitions fire anyway, so we need to make sure we've hidden the - // button if necessary: - if (this.forwardButton && this.forwardButton.hasAttribute("disabled")) { - this.setForwardButtonOcclusion(true); - } - }, - uninit: function() { - if (gURLBar) - gURLBar.removeEventListener("transitionend", this); - }, - handleEvent: function(aEvent) { - if (aEvent.type == "transitionend" && - (aEvent.propertyName == "margin-left" || aEvent.propertyName == "margin-right") && - this.forwardButton.hasAttribute("disabled")) { - this.setForwardButtonOcclusion(true); - } - }, - setForwardButtonOcclusion: function(shouldBeOccluded) { - if (!this.forwardButton) - return; - - let hasAttribute = this.forwardButton.hasAttribute("occluded-by-urlbar"); - if (shouldBeOccluded && !hasAttribute) - this.forwardButton.setAttribute("occluded-by-urlbar", "true"); - else if (!shouldBeOccluded && hasAttribute) - this.forwardButton.removeAttribute("occluded-by-urlbar"); - } -} - var CombinedStopReload = { init: function () { if (this._initialized) return; let reload = document.getElementById("urlbar-reload-button"); let stop = document.getElementById("urlbar-stop-button"); if (!stop || !reload || reload.nextSibling != stop)
--- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -651,31 +651,24 @@ class="chromeclass-location" overflows="false"> <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional" label="&backCmd.label;" command="Browser:BackOrBackDuplicate" cui-areatype="toolbar" onclick="checkForMiddleClick(this, event);" tooltip="back-button-tooltip" context="backForwardMenu"/> - <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional" - label="&forwardCmd.label;" - command="Browser:ForwardOrForwardDuplicate" - cui-areatype="toolbar" - onclick="checkForMiddleClick(this, event);" - tooltip="forward-button-tooltip" - context="backForwardMenu"/> - <dummyobservertarget hidden="true" - onbroadcast="if (this.getAttribute('disabled') == 'true') - this.parentNode.setAttribute('forwarddisabled', 'true'); - else - this.parentNode.removeAttribute('forwarddisabled');"> - <observes element="Browser:ForwardOrForwardDuplicate" attribute="disabled"/> - </dummyobservertarget> - <hbox id="urlbar-wrapper" flex="1" align="center"> + <hbox id="urlbar-wrapper" flex="1"> + <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional" + label="&forwardCmd.label;" + command="Browser:ForwardOrForwardDuplicate" + cui-areatype="toolbar" + onclick="checkForMiddleClick(this, event);" + tooltip="forward-button-tooltip" + context="backForwardMenu"/> <textbox id="urlbar" flex="1" placeholder="&urlbar.placeholder2;" type="autocomplete" autocompletesearch="urlinline history" autocompletesearchparam="enable-actions" autocompletepopup="PopupAutoCompleteRichResult" completeselectedindex="true" tabscrolling="true" @@ -1183,32 +1176,23 @@ oncommand="DeveloperToolbar.hide();" tooltiptext="&devToolbarCloseButton.tooltiptext;"/> #endif </toolbar> </vbox> <svg:svg height="0"> #include tab-shape.inc.svg - + <svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse"> #ifndef XP_MACOSX - <svg:clipPath id="keyhole-forward-clip-path" clipPathUnits="objectBoundingBox"> - <svg:path d="m 0,0 c .3,.25 .3,.75, 0,1 l 1,0 0,-1 z"/> - </svg:clipPath> - <svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="m 0,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/> + <svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/> +#else + <svg:path d="M -11,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/> +#endif </svg:clipPath> -#else - <svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="M 0,0 a 16 16 0 0 1 0,24 l 10000,0 l 0,-24 l -10000,0 z"/> - </svg:clipPath> - <svg:clipPath id="osx-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse"> - <svg:path d="M -12,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/> - </svg:clipPath> -#endif </svg:svg> </vbox> # <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck. # Introducing the iframe dynamically, as needed, was found to be better than # starting with an empty iframe here in browser.xul from a Ts standpoint. </deck>
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1007,22 +1007,22 @@ newBrowser.setAttribute("type", "content-primary"); newBrowser.docShellIsActive = (window.windowState != window.STATE_MINIMIZED); this.mCurrentBrowser = newBrowser; this.mCurrentTab = this.tabContainer.selectedItem; this.showTab(this.mCurrentTab); - var backForwardContainer = document.getElementById("urlbar-container"); - if (backForwardContainer) { - backForwardContainer.setAttribute("switchingtabs", "true"); + var forwardButtonContainer = document.getElementById("urlbar-wrapper"); + if (forwardButtonContainer) { + forwardButtonContainer.setAttribute("switchingtabs", "true"); window.addEventListener("MozAfterPaint", function removeSwitchingtabsAttr() { window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr); - backForwardContainer.removeAttribute("switchingtabs"); + forwardButtonContainer.removeAttribute("switchingtabs"); }); } this._appendStatusPanel(); if (updateBlockedPopups) this.mCurrentBrowser.updateBlockedPopups(false);
--- a/browser/base/content/test/general/browser_aboutHome.js +++ b/browser/base/content/test/general/browser_aboutHome.js @@ -85,67 +85,68 @@ let gTests = [ "Search engine logo's alt text is a nonempty string"); isnot(altText, "undefined", "Search engine logo's alt text shouldn't be the string 'undefined'"); } }, // Disabled on Linux for intermittent issues with FHR, see Bug 945667. -// Disabled always due to bug 992485 { desc: "Check that performing a search fires a search event and records to " + "Firefox Health Report.", setup: function () { }, run: function () { - // Skip this test always for now since it loads google.com and that causes bug 992485 - return; - // Skip this test on Linux. if (navigator.platform.indexOf("Linux") == 0) { return; } try { let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); cm.getCategoryEntry("healthreport-js-provider-default", "SearchesProvider"); } catch (ex) { // Health Report disabled, or no SearchesProvider. return Promise.resolve(); } let numSearchesBefore = 0; - let deferred = Promise.defer(); + let searchEventDeferred = Promise.defer(); let doc = gBrowser.contentDocument; let engineName = doc.documentElement.getAttribute("searchEngineName"); doc.addEventListener("AboutHomeSearchEvent", function onSearch(e) { let data = JSON.parse(e.detail); is(data.engineName, engineName, "Detail is search engine name"); // We use executeSoon() to ensure that this code runs after the // count has been updated in browser.js, since it uses the same // event. executeSoon(function () { getNumberOfSearches(engineName).then(num => { is(num, numSearchesBefore + 1, "One more search recorded."); - deferred.resolve(); + searchEventDeferred.resolve(); }); }); }, true, true); // Get the current number of recorded searches. + let searchStr = "a search"; getNumberOfSearches(engineName).then(num => { numSearchesBefore = num; info("Perform a search."); - doc.getElementById("searchText").value = "a search"; + doc.getElementById("searchText").value = searchStr; doc.getElementById("searchSubmit").click(); - gBrowser.stop(); }); - return deferred.promise; + let expectedURL = Services.search.currentEngine. + getSubmission(searchStr, null, "homepage"). + uri.spec; + let loadPromise = waitForDocLoadAndStopIt(expectedURL); + + return Promise.all([searchEventDeferred.promise, loadPromise]); } }, { desc: "Check snippets map is cleared if cached version is old", setup: function (aSnippetsMap) { aSnippetsMap.set("snippets", "test");
--- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -287,16 +287,48 @@ function promiseHistoryClearedState(aURI "history visit " + aURI.spec + " should " + niceStr + " exist"); callbackDone(); }); }); return deferred.promise; } +/** + * Waits for the next top-level document load in the current browser. The URI + * of the document is compared against aExpectedURL. The load is then stopped + * before it actually starts. + * + * @param aExpectedURL + * The URL of the document that is expected to load. + * @return promise + */ +function waitForDocLoadAndStopIt(aExpectedURL) { + let deferred = Promise.defer(); + let progressListener = { + onStateChange: function (webProgress, req, flags, status) { + info("waitForDocLoadAndStopIt: onStateChange: " + req.name); + let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | + Ci.nsIWebProgressListener.STATE_START; + if ((flags & docStart) && webProgress.isTopLevel) { + info("waitForDocLoadAndStopIt: Document start: " + + req.QueryInterface(Ci.nsIChannel).URI.spec); + is(req.originalURI.spec, aExpectedURL, + "waitForDocLoadAndStopIt: The expected URL was loaded"); + req.cancel(Components.results.NS_ERROR_FAILURE); + gBrowser.removeProgressListener(progressListener); + deferred.resolve(); + } + }, + }; + gBrowser.addProgressListener(progressListener); + info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL); + return deferred.promise; +} + let FullZoomHelper = { selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(tab) { if (!tab) throw new Error("tab must be given."); if (gBrowser.selectedTab == tab) return Promise.resolve(); gBrowser.selectedTab = tab;
--- a/browser/components/downloads/content/downloadsOverlay.xul +++ b/browser/components/downloads/content/downloadsOverlay.xul @@ -99,16 +99,20 @@ <richlistbox id="downloadsListBox" class="plain" flex="1" context="downloadsContextMenu" onmouseover="DownloadsView.onDownloadMouseOver(event);" onmouseout="DownloadsView.onDownloadMouseOut(event);" oncontextmenu="DownloadsView.onDownloadContextMenu(event);" ondragstart="DownloadsView.onDownloadDragStart(event);"/> + <description id="emptyDownloads" + mousethrough="always"> + &downloadsPanelEmpty.label; + </description> <vbox id="downloadsFooter"> <hbox id="downloadsSummary" align="center" orient="horizontal" onkeydown="DownloadsSummary.onKeyDown(event);" onclick="DownloadsSummary.onClick(event);"> <image class="downloadTypeIcon" />
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.dtd +++ b/browser/locales/en-US/chrome/browser/downloads/downloads.dtd @@ -79,13 +79,18 @@ <!ENTITY clearDownloadsButton.tooltip "Clears completed, canceled and failed downloads"> <!-- LOCALIZATION NOTE (downloadsListEmpty.label): This string is shown when there are no items in the Downloads view, when it is displayed inside a browser tab. --> <!ENTITY downloadsListEmpty.label "There are no downloads."> +<!-- LOCALIZATION NOTE (downloadsPanelEmpty.label): + This string is shown when there are no items in the Downloads Panel. + --> +<!ENTITY downloadsPanelEmpty.label "No downloads for this session."> + <!-- LOCALIZATION NOTE (downloadsListNoMatch.label): This string is shown when some search terms are specified, but there are no results in the Downloads view. --> <!ENTITY downloadsListNoMatch.label "Could not find any matching downloads.">
--- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -10,17 +10,17 @@ @namespace html url("http://www.w3.org/1999/xhtml"); @namespace svg url("http://www.w3.org/2000/svg"); %include ../shared/browser.inc %include linuxShared.inc %filter substitution %define forwardTransitionLength 150ms -%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container +%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper %define conditionalForwardWithUrlbarWidth 30 #menubar-items { -moz-box-orient: vertical; /* for flex hack */ } #main-menubar { -moz-box-flex: 1; /* make menu items expand to fill toolbar height */ @@ -730,45 +730,49 @@ toolbarbutton[sdk-button="true"][cui-are } #main-window:not([customizing]) #back-button[disabled] > .toolbarbutton-icon { box-shadow: 0 0 0 1px hsla(210,54%,20%,.55), 0 1px 0 hsla(210,54%,20%,.65) !important; transition: none; } -#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, -#forward-button:-moz-locale-dir(rtl) { +#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon { transform: scaleX(-1); } -@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] { - opacity: 0; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button { - transition: opacity @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@ > #forward-button[occluded-by-urlbar] { - visibility: hidden; -} - #forward-button { padding: 0; } #forward-button > .toolbarbutton-icon { background-clip: padding-box; - clip-path: url("chrome://browser/content/browser.xul#keyhole-forward-clip-path"); - margin-left: -6px; + padding-left: 9px; + padding-right: 3px; + border: 1px solid #9a9a9a; border-left-style: none; border-radius: 0; - padding: 2px 3px 2px 9px; - border: 1px solid #9a9a9a; +} + +@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button { + transition: margin-left @forwardTransitionLength@ ease-out; +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] { + margin-left: -@conditionalForwardWithUrlbarWidth@px; +} + +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] { + /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ + transition-delay: 100s; +} + +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] { + /* when not hovered anymore, trigger a new transition to hide the forward button immediately */ + margin-left: -@conditionalForwardWithUrlbarWidth@.01px; } /* tabview menu item */ #menu_tabview { list-style-image: url(chrome://browser/skin/tabview/tabview.png); -moz-image-region: rect(0, 80px, 16px, 64px); } @@ -898,67 +902,44 @@ toolbarbutton[sdk-button="true"][cui-are .urlbar-history-dropmarker { -moz-appearance: toolbarbutton-dropdown; } #urlbar-container { -moz-box-align: center; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper { - padding-left: @conditionalForwardWithUrlbarWidth@px; - -moz-margin-start: -@conditionalForwardWithUrlbarWidth@px; - position: relative; - pointer-events: none; +@conditionalForwardWithUrlbar@ > #urlbar { + -moz-border-start: none; + margin-left: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar { - -moz-border-start: none; - margin-left: 0; - pointer-events: all; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - transition: margin-left @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(ltr) { +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(ltr) { border-top-left-radius: 0; border-bottom-left-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { border-top-right-radius: 0; border-bottom-right-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper { +@conditionalForwardWithUrlbar@ { clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path"); -} - -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar { - margin-left: -@conditionalForwardWithUrlbarWidth@px; + -moz-margin-start: -5px; } -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ - transition-delay: 100s; +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl), +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { + /* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */ + transform: scaleX(-1); } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar, -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar { - /* when switching tabs, or when not hovered anymore, trigger a new transition - * to hide the forward button immediately */ - margin-left: -@conditionalForwardWithUrlbarWidth@.01px; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { - /* let windows-urlbar-back-button-mask clip the urlbar's right side for RTL */ - transform: scaleX(-1); +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl) { + -moz-box-direction: reverse; } #urlbar-icons { -moz-box-align: center; } .urlbar-icon { cursor: pointer; @@ -1010,43 +991,43 @@ toolbarbutton[sdk-button="true"][cui-are border-bottom-right-radius: 1.5px; } #notification-popup-box:not([hidden]) + #identity-box { -moz-padding-start: 10px; border-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box { +@conditionalForwardWithUrlbar@ > #urlbar > #identity-box { border-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { - padding-left: 5px; - transition: padding-left; +@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box { + transition: padding-left, padding-right; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { - padding-right: 5px; - transition: padding-right; +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { + padding-left: 5px; } -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box { +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { + padding-right: 5px; +} + +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box { /* forward button hiding is delayed when hovered */ transition-delay: 100s; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { /* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */ padding-left: 5.01px; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { /* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */ padding-right: 5.01px; } #urlbar[pageproxystate="valid"] > #identity-box.chromeUI, #urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity { -moz-margin-end: 4px; } @@ -1066,24 +1047,20 @@ toolbarbutton[sdk-button="true"][cui-are } %include ../shared/identity-block.inc.css #page-proxy-favicon { margin-top: 1px; margin-bottom: 1px; -moz-margin-start: 3px; - -moz-margin-end: 2px; + -moz-margin-end: 1px; -moz-image-region: rect(0, 16px, 16px, 0); } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box > #page-proxy-favicon { - -moz-margin-end: 1px; -} - #identity-box:hover > #page-proxy-favicon { -moz-image-region: rect(0, 32px, 16px, 16px); } #identity-box:hover:active > #page-proxy-favicon, #identity-box[open=true] > #page-proxy-favicon { -moz-image-region: rect(0, 48px, 16px, 32px); }
--- a/browser/themes/linux/downloads/downloads.css +++ b/browser/themes/linux/downloads/downloads.css @@ -13,23 +13,32 @@ padding: 4px; color: inherit; } #downloadsPanel:not([hasdownloads]) > #downloadsListBox { display: none; } +#downloadsPanel[hasdownloads] > #emptyDownloads { + display: none; +} + +#emptyDownloads { + padding: 10px 20px; + max-width: 40ch; +} + #downloadsHistory { background: transparent; color: -moz-nativehyperlinktext; cursor: pointer; } -#downloadsPanel[hasdownloads] > #downloadsFooter { +#downloadsFooter { border-top: 1px solid ThreeDShadow; background-image: linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px); } #downloadsHistory > .button-box { margin: 1em; }
--- a/browser/themes/osx/browser.css +++ b/browser/themes/osx/browser.css @@ -2,18 +2,18 @@ * 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/. */ @import url("chrome://global/skin/"); %include shared.inc %filter substitution %define forwardTransitionLength 150ms -%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container -%define conditionalForwardWithUrlbarWidth 30 +%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper +%define conditionalForwardWithUrlbarWidth 32 %define spaceAboveTabbar 9px %define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"]) %define windowButtonMarginTop 11px @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); @namespace html url("http://www.w3.org/1999/xhtml"); @namespace svg url("http://www.w3.org/2000/svg"); @@ -1415,30 +1415,27 @@ toolbarbutton[sdk-button="true"][cui-are } #back-button:-moz-window-inactive, #forward-button:-moz-window-inactive { background-color: rgba(0,0,0,0.04); border-color: rgba(0,0,0,0.2); } -#back-button:-moz-locale-dir(rtl), -#forward-button:-moz-locale-dir(rtl) { +#back-button:-moz-locale-dir(rtl) { transform: scaleX(-1); } /* Back button styles */ #back-button { - -moz-margin-end: -7px; - position: relative; - z-index: 1; width: 32px; height: 32px; padding: 4px 5px 4px 3px; + -moz-margin-end: 0; border-radius: 10000px; } #back-button:not(:-moz-lwtheme) { height: 33px; padding: 4px 5px 5px 3px; margin-bottom: -1px; background: url(chrome://browser/skin/keyhole-circle.png) 0 0 no-repeat; @@ -1458,68 +1455,50 @@ toolbarbutton[sdk-button="true"][cui-are #back-button:not([disabled="true"]):active:hover:not(:-moz-lwtheme), #back-button[open="true"]:not(:-moz-lwtheme) { background-position: -32px 0; } /* Forward button styles */ #forward-button { - -moz-margin-start: 0; - -moz-margin-end: 0; + margin-left: -2px; + margin-right: 0; + padding-left: 2px; width: 32px; - clip-path: url(chrome://browser/content/browser.xul#osx-keyhole-forward-clip-path); } #forward-button > .toolbarbutton-icon { /* shift the icon away from the back button */ margin-left: 3px; margin-right: -1px; } -#forward-button:-moz-lwtheme { - -moz-padding-start: 2px; - -moz-padding-end: 0; -} - #forward-button:not(:-moz-lwtheme) { - -moz-padding-start: 2px; background: linear-gradient(hsl(0,0%,99%), hsl(0,0%,67%)) padding-box; border: 1px solid; border-color: hsl(0,0%,31%) hsla(0,0%,29%,.6) hsl(0,0%,27%); box-shadow: inset 0 1px 0 hsla(0,0%,100%,.35), 0 1px 0 hsla(0,0%,100%,.2); } -#urlbar-container:not([switchingtabs]) > #forward-button { - transition: opacity @forwardTransitionLength@ ease-out; -} - #forward-button:hover:active:not(:-moz-lwtheme) { background-image: linear-gradient(hsl(0,0%,74%), hsl(0,0%,61%)); box-shadow: inset rgba(0,0,0,.3) 0 -6px 10px, inset #000 0 1px 3px, inset rgba(0,0,0,.2) 0 1px 3px, 0 1px 0 hsla(0,0%,100%,.2); } #forward-button:-moz-window-inactive:not(:-moz-lwtheme) { border-color: hsl(0,0%,64%) hsl(0,0%,65%) hsl(0,0%,66%); background-image: linear-gradient(hsl(0,0%,99%), hsl(0,0%,82%)); box-shadow: inset 0 1px 0 hsla(0,0%,100%,.35); } -#urlbar-container:not(:hover) > #forward-button[disabled] { - opacity: 0; -} - -@conditionalForwardWithUrlbar@ > #forward-button[occluded-by-urlbar] { - visibility: hidden; -} - @media (-moz-mac-lion-theme) { #forward-button:not(:-moz-lwtheme) { background-image: linear-gradient(hsla(0,0%,100%,.73), hsla(0,0%,100%,.05) 85%); border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.25) hsla(0,0%,0%,.2); box-shadow: inset 0 1px 0 hsla(0,0%,100%,.2), inset 0 0 1px hsla(0,0%,100%,.1), 0 1px 0 hsla(0,0%,100%,.2); } @@ -1533,16 +1512,34 @@ toolbarbutton[sdk-button="true"][cui-are } #forward-button:-moz-window-inactive:not(:-moz-lwtheme) { background-image: none; border-color: hsla(0,0%,0%,.2); } } +@conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button { + transition: margin-left @forwardTransitionLength@ ease-out; +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] { + margin-left: -@conditionalForwardWithUrlbarWidth@px; +} + +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] { + /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ + transition-delay: 100s; +} + +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] { + /* when not hovered anymore, trigger a new transition to hide the forward button immediately */ + margin-left: -@conditionalForwardWithUrlbarWidth@.01px; +} + .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr), .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) { list-style-image: url("chrome://browser/skin/menu-back.png") !important; } .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(ltr), .unified-nav-back[_moz-menuactive]:-moz-locale-dir(rtl) { list-style-image: url("chrome://browser/skin/menu-forward.png") !important; @@ -1716,69 +1713,46 @@ toolbarbutton[sdk-button="true"][cui-are -moz-box-align: center; } #urlbar { -moz-padding-end: 4px; border-radius: @toolbarbuttonCornerRadius@; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper { - padding-left: @conditionalForwardWithUrlbarWidth@px; - -moz-margin-start: -@conditionalForwardWithUrlbarWidth@px; - position: relative; - pointer-events: none; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar { +@conditionalForwardWithUrlbar@ > #urlbar { -moz-border-start: none; margin-left: 0; - pointer-events: all; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - transition: margin-left @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(ltr) { +} + +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(ltr) { border-top-left-radius: 0; border-bottom-left-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { border-top-right-radius: 0; border-bottom-right-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper { - clip-path: url("chrome://browser/content/browser.xul#osx-urlbar-back-button-clip-path"); -} - -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar { - margin-left: -@conditionalForwardWithUrlbarWidth@px; -} - -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ - transition-delay: 100s; -} - -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar, -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar { - /* when switching tabs, or when not hovered anymore, trigger a new transition - * to hide the forward button immediately */ - margin-left: -@conditionalForwardWithUrlbarWidth@.01px; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { - /* let osx-urlbar-back-button-clip-path clip the urlbar's right side for RTL */ +@conditionalForwardWithUrlbar@ { + clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path"); + -moz-margin-start: -6px; +} + +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl), +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { + /* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */ transform: scaleX(-1); } +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl) { + -moz-box-direction: reverse; +} + #identity-box { -moz-margin-end: 3px; padding-top: 1px; padding-bottom: 1px; -moz-padding-start: 4px; -moz-padding-end: 0; font-size: .9em; } @@ -1793,42 +1767,42 @@ toolbarbutton[sdk-button="true"][cui-are border-bottom-right-radius: 2px; } #notification-popup-box:not([hidden]) + #identity-box { -moz-padding-start: 10px; border-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box { +@conditionalForwardWithUrlbar@ > #urlbar > #identity-box { border-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { - transition: 0s padding-left; +@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box { + transition: padding-left, padding-right; +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { padding-left: 10px; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { - transition: 0s padding-right; +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { padding-right: 10px; } -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box { - /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box { + /* forward button hiding is delayed when hovered */ transition-delay: 100s; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { padding-left: 10.01px; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { padding-right: 10.01px; } #urlbar[pageproxystate="valid"] > #identity-box.chromeUI, #urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity { -moz-padding-end: 4px; } @@ -3395,17 +3369,17 @@ toolbarbutton.chevron > .toolbarbutton-m } @media (min-resolution: 2dppx) { #notification-popup-box { border-image: url("chrome://browser/skin/urlbar-arrow@2x.png") 0 16 0 0 fill; } } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box { +@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar > #notification-popup-box { padding-left: 7px; } #notification-popup-box:-moz-locale-dir(rtl), .notification-anchor-icon:-moz-locale-dir(rtl) { transform: scaleX(-1); }
--- a/browser/themes/osx/downloads/downloads.css +++ b/browser/themes/osx/downloads/downloads.css @@ -17,28 +17,37 @@ padding: 4px; color: inherit; } #downloadsPanel:not([hasdownloads]) > #downloadsListBox { display: none; } +#downloadsPanel[hasdownloads] > #emptyDownloads { + display: none; +} + +#emptyDownloads { + padding: 10px 20px; + max-width: 40ch; +} + #downloadsFooter { border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; } #downloadsHistory { background: transparent; color: hsl(210,100%,75%); cursor: pointer; } -#downloadsPanel[hasdownloads] > #downloadsFooter { +#downloadsFooter { background: #e5e5e5; border-top: 1px solid hsla(0,0%,0%,.1); box-shadow: 0 -1px hsla(0,0%,100%,.5) inset, 0 1px 1px hsla(0,0%,0%,.03) inset; } #downloadsHistory > .button-box { color: #808080; margin: 1em; @@ -47,21 +56,16 @@ #downloadsPanel[keyfocus] > #downloadsFooter > #downloadsSummary:focus, #downloadsPanel[keyfocus] > #downloadsFooter > #downloadsHistory:focus { outline: 2px -moz-mac-focusring solid; outline-offset: -2px; -moz-outline-radius-bottomleft: 4px; -moz-outline-radius-bottomright: 4px; } -#downloadsPanel:not([hasdownloads]) > #downloadsFooter > #downloadsHistory:focus { - -moz-outline-radius-topleft: 4px; - -moz-outline-radius-topright: 4px; -} - /*** Downloads Summary and List items ***/ #downloadsSummary, richlistitem[type="download"] { height: 7em; -moz-padding-end: 0; color: inherit; }
--- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -9,17 +9,17 @@ @namespace svg url("http://www.w3.org/2000/svg"); %include ../shared/browser.inc %include windowsShared.inc %filter substitution %define toolbarShadowColor hsla(209,67%,12%,0.35) %define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32); %define forwardTransitionLength 150ms -%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container +%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper %define conditionalForwardWithUrlbarWidth 30 #menubar-items { -moz-box-orient: vertical; /* for flex hack */ } #main-menubar { -moz-box-flex: 1; /* make menu items expand to fill toolbar height */ @@ -881,46 +881,38 @@ toolbarbutton[sdk-button="true"][cui-are } #forward-button > menupopup { margin-top: 1px !important; } #forward-button > .toolbarbutton-icon { background-clip: padding-box !important; - /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */ - clip-path: url(chrome://browser/content/browser.xul#keyhole-forward-clip-path) !important; - margin-left: -6px !important; border-left-style: none !important; border-radius: 0 !important; padding-left: 9px !important; padding-right: 3px !important; } -%ifdef WINDOWS_AERO -@media (-moz-os-version: windows-vista), - (-moz-os-version: windows-win7) { -%endif - #forward-button > .toolbarbutton-icon { - margin-left: -6px !important; - } -%ifdef WINDOWS_AERO -} -%endif - @conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button { - transition: opacity @forwardTransitionLength@ ease-out; + transition: margin-left @forwardTransitionLength@ ease-out; +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] { + margin-left: -@conditionalForwardWithUrlbarWidth@px; +} + +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] { + /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ + transition-delay: 100s; } @conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] { - opacity: 0; -} - -@conditionalForwardWithUrlbar@ > #forward-button[occluded-by-urlbar] { - visibility: hidden; + /* when not hovered anymore, trigger a new transition to hide the forward button immediately */ + margin-left: -@conditionalForwardWithUrlbarWidth@.01px; } #back-button { padding-top: 3px !important; padding-bottom: 3px !important; -moz-padding-start: 5px !important; -moz-padding-end: 0 !important; position: relative !important; @@ -994,18 +986,17 @@ toolbarbutton[sdk-button="true"][cui-are box-shadow: 0 0 0 1px hsla(210,54%,20%,.55), 0 1px 0 hsla(210,54%,20%,.65) !important; transition: none; } %ifdef WINDOWS_AERO } %endif -#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, -#forward-button:-moz-locale-dir(rtl) { +#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon { transform: scaleX(-1); } .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr), .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) { list-style-image: url("chrome://browser/skin/menu-back.png") !important; } @@ -1167,69 +1158,46 @@ toolbarbutton[sdk-button="true"][cui-are background-color: rgba(255,255,255,.9); } #urlbar:-moz-lwtheme[focused]:not([readonly]), .searchbar-textbox:-moz-lwtheme[focused] { background-color: white; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper { - padding-left: @conditionalForwardWithUrlbarWidth@px; - -moz-margin-start: -@conditionalForwardWithUrlbarWidth@px; - position: relative; - pointer-events: none; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar { +@conditionalForwardWithUrlbar@ > #urlbar { -moz-border-start: none; margin-left: 0; - pointer-events: all; -} - -@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - transition: margin-left @forwardTransitionLength@ ease-out; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(ltr) { +} + +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(ltr) { border-top-left-radius: 0; border-bottom-left-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { border-top-right-radius: 0; border-bottom-right-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper { +@conditionalForwardWithUrlbar@ { clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path"); -} - -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar { - margin-left: -@conditionalForwardWithUrlbarWidth@px; -} - -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar { - /* delay the hiding of the forward button when hovered to avoid accidental clicks on the url bar */ - transition-delay: 100s; -} - -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar, -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar { - /* when switching tabs, or when not hovered anymore, trigger a new transition - * to hide the forward button immediately */ - margin-left: -@conditionalForwardWithUrlbarWidth@.01px; -} - -@conditionalForwardWithUrlbar@ > #urlbar-wrapper:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar:-moz-locale-dir(rtl) { - /* let windows-urlbar-back-button-mask clip the urlbar's right side for RTL */ + -moz-margin-start: -5px; +} + +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl), +@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) { + /* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */ transform: scaleX(-1); } +@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl) { + -moz-box-direction: reverse; +} + html|*.urlbar-input:-moz-lwtheme::-moz-placeholder, .searchbar-textbox:-moz-lwtheme > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input::-moz-placeholder { opacity: 1.0; color: #777; } #urlbar-container { -moz-box-align: center; @@ -1309,43 +1277,43 @@ html|*.urlbar-input:-moz-lwtheme::-moz-p border-bottom-right-radius: 1.5px; } #notification-popup-box:not([hidden]) + #identity-box { -moz-padding-start: 10px; border-radius: 0; } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box { +@conditionalForwardWithUrlbar@ > #urlbar > #identity-box { border-radius: 0; } -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { +@conditionalForwardWithUrlbar@:not([switchingtabs]) > #urlbar > #identity-box { + transition: padding-left, padding-right; +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { padding-left: 5px; - transition: padding-left; -} - -@conditionalForwardWithUrlbar@[forwarddisabled] > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { +} + +@conditionalForwardWithUrlbar@ > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { padding-right: 5px; - transition: padding-right; -} - -@conditionalForwardWithUrlbar@[forwarddisabled]:hover:not([switchingtabs]) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box { +} + +@conditionalForwardWithUrlbar@:hover:not([switchingtabs]) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box { /* forward button hiding is delayed when hovered */ transition-delay: 100s; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) { /* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */ padding-left: 5.01px; } -@conditionalForwardWithUrlbar@[forwarddisabled][switchingtabs] + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl), -@conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) > #urlbar-wrapper > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { +@conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] + #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) { /* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */ padding-right: 5.01px; } #urlbar[pageproxystate="valid"] > #identity-box.chromeUI, #urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity { -moz-margin-end: 4px; } @@ -1390,24 +1358,20 @@ html|*.urlbar-input:-moz-lwtheme::-moz-p /* page proxy icon */ %include ../shared/identity-block.inc.css #page-proxy-favicon { margin-top: 1px; margin-bottom: 1px; -moz-margin-start: 3px; - -moz-margin-end: 2px; + -moz-margin-end: 1px; -moz-image-region: rect(0, 16px, 16px, 0); } -@conditionalForwardWithUrlbar@ > #urlbar-wrapper > #urlbar > #identity-box > #page-proxy-favicon { - -moz-margin-end: 1px; -} - #identity-box:hover > #page-proxy-favicon { -moz-image-region: rect(0, 32px, 16px, 16px); } #identity-box:hover:active > #page-proxy-favicon, #identity-box[open=true] > #page-proxy-favicon { -moz-image-region: rect(0, 48px, 16px, 32px); }
--- a/browser/themes/windows/downloads/downloads.css +++ b/browser/themes/windows/downloads/downloads.css @@ -13,16 +13,25 @@ padding: 4px; color: inherit; } #downloadsPanel:not([hasdownloads]) > #downloadsListBox { display: none; } +#downloadsPanel[hasdownloads] > #emptyDownloads { + display: none; +} + +#emptyDownloads { + padding: 10px 20px; + max-width: 40ch; +} + #downloadsHistory { background: transparent; cursor: pointer; } %ifdef WINDOWS_AERO @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { @@ -39,46 +48,46 @@ outline-offset: -1px; } #downloadsHistory > .button-box { border: none; margin: 1em; } -#downloadsPanel[hasdownloads] > #downloadsFooter { +#downloadsFooter { background-color: hsla(210,4%,10%,.04); box-shadow: 0 1px 0 hsla(210,4%,10%,.08) inset; transition-duration: 150ms; transition-property: background-color; } -#downloadsPanel[hasdownloads] > #downloadsFooter:hover { +#downloadsFooter:hover { background-color: hsla(210,4%,10%,.05); } -#downloadsPanel[hasdownloads] > #downloadsFooter:hover:active { +#downloadsFooter:hover:active { background-color: hsla(210,4%,10%,.1); box-shadow: 0 2px 0 0 hsla(210,4%,10%,.1) inset; } %ifdef WINDOWS_AERO @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { %endif @media (-moz-windows-default-theme) { - #downloadsPanel[hasdownloads] > #downloadsFooter { + #downloadsFooter { border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; transition-duration: 0s; } - #downloadsPanel[hasdownloads] > #downloadsFooter, - #downloadsPanel[hasdownloads] > #downloadsFooter:hover, - #downloadsPanel[hasdownloads] > #downloadsFooter:hover:active { + #downloadsFooter, + #downloadsFooter:hover, + #downloadsFooter:hover:active { %ifdef WINDOWS_AERO background-color: #f1f5fb; %else background-color: hsla(216,45%,88%,.98); %endif box-shadow: 0px 1px 2px rgb(204,214,234) inset; } }
--- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -1624,68 +1624,58 @@ int64_t GetPluginLastModifiedTime(const localfile->GetLastModifiedTime(&fileModTime); #endif return fileModTime; } bool GetPluginIsFromExtension(const nsCOMPtr<nsIFile>& pluginFile, - const nsCOMPtr<nsISimpleEnumerator>& extensionDirs) + const nsCOMArray<nsIFile>& extensionDirs) { - if (!extensionDirs) { - return false; - } - - bool hasMore; - while (NS_SUCCEEDED(extensionDirs->HasMoreElements(&hasMore)) && hasMore) { - nsCOMPtr<nsISupports> supports; - nsresult rv = extensionDirs->GetNext(getter_AddRefs(supports)); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr<nsIFile> extDir(do_QueryInterface(supports, &rv)); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr<nsIFile> dir; - if (NS_FAILED(extDir->Clone(getter_AddRefs(dir)))) { - continue; - } - + for (uint32_t i = 0; i < extensionDirs.Length(); ++i) { bool contains; - if (NS_FAILED(dir->Contains(pluginFile, true, &contains)) || !contains) { + if (NS_FAILED(extensionDirs[i]->Contains(pluginFile, true, &contains)) || !contains) { continue; } return true; } return false; } -nsCOMPtr<nsISimpleEnumerator> -GetExtensionDirectories() +void +GetExtensionDirectories(nsCOMArray<nsIFile>& dirs) { nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); if (!dirService) { - return nullptr; + return; } nsCOMPtr<nsISimpleEnumerator> list; nsresult rv = dirService->Get(XRE_EXTENSIONS_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list)); if (NS_FAILED(rv)) { - return nullptr; + return; } - return list; + bool more; + while (NS_SUCCEEDED(list->HasMoreElements(&more)) && more) { + nsCOMPtr<nsISupports> next; + if (NS_FAILED(list->GetNext(getter_AddRefs(next)))) { + break; + } + nsCOMPtr<nsIFile> file = do_QueryInterface(next); + if (file) { + file->Normalize(); + dirs.AppendElement(file); + } + } } struct CompareFilesByTime { bool LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const { return GetPluginLastModifiedTime(a) < GetPluginLastModifiedTime(b); @@ -1741,20 +1731,18 @@ nsresult nsPluginHost::ScanPluginsDirect if (nsPluginsDir::IsPluginFile(dirEntry)) { pluginFiles.AppendElement(dirEntry); } } pluginFiles.Sort(CompareFilesByTime()); - nsCOMPtr<nsISimpleEnumerator> extensionDirs = GetExtensionDirectories(); - if (!extensionDirs) { - PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("Could not get extension directories.")); - } + nsCOMArray<nsIFile> extensionDirs; + GetExtensionDirectories(extensionDirs); bool warnOutdated = false; for (int32_t i = (pluginFiles.Length() - 1); i >= 0; i--) { nsCOMPtr<nsIFile>& localfile = pluginFiles[i]; nsString utf16FilePath; rv = localfile->GetPath(utf16FilePath);
--- a/dom/plugins/test/testaddon/Makefile.in +++ b/dom/plugins/test/testaddon/Makefile.in @@ -1,23 +1,23 @@ # 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/. include $(topsrcdir)/config/rules.mk ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) -plugin_file_name = Test.plugin +plugin_file_names = Test.plugin SecondTest.plugin addon_file_name = testaddon_$(TARGET_XPCOM_ABI).xpi else -plugin_file_name = $(DLL_PREFIX)nptest$(DLL_SUFFIX) +plugin_file_names = $(DLL_PREFIX)nptest$(DLL_SUFFIX) $(DLL_PREFIX)npsecondtest$(DLL_SUFFIX) addon_file_name = testaddon.xpi endif # This is so hacky. Waiting on bug 988938. testdir = $(abspath $(DEPTH)/_tests/xpcshell/dom/plugins/test/unit/) addonpath = $(testdir)/$(addon_file_name) libs:: $(NSINSTALL) -D $(testdir) rm -f $(addonpath) cd $(srcdir) && zip -rD $(addonpath) install.rdf - cd $(DIST) && zip -rD $(addonpath) plugins/$(plugin_file_name) + cd $(DIST) && zip -rD $(addonpath) $(foreach name,$(plugin_file_names),plugins/$(name))
--- a/dom/plugins/test/unit/head_plugins.js +++ b/dom/plugins/test/unit/head_plugins.js @@ -9,37 +9,23 @@ Cu.import("resource://gre/modules/Promis const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc); const gIsOSX = ("nsILocalFileMac" in Ci); const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) || ("@mozilla.org/gio-service;1" in Cc); const gDirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); // Finds the test plugin library -function get_test_plugin() { +function get_test_plugin(secondplugin=false) { var pluginEnum = gDirSvc.get("APluginsDL", Ci.nsISimpleEnumerator); while (pluginEnum.hasMoreElements()) { let dir = pluginEnum.getNext().QueryInterface(Ci.nsILocalFile); + let name = get_platform_specific_plugin_name(secondplugin); let plugin = dir.clone(); - // OSX plugin - plugin.append("Test.plugin"); - if (plugin.exists()) { - plugin.normalize(); - return plugin; - } - plugin = dir.clone(); - // *nix plugin - plugin.append("libnptest.so"); - if (plugin.exists()) { - plugin.normalize(); - return plugin; - } - // Windows plugin - plugin = dir.clone(); - plugin.append("nptest.dll"); + plugin.append(name); if (plugin.exists()) { plugin.normalize(); return plugin; } } return null; } @@ -88,21 +74,27 @@ function do_get_profile_startup() { throw Components.results.NS_ERROR_NO_INTERFACE; } }; dirSvc.QueryInterface(Components.interfaces.nsIDirectoryService) .registerProvider(provider); return file.clone(); } -function get_platform_specific_plugin_name() { - if (gIsWindows) return "nptest.dll"; - else if (gIsOSX) return "Test.plugin"; - else if (gIsLinux) return "libnptest.so"; - else return null; +function get_platform_specific_plugin_name(secondplugin=false) { + if (secondplugin) { + if (gIsWindows) return "npsecondtest.dll"; + if (gIsOSX) return "SecondTest.plugin"; + if (gIsLinux) return "libnpsecondtest.so"; + } else { + if (gIsWindows) return "nptest.dll"; + if (gIsOSX) return "Test.plugin"; + if (gIsLinux) return "libnptest.so"; + } + return null; } function get_platform_specific_plugin_suffix() { if (gIsWindows) return ".dll"; else if (gIsOSX) return ".plugin"; else if (gIsLinux) return ".so"; else return null; }
--- a/dom/plugins/test/unit/test_plugin_default_state_xpi.js +++ b/dom/plugins/test/unit/test_plugin_default_state_xpi.js @@ -36,16 +36,21 @@ function run_test() { run_next_test(); } add_task(function* test_state() { // Remove test so we will have only one "Test Plug-in" registered. // xpcshell tests have plugins in per-test profiles, so that's fine. let file = get_test_plugin(); file.remove(true); + file = get_test_plugin(true); + file.remove(true); + + Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_CLICKTOPLAY); + Services.prefs.setIntPref("plugin.defaultXpi.state", Ci.nsIPluginTag.STATE_ENABLED); let success = yield installAddon(getTestaddonFilename()); Assert.ok(success, "Should have installed addon."); let addonDir = getAddonRoot(gProfileDir, ADDON_ID); let provider = { classID: Components.ID("{0af6b2d7-a06c-49b7-babc-636d292b0dbb}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider, @@ -100,9 +105,13 @@ add_task(function* test_state() { Assert.ok(!addon.userDisabled, "Addon should not be user disabled"); let testPlugin = get_test_plugintag(); Assert.notEqual(testPlugin, null, "Test plugin should have been found"); Assert.equal(testPlugin.enabledState, Ci.nsIPluginTag.STATE_ENABLED, "Test plugin from addon should have state enabled"); pluginDir.append(testPlugin.filename); Assert.ok(pluginDir.exists(), "Plugin file should exist in addon directory: " + pluginDir.path); + + testPlugin = get_test_plugintag("Second Test Plug-in"); + Assert.notEqual(testPlugin, null, "Second test plugin should have been found"); + Assert.equal(testPlugin.enabledState, Ci.nsIPluginTag.STATE_ENABLED, "Second test plugin from addon should have state enabled"); });
--- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -1915,17 +1915,17 @@ abstract public class BrowserApp extends } /** * Add the provided item to the provided menu, which should be * the root (mMenu). */ private void addAddonMenuItemToMenu(final Menu menu, final MenuItemInfo info) { info.added = true; - + final Menu destination; if (info.parent == 0) { destination = menu; } else if (info.parent == GECKO_TOOLS_MENU) { MenuItem tools = menu.findItem(R.id.tools); destination = tools != null ? tools.getSubMenu() : menu; } else { MenuItem parent = menu.findItem(info.parent); @@ -2051,17 +2051,17 @@ abstract public class BrowserApp extends } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Sets mMenu = menu. super.onCreateOptionsMenu(menu); - // Inform the menu about the action-items bar. + // Inform the menu about the action-items bar. if (menu instanceof GeckoMenu && HardwareUtils.isTablet()) { ((GeckoMenu) menu).setActionItemBarPresenter(mBrowserToolbar); } MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.browser_app_menu, mMenu); @@ -2465,17 +2465,17 @@ abstract public class BrowserApp extends } } return super.onKeyLongPress(keyCode, event); } /* * If the app has been launched a certain number of times, and we haven't asked for feedback before, * open a new tab with about:feedback when launching the app from the icon shortcut. - */ + */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String action = intent.getAction(); if (AppConstants.MOZ_ANDROID_BEAM && Build.VERSION.SDK_INT >= 10 && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { String uri = intent.getDataString(); @@ -2567,17 +2567,17 @@ abstract public class BrowserApp extends } }).execute(); } // HomePager.OnNewTabsListener @Override public void onNewTabs(String[] urls) { final EnumSet<OnUrlOpenListener.Flags> flags = EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB); - + for (String url : urls) { if (!maybeSwitchToTab(url, flags)) { openUrlAndStopEditing(url, true); } } } // HomePager.OnUrlOpenListener
--- a/mobile/android/base/gfx/TouchEventHandler.java +++ b/mobile/android/base/gfx/TouchEventHandler.java @@ -249,16 +249,18 @@ final class TouchEventHandler implements MotionEvent event = mEventQueue.poll(); while (true) { // event being null here is valid and represents a block of events // that has already been dispatched. if (event != null) { dispatchEvent(event, allowDefaultAction); + event.recycle(); + event = null; } if (mEventQueue.isEmpty()) { // we have processed the backlog of events, and are all caught up. // now we can set clear the hold flag and set the dispatch flag so // that the handleEvent() function can do the right thing for all // remaining events in this block (which is still ongoing) without // having to put them in the queue. mHoldInQueue = false;
--- a/mobile/android/base/home/PanelItemView.java +++ b/mobile/android/base/home/PanelItemView.java @@ -73,16 +73,19 @@ class PanelItemView extends LinearLayout .into(image); } } private static class ArticleItemView extends PanelItemView { private ArticleItemView(Context context) { super(context, R.layout.panel_article_item); setOrientation(LinearLayout.HORIZONTAL); + + final int padding = getResources().getDimensionPixelSize(R.dimen.article_item_view_padding); + setPadding(0, padding, 0, padding); } } private static class ImageItemView extends PanelItemView { private ImageItemView(Context context) { super(context, R.layout.panel_image_item); setOrientation(LinearLayout.VERTICAL); }
--- a/mobile/android/base/home/TabMenuStrip.java +++ b/mobile/android/base/home/TabMenuStrip.java @@ -11,191 +11,90 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; +import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; -public class TabMenuStrip extends LinearLayout - implements HomePager.Decor, - View.OnFocusChangeListener { - private static final String LOGTAG = "GeckoTabMenuStrip"; +/** + * {@code TabMenuStrip} is the view used to display {@code HomePager} tabs + * on tablets. See {@code TabMenuStripLayout} for details about how the + * tabs are created and updated. + */ +public class TabMenuStrip extends HorizontalScrollView + implements HomePager.Decor { - private HomePager.OnTitleClickListener mOnTitleClickListener; - private Drawable mStrip; - private View mSelectedView; + // Offset between the selected tab title and the edge of the screen, + // except for the first and last tab in the tab strip. + private static final int TITLE_OFFSET_DIPS = 24; - // Data associated with the scrolling of the strip drawable. - private View toTab; - private View fromTab; - private float progress; - - // This variable is used to predict the direction of scroll. - private float mPrevProgress; + private final int titleOffset; + private final TabMenuStripLayout layout; public TabMenuStrip(Context context, AttributeSet attrs) { super(context, attrs); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabMenuStrip); - final int stripResId = a.getResourceId(R.styleable.TabMenuStrip_strip, -1); - a.recycle(); + // Disable the scroll bar. + setHorizontalScrollBarEnabled(false); - if (stripResId != -1) { - mStrip = getResources().getDrawable(stripResId); - } + titleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); - setWillNotDraw(false); + layout = new TabMenuStripLayout(context, attrs); + addView(layout, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); } @Override public void onAddPagerView(String title) { - final TextView button = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.tab_menu_strip, this, false); - button.setText(title.toUpperCase()); - - addView(button); - button.setOnClickListener(new ViewClickListener(getChildCount() - 1)); - button.setOnFocusChangeListener(this); + layout.onAddPagerView(title); } @Override public void removeAllPagerViews() { - removeAllViews(); + layout.removeAllViews(); } @Override public void onPageSelected(final int position) { - mSelectedView = getChildAt(position); - - // Callback to measure and draw the strip after the view is visible. - ViewTreeObserver vto = mSelectedView.getViewTreeObserver(); - if (vto.isAlive()) { - vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - mSelectedView.getViewTreeObserver().removeGlobalOnLayoutListener(this); - - if (mStrip != null) { - mStrip.setBounds(mSelectedView.getLeft(), - mSelectedView.getTop(), - mSelectedView.getRight(), - mSelectedView.getBottom()); - } - - mPrevProgress = position; - } - }); - } + layout.onPageSelected(position); } - // Page scroll animates the drawable and its bounds from the previous to next child view. @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - if (mStrip == null) { - return; - } + layout.onPageScrolled(position, positionOffset, positionOffsetPixels); - setScrollingData(position, positionOffset); - - if (fromTab == null || toTab == null) { + final View selectedTitle = layout.getChildAt(position); + if (selectedTitle == null) { return; } - final int fromTabLeft = fromTab.getLeft(); - final int fromTabRight = fromTab.getRight(); - - final int toTabLeft = toTab.getLeft(); - final int toTabRight = toTab.getRight(); - - mStrip.setBounds((int) (fromTabLeft + ((toTabLeft - fromTabLeft) * progress)), - 0, - (int) (fromTabRight + ((toTabRight - fromTabRight) * progress)), - getHeight()); - invalidate(); - } + final int selectedTitleOffset = (int) (positionOffset * selectedTitle.getWidth()); - /* - * position + positionOffset goes from 0 to 2 as we scroll from page 1 to 3. - * Normalized progress is relative to the the direction the page is being scrolled towards. - * For this, we maintain direction of scroll with a state, and the child view we are moving towards and away from. - */ - private void setScrollingData(int position, float positionOffset) { - if (position >= getChildCount() - 1) { - return; - } - - final float currProgress = position + positionOffset; - - if (mPrevProgress > currProgress) { - toTab = getChildAt(position); - fromTab = getChildAt(position + 1); - progress = 1 - positionOffset; - } else { - toTab = getChildAt(position + 1); - fromTab = getChildAt(position); - progress = positionOffset; + int titleLeft = selectedTitle.getLeft() + selectedTitleOffset; + if (position > 0) { + titleLeft -= titleOffset; } - mPrevProgress = currProgress; - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mStrip != null) { - mStrip.draw(canvas); - } - } - - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (v == this && hasFocus && getChildCount() > 0) { - mSelectedView.requestFocus(); - return; + int titleRight = selectedTitle.getRight() + selectedTitleOffset; + if (position < layout.getChildCount() - 1) { + titleRight += titleOffset; } - if (!hasFocus) { - return; - } - - int i = 0; - final int numTabs = getChildCount(); - - while (i < numTabs) { - View view = getChildAt(i); - if (view == v) { - view.requestFocus(); - if (isShown()) { - // A view is focused so send an event to announce the menu strip state. - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); - } - break; - } - - i++; + final int scrollX = getScrollX(); + if (titleLeft < scrollX) { + // Tab strip overflows to the left. + scrollTo(titleLeft, 0); + } else if (titleRight > scrollX + getWidth()) { + // Tab strip overflows to the right. + scrollTo(titleRight - getWidth(), 0); } } @Override public void setOnTitleClickListener(HomePager.OnTitleClickListener onTitleClickListener) { - mOnTitleClickListener = onTitleClickListener; - } - - private class ViewClickListener implements OnClickListener { - private final int mIndex; - - public ViewClickListener(int index) { - mIndex = index; - } - - @Override - public void onClick(View view) { - if (mOnTitleClickListener != null) { - mOnTitleClickListener.onTitleClicked(mIndex); - } - } + layout.setOnTitleClickListener(onTitleClickListener); } }
new file mode 100644 --- /dev/null +++ b/mobile/android/base/home/TabMenuStripLayout.java @@ -0,0 +1,194 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * 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/. */ + +package org.mozilla.gecko.home; + +import org.mozilla.gecko.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; +import android.widget.LinearLayout; +import android.widget.TextView; + +/** + * {@code TabMenuStripLayout} is the view that draws the {@code HomePager} + * tabs that are displayed in {@code TabMenuStrip}. + */ +class TabMenuStripLayout extends LinearLayout + implements View.OnFocusChangeListener { + + private HomePager.OnTitleClickListener onTitleClickListener; + private Drawable strip; + private View selectedView; + + // Data associated with the scrolling of the strip drawable. + private View toTab; + private View fromTab; + private float progress; + + // This variable is used to predict the direction of scroll. + private float prevProgress; + + TabMenuStripLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabMenuStrip); + final int stripResId = a.getResourceId(R.styleable.TabMenuStrip_strip, -1); + a.recycle(); + + if (stripResId != -1) { + strip = getResources().getDrawable(stripResId); + } + + setWillNotDraw(false); + } + + void onAddPagerView(String title) { + final TextView button = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.tab_menu_strip, this, false); + button.setText(title.toUpperCase()); + + addView(button); + button.setOnClickListener(new ViewClickListener(getChildCount() - 1)); + button.setOnFocusChangeListener(this); + } + + void onPageSelected(final int position) { + selectedView = getChildAt(position); + + // Callback to measure and draw the strip after the view is visible. + ViewTreeObserver vto = selectedView.getViewTreeObserver(); + if (vto.isAlive()) { + vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + selectedView.getViewTreeObserver().removeGlobalOnLayoutListener(this); + + if (strip != null) { + strip.setBounds(selectedView.getLeft(), + selectedView.getTop(), + selectedView.getRight(), + selectedView.getBottom()); + } + + prevProgress = position; + } + }); + } + } + + // Page scroll animates the drawable and its bounds from the previous to next child view. + void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (strip == null) { + return; + } + + setScrollingData(position, positionOffset); + + if (fromTab == null || toTab == null) { + return; + } + + final int fromTabLeft = fromTab.getLeft(); + final int fromTabRight = fromTab.getRight(); + + final int toTabLeft = toTab.getLeft(); + final int toTabRight = toTab.getRight(); + + strip.setBounds((int) (fromTabLeft + ((toTabLeft - fromTabLeft) * progress)), + 0, + (int) (fromTabRight + ((toTabRight - fromTabRight) * progress)), + getHeight()); + invalidate(); + } + + /* + * position + positionOffset goes from 0 to 2 as we scroll from page 1 to 3. + * Normalized progress is relative to the the direction the page is being scrolled towards. + * For this, we maintain direction of scroll with a state, and the child view we are moving towards and away from. + */ + void setScrollingData(int position, float positionOffset) { + if (position >= getChildCount() - 1) { + return; + } + + final float currProgress = position + positionOffset; + + if (prevProgress > currProgress) { + toTab = getChildAt(position); + fromTab = getChildAt(position + 1); + progress = 1 - positionOffset; + } else { + toTab = getChildAt(position + 1); + fromTab = getChildAt(position); + progress = positionOffset; + } + + prevProgress = currProgress; + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (strip != null) { + strip.draw(canvas); + } + } + + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (v == this && hasFocus && getChildCount() > 0) { + selectedView.requestFocus(); + return; + } + + if (!hasFocus) { + return; + } + + int i = 0; + final int numTabs = getChildCount(); + + while (i < numTabs) { + View view = getChildAt(i); + if (view == v) { + view.requestFocus(); + if (isShown()) { + // A view is focused so send an event to announce the menu strip state. + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + break; + } + + i++; + } + } + + void setOnTitleClickListener(HomePager.OnTitleClickListener onTitleClickListener) { + this.onTitleClickListener = onTitleClickListener; + } + + private class ViewClickListener implements OnClickListener { + private final int mIndex; + + public ViewClickListener(int index) { + mIndex = index; + } + + @Override + public void onClick(View view) { + if (onTitleClickListener != null) { + onTitleClickListener.onTitleClicked(mIndex); + } + } + } +}
--- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -274,16 +274,17 @@ gbjar.sources += [ 'home/ReadingListPanel.java', 'home/ReadingListRow.java', 'home/SearchEngine.java', 'home/SearchEngineRow.java', 'home/SearchLoader.java', 'home/SimpleCursorLoader.java', 'home/SuggestClient.java', 'home/TabMenuStrip.java', + 'home/TabMenuStripLayout.java', 'home/TopSitesGridItemView.java', 'home/TopSitesGridView.java', 'home/TopSitesPanel.java', 'home/TopSitesThumbnailView.java', 'home/TwoLinePageRow.java', 'InputMethods.java', 'JavaAddonManager.java', 'LightweightTheme.java',
--- a/mobile/android/base/resources/layout/panel_article_item.xml +++ b/mobile/android/base/resources/layout/panel_article_item.xml @@ -3,29 +3,24 @@ - 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/. --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/image" android:layout_width="54dp" android:layout_height="44dp" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" android:layout_marginLeft="10dip" android:scaleType="centerCrop"/> <LinearLayout android:id="@+id/title_desc_container" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:paddingTop="15dip" - android:paddingBottom="15dip" android:paddingLeft="10dip" android:paddingRight="10dip" - android:minHeight="@dimen/page_row_height" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/title" style="@style/Widget.PanelItemView.Title" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
--- a/mobile/android/base/resources/values/dimens.xml +++ b/mobile/android/base/resources/values/dimens.xml @@ -102,9 +102,12 @@ <dimen name="home_banner_height">72dp</dimen> <!-- Icon Grid --> <dimen name="icongrid_columnwidth">128dp</dimen> <dimen name="icongrid_padding">16dp</dimen> <!-- PanelGridView dimensions --> <dimen name="panel_grid_view_column_width">150dp</dimen> + + <!-- ArticleItemView dimensions --> + <dimen name="article_item_view_padding">15dp</dimen> </resources>
--- a/mobile/android/base/tests/BaseTest.java +++ b/mobile/android/base/tests/BaseTest.java @@ -433,19 +433,18 @@ abstract class BaseTest extends BaseRobo public void selectMenuItemByPath(String[] listItems) { int listLength = listItems.length; if (listLength > 0) { selectMenuItem(listItems[0]); } if (listLength > 1) { for (int i = 1; i < listLength; i++) { String itemName = "^" + listItems[i] + "$"; - if (!waitForPreferencesText(itemName)) { - mSolo.scrollDown(); - } + mAsserter.ok(waitForPreferencesText(itemName), "Waiting for and scrolling once to find item " + itemName, itemName + " found"); + mAsserter.ok(waitForEnabledText(itemName), "Waiting for enabled text " + itemName, itemName + " option is present and enabled"); mSolo.clickOnText(itemName); } } } public final void selectMenuItem(String menuItemName) { // build the item name ready to be used String itemName = "^" + menuItemName + "$";
--- a/mobile/android/base/tests/MotionEventHelper.java +++ b/mobile/android/base/tests/MotionEventHelper.java @@ -21,39 +21,54 @@ class MotionEventHelper { mSurfaceOffsetY = surfaceOffsetY; Log.i(LOGTAG, "Initialized using offset (" + mSurfaceOffsetX + "," + mSurfaceOffsetY + ")"); } public long down(float x, float y) { Log.d(LOGTAG, "Triggering down at (" + x + "," + y + ")"); long downTime = SystemClock.uptimeMillis(); MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - mInstrumentation.sendPointerSync(event); + try { + mInstrumentation.sendPointerSync(event); + } finally { + event.recycle(); + event = null; + } return downTime; } public long move(long downTime, float x, float y) { return move(downTime, SystemClock.uptimeMillis(), x, y); } public long move(long downTime, long moveTime, float x, float y) { Log.d(LOGTAG, "Triggering move to (" + x + "," + y + ")"); MotionEvent event = MotionEvent.obtain(downTime, moveTime, MotionEvent.ACTION_MOVE, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - mInstrumentation.sendPointerSync(event); + try { + mInstrumentation.sendPointerSync(event); + } finally { + event.recycle(); + event = null; + } return downTime; } public long up(long downTime, float x, float y) { return up(downTime, SystemClock.uptimeMillis(), x, y); } public long up(long downTime, long upTime, float x, float y) { Log.d(LOGTAG, "Triggering up at (" + x + "," + y + ")"); MotionEvent event = MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - mInstrumentation.sendPointerSync(event); + try { + mInstrumentation.sendPointerSync(event); + } finally { + event.recycle(); + event = null; + } return -1L; } public Thread dragAsync(final float startX, final float startY, final float endX, final float endY, final long durationMillis) { Thread t = new Thread() { @Override public void run() { int numEvents = (int)(durationMillis * DRAG_EVENTS_PER_SECOND / 1000);
--- a/mobile/android/base/tests/MotionEventReplayer.java +++ b/mobile/android/base/tests/MotionEventReplayer.java @@ -198,18 +198,23 @@ class MotionEventReplayer { long.class, long.class, int.class, int.class, pointerIds.getClass(), pointerData.getClass(), int.class, float.class, float.class, int.class, int.class); } event = (MotionEvent)mObtainNanoMethod.invoke(null, downTime, eventTime, eventTime * 1000000, action, pointerCount, pointerIds, (float[])pointerData, metaState, xPrecision, yPrecision, deviceId, edgeFlags); } - Log.v(LOGTAG, "Injecting " + event.toString()); - mInstrumentation.sendPointerSync(event); + try { + Log.v(LOGTAG, "Injecting " + event.toString()); + mInstrumentation.sendPointerSync(event); + } finally { + event.recycle(); + event = null; + } eventProperties.clear(); } } finally { br.close(); } } }
--- a/mobile/android/base/toolbar/BrowserToolbar.java +++ b/mobile/android/base/toolbar/BrowserToolbar.java @@ -45,16 +45,17 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; @@ -185,17 +186,20 @@ public class BrowserToolbar extends Them final Resources res = getResources(); urlBarViewOffset = res.getDimensionPixelSize(R.dimen.url_bar_offset_left); defaultForwardMargin = res.getDimensionPixelSize(R.dimen.forward_default_offset); urlDisplayLayout = (ToolbarDisplayLayout) findViewById(R.id.display_layout); urlBarEntry = findViewById(R.id.url_bar_entry); urlEditLayout = (ToolbarEditLayout) findViewById(R.id.edit_layout); urlBarEntryDefaultLayoutParams = (RelativeLayout.LayoutParams) urlBarEntry.getLayoutParams(); - urlBarEntryShrunkenLayoutParams = new RelativeLayout.LayoutParams(urlBarEntryDefaultLayoutParams); + // API level 19 adds a RelativeLayout.LayoutParams copy constructor, so we explicitly cast + // to ViewGroup.MarginLayoutParams to ensure consistency across platforms. + urlBarEntryShrunkenLayoutParams = new RelativeLayout.LayoutParams( + (ViewGroup.MarginLayoutParams) urlBarEntryDefaultLayoutParams); urlBarEntryShrunkenLayoutParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.edit_layout); urlBarEntryShrunkenLayoutParams.rightMargin = 0; // This will clip the translating edge's image at 60% of its width urlBarTranslatingEdge = (ImageView) findViewById(R.id.url_bar_translating_edge); if (urlBarTranslatingEdge != null) { urlBarTranslatingEdge.getDrawable().setLevel(6000); } @@ -392,17 +396,17 @@ public class BrowserToolbar extends Them } public void refresh() { urlDisplayLayout.dismissSiteIdentityPopup(); } public boolean onBackPressed() { if (isEditing()) { - stopEditing(); + cancelEdit(); return true; } return urlDisplayLayout.dismissSiteIdentityPopup(); } public boolean onKey(int keyCode, KeyEvent event) { if (event.getAction() != KeyEvent.ACTION_DOWN) {