Bug 1355507 - Releasing a tab while dragging through the tabstrip on the same window should show a transition to its final resting place.
MozReview-Commit-ID: Lb7D1wnifBp
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -189,17 +189,21 @@ tabbrowser {
.tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected] {
position: relative;
z-index: 2;
pointer-events: none; /* avoid blocking dragover events on scroll buttons */
}
.tabbrowser-tabs[movingtab] > .tabbrowser-tab[fadein]:not([selected]) {
- transition: transform 200ms ease-out;
+ transition: transform 200ms cubic-bezier(.07, .95, 0, 1);
+}
+
+.tabbrowser-tab[finish-movingtab] {
+ transition: transform 200ms cubic-bezier(.07, .95, 0, 1);
}
.new-tab-popup,
#alltabs-popup {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
}
toolbar[printpreview="true"] {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -6226,20 +6226,25 @@
if (tab._tPos > draggedTab._tPos && tab._tPos < dropIndex)
return rtl ? tabWidth : -tabWidth;
return 0;
}
]]></body>
</method>
<method name="_finishAnimateTabMove">
+ <parameter name="draggedTab"/>
<body><![CDATA[
if (this.getAttribute("movingtab") != "true")
return;
+ // for (let tab of this.tabbrowser.visibleTabs)
+ // if (tab != draggedTab)
+ // tab.style.transform = "";
+
for (let tab of this.tabbrowser.visibleTabs)
tab.style.transform = "";
this.removeAttribute("movingtab");
this._handleTabSelect();
]]></body>
</method>
@@ -6917,24 +6922,60 @@
if (draggedTab && dropEffect == "copy") {
// copy the dropped tab (wherever it's from)
let newIndex = this._getDropIndex(event, false);
let newTab = this.tabbrowser.duplicateTab(draggedTab);
this.tabbrowser.moveTabTo(newTab, newIndex);
if (draggedTab.parentNode != this || event.shiftKey)
this.selectedItem = newTab;
} else if (draggedTab && draggedTab.parentNode == this) {
- this._finishAnimateTabMove();
-
- // actually move the dragged tab
+ let newIndex = draggedTab._dragData.animDropIndex;
+ if (newIndex > draggedTab._tPos)
+ newIndex--;
if ("animDropIndex" in draggedTab._dragData) {
- let newIndex = draggedTab._dragData.animDropIndex;
- if (newIndex > draggedTab._tPos)
- newIndex--;
- this.tabbrowser.moveTabTo(draggedTab, newIndex);
+ let tabWidth = draggedTab.getBoundingClientRect().width;
+ let translateX = parseFloat(draggedTab.style.transform.substring(11));
+ let mod = translateX % tabWidth;
+ if (translateX > 0) {
+ translateX = mod > tabWidth / 2 ?
+ translateX + tabWidth - mod :
+ translateX - mod;
+ } else {
+ translateX = -mod > tabWidth / 2 ?
+ translateX - tabWidth - mod :
+ translateX - mod;
+ }
+
+ Services.console.logStringMessage(
+ `animDropIndex: ${draggedTab._dragData.animDropIndex}; ` +
+ `_tPos: ${draggedTab._tPos}; ` +
+ `newIndex: ${newIndex}; ` +
+ `tabWidth: ${tabWidth}; ` +
+ `translateX: ${translateX}; ` +
+ `originalTransform: ${draggedTab.style.transform}`);
+
+ this.setAttribute("finish-movingtab", "true");
+ draggedTab.setAttribute("finish-movingtab", "true");
+ draggedTab.style.transform = `translateX(${translateX}px)`;
+ draggedTab.addEventListener("transitionend", event => {
+ event.target.removeAttribute("finish-movingtab");
+ this.removeAttribute("finish-movingtab");
+
+ this._finishAnimateTabMove(draggedTab);
+
+ this.tabbrowser.moveTabTo(draggedTab, newIndex);
+ draggedTab.style.transform = "";
+ }, {once: true});
+ } else {
+ this._finishAnimateTabMove();
+
+ // actually move the dragged tab
+ if ("animDropIndex" in draggedTab._dragData) {
+ this.tabbrowser.moveTabTo(draggedTab, newIndex);
+ }
}
} else if (draggedTab) {
let newIndex = this._getDropIndex(event, false);
this.tabbrowser.adoptTab(draggedTab, newIndex, true);
} else {
// Pass true to disallow dropping javascript: or data: urls
let links;
try {
@@ -6969,16 +7010,19 @@
}
]]></handler>
<handler event="dragend"><![CDATA[
// Note: while this case is correctly handled here, this event
// isn't dispatched when the tab is moved within the tabstrip,
// see bug 460801.
+ if (this.getAttribute("finish-movingtab"))
+ return;
+
this._finishAnimateTabMove();
var dt = event.dataTransfer;
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if (dt.mozUserCancelled || dt.dropEffect != "none" || this._isCustomizing) {
delete draggedTab._dragData;
return;
}