Bug 1157404 - Don't visuallyselect remote tabs during moveTabTo. r?jaws draft
authorMike Conley <mconley@mozilla.com>
Wed, 27 Jan 2016 13:38:54 -0500
changeset 393354 87ff4978768a2dde2877aaefaa9e04b6d0ff0b29
parent 392429 66498480fe6516aa48f8e7265d09b03122d17d7a
child 526574 c367830fafcf106e529f3acb8672702c5496adf6
push id24301
push usermconley@mozilla.com
push dateWed, 27 Jul 2016 20:05:15 +0000
reviewersjaws
bugs1157404
milestone50.0a1
Bug 1157404 - Don't visuallyselect remote tabs during moveTabTo. r?jaws If we're in the midst of an async tab switch while calling moveTabTo, we can get into a case where _visuallySelected is set to true on two different tabs. What we want to do in moveTabTo is to remove logical selection from all tabs, and then re-add logical selection to mCurrentTab (and visual selection as well if we're not running with e10s). If we're running with e10s, then the visual selection will not be changed, which is fine, since if we weren't in the midst of a tab switch, the previously visually selected tab should still be correct, and if we are in the midst of a tab switch, then the async tab switcher will set the visually selected tab once the tab switch has completed. MozReview-Commit-ID: 6nAuxE3wH0e
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3030,33 +3030,45 @@
           if (oldPosition == aIndex)
             return;
 
           this._lastRelatedTab = null;
 
           let wasFocused = (document.activeElement == this.mCurrentTab);
 
           aIndex = aIndex < aTab._tPos ? aIndex: aIndex+1;
-          this.mCurrentTab._logicallySelected = false;
-          this.mCurrentTab._visuallySelected = false;
 
           // invalidate cache
           this._visibleTabs = null;
 
           // use .item() instead of [] because dragging to the end of the strip goes out of
           // bounds: .item() returns null (so it acts like appendChild), but [] throws
           this.tabContainer.insertBefore(aTab, this.tabs.item(aIndex));
 
           for (let i = 0; i < this.tabs.length; i++) {
             this.tabs[i]._tPos = i;
-            this.tabs[i]._logicallySelected = false;
-            this.tabs[i]._visuallySelected = false;
+            this.tabs[i]._selected = false;
           }
-          this.mCurrentTab._logicallySelected = true;
-          this.mCurrentTab._visuallySelected = true;
+
+          // If we're in the midst of an async tab switch while calling
+          // moveTabTo, we can get into a case where _visuallySelected
+          // is set to true on two different tabs.
+          //
+          // What we want to do in moveTabTo is to remove logical selection
+          // from all tabs, and then re-add logical selection to mCurrentTab
+          // (and visual selection as well if we're not running with e10s, which
+          // setting _selected will do automatically).
+          //
+          // If we're running with e10s, then the visual selection will not
+          // be changed, which is fine, since if we weren't in the midst of a
+          // tab switch, the previously visually selected tab should still be
+          // correct, and if we are in the midst of a tab switch, then the async
+          // tab switcher will set the visually selected tab once the tab switch
+          // has completed.
+          this.mCurrentTab._selected = true;
 
           if (wasFocused)
             this.mCurrentTab.focus();
 
           this.tabContainer._handleTabSelect(false);
 
           if (aTab.pinned)
             this.tabContainer._positionPinnedTabs();
@@ -6283,36 +6295,26 @@
 
           this._setPositionAttributes(val);
 
           return val;
           ]]>
         </setter>
       </property>
 
-      <property name="_logicallySelected">
-        <setter>
-          <![CDATA[
-          if (val)
-            this.setAttribute("selected", "true");
-          else
-            this.removeAttribute("selected");
-
-          return val;
-          ]]>
-        </setter>
-      </property>
-
       <property name="_selected">
         <setter>
           <![CDATA[
           // in e10s we want to only pseudo-select a tab before its rendering is done, so that
           // the rest of the system knows that the tab is selected, but we don't want to update its
           // visual status to selected until after we receive confirmation that its content has painted.
-          this._logicallySelected = val;
+          if (val)
+            this.setAttribute("selected", "true");
+          else
+            this.removeAttribute("selected");
 
           // If we're non-e10s we should update the visual selection as well at the same time,
           // *or* if we're e10s and the visually selected tab isn't changing, in which case the
           // tab switcher code won't run and update anything else (like the before- and after-
           // selected attributes).
           if (!gMultiProcessBrowser || (val && this.hasAttribute("visuallyselected"))) {
             this._visuallySelected = val;
           }