Bug 1370035 - Make adjusting focus during a tab switch one of the last things that occurs during any given tick. r?dao draft
authorMike Conley <mconley@mozilla.com>
Tue, 06 Jun 2017 14:53:00 -0400
changeset 592900 34367739efc8c2c4f27d5fc8ecf6375f6cb60024
parent 592668 2a63a6c35033b5cbc6c98cabc7657c7290284691
child 632957 34768fd678ac9682be6ea7f540ff1ba4378f3503
push id63531
push usermconley@mozilla.com
push dateMon, 12 Jun 2017 21:30:05 +0000
reviewersdao
bugs1370035
milestone56.0a1
Bug 1370035 - Make adjusting focus during a tab switch one of the last things that occurs during any given tick. r?dao It is possible for the async tab switcher to switch synchronously to tabs that it knows it can switch to immediately (for example, tabs that it knows it can display as blank). Unfortunately, the way that the async tab switcher is structured, when this occurs, the focus adjustment occurs before the updateCurrentBrowser method is run inside tabbrowser. This breaks focus adjustment during tab switching when the browser is unrestored / pending, since the updateCurrentBrowser method fires the event that causes the browser to _become_ focusable. This patch works around this problem by putting the adjustment of focus inside a requestAnimationFrame. This ensures that the adjustment will still happen in the same tick, but if an updateCurrentBrowser call is going to happen, it'll happen after that. MozReview-Commit-ID: Fud1N8iXN4y
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4218,17 +4218,26 @@
                 let tabs = this.tabbrowser.mTabBox.tabs;
                 let tabPanel = this.tabbrowser.mPanelContainer;
                 let showPanel = tabs.getRelatedElement(showTab);
                 let index = Array.indexOf(tabPanel.childNodes, showPanel);
                 if (index != -1) {
                   this.log(`Switch to tab ${index} - ${this.tinfo(showTab)}`);
                   tabPanel.setAttribute("selectedIndex", index);
                   if (showTab === this.requestedTab) {
-                    this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
+                    // It's possible for the tab we're switching to not be
+                    // focusable until later on this tick (example: it might be
+                    // pending). We ensure that the "select" event has had the
+                    // opportunity to fire by making sure that the focus adjustment
+                    // is one of the last things to occur.
+                    window.requestAnimationFrame(() => {
+                      if (this.visibleTab == showTab) {
+                        this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
+                      }
+                    });
                   }
                 }
 
                 // 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;