diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-09-17 08:51:49 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-09-17 08:51:49 +0200 |
commit | 882aaf5b1fda7b216051b55e268de78fd5126f42 (patch) | |
tree | ccb3f6f6299a5d1c603e6b73d3892f635bb96a8e /application/palemoon | |
parent | 8ee235ca5df26f39ca3066935bef90c4d28dd61a (diff) | |
parent | d118d486a680ed42030b1bdee263a29831da3e86 (diff) | |
download | UXP-882aaf5b1fda7b216051b55e268de78fd5126f42.tar UXP-882aaf5b1fda7b216051b55e268de78fd5126f42.tar.gz UXP-882aaf5b1fda7b216051b55e268de78fd5126f42.tar.lz UXP-882aaf5b1fda7b216051b55e268de78fd5126f42.tar.xz UXP-882aaf5b1fda7b216051b55e268de78fd5126f42.zip |
Merge branch 'master' into Pale_Moon-release
# Conflicts:
# application/palemoon/config/version.txt
# js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h
# toolkit/components/search/orginal/nsSearchService.js
Diffstat (limited to 'application/palemoon')
21 files changed, 543 insertions, 468 deletions
diff --git a/application/palemoon/app/blocklist.xml b/application/palemoon/app/blocklist.xml index 296b8ad24..d55784169 100644 --- a/application/palemoon/app/blocklist.xml +++ b/application/palemoon/app/blocklist.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='utf-8'?> -<blocklist lastupdate="1521130300000" +<blocklist lastupdate="1534840140000" xmlns="http://www.mozilla.org/2006/addons-blocklist"> <emItems> <emItem blockID="i545" id="superlrcs@svenyor.net"> @@ -2513,7 +2513,17 @@ xmlns="http://www.mozilla.org/2006/addons-blocklist"> <versionRange minVersion="0" maxVersion="52.4.2" severity="3"> </versionRange> <prefs></prefs> - </emItem> + </emItem> + <emItem blockID="pm112" id="{73a6fe31-595d-460b-a920-fcc0f8843232}"> + <versionRange minVersion="0" maxVersion="*" severity="1"> + </versionRange> + <prefs></prefs> + </emItem> + <emItem blockID="pm113" id="addonsmanagerfix@sonco.com"> + <versionRange minVersion="0" maxVersion="*" severity="3"> + </versionRange> + <prefs></prefs> + </emItem> </emItems> <pluginItems> <pluginItem blockID="p26"> diff --git a/application/palemoon/base/content/browser-sets.inc b/application/palemoon/base/content/browser-sets.inc index 64228678e..25794a65c 100644 --- a/application/palemoon/base/content/browser-sets.inc +++ b/application/palemoon/base/content/browser-sets.inc @@ -79,7 +79,6 @@ <command id="Browser:NextTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(1, true);"/> <command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/> <command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/> - <command id="Browser:FocusNextFrame" oncommand="focusNextFrame(event);"/> <command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/> <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/> <command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/> @@ -251,8 +250,6 @@ #ifndef XP_MACOSX <key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/> <key keycode="VK_F5" command="Browser:ReloadSkipCache" modifiers="accel"/> - <key keycode="VK_F6" command="Browser:FocusNextFrame"/> - <key keycode="VK_F6" command="Browser:FocusNextFrame" modifiers="shift"/> <key id="key_fullScreen" keycode="VK_F11" command="View:FullScreen"/> #else <key id="key_fullScreen" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,control"/> diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 7421fc5c3..5cf43850a 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -53,13 +53,20 @@ var gEditUIVisible = true; // Smart getter for the findbar. If you don't wish to force the creation of // the findbar, check gFindBarInitialized first. - -this.__defineGetter__("gFindBar", function() { - return window.gBrowser.getFindBar(); -}); - -this.__defineGetter__("gFindBarInitialized", function() { - return window.gBrowser.isFindBarInitialized(); +var gFindBarInitialized = false; +XPCOMUtils.defineLazyGetter(window, "gFindBar", function() { + let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + let findbar = document.createElementNS(XULNS, "findbar"); + findbar.id = "FindToolbar"; + + let browserBottomBox = document.getElementById("browser-bottombox"); + browserBottomBox.insertBefore(findbar, browserBottomBox.firstChild); + + // Force a style flush to ensure that our binding is attached. + findbar.clientTop; + findbar.browser = gBrowser.mCurrentBrowser; + window.gFindBarInitialized = true; + return findbar; }); XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", @@ -7222,14 +7229,6 @@ var MousePosTracker = { } }; -function focusNextFrame(event) { - let fm = Services.focus; - let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC; - let element = fm.moveFocus(window, null, dir, fm.FLAG_BYKEY); - if (element.ownerDocument == document) - focusAndSelectUrlBar(); -} - var BrowserChromeTest = { _cb: null, _ready: false, diff --git a/application/palemoon/base/content/browser.xul b/application/palemoon/base/content/browser.xul index 90899bb88..07ca54722 100644 --- a/application/palemoon/base/content/browser.xul +++ b/application/palemoon/base/content/browser.xul @@ -59,6 +59,7 @@ macanimationtype="document" screenX="4" screenY="4" fullscreenbutton="true" + retargetdocumentfocus="urlbar" persist="screenX screenY width height sizemode"> # All JS files which are not content (only) dependent that browser.xul diff --git a/application/palemoon/base/content/nsContextMenu.js b/application/palemoon/base/content/nsContextMenu.js index 19b2fac77..1d4f88816 100644 --- a/application/palemoon/base/content/nsContextMenu.js +++ b/application/palemoon/base/content/nsContextMenu.js @@ -838,30 +838,8 @@ nsContextMenu.prototype = { // View Partial Source viewPartialSource: function(aContext) { - var focusedWindow = document.commandDispatcher.focusedWindow; - if (focusedWindow == window) - focusedWindow = content; - - var docCharset = null; - if (focusedWindow) - docCharset = "charset=" + focusedWindow.document.characterSet; - - // "View Selection Source" and others such as "View MathML Source" - // are mutually exclusive, with the precedence given to the selection - // when there is one - var reference = null; - if (aContext == "selection") - reference = focusedWindow.getSelection(); - else if (aContext == "mathml") - reference = this.target; - else - throw "not reached"; - - // unused (and play nice for fragments generated via XSLT too) - var docUrl = null; - window.openDialog("chrome://global/content/viewPartialSource.xul", - "_blank", "scrollbars,resizable,chrome,dialog=no", - docUrl, docCharset, reference, aContext); + let target = aContext == "mathml" ? this.target : null; + top.gViewSourceUtils.viewPartialSourceInBrowser(gBrowser.selectedBrowser, target); }, // Open new "view source" window with the frame's URL. diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index d5735149e..93818e290 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -128,10 +128,6 @@ false </field> - <field name="_lastFindValue"> - "" - </field> - <property name="_numPinnedTabs" readonly="true"> <getter><![CDATA[ for (var i = 0; i < this.tabs.length; i++) { @@ -158,43 +154,6 @@ ]]></getter> </property> - <method name="isFindBarInitialized"> - <parameter name="aTab"/> - <body><![CDATA[ - return (aTab || this.selectedTab)._findBar != undefined; - ]]></body> - </method> - - <method name="getFindBar"> - <parameter name="aTab"/> - <body><![CDATA[ - if (!aTab) - aTab = this.selectedTab; - - if (aTab._findBar) - return aTab._findBar; - - let findBar = document.createElementNS(this.namespaceURI, "findbar"); - let browser = this.getBrowserForTab(aTab); - let browserContainer = this.getBrowserContainer(browser); - browserContainer.appendChild(findBar); - - // Force a style flush to ensure that our binding is attached. - findBar.clientTop; - - findBar.browser = browser; - findBar._findField.value = this._lastFindValue; - - aTab._findBar = findBar; - - let event = document.createEvent("Events"); - event.initEvent("TabFindInitialized", true, false); - aTab.dispatchEvent(event); - - return findBar; - ]]></body> - </method> - <method name="updateWindowResizers"> <body><![CDATA[ if (!window.gShowPageResizers) @@ -1082,6 +1041,11 @@ // Bug 666809 - SecurityUI support for e10s var webProgress = this.mCurrentBrowser.webProgress; var securityUI = this.mCurrentBrowser.securityUI; + + // Update global findbar with new content browser + if (gFindBarInitialized) { + gFindBar.browser = newBrowser; + } this._callProgressListeners(null, "onLocationChange", [webProgress, null, loc, 0], true, @@ -1104,11 +1068,9 @@ this.mCurrentTab.removeAttribute("unread"); this.selectedTab.lastAccessed = Date.now(); - let oldFindBar = oldTab._findBar; - if (oldFindBar && - oldFindBar.findMode == oldFindBar.FIND_NORMAL && - !oldFindBar.hidden) - this._lastFindValue = oldFindBar._findField.value; + // Bug 666816 - TypeAheadFind support for e10s + if (!gMultiProcessBrowser) + this._fastFind.setDocShell(this.mCurrentBrowser.docShell); this.updateTitlebar(); @@ -1159,11 +1121,6 @@ // Adjust focus oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused); - if (this.isFindBarInitialized(oldTab)) { - let findBar = this.getFindBar(oldTab); - oldTab._findBarFocused = (!findBar.hidden && - findBar._findField.getAttribute("focused") == "true"); - } do { // When focus is in the tab bar, retain it there. if (document.activeElement == oldTab) { @@ -1199,12 +1156,11 @@ } } - // Focus the find bar if it was previously focused for that tab. - if (gFindBarInitialized && !gFindBar.hidden && - this.selectedTab._findBarFocused) { - gFindBar._findField.focus(); + // If the find bar is focused, keep it focused. + if (gFindBarInitialized && + !gFindBar.hidden && + gFindBar.getElement("findbar-textbox").getAttribute("focused") == "true") break; - } // Otherwise, focus the content area. let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); @@ -1473,6 +1429,7 @@ var aRelatedToCurrent; var aSkipAnimation; var aOriginPrincipal; + var aSkipBackgroundNotify; if (arguments.length == 2 && typeof arguments[1] == "object" && !(arguments[1] instanceof Ci.nsIURI)) { @@ -1488,6 +1445,7 @@ aRelatedToCurrent = params.relatedToCurrent; aSkipAnimation = params.skipAnimation; aOriginPrincipal = params.originPrincipal; + aSkipBackgroundNotify = params.skipBackgroundNotify; } // if we're adding tabs, we're past interrupt mode, ditch the owner @@ -1511,6 +1469,11 @@ t.setAttribute("crop", "end"); t.setAttribute("validate", "never"); //PMed t.setAttribute("onerror", "this.removeAttribute('image');"); + + if (aSkipBackgroundNotify) { + t.setAttribute("skipbackgroundnotify", true); + } + t.className = "tabbrowser-tab"; this.tabContainer._unlockTabSizing(); @@ -1622,6 +1585,7 @@ this.mTabListeners[position] = tabListener; this.mTabFilters[position] = filter; + b._fastFind = this.fastFind; b.droppedLinkHandler = handleDroppedLink; // If we just created a new tab that loads the default @@ -2310,17 +2274,6 @@ this._swapBrowserDocShells(aOurTab, otherBrowser); } - // Handle findbar data (if any) - let otherFindBar = aOtherTab._findBar; - if (otherFindBar && - otherFindBar.findMode == otherFindBar.FIND_NORMAL) { - let ourFindBar = this.getFindBar(aOurTab); - ourFindBar._findField.value = otherFindBar._findField.value; - if (!otherFindBar.hidden) { - ourFindBar.onFindCommand(); - } - } - // Finish tearing down the tab that's going away. remoteBrowser._endRemoveTab(aOtherTab); @@ -2873,6 +2826,21 @@ onget="return this.mCurrentBrowser.currentURI;" readonly="true"/> + <field name="_fastFind">null</field> + <property name="fastFind" + readonly="true"> + <getter> + <![CDATA[ + if (!this._fastFind) { + this._fastFind = Components.classes["@mozilla.org/typeaheadfind;1"] + .createInstance(Components.interfaces.nsITypeAheadFind); + this._fastFind.init(this.docShell); + } + return this._fastFind; + ]]> + </getter> + </property> + <field name="_lastSearchString">null</field> <field name="_lastSearchHighlight">false</field> @@ -3176,28 +3144,6 @@ window.focus(); break; } - case "Findbar:Keypress": - let tab = this.getTabForBrowser(browser); - // If the find bar for this tab is not yet alive, only initialize - // it if there's a possibility FindAsYouType will be used. - // There's no point in doing it for most random keypresses. - if (!this.isFindBarInitialized(tab) && - aMessage.data.shouldFastFind) { - let shouldFastFind = this._findAsYouType; - if (!shouldFastFind) { - // Please keep in sync with toolkit/content/widgets/findbar.xml - const FAYT_LINKS_KEY = "'"; - const FAYT_TEXT_KEY = "/"; - let charCode = aMessage.data.fakeEvent.charCode; - let key = charCode ? String.fromCharCode(charCode) : null; - shouldFastFind = key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY; - } - if (shouldFastFind) { - // Make sure we return the result. - return this.getFindBar(tab).receiveMessage(aMessage); - } - } - break; } ]]></body> </method> @@ -3264,11 +3210,6 @@ this.mCurrentBrowser); } messageManager.addMessageListener("DOMWebNotificationClicked", this); - - // To correctly handle keypresses for potential FindAsYouType, while - // the tab's find bar is not yet initialized. - this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind"); - messageManager.addMessageListener("Findbar:Keypress", this); ]]> </constructor> @@ -3523,7 +3464,6 @@ tab.setAttribute("onerror", "this.removeAttribute('image');"); this.adjustTabstrip(); - Services.prefs.addObserver("accessibility.typeaheadfind", this._prefObserver, false); Services.prefs.addObserver("browser.tabs.", this._prefObserver, false); window.addEventListener("resize", this, false); window.addEventListener("load", this, false); @@ -3539,7 +3479,6 @@ <destructor> <![CDATA[ - Services.prefs.removeObserver("accessibility.typeaheadfind", this._prefObserver); Services.prefs.removeObserver("browser.tabs.", this._prefObserver); ]]> </destructor> @@ -3605,9 +3544,6 @@ observe: function (subject, topic, data) { switch (data) { - case "accessibility.typeaheadfind": - this._findAsYouType = Services.prefs.getBoolPref(data); - break; case "browser.tabs.closeButtons": this.tabContainer.mCloseButtons = Services.prefs.getIntPref(data); this.tabContainer.adjustTabstrip(); @@ -4214,7 +4150,11 @@ this._fillTrailingGap(); this._handleTabSelect(); } else { - this._notifyBackgroundTab(tab); + if (tab.hasAttribute("skipbackgroundnotify")) { + tab.removeAttribute("skipbackgroundnotify"); + } else { + this._notifyBackgroundTab(tab); + } } // XXXmano: this is a temporary workaround for bug 345399 diff --git a/application/palemoon/components/downloads/content/downloadsOverlay.xul b/application/palemoon/components/downloads/content/downloadsOverlay.xul index 2a4fe9099..ca35ee3cf 100644 --- a/application/palemoon/components/downloads/content/downloadsOverlay.xul +++ b/application/palemoon/components/downloads/content/downloadsOverlay.xul @@ -35,7 +35,7 @@ oncommand="goDoCommand('downloadsCmd_clearList')"/> </commandset> - <popupset> + <popupset id="mainPopupSet"> <!-- The panel has level="top" to ensure that it is never hidden by the taskbar on Windows. See bug 672365. For accessibility to screen readers, we use a label on the panel instead of the anchor because the diff --git a/application/palemoon/components/preferences/jar.mn b/application/palemoon/components/preferences/jar.mn index 2e2949306..47909ddc9 100644 --- a/application/palemoon/components/preferences/jar.mn +++ b/application/palemoon/components/preferences/jar.mn @@ -24,6 +24,7 @@ browser.jar: content/browser/preferences/languages.js * content/browser/preferences/main.xul content/browser/preferences/main.js + content/browser/preferences/newtaburl.js content/browser/preferences/permissions.xul * content/browser/preferences/permissions.js * content/browser/preferences/preferences.xul diff --git a/application/palemoon/components/preferences/main.xul b/application/palemoon/components/preferences/main.xul index 7634056eb..bb51947b0 100644 --- a/application/palemoon/components/preferences/main.xul +++ b/application/palemoon/components/preferences/main.xul @@ -96,6 +96,7 @@ type="autocomplete" autocompletesearch="history" onsyncfrompreference="return gMainPane.syncFromHomePref();" onsynctopreference="return gMainPane.syncToHomePref(this.value);" + oninput="gNewtabUrl.writeNewtabUrl(null, this.value);" placeholder="&abouthome.pageTitle;" preference="browser.startup.homepage"/> </hbox> @@ -103,15 +104,15 @@ <button label="" accesskey="&useCurrentPage.accesskey;" label1="&useCurrentPage.label;" label2="&useMultiple.label;" - oncommand="gMainPane.setHomePageToCurrent();" + oncommand="gMainPane.setHomePageToCurrent(); gNewtabUrl.writeNewtabUrl();" id="useCurrent" preference="pref.browser.homepage.disable_button.current_page"/> <button label="&chooseBookmark.label;" accesskey="&chooseBookmark.accesskey;" - oncommand="gMainPane.setHomePageToBookmark();" + oncommand="gMainPane.setHomePageToBookmark(); gNewtabUrl.writeNewtabUrl();" id="useBookmark" preference="pref.browser.homepage.disable_button.bookmark_page"/> <button label="&restoreDefault.label;" accesskey="&restoreDefault.accesskey;" - oncommand="gMainPane.restoreDefaultHomePage();" + oncommand="gMainPane.restoreDefaultHomePage(); gNewtabUrl.writeNewtabUrl();" id="restoreDefaultHomePage" preference="pref.browser.homepage.disable_button.restore_default"/> </hbox> diff --git a/application/palemoon/components/preferences/newtaburl.js b/application/palemoon/components/preferences/newtaburl.js new file mode 100644 index 000000000..ac0eec1c5 --- /dev/null +++ b/application/palemoon/components/preferences/newtaburl.js @@ -0,0 +1,68 @@ +/* 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/. */
+
+var gNewtabUrl = {
+ /**
+ * Writes browser.newtab.url with the appropriate value.
+ * If the choice is "my home page", get and sanitize
+ * the browser home page URL to make it suitable for newtab use.
+ *
+ * Called from prefwindow ondialogaccept in preferences.xul,
+ * newtabPage oncommand in tabs.xul, browserHomePage oninput,
+ * useCurrent, useBookmark and restoreDefaultHomePage oncommand
+ * in main.xul to consider instantApply.
+ */
+ writeNewtabUrl: function(newtabUrlChoice, browserHomepageUrl) {
+ try {
+ if (newtabUrlChoice) {
+ if (Services.prefs.getBoolPref("browser.preferences.instantApply")) {
+ newtabUrlChoice = parseInt(newtabUrlChoice);
+ } else {
+ return;
+ }
+ } else {
+ newtabUrlChoice = Services.prefs.getIntPref("browser.newtab.choice");
+ }
+ if (browserHomepageUrl || browserHomepageUrl == "") {
+ if (Services.prefs.getBoolPref("browser.preferences.instantApply")) {
+ if (browserHomepageUrl == "") {
+ browserHomepageUrl = "about:home";
+ }
+ } else {
+ return;
+ }
+ } else {
+ browserHomepageUrl = Services.prefs.getComplexValue("browser.startup.homepage",
+ Components.interfaces.nsIPrefLocalizedString).data;
+ }
+ let newtabUrlPref = Services.prefs.getCharPref("browser.newtab.url");
+ switch (newtabUrlChoice) {
+ case 1:
+ newtabUrlPref = "about:logopage";
+ break;
+ case 2:
+ newtabUrlPref = Services.prefs.getDefaultBranch("browser.")
+ .getComplexValue("startup.homepage",
+ Components.interfaces.nsIPrefLocalizedString).data;
+ break;
+ case 3:
+ // If url is a pipe-delimited set of pages, just take the first one.
+ let newtabUrlSanitizedPref=browserHomepageUrl.split("|")[0];
+ // XXX: do we need extra sanitation here, e.g. for invalid URLs?
+ Services.prefs.setCharPref("browser.newtab.myhome", newtabUrlSanitizedPref);
+ newtabUrlPref = newtabUrlSanitizedPref;
+ break;
+ case 4:
+ newtabUrlPref = "about:newtab";
+ break;
+ default:
+ // In case of any other value it's a custom URL, consider instantApply.
+ if (this.newtabPageCustom) {
+ newtabUrlPref = this.newtabPageCustom;
+ }
+ }
+ Services.prefs.setCharPref("browser.newtab.url",newtabUrlPref);
+ } catch(e) { console.error(e); }
+ }
+};
diff --git a/application/palemoon/components/preferences/preferences.xul b/application/palemoon/components/preferences/preferences.xul index 2f00b960a..a1d9c8cf7 100644 --- a/application/palemoon/components/preferences/preferences.xul +++ b/application/palemoon/components/preferences/preferences.xul @@ -56,10 +56,10 @@ #endif #endif onunload="if (typeof gSecurityPane != 'undefined') gSecurityPane.syncAddonSecurityLevel();" - ondialogaccept="if (typeof gTabsPane != 'undefined') gTabsPane.writeNewtabUrl(); - return true;"> + ondialogaccept="gNewtabUrl.writeNewtabUrl();"> <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/> + <script type="application/javascript" src="chrome://browser/content/preferences/newtaburl.js"/> <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/> <stringbundle id="bundlePreferences" diff --git a/application/palemoon/components/preferences/tabs.js b/application/palemoon/components/preferences/tabs.js index f0ad8490c..17084a770 100644 --- a/application/palemoon/components/preferences/tabs.js +++ b/application/palemoon/components/preferences/tabs.js @@ -85,11 +85,14 @@ var gTabsPane = { let newtabUrlPref = document.getElementById("browser.newtab.url"); let newtabUrlSanitizedPref = document.getElementById("browser.newtab.myhome"); let newtabUrlChoice = document.getElementById("browser.newtab.choice"); + let defaultStartupHomepage = Services.prefs.getDefaultBranch("browser.") + .getComplexValue("startup.homepage", + Components.interfaces.nsIPrefLocalizedString).data; switch (newtabUrlPref.value) { case "about:logopage": newtabUrlChoice.value = 1; break; - case "http://start.palemoon.org/": + case defaultStartupHomepage: newtabUrlChoice.value = 2; break; case newtabUrlSanitizedPref.value: @@ -104,54 +107,5 @@ var gTabsPane = { // We need this to consider instantApply. this.newtabPageCustom = newtabUrlPref.value; } - }, - - /** - * Writes browser.newtab.url with the appropriate value. - * if the choice is "my home page", get and sanitize the browser home page - * URL to make it suitable for newtab use. - * - * Called from prefwindow's ondialogaccept handler and - * from browser.newtab.choice's oncommand to consider instantApply. - */ - writeNewtabUrl: function(newtabUrlChoice) { - try { - if (newtabUrlChoice) { - if (Services.prefs.getBoolPref("browser.preferences.instantApply")) { - newtabUrlChoice = parseInt(newtabUrlChoice); - } else { - return; - } - } else { - newtabUrlChoice = Services.prefs.getIntPref("browser.newtab.choice"); - } - let browserHomepageUrl = Services.prefs.getComplexValue("browser.startup.homepage", - Components.interfaces.nsIPrefLocalizedString).data; - let newtabUrlPref = Services.prefs.getCharPref("browser.newtab.url"); - switch (newtabUrlChoice) { - case 1: - newtabUrlPref = "about:logopage"; - break; - case 2: - newtabUrlPref = "http://start.palemoon.org/"; - break; - case 3: - // If url is a pipe-delimited set of pages, just take the first one. - let newtabUrlSanitizedPref=browserHomepageUrl.split("|")[0]; - // XXX: do we need extra sanitation here, e.g. for invalid URLs? - Services.prefs.setCharPref("browser.newtab.myhome", newtabUrlSanitizedPref); - newtabUrlPref = newtabUrlSanitizedPref; - break; - case 4: - newtabUrlPref = "about:newtab"; - break; - default: - // In case of any other value it's a custom URL, consider instantApply. - if (this.newtabPageCustom) { - newtabUrlPref = this.newtabPageCustom; - } - } - Services.prefs.setCharPref("browser.newtab.url",newtabUrlPref); - } catch(e) { console.error(e); } } }; diff --git a/application/palemoon/components/preferences/tabs.xul b/application/palemoon/components/preferences/tabs.xul index f5b44b776..64529d60d 100644 --- a/application/palemoon/components/preferences/tabs.xul +++ b/application/palemoon/components/preferences/tabs.xul @@ -85,7 +85,7 @@ <menulist id="newtabPage" preference="browser.newtab.choice" - oncommand="gTabsPane.writeNewtabUrl(event.target.value);"> + oncommand="gNewtabUrl.writeNewtabUrl(event.target.value);"> <menupopup> <menuitem label="&newtabPage.custom.label;" value="0" id="newtabPageCustom" hidden="true" /> <menuitem label="&newtabPage.blank.label;" value="1" /> diff --git a/application/palemoon/components/sessionstore/SessionStore.jsm b/application/palemoon/components/sessionstore/SessionStore.jsm index c5e55321c..e19a578f4 100644 --- a/application/palemoon/components/sessionstore/SessionStore.jsm +++ b/application/palemoon/components/sessionstore/SessionStore.jsm @@ -2739,7 +2739,9 @@ var SessionStoreInternal = { for (var t = 0; t < newTabCount; t++) { tabs.push(t < openTabCount ? tabbrowser.tabs[t] : - tabbrowser.addTab("about:blank", {skipAnimation: true})); + tabbrowser.addTab("about:blank", + {skipAnimation: true, + skipBackgroundNotify: true})); // when resuming at startup: add additionally requested pages to the end if (!aOverwriteTabs && root._firstTabs) { tabbrowser.moveTabTo(tabs[t], t); @@ -4684,7 +4686,8 @@ var TabAttributes = { // 'image' should not be accessed directly but handled by using the // gBrowser.getIcon()/setIcon() methods. // 'pending' is used internal by sessionstore and managed accordingly. - _skipAttrs: new Set(["image", "pending"]), + // 'skipbackgroundnotify' is used internal by tabbrowser.xml. + _skipAttrs: new Set(["image", "pending", "skipbackgroundnotify"]), persist: function (name) { if (this._attrs.has(name) || this._skipAttrs.has(name)) { diff --git a/application/palemoon/config/version.txt b/application/palemoon/config/version.txt index 41f060f2f..035159168 100644 --- a/application/palemoon/config/version.txt +++ b/application/palemoon/config/version.txt @@ -1 +1 @@ -28.0.1
\ No newline at end of file +28.1.0
\ No newline at end of file diff --git a/application/palemoon/locales/en-US/installer/custom.properties b/application/palemoon/locales/en-US/installer/custom.properties index ef29b1e7e..8f95a194b 100644 --- a/application/palemoon/locales/en-US/installer/custom.properties +++ b/application/palemoon/locales/en-US/installer/custom.properties @@ -46,7 +46,9 @@ WARN_MANUALLY_CLOSE_APP_UNINSTALL=$BrandShortName must be closed to proceed with WARN_MANUALLY_CLOSE_APP_LAUNCH=$BrandShortName is already running.\n\nPlease close $BrandShortName prior to launching the version you have just installed. WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory. WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location. -WARN_MIN_SUPPORTED_OS_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. +WARN_MIN_SUPPORTED_OSVER_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. +WARN_MIN_SUPPORTED_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires a processor with ${MinSupportedCPU} support. +WARN_MIN_SUPPORTED_OSVER_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer and a processor with ${MinSupportedCPU} support. WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of $BrandShortName. Do you want to reboot now? WARN_RESTART_REQUIRED_UPGRADE=Your computer must be restarted to complete a previous upgrade of $BrandShortName. Do you want to reboot now? ERROR_CREATE_DIRECTORY_PREFIX=Error creating directory: diff --git a/application/palemoon/locales/en-US/installer/nsisstrings.properties b/application/palemoon/locales/en-US/installer/nsisstrings.properties index 0144c2a98..fc2898860 100644 --- a/application/palemoon/locales/en-US/installer/nsisstrings.properties +++ b/application/palemoon/locales/en-US/installer/nsisstrings.properties @@ -25,7 +25,9 @@ INSTALL_BLURB1=You're about to enjoy the very latest in speed, flexibility and s INSTALL_BLURB2=That's because $BrandShortName is made by a non-profit to make browsing and the Web better for you. INSTALL_BLURB3=You're also joining a global community of users, contributors and developers working to make the best browser in the world. -WARN_MIN_SUPPORTED_OS_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. +WARN_MIN_SUPPORTED_OSVER_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer. +WARN_MIN_SUPPORTED_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires a processor with ${MinSupportedCPU} support. +WARN_MIN_SUPPORTED_OSVER_CPU_MSG=Sorry, $BrandShortName can't be installed. This version of $BrandShortName requires ${MinSupportedVer} or newer and a processor with ${MinSupportedCPU} support. WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory. WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location. WARN_ROOT_INSTALL=Unable to install to the root of your disk.\n\nClick OK to select a different location. @@ -46,15 +48,16 @@ ADD_CheckboxShortcutInStartMenu=In my &Start Menu Programs Folder ADD_CheckboxShortcutOnDesktop=On my &Desktop SPACE_REQUIRED=Space Required: SPACE_AVAILABLE=Space Available: -ONE_MOMENT=One moment, $BrandShortName will launch as soon as the install is complete… +ONE_MOMENT_INSTALL=One moment, $BrandShortName will launch as soon as the install is complete… +ONE_MOMENT_UPGRADE=One moment, $BrandShortName will launch as soon as the upgrade is complete… +INSTALL_MAINT_SERVICE=&Install the $BrandShortName background update service SEND_PING=S&end information about this installation to Mozilla BROWSE_BUTTON=B&rowse… DEST_FOLDER=Destination Folder -DOWNLOADING_IN_PROGRESS=Downloading… -DOWNLOADING_DONE=Downloaded -INSTALLING_TO_BE_DONE=Installing -INSTALLING_IN_PROGRESS=Installing… +DOWNLOADING_LABEL=Downloading $BrandShortName… +INSTALLING_LABEL=Installing $BrandShortName… +UPGRADING_LABEL=Upgrading $BrandShortName… SELECT_FOLDER_TEXT=Select the folder to install $BrandShortName in. diff --git a/application/palemoon/modules/WindowsPreviewPerTab.jsm b/application/palemoon/modules/WindowsPreviewPerTab.jsm index c1ed05c39..243a00aae 100644 --- a/application/palemoon/modules/WindowsPreviewPerTab.jsm +++ b/application/palemoon/modules/WindowsPreviewPerTab.jsm @@ -3,12 +3,10 @@ * 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/. */ /* - * This module implements the front end behavior for AeroPeek. Starting in - * Windows Vista, the taskbar began showing live thumbnail previews of windows - * when the user hovered over the window icon in the taskbar. Starting with - * Windows 7, the taskbar allows an application to expose its tabbed interface - * in the taskbar by showing thumbnail previews rather than the default window - * preview. Additionally, when a user hovers over a thumbnail (tab or window), + * This module implements the front end behavior for AeroPeek. The taskbar + * allows an application to expose its tabbed interface by showing thumbnail + * previews rather than the default window preview. + * Additionally, when a user hovers over a thumbnail (tab or window), * they are shown a live preview of the window (or tab + its containing window). * * In Windows 7, a title, icon, close button and optional toolbar are shown for @@ -31,7 +29,7 @@ * Screen real estate is limited so when there are too many thumbnails to fit * on the screen, the taskbar stops displaying thumbnails and instead displays * just the title, icon and close button in a similar fashion to previous - * versions of the taskbar. If there are still too many previews to fit on the + * versions of the taskbar. If there are still too many previews to fit on the * screen, the taskbar resorts to a scroll up and scroll down button pair to let * the user scroll through the list of tabs. Since this is undoubtedly * inconvenient for users with many tabs, the AeroPeek objects turns off all of @@ -47,9 +45,11 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/PlacesUtils.jsm"); Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); // Pref to enable/disable preview-per-tab const TOGGLE_PREF_NAME = "browser.taskbar.previews.enable"; @@ -60,17 +60,15 @@ const CACHE_EXPIRATION_TIME_PREF_NAME = "browser.taskbar.previews.cachetime"; const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1"; -//////////////////////////////////////////////////////////////////////////////// -//// Various utility properties +// Various utility properties XPCOMUtils.defineLazyServiceGetter(this, "imgTools", "@mozilla.org/image/tools;1", "imgITools"); -XPCOMUtils.defineLazyServiceGetter(this, "faviconSvc", - "@mozilla.org/browser/favicon-service;1", - "nsIFaviconService"); +XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs", + "resource://gre/modules/PageThumbs.jsm"); // nsIURI -> imgIContainer -function _imageFromURI(doc, uri, privateMode, callback) { +function _imageFromURI(uri, privateMode, callback) { let channel = NetUtil.newChannel({ uri: uri, loadUsingSystemPrincipal: true, @@ -93,19 +91,20 @@ function _imageFromURI(doc, uri, privateMode, callback) { } catch (e) { // We failed, so use the default favicon (only if this wasn't the default // favicon). - let defaultURI = faviconSvc.defaultFavicon; + let defaultURI = PlacesUtils.favicons.defaultFavicon; if (!defaultURI.equals(uri)) - _imageFromURI(doc, defaultURI, privateMode, callback); + _imageFromURI(defaultURI, privateMode, callback); } }); } // string? -> imgIContainer -function getFaviconAsImage(doc, iconurl, privateMode, callback) { - if (iconurl) - _imageFromURI(doc, NetUtil.newURI(iconurl), privateMode, callback); - else - _imageFromURI(doc, faviconSvc.defaultFavicon, privateMode, callback); +function getFaviconAsImage(iconurl, privateMode, callback) { + if (iconurl) { + _imageFromURI(NetUtil.newURI(iconurl), privateMode, callback); + } else { + _imageFromURI(PlacesUtils.favicons.defaultFavicon, privateMode, callback); + } } // Snaps the given rectangle to be pixel-aligned at the given scale @@ -121,16 +120,17 @@ function snapRectAtScale(r, scale) { r.height = height / scale; } -//////////////////////////////////////////////////////////////////////////////// -//// PreviewController +// PreviewController /* - * This class manages the behavior of the preview. - * - * To give greater performance when drawing, the dirty areas of the content - * window are tracked and drawn on demand into a canvas of the same size. - * This provides a great increase in responsiveness when drawing a preview - * for unchanged (or even only slightly changed) tabs. + * This class manages the behavior of thumbnails and previews. It has the following + * responsibilities: + * 1) Responding to requests from Windows taskbar for a thumbnail or window + * preview. + * 2) Listening for DOM events that result in a thumbnail or window preview needing + * to be refreshed, and communicating this to the taskbar. + * 3) Handling queryies and returning new thumbnail or window preview images to the + * taskbar through PageThumbs. * * @param win * The TabWindow (see below) that owns the preview that this controls @@ -143,206 +143,182 @@ function PreviewController(win, tab) { this.linkedBrowser = tab.linkedBrowser; this.preview = this.win.createTabPreview(this); - this.linkedBrowser.addEventListener("MozAfterPaint", this, false); this.tab.addEventListener("TabAttrModified", this, false); XPCOMUtils.defineLazyGetter(this, "canvasPreview", function () { - let canvas = this.win.win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); + let canvas = PageThumbs.createCanvas(); canvas.mozOpaque = true; return canvas; }); - - XPCOMUtils.defineLazyGetter(this, "dirtyRegion", - function () { - let dirtyRegion = Cc["@mozilla.org/gfx/region;1"] - .createInstance(Ci.nsIScriptableRegion); - dirtyRegion.init(); - return dirtyRegion; - }); - - XPCOMUtils.defineLazyGetter(this, "winutils", - function () { - let win = tab.linkedBrowser.contentWindow; - return win.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDOMWindowUtils); - }); } PreviewController.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsITaskbarPreviewController, Ci.nsIDOMEventListener]), + destroy: function () { this.tab.removeEventListener("TabAttrModified", this, false); - this.linkedBrowser.removeEventListener("MozAfterPaint", this, false); // Break cycles, otherwise we end up leaking the window with everything // attached to it. delete this.win; delete this.preview; - delete this.dirtyRegion; }, + get wrappedJSObject() { return this; }, - get dirtyRects() { - let rectstream = this.dirtyRegion.getRects(); - if (!rectstream) - return []; - let rects = []; - for (let i = 0; i < rectstream.length; i+= 4) { - let r = {x: rectstream[i], - y: rectstream[i+1], - width: rectstream[i+2], - height: rectstream[i+3]}; - rects.push(r); - } - return rects; - }, - // Resizes the canvasPreview to 0x0, essentially freeing its memory. - // updateCanvasPreview() will detect the size mismatch as a resize event - // the next time it is called. resetCanvasPreview: function () { this.canvasPreview.width = 0; this.canvasPreview.height = 0; }, + /** + * Set the canvas dimensions. + */ + resizeCanvasPreview: function (aRequestedWidth, aRequestedHeight) { + this.canvasPreview.width = aRequestedWidth; + this.canvasPreview.height = aRequestedHeight; + }, + + get zoom() { // Note that winutils.fullZoom accounts for "quantization" of the zoom factor - // from nsIMarkupDocumentViewer due to conversion through appUnits. + // from nsIContentViewer due to conversion through appUnits. // We do -not- want screenPixelsPerCSSPixel here, because that would -also- // incorporate any scaling that is applied due to hi-dpi resolution options. - return this.winutils.fullZoom; - }, - - // Updates the controller's canvas with the parts of the <browser> that need - // to be redrawn. - updateCanvasPreview: function () { - let win = this.linkedBrowser.contentWindow; - let bx = this.linkedBrowser.boxObject; - // Check for resize - if (bx.width != this.canvasPreview.width || - bx.height != this.canvasPreview.height) { - // Invalidate the entire area and repaint - this.onTabPaint({left:0, top:0, right:win.innerWidth, bottom:win.innerHeight}); - this.canvasPreview.width = bx.width; - this.canvasPreview.height = bx.height; - } + return this.tab.linkedBrowser.fullZoom; + }, - // Draw dirty regions - let ctx = this.canvasPreview.getContext("2d"); - let scale = this.zoom; - - let flags = this.canvasPreviewFlags; - // The dirty region may include parts that are offscreen so we clip to the - // canvas area. - this.dirtyRegion.intersectRect(0, 0, win.innerWidth, win.innerHeight); - this.dirtyRects.forEach(function (r) { - // We need to snap the rectangle to be pixel aligned in the destination - // coordinate space. Otherwise natively themed widgets might not draw. - snapRectAtScale(r, scale); - let x = r.x; - let y = r.y; - let width = r.width; - let height = r.height; + get screenPixelsPerCSSPixel() { + let chromeWin = this.tab.ownerGlobal; + let windowUtils = chromeWin.getInterface(Ci.nsIDOMWindowUtils); + return windowUtils.screenPixelsPerCSSPixel; + }, - ctx.save(); - ctx.scale(scale, scale); - ctx.translate(x, y); - ctx.drawWindow(win, x, y, width, height, "white", flags); - ctx.restore(); - }); - this.dirtyRegion.setToRect(0,0,0,0); + get browserDims() { + return this.tab.linkedBrowser.getBoundingClientRect(); + }, + + cacheBrowserDims: function () { + let dims = this.browserDims; + this._cachedWidth = dims.width; + this._cachedHeight = dims.height; + }, + testCacheBrowserDims: function () { + let dims = this.browserDims; + return this._cachedWidth == dims.width && + this._cachedHeight == dims.height; + }, + + /** + * Capture a new thumbnail image for this preview. Called by the controller + * in response to a request for a new thumbnail image. + */ + updateCanvasPreview: function (aFullScale, aCallback) { + // Update our cached browser dims so that delayed resize + // events don't trigger another invalidation if this tab becomes active. + this.cacheBrowserDims(); + PageThumbs.captureToCanvas(this.linkedBrowser, this.canvasPreview, + aCallback, { fullScale: aFullScale }); // If we're updating the canvas, then we're in the middle of a peek so // don't discard the cache of previews. AeroPeek.resetCacheTimer(); }, - onTabPaint: function (rect) { - let x = Math.floor(rect.left), - y = Math.floor(rect.top), - width = Math.ceil(rect.right) - x, - height = Math.ceil(rect.bottom) - y; - this.dirtyRegion.unionRect(x, y, width, height); - }, - updateTitleAndTooltip: function () { let title = this.win.tabbrowser.getWindowTitleForBrowser(this.linkedBrowser); this.preview.title = title; this.preview.tooltip = title; }, - ////////////////////////////////////////////////////////////////////////////// - //// nsITaskbarPreviewController + // nsITaskbarPreviewController + // window width and height, not browser get width() { return this.win.width; }, + // window width and height, not browser get height() { return this.win.height; }, get thumbnailAspectRatio() { - let boxObject = this.tab.linkedBrowser.boxObject; + let browserDims = this.browserDims; // Avoid returning 0 - let tabWidth = boxObject.width || 1; + let tabWidth = browserDims.width || 1; // Avoid divide by 0 - let tabHeight = boxObject.height || 1; + let tabHeight = browserDims.height || 1; return tabWidth / tabHeight; }, - drawPreview: function (ctx) { - let self = this; - this.win.tabbrowser.previewTab(this.tab, function () self.previewTabCallback(ctx)); - - // We must avoid having the frame drawn around the window. See bug 520807 - return false; - }, - - previewTabCallback: function (ctx) { - // This will extract the resolution-scale component of the scaling we need, - // which should be applied to both chrome and content; - // the page zoom component is applied (to content only) within updateCanvasPreview. - let scale = this.winutils.screenPixelsPerCSSPixel / this.winutils.fullZoom; - ctx.save(); - ctx.scale(scale, scale); - let width = this.win.width; - let height = this.win.height; - // Draw our toplevel window - ctx.drawWindow(this.win.win, 0, 0, width, height, "transparent"); - - // XXX (jfkthame): Pending tabs don't seem to draw with the proper scaling - // unless we use this block of code; but doing this for "normal" (loaded) tabs - // results in blurry rendering on hidpi systems, so we avoid it if possible. - // I don't understand why pending and loaded tabs behave differently here... - // (see bug 857061). - if (this.tab.hasAttribute("pending")) { - // Compositor, where art thou? - // Draw the tab content on top of the toplevel window - this.updateCanvasPreview(); - - let boxObject = this.linkedBrowser.boxObject; - ctx.translate(boxObject.x, boxObject.y); - ctx.drawImage(this.canvasPreview, 0, 0); - } + /** + * Responds to taskbar requests for window previews. Returns the results asynchronously + * through updateCanvasPreview. + * + * @param aTaskbarCallback nsITaskbarPreviewCallback results callback + */ + requestPreview: function (aTaskbarCallback) { + // Grab a high res content preview + this.resetCanvasPreview(); + this.updateCanvasPreview(true, (aPreviewCanvas) => { + let winWidth = this.win.width; + let winHeight = this.win.height; - ctx.restore(); - }, + let composite = PageThumbs.createCanvas(); + + // Use transparency, Aero glass is drawn black without it. + composite.mozOpaque = false; - drawThumbnail: function (ctx, width, height) { - this.updateCanvasPreview(); + let ctx = composite.getContext('2d'); + let scale = this.screenPixelsPerCSSPixel / this.zoom; - let scale = width/this.linkedBrowser.boxObject.width; - ctx.scale(scale, scale); - ctx.drawImage(this.canvasPreview, 0, 0); + composite.width = winWidth * scale; + composite.height = winHeight * scale; - // Don't draw a frame around the thumbnail - return false; + ctx.save(); + ctx.scale(scale, scale); + + // Draw chrome. Note we currently do not get scrollbars for remote frames + // in the image above. + ctx.drawWindow(this.win.win, 0, 0, winWidth, winHeight, "rgba(0,0,0,0)"); + + // Draw the content are into the composite canvas at the right location. + ctx.drawImage(aPreviewCanvas, this.browserDims.x, this.browserDims.y, + aPreviewCanvas.width, aPreviewCanvas.height); + ctx.restore(); + + // Deliver the resulting composite canvas to Windows + this.win.tabbrowser.previewTab(this.tab, function () { + aTaskbarCallback.done(composite, false); + }); + }); + }, + + /** + * Responds to taskbar requests for tab thumbnails. Returns the results asynchronously + * through updateCanvasPreview. + * + * Note Windows requests a specific width and height here, if the resulting thumbnail + * does not match these dimensions thumbnail display will fail. + * + * @param aTaskbarCallback nsITaskbarPreviewCallback results callback + * @param aRequestedWidth width of the requested thumbnail + * @param aRequestedHeight height of the requested thumbnail + */ + requestThumbnail: function (aTaskbarCallback, aRequestedWidth, aRequestedHeight) { + this.resizeCanvasPreview(aRequestedWidth, aRequestedHeight); + this.updateCanvasPreview(false, (aThumbnailCanvas) => { + aTaskbarCallback.done(aThumbnailCanvas, false); + }); }, + // Event handling + onClose: function () { this.win.tabbrowser.removeTab(this.tab); }, @@ -355,22 +331,9 @@ PreviewController.prototype = { return true; }, - //// nsIDOMEventListener + // nsIDOMEventListener handleEvent: function (evt) { switch (evt.type) { - case "MozAfterPaint": - if (evt.originalTarget === this.linkedBrowser.contentWindow) { - let clientRects = evt.clientRects; - let length = clientRects.length; - for (let i = 0; i < length; i++) { - let r = clientRects.item(i); - this.onTabPaint(r); - } - } - let preview = this.preview; - if (preview.visible) - preview.invalidate(); - break; case "TabAttrModified": this.updateTitleAndTooltip(); break; @@ -386,14 +349,13 @@ XPCOMUtils.defineLazyGetter(PreviewController.prototype, "canvasPreviewFlags", | canvasInterface.DRAWWINDOW_DO_NOT_FLUSH; }); -//////////////////////////////////////////////////////////////////////////////// -//// TabWindow +// TabWindow /* * This class monitors a browser window for changes to its tabs * * @param win - * The nsIDOMWindow browser window + * The nsIDOMWindow browser window */ function TabWindow(win) { this.win = win; @@ -403,6 +365,10 @@ function TabWindow(win) { for (let i = 0; i < this.tabEvents.length; i++) this.tabbrowser.tabContainer.addEventListener(this.tabEvents[i], this, false); + + for (let i = 0; i < this.winEvents.length; i++) + this.win.addEventListener(this.winEvents[i], this, false); + this.tabbrowser.addTabsProgressListener(this); AeroPeek.windows.push(this); @@ -416,7 +382,10 @@ function TabWindow(win) { TabWindow.prototype = { _enabled: false, + _cachedWidth: 0, + _cachedHeight: 0, tabEvents: ["TabOpen", "TabClose", "TabSelect", "TabMove"], + winEvents: ["resize"], destroy: function () { this._destroying = true; @@ -424,6 +393,10 @@ TabWindow.prototype = { let tabs = this.tabbrowser.tabs; this.tabbrowser.removeTabsProgressListener(this); + + for (let i = 0; i < this.winEvents.length; i++) + this.win.removeEventListener(this.winEvents[i], this, false); + for (let i = 0; i < this.tabEvents.length; i++) this.tabbrowser.tabContainer.removeEventListener(this.tabEvents[i], this, false); @@ -442,6 +415,15 @@ TabWindow.prototype = { return this.win.innerHeight; }, + cacheDims: function () { + this._cachedWidth = this.width; + this._cachedHeight = this.height; + }, + + testCacheDims: function () { + return this._cachedWidth == this.width && this._cachedHeight == this.height; + }, + // Invoked when the given tab is added to this window newTab: function (tab) { let controller = new PreviewController(this, tab); @@ -461,18 +443,8 @@ TabWindow.prototype = { let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller); preview.visible = AeroPeek.enabled; preview.active = this.tabbrowser.selectedTab == controller.tab; - // Grab the default favicon - getFaviconAsImage( - controller.linkedBrowser.contentWindow.document, - null, - PrivateBrowsingUtils.isWindowPrivate(this.win), - function (img) { - // It is possible that we've already gotten the real favicon, so make sure - // we have not set one before setting this default one. - if (!preview.icon) - preview.icon = img; - }); - + this.onLinkIconAvailable(controller.tab.linkedBrowser, + controller.tab.getAttribute("image")); return preview; }, @@ -484,8 +456,6 @@ TabWindow.prototype = { preview.move(null); preview.controller.wrappedJSObject.destroy(); - // We don't want to splice from the array if the tabs aren't being removed - // from the tab bar as well (as is the case when the window closes). this.previews.delete(tab); AeroPeek.removePreview(preview); }, @@ -499,7 +469,7 @@ TabWindow.prototype = { // Because making a tab visible requires that the tab it is next to be // visible, it is far simpler to unset the 'next' tab and recreate them all // at once. - for (let [tab, preview] of this.previews) { + for (let [, preview] of this.previews) { preview.move(null); preview.visible = enable; } @@ -514,27 +484,25 @@ TabWindow.prototype = { let previews = this.previews; let tabs = this.tabbrowser.tabs; - // Previews are internally stored using a map, so we need to iterate over - // the tabbrowser's array of tabs to retrieve previews in the same order. - // Tycho: let inorder = [previews.get(t) for (t of tabs) if (previews.has(t))]; + // Previews are internally stored using a map, so we need to iterate the + // tabbrowser's array of tabs to retrieve previews in the same order. let inorder = []; - for (let t of tabs) { if (previews.has(t)) { inorder.push(previews.get(t)); } } - // Since the internal taskbar array has not yet been updated, we must force - // the sorting order of our local array on it. To do so, we must walk - // the local array backwards, because otherwise we would send move requests - // in the wrong order. See bug 522610 for details. + // Since the internal taskbar array has not yet been updated we must force + // on it the sorting order of our local array. To do so we must walk + // the local array backwards, otherwise we would send move requests in the + // wrong order. See bug 522610 for details. for (let i = inorder.length - 1; i >= 0; i--) { inorder[i].move(inorder[i + 1] || null); } }, - //// nsIDOMEventListener + // nsIDOMEventListener handleEvent: function (evt) { let tab = evt.originalTarget; switch (evt.type) { @@ -552,28 +520,117 @@ TabWindow.prototype = { case "TabMove": this.updateTabOrdering(); break; + case "resize": + if (!AeroPeek._prefenabled) + return; + this.onResize(); + break; + } + }, + + // Set or reset a timer that will invalidate visible thumbnails soon. + setInvalidationTimer: function () { + if (!this.invalidateTimer) { + this.invalidateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + } + this.invalidateTimer.cancel(); + + // delay 1 second before invalidating + this.invalidateTimer.initWithCallback(() => { + // invalidate every preview. note the internal implementation of + // invalidate ignores thumbnails that aren't visible. + this.previews.forEach(function (aPreview) { + let controller = aPreview.controller.wrappedJSObject; + if (!controller.testCacheBrowserDims()) { + controller.cacheBrowserDims(); + aPreview.invalidate(); + } + }); + }, 1000, Ci.nsITimer.TYPE_ONE_SHOT); + }, + + onResize: function () { + // Specific to a window. + + // Call invalidate on each tab thumbnail so that Windows will request an + // updated image. However don't do this repeatedly across multiple resize + // events triggered during window border drags. + + if (this.testCacheDims()) { + return; + } + + // update the window dims on our TabWindow object. + this.cacheDims(); + + // invalidate soon + this.setInvalidationTimer(); + }, + + invalidateTabPreview: function(aBrowser) { + for (let [tab, preview] of this.previews) { + if (aBrowser == tab.linkedBrowser) { + preview.invalidate(); + break; + } + } + }, + + // Browser progress listener + + onLocationChange: function (aBrowser) { + // I'm not sure we need this, onStateChange does a really good job + // of picking up page changes. + // this.invalidateTabPreview(aBrowser); + }, + + onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { + if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && + aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) { + this.invalidateTabPreview(aBrowser); } }, - //// Browser progress listener + directRequestProtocols: new Set([ + "file", "chrome", "resource", "about" + ]), onLinkIconAvailable: function (aBrowser, aIconURL) { - let self = this; + let requestURL = null; + if (aIconURL) { + let shouldRequestFaviconURL = true; + try { + let urlObject = NetUtil.newURI(aIconURL); + shouldRequestFaviconURL = + !this.directRequestProtocols.has(urlObject.scheme); + } catch (ex) {} + + requestURL = shouldRequestFaviconURL ? + "moz-anno:favicon:" + aIconURL : + aIconURL; + } + let isDefaultFavicon = !requestURL; getFaviconAsImage( - aBrowser.contentWindow.document, - aIconURL,PrivateBrowsingUtils.isWindowPrivate(this.win), - function (img) { - let index = self.tabbrowser.browsers.indexOf(aBrowser); - // Only add it if we've found the index. The tab could have closed! + requestURL, + PrivateBrowsingUtils.isWindowPrivate(this.win), + img => { + let index = this.tabbrowser.browsers.indexOf(aBrowser); + // Only add it if we've found the index and the URI is still the same. + // The tab could have closed, and there's no guarantee the icons + // will have finished fetching 'in order'. if (index != -1) { - let tab = self.tabbrowser.tabs[index]; - self.previews.get(tab).icon = img; + let tab = this.tabbrowser.tabs[index]; + let preview = this.previews.get(tab); + if (tab.getAttribute("image") == aIconURL || + (!preview.icon && isDefaultFavicon)) { + preview.icon = img; + } } - }); + } + ); } } -//////////////////////////////////////////////////////////////////////////////// -//// AeroPeek +// AeroPeek /* * This object acts as global storage and external interface for this feature. @@ -582,10 +639,12 @@ TabWindow.prototype = { this.AeroPeek = { available: false, // Does the pref say we're enabled? - _prefenabled: true, + __prefenabled: false, _enabled: true, + initialized: false, + // nsITaskbarTabPreview array previews: [], @@ -609,24 +668,14 @@ this.AeroPeek = { if (!this.available) return; - this.prefs.addObserver(TOGGLE_PREF_NAME, this, false); - this.prefs.addObserver(DISABLE_THRESHOLD_PREF_NAME, this, false); - this.prefs.addObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this, false); - - this.cacheLifespan = this.prefs.getIntPref(CACHE_EXPIRATION_TIME_PREF_NAME); - - this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME); - + this.prefs.addObserver(TOGGLE_PREF_NAME, this, true); this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); + this.initialized = true; }, destroy: function destroy() { this._enabled = false; - this.prefs.removeObserver(TOGGLE_PREF_NAME, this); - this.prefs.removeObserver(DISABLE_THRESHOLD_PREF_NAME, this); - this.prefs.removeObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this); - if (this.cacheTimer) this.cacheTimer.cancel(); }, @@ -646,6 +695,61 @@ this.AeroPeek = { }); }, + get _prefenabled() { + return this.__prefenabled; + }, + + set _prefenabled(enable) { + if (enable == this.__prefenabled) { + return; + } + this.__prefenabled = enable; + + if (enable) { + this.enable(); + } else { + this.disable(); + } + }, + + _observersAdded: false, + + enable() { + if (!this._observersAdded) { + this.prefs.addObserver(DISABLE_THRESHOLD_PREF_NAME, this, true); + this.prefs.addObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this, true); + PlacesUtils.history.addObserver(this, true); + this._observersAdded = true; + } + + this.cacheLifespan = this.prefs.getIntPref(CACHE_EXPIRATION_TIME_PREF_NAME); + + this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME); + + // If the user toggled us on/off while the browser was already up + // (rather than this code running on startup because the pref was + // already set to true), we must initialize previews for open windows: + if (this.initialized) { + let browserWindows = Services.wm.getEnumerator("navigator:browser"); + while (browserWindows.hasMoreElements()) { + let win = browserWindows.getNext(); + if (!win.closed) { + this.onOpenWindow(win); + } + } + } + }, + + disable() { + while (this.windows.length) { + // We can't call onCloseWindow here because it'll bail if we're not + // enabled. + let tabWinObject = this.windows[0]; + tabWinObject.destroy(); // This will remove us from the array. + delete tabWinObject.win.gTaskbarTabGroup; // Tidy up the window. + } + }, + addPreview: function (preview) { this.previews.push(preview); this.checkPreviewCount(); @@ -658,15 +762,15 @@ this.AeroPeek = { }, checkPreviewCount: function () { - if (this.previews.length > this.maxpreviews) - this.enabled = false; - else - this.enabled = this._prefenabled; + if (!this._prefenabled) { + return; + } + this.enabled = this.previews.length <= this.maxpreviews; }, onOpenWindow: function (win) { // This occurs when the taskbar service is not available (xp, vista) - if (!this.available) + if (!this.available || !this._prefenabled) return; win.gTaskbarTabGroup = new TabWindow(win); @@ -674,7 +778,7 @@ this.AeroPeek = { onCloseWindow: function (win) { // This occurs when the taskbar service is not available (xp, vista) - if (!this.available) + if (!this.available || !this._prefenabled) return; win.gTaskbarTabGroup.destroy(); @@ -689,16 +793,20 @@ this.AeroPeek = { this.cacheTimer.init(this, 1000*this.cacheLifespan, Ci.nsITimer.TYPE_ONE_SHOT); }, - //// nsIObserver + // nsIObserver observe: function (aSubject, aTopic, aData) { + if (aTopic == "nsPref:changed" && aData == TOGGLE_PREF_NAME) { + this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); + } + if (!this._prefenabled) { + return; + } switch (aTopic) { case "nsPref:changed": if (aData == CACHE_EXPIRATION_TIME_PREF_NAME) break; - if (aData == TOGGLE_PREF_NAME) - this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); - else if (aData == DISABLE_THRESHOLD_PREF_NAME) + if (aData == DISABLE_THRESHOLD_PREF_NAME) this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME); // Might need to enable/disable ourselves this.checkPreviewCount(); @@ -710,10 +818,38 @@ this.AeroPeek = { }); break; } - } + }, + + /* nsINavHistoryObserver implementation */ + onBeginUpdateBatch() {}, + onEndUpdateBatch() {}, + onVisit() {}, + onTitleChanged() {}, + onFrecencyChanged() {}, + onManyFrecenciesChanged() {}, + onDeleteURI() {}, + onClearHistory() {}, + onDeleteVisits() {}, + onPageChanged(uri, changedConst, newValue) { + if (this.enabled && changedConst == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) { + for (let win of this.windows) { + for (let [tab, ] of win.previews) { + if (tab.getAttribute("image") == newValue) { + win.onLinkIconAvailable(tab.linkedBrowser, newValue); + } + } + } + } + }, + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsISupportsWeakReference, + Ci.nsINavHistoryObserver, + Ci.nsIObserver + ]), }; -XPCOMUtils.defineLazyGetter(AeroPeek, "cacheTimer", function () +XPCOMUtils.defineLazyGetter(AeroPeek, "cacheTimer", () => Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer) ); diff --git a/application/palemoon/themes/linux/browser.css b/application/palemoon/themes/linux/browser.css index 987406264..c6587babc 100644 --- a/application/palemoon/themes/linux/browser.css +++ b/application/palemoon/themes/linux/browser.css @@ -1570,12 +1570,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- background-color: Window; } -.browserContainer > findbar { - background-color: -moz-dialog; - color: -moz-DialogText; - text-shadow: none; -} - /* Throbber */ #navigator-throbber { width: 16px; diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css index 97073b161..a915af3a3 100644 --- a/application/palemoon/themes/osx/browser.css +++ b/application/palemoon/themes/osx/browser.css @@ -1601,12 +1601,6 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url- -moz-padding-start: 0px; } -.browserContainer > findbar { - background-color: -moz-dialog; - color: -moz-DialogText; - text-shadow: none; -} - /* ::::: throbber ::::: */ #navigator-throbber { diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css index 1aefa428c..45f0e066c 100644 --- a/application/palemoon/themes/windows/browser.css +++ b/application/palemoon/themes/windows/browser.css @@ -1788,12 +1788,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- -moz-padding-start: 0px; } -.browserContainer > findbar { - background-color: -moz-dialog; - color: -moz-DialogText; - text-shadow: none; -} - /* ::::: throbber ::::: */ #navigator-throbber { |