Bug 1397426 - Make async tab switcher use new nsITabParent renderLayers function. r=billm draft
authorMike Conley <mconley@mozilla.com>
Fri, 03 Nov 2017 10:27:35 -0400
changeset 715459 f12e8c368807028f88456c1649a46235cd7e8d97
parent 715458 0e59b548c6c01d7feaf9f40c282ab2f55e47bab7
child 715460 1840908f74a1ccb9aa50ce95d57cf38d5e55efa0
push id94165
push usermconley@mozilla.com
push dateWed, 03 Jan 2018 23:25:52 +0000
reviewersbillm
bugs1397426
milestone59.0a1
Bug 1397426 - Make async tab switcher use new nsITabParent renderLayers function. r=billm MozReview-Commit-ID: Go2EdMXGwa7
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4392,26 +4392,36 @@
 
             setTabState(tab, state) {
               this.setTabStateNoAction(tab, state);
 
               let browser = tab.linkedBrowser;
               let {tabParent} = browser.frameLoader;
               if (state == this.STATE_LOADING) {
                 this.assert(!this.minimizedOrFullyOccluded);
-                browser.docShellIsActive = true;
-                if (!tabParent) {
+
+                if (!this.tabbrowser.tabWarmingEnabled) {
+                  browser.docShellIsActive = true;
+                }
+
+                if (tabParent) {
+                  tabParent.renderLayers(true);
+                } else {
                   this.onLayersReady(browser);
                 }
               } else if (state == this.STATE_UNLOADING) {
                 this.unwarmTab(tab);
+                // Setting the docShell to be inactive will also cause it
+                // to stop rendering layers.
                 browser.docShellIsActive = false;
                 if (!tabParent) {
                   this.onLayersCleared(browser);
                 }
+              } else if (state == this.STATE_LOADED) {
+                this.maybeActivateDocShell(tab);
               }
 
               if (!tab.linkedBrowser.isRemoteBrowser) {
                 // setTabState is potentially re-entrant in the non-remote case,
                 // so we must re-get the state for this assertion.
                 let nonRemoteState = this.getTabState(tab);
                 // Non-remote tabs can never stay in the STATE_LOADING
                 // or STATE_UNLOADING states. By the time this function
@@ -4450,16 +4460,20 @@
               let tabIsLoaded = !browser.isRemoteBrowser ||
                                 browser.frameLoader.tabParent.hasPresented;
 
               if (!this.minimizedOrFullyOccluded) {
                 this.log("Initial tab is loaded?: " + tabIsLoaded);
                 this.setTabState(tab, tabIsLoaded ? this.STATE_LOADED
                                                   : this.STATE_LOADING);
               }
+              for (let ppBrowser of this.tabbrowser._printPreviewBrowsers) {
+                let ppTab = this.tabbrowser.getTabForBrowser(ppBrowser);
+                this.setTabState(ppTab, this.STATE_LOADING);
+              }
             },
 
             destroy() {
               if (this.unloadTimer) {
                 this.clearTimer(this.unloadTimer);
                 this.unloadTimer = null;
               }
               if (this.loadTimer) {
@@ -4617,16 +4631,18 @@
                        * the tab switch.
                        */
                       this.tabbrowser.addEventListener("select", () => {
                         this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
                       }, {once: true});
                     } else {
                       this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
                     }
+
+                    this.maybeActivateDocShell(this.requestedTab);
                   }
                 }
 
                 // This doesn't necessarily exist if we're a new window and haven't switched tabs yet
                 if (this.lastVisibleTab)
                   this.lastVisibleTab._visuallySelected = false;
 
                 this.visibleTab._visuallySelected = true;
@@ -4655,16 +4671,39 @@
               // In that case we just overwrite it with a different tab; it's had its chance.
               this.loadingTab = this.requestedTab;
               this.log("Loading tab " + this.tinfo(this.loadingTab));
 
               this.loadTimer = this.setTimer(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
               this.setTabState(this.requestedTab, this.STATE_LOADING);
             },
 
+            maybeActivateDocShell(tab) {
+              // If we've reached the point where the requested tab has entered
+              // the loaded state, but the DocShell is still not yet active, we
+              // should activate it.
+              let browser = tab.linkedBrowser;
+              let state = this.getTabState(tab);
+              let canCheckDocShellState = !browser.mDestroyed &&
+                                          (browser.docShell ||
+                                           browser.frameLoader.tabParent);
+              if (tab == this.requestedTab &&
+                  canCheckDocShellState &&
+                  state == this.STATE_LOADED &&
+                  !browser.docShellIsActive &&
+                  !this.minimizedOrFullyOccluded) {
+                browser.docShellIsActive = true;
+                this.logState("Set requested tab docshell to active and preserveLayers to false");
+                // If we minimized the window before the switcher was activated,
+                // we might have set the preserveLayers flag for the current
+                // browser. Let's clear it.
+                browser.preserveLayers(false);
+              }
+            },
+
             // This function runs before every event. It fixes up the state
             // to account for closed tabs.
             preActions() {
               this.assert(this.tabbrowser._switcher);
               this.assert(this.tabbrowser._switcher === this);
 
               for (let [tab, ] of this.tabState) {
                 if (!tab.linkedBrowser) {
@@ -4971,17 +5010,22 @@
             shouldActivateDocShell(browser) {
               let tab = this.tabbrowser.getTabForBrowser(browser);
               let state = this.getTabState(tab);
               return state == this.STATE_LOADING || state == this.STATE_LOADED;
             },
 
             activateBrowserForPrintPreview(browser) {
               let tab = this.tabbrowser.getTabForBrowser(browser);
-              this.setTabState(tab, this.STATE_LOADING);
+              let state = this.getTabState(tab);
+              if (state != this.STATE_LOADING &&
+                  state != this.STATE_LOADED) {
+                this.setTabState(tab, this.STATE_LOADING);
+                this.logState("Activated browser " + this.tinfo(tab) + " for print preview");
+              }
             },
 
             canWarmTab(tab) {
               if (!this.tabbrowser.tabWarmingEnabled) {
                 return false;
               }
 
               // If the tab is not yet inserted, closing, not remote,