From e05442f9a2caf6815768686c91eedcdf4f2b33d4 Mon Sep 17 00:00:00 2001 From: Frank Yan Date: Tue, 26 Jul 2011 22:26:14 -0700 Subject: [PATCH] Bug 455694 - Animate tab reordering & detaching. r=dolske ui-r=limi --- browser/base/content/browser.css | 34 + browser/base/content/tabbrowser.css | 10 + browser/base/content/tabbrowser.xml | 911 ++++++++++++------ browser/base/content/utilityOverlay.js | 2 - .../themes/gnomestripe/browser/browser.css | 4 + browser/themes/pinstripe/browser/browser.css | 14 + .../themes/winstripe/browser/browser-aero.css | 28 + browser/themes/winstripe/browser/browser.css | 24 +- 8 files changed, 705 insertions(+), 322 deletions(-) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index 514f949dc12f..6bb19ff779f3 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -13,6 +13,7 @@ tabbrowser { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs"); } +#tabbrowser-tabs[drag=detach][closebuttons=hidden] > .tabbrowser-arrowscrollbox > .tabs-newtab-button, #tabbrowser-tabs:not([overflow="true"]) + #new-tab-button, #tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button, #TabsToolbar[currentset]:not([currentset*="tabbrowser-tabs,new-tab-button"]) > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button, @@ -62,6 +63,39 @@ tabbrowser { display: block; /* position:fixed already does this (bug 579776), but let's be explicit */ } +.tabbrowser-tabs[drag] > .tabbrowser-tab { + pointer-events: none; /* suppress tooltips */ +} + +.tabbrowser-tabs[drag] > .tabbrowser-tab[selected] { + z-index: 2; /* ensure selected tab stays on top despite -moz-transform */ +} + +.tabbrowser-tabs[drag] > .tabbrowser-tab[dragged] { + -moz-transition: 0s; /* suppress opening animation when reattaching tab */ +} + +/* visibility: collapse might collapse the tab bar, so we use this instead */ +.tabbrowser-tabs[drag=detach] > .tabbrowser-tab[dragged]:not(:only-child) { + min-width: 0 !important; + max-width: 0 !important; + border: 0 !important; + opacity: 0; + overflow: hidden; + -moz-transition: max-width 150ms ease-out; +} +.tabbrowser-tabs[drag=detach] > .tabbrowser-tab[dragged]:only-child { + visibility: hidden; +} + +.tabbrowser-tabs[drag=move] > .tabbrowser-tab[fadein]:not([dragged]) { + -moz-transition: -moz-transform 200ms ease-out; +} + +.tabbrowser-tabs[drag=finish] > .tabbrowser-tab[dragged][fadein] { + -moz-transition: -moz-transform 100ms ease-out; +} + #alltabs-popup { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup"); } diff --git a/browser/base/content/tabbrowser.css b/browser/base/content/tabbrowser.css index a3f03fae5ced..b945be2e9e3f 100644 --- a/browser/base/content/tabbrowser.css +++ b/browser/base/content/tabbrowser.css @@ -38,6 +38,16 @@ tabpanels { background-color: transparent; } +.tab-drag-preview { + background: -moz-element(#content) left top; + background-clip: content-box; + background-size: cover; +} + +.tab-drag-panel[target] > .tab-drag-preview { + display: none; +} + .tab-drop-indicator { position: relative; z-index: 2; diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 057e1ff3e51f..0a215fda7188 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1497,6 +1497,9 @@ if (!this._beginRemoveTab(aTab, false, null, true)) return; + if (this.tabContainer.draggedTab == aTab) + this.tabContainer._endTabDrag(); + if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse) this.tabContainer._lockTabSizing(aTab); else @@ -1698,6 +1701,8 @@ setTimeout(function(tabs) { tabs._lastTabClosedByMouse = false; }, 0, this.tabContainer); + + this.tabContainer._handleTabDrag(); // Update drag feedback. } // update first-tab/last-tab/beforeselected/afterselected attributes @@ -2676,7 +2681,7 @@ + + + + + + = this._dragTime + this._dragOverDelay) + this.selectedItem = tab; + ind.collapsed = true; + return; + } + } + + var newIndex = this._getDropIndex(event); + var scrollRect = tabStrip.scrollClientRect; + var rect = this.getBoundingClientRect(); + var minMargin = scrollRect.left - rect.left; + var maxMargin = Math.min(minMargin + scrollRect.width, + scrollRect.right); + if (!ltr) + [minMargin, maxMargin] = [this.clientWidth - maxMargin, + this.clientWidth - minMargin]; + var newMargin; + if (pixelsToScroll) { + // If we are scrolling, put the drop indicator at the edge, + // so that it doesn't jump while scrolling. + newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin; + } + else { + if (newIndex == this.childNodes.length) { + let tabRect = this.childNodes[newIndex-1].getBoundingClientRect(); + if (ltr) + newMargin = tabRect.right - rect.left; + else + newMargin = rect.right - tabRect.left; + } + else { + let tabRect = this.childNodes[newIndex].getBoundingClientRect(); + if (ltr) + newMargin = tabRect.left - rect.left; + else + newMargin = rect.right - tabRect.right; + } + } + + ind.collapsed = false; + + newMargin += ind.clientWidth / 2; + if (!ltr) + newMargin *= -1; + + ind.style.MozTransform = "translate(" + Math.round(newMargin) + "px)"; + ind.style.MozMarginStart = (-ind.clientWidth) + "px"; + ]]> + + + + document.getAnonymousElementByAttribute(this, "anonid", "tab-drag-panel"); + + + null + + + + right) + transformX += right - tabX - tabWidth - (ltr ? 0 : 1); + draggedTab.style.MozTransform = "translate(" + transformX + "px)"; + + let newIndex = this._getDropIndex(event, draggedTab); + let tabAtNewIndex = this.childNodes[newIndex > draggedTab._tPos ? + newIndex-1 : newIndex]; + this._positionDropIndicator(event, tabAtNewIndex.pinned == draggedTab.pinned); + + if (newIndex == draggedTab._dragData._dropIndex) + return; + draggedTab._dragData._dropIndex = newIndex; + + if (!ltr) + tabWidth *= -1; + tabs.forEach(function(tab) { + if (tab == draggedTab || tab.pinned != draggedTab.pinned) + return; + else if (tab._tPos < draggedTab._tPos && tab._tPos >= newIndex) + tab.style.MozTransform = "translate(" + tabWidth + "px)"; + else if (tab._tPos > draggedTab._tPos && tab._tPos < newIndex) + tab.style.MozTransform = "translate(" + -tabWidth + "px)"; + else + tab.style.MozTransform = ""; + }); + ]]> + + + + + + = win.screenX + win.outerWidth || + event.screenY < win.screenY || event.screenY >= win.screenY + win.outerHeight); + } + if (isEventOutsideWindow(event, data._targetWindow) || + Services.ww.activeWindow != data._targetWindow) { + // Iterate through browser windows in hopefully front-to-back order. + let winEnum = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true); + let wins = []; + while (winEnum.hasMoreElements()) + wins.push(winEnum.getNext()); + // Work around broken z-order enumerator on Linux. See bug 156333. + if (!wins.length) { + winEnum = Services.wm.getEnumerator("navigator:browser"); + while (winEnum.hasMoreElements()) + wins.unshift(winEnum.getNext()); + } + wins.every(function(win) { + if (win.closed || win.windowState == STATE_MINIMIZED || + isEventOutsideWindow(event, win)) + return true; + data._targetWindow = win; + win.focus(); // Raise window when cursor moves over it. + }); + } + + let detached = (this.getAttribute("drag") == "detach"); + let loneTab = (this.childElementCount == 1); + let bo = loneTab ? draggedTab.boxObject : this.parentNode.boxObject; + // Detach tab if outside window, to the left or right of tab strip, or + // at least one tab height above or below it. + if (data._targetWindow != window || + event.screenX < bo.screenX || event.screenX >= bo.screenX + bo.width || + event.screenY < bo.screenY - (detached || loneTab ? 0 : 1) * bo.height || + event.screenY >= bo.screenY + (detached || loneTab ? 1 : 2) * bo.height) { + if (data._targetWindow != window && + data._targetWindow.windowState != STATE_MINIMIZED) { + let that = data._targetWindow.gBrowser.tabContainer; + let bo = that.parentNode.boxObject; + if (event.screenX >= bo.screenX && event.screenX < bo.screenX + bo.width && + event.screenY >= bo.screenY && event.screenY < bo.screenY + bo.height) { + that._positionDropIndicator(event); + data._dropTarget = that; + } + } + + let dragPanel = this._tabDragPanel; + if (data._dropTarget) + dragPanel.setAttribute("target", "true"); + else + dragPanel.removeAttribute("target"); + + if (!detached) { + this.setAttribute("drag", "detach"); + this._clearDragTransforms(); + this._tabDropIndicator.collapsed = true; + if (draggedTab.style.maxWidth) { + data._maxWidth = draggedTab.style.maxWidth; + draggedTab.style.maxWidth = ""; + } + delete draggedTab._dropIndex; + let label = dragPanel.firstChild; + let preview = dragPanel.lastChild; + label.value = draggedTab.label; + label.width = preview.width = Math.min(outerWidth / 2, screen.availWidth / 5); + let aspectRatio = this.tabbrowser.clientWidth / this.tabbrowser.clientHeight; + preview.height = Math.min(preview.width / aspectRatio, screen.availHeight / 5); + dragPanel.hidden = false; + dragPanel.openPopupAtScreen(event.screenX, event.screenY, false); + } + let width = dragPanel.clientWidth; + let [left, top] = this._getAdjustedCoords(event.screenX, event.screenY, width, + dragPanel.clientHeight, width / 2, 12, true); + dragPanel.moveTo(left, top); + return true; + } + if (detached) { // Otherwise, put tab back in the tab strip. + this.setAttribute("drag", "move"); + if (data._maxWidth) { + draggedTab.style.setProperty("max-width", data._maxWidth, "important"); + delete draggedTab._maxWidth; + } + this.mTabstrip._updateScrollButtonsDisabledState(); + this._tabDragPanel.hidePopup(); + } + ]]> + + + + + + + + + + + + + + + + + + + + + + oldIndex) + newIndex--; + this.removeAttribute("drag"); + this._endTabDrag(); + + if (!draggedTab.pinned && newIndex < this.tabbrowser._numPinnedTabs) + this.tabbrowser.pinTab(draggedTab); + else if (draggedTab.pinned && newIndex >= this.tabbrowser._numPinnedTabs) + this.tabbrowser.unpinTab(draggedTab); + else if (Services.prefs.getBoolPref("browser.tabs.animate")) { + let difference = 0; + // Calculate number of visible tabs between start and destination. + if (newIndex != oldIndex) { + let tabs = this.tabbrowser.visibleTabs; + for (let i = 0; i < tabs.length; i++) { + let position = tabs[i]._tPos; + if (position <= newIndex && position > oldIndex) + difference++; + else if (position >= newIndex && position < oldIndex) + difference--; + } + } + let displacement = difference * draggedTab.getBoundingClientRect().width; + if (window.getComputedStyle(this).direction == "rtl") + displacement *= -1; + let destination = "translate(" + displacement + "px)"; + if (draggedTab.style.MozTransform != destination) { + this.setAttribute("drag", "finish"); + draggedTab.style.MozTransform = destination; + draggedTab.addEventListener("transitionend", function finish(event) { + if (event.eventPhase != Event.AT_TARGET || + event.propertyName != "-moz-transform") + return; + draggedTab.removeEventListener("transitionend", finish); + draggedTab.removeAttribute("dragged"); + let that = draggedTab.parentNode; + that.removeAttribute("drag"); + that._clearDragTransforms(); + that.tabbrowser.moveTabTo(draggedTab, newIndex); + }); + return; + } + } + draggedTab.removeAttribute("dragged"); + this._clearDragTransforms(); + this.tabbrowser.moveTabTo(draggedTab, newIndex); + ]]> + + + + + + + + + this.tabbrowser.visibleTabs.forEach(function(visibleTab) { + visibleTab.style.MozTransform = ""; + }); + + + 350 0 @@ -2964,8 +3437,7 @@ } } this._hasTabTempMaxWidth = true; - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); + window.addEventListener("mouseout", this); } ]]> @@ -2976,15 +3448,13 @@ let spacer = this._closingTabsSpacer; spacer.style.width = parseFloat(spacer.style.width) + pixels + "px"; this._usingClosingTabsSpacer = true; - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); + window.addEventListener("mouseout", this); ]]> = bo.screenX && aEvent.screenX < bo.screenX + bo.width && + aEvent.screenY >= bo.screenY && aEvent.screenY < bo.screenY + bo.height) + break; + let tabContextMenu = document.getElementById("tabContextMenu"); + if (tabContextMenu.state == "open") + tabContextMenu.addEventListener("popuphidden", this); + else this._unlockTabSizing(); break; + case "popuphidden": // Tab context menu was closed. + if (aEvent.eventPhase != Event.AT_TARGET) + break; + aEvent.target.removeEventListener("popuphidden", this); + this._unlockTabSizing(); + break; + case "mousemove": + this._handleTabDrag(aEvent); + break; + case "mouseup": + this._handleTabDrop(aEvent); + break; + case "TabSelect": // Focus was stolen from dragged tab! + this._endTabDrag(aEvent); + window.focus(); + break; + case "scroll": // Tab strip was scrolled. + this._handleTabDrag(); + break; } ]]> @@ -3125,19 +3617,45 @@ + tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2) - return i; + function compare(a, b, lessThan) lessThan ? a < b : a > b; + let ltr = (window.getComputedStyle(this).direction == "ltr"); + let eX = event.screenX; + let tabs = this.tabbrowser.visibleTabs; + + if (draggedTab) { + let dist = draggedTab._dragData._dragDistX; + let tabX = draggedTab.boxObject.screenX + dist; + let draggingRight = dist > 0; + if (draggingRight) + tabX += draggedTab.boxObject.width; + // iterate through app tabs first, since their z-index is higher + else if (!draggedTab.pinned) + for (let i = 0, numPinned = this.tabbrowser._numPinnedTabs; i < numPinned; i++) + if (compare(eX, tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2, ltr)) + return i; + + let i = tabs.indexOf(draggedTab), tab = draggedTab, next; + while (next = ltr ^ draggingRight ? tabs[--i] : tabs[++i]) { + let x = next.pinned == draggedTab.pinned ? tabX : eX; + let middleOfNextTab = next.boxObject.screenX + next.boxObject.width / 2; + if (!compare(x, middleOfNextTab, !draggingRight)) + break; + // ensure an app tab is actually inside the normal tab region + if (draggedTab.pinned && !next.pinned && + x < this.mTabstrip._scrollButtonUp.boxObject.screenX) + break; + tab = next; + } + return tab._tPos + (ltr ^ draggingRight ? 0 : 1); } - return tabs.length; + + let tab = this._getDragTargetTab(event); + for (let i = tab ? tab._tPos : 0; i < tabs.length; i++) + if (compare(eX, tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2, ltr)) + return tabs[i]._tPos; + return this.childElementCount; ]]> @@ -3149,27 +3667,6 @@ if (dt.mozItemCount > 1) return dt.effectAllowed = "none"; - var types = dt.mozTypesAt(0); - var sourceNode = null; - // tabs are always added as the first type - if (types[0] == TAB_DROP_TYPE) { - var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - if (sourceNode instanceof XULElement && - sourceNode.localName == "tab" && - (sourceNode.parentNode == this || - (sourceNode.ownerDocument.defaultView instanceof ChromeWindow && - sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser"))) { - if (sourceNode.parentNode == this && - (event.screenX >= sourceNode.boxObject.screenX && - event.screenX <= (sourceNode.boxObject.screenX + - sourceNode.boxObject.width))) { - return dt.effectAllowed = "none"; - } - - return dt.effectAllowed = "copyMove"; - } - } - if (browserDragAndDrop.canDropLink(event)) { // Here we need to do this manually return dt.effectAllowed = dt.dropEffect = "link"; @@ -3178,20 +3675,6 @@ ]]> - - - = t.boxObject.screenX && - event.screenX <= t.boxObject.screenX + t.boxObject.width && - event.screenY >= t.boxObject.screenY && - event.screenY <= t.boxObject.screenY + t.boxObject.height) - this.mTabstrip.ensureElementIsVisible(t); - ]]> - - - - var ind = this._tabDropIndicator; - if (effects == "" || effects == "none") { - ind.collapsed = true; - this._continueScroll(event); + = this._dragTime + this._dragOverDelay) + let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); + + if (event.shiftKey) + bgLoad = !bgLoad; + + let tab = this._getDragTargetTab(event); + if (!tab) { + // We're adding a new tab. + let newIndex = this._getDropIndex(event); + let newTab = this.tabbrowser.loadOneTab(getShortcutOrURI(url), {inBackground: bgLoad}); + this.tabbrowser.moveTabTo(newTab, newIndex); + } else { + // Load in an existing tab. + try { + this.tabbrowser.getBrowserForTab(tab).loadURI(getShortcutOrURI(url)); + if (!bgLoad) this.selectedItem = tab; ind.collapsed = true; return; + } catch(ex) { + // Just ignore invalid urls. } } - - var newIndex = this._getDropIndex(event); - var scrollRect = tabStrip.scrollClientRect; - var rect = this.getBoundingClientRect(); - var minMargin = scrollRect.left - rect.left; - var maxMargin = Math.min(minMargin + scrollRect.width, - scrollRect.right); - if (!ltr) - [minMargin, maxMargin] = [this.clientWidth - maxMargin, - this.clientWidth - minMargin]; - var newMargin; - if (pixelsToScroll) { - // if we are scrolling, put the drop indicator at the edge - // so that it doesn't jump while scrolling - newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin; - } - else { - if (newIndex == this.childNodes.length) { - let tabRect = this.childNodes[newIndex-1].getBoundingClientRect(); - if (ltr) - newMargin = tabRect.right - rect.left; - else - newMargin = rect.right - tabRect.left; - } - else { - let tabRect = this.childNodes[newIndex].getBoundingClientRect(); - if (ltr) - newMargin = tabRect.left - rect.left; - else - newMargin = rect.right - tabRect.right; - } - } - - ind.collapsed = false; - - newMargin += ind.clientWidth / 2; - if (!ltr) - newMargin *= -1; - - ind.style.MozTransform = "translate(" + Math.round(newMargin) + "px)"; - ind.style.MozMarginStart = (-ind.clientWidth) + "px"; - ]]> - - draggedTab._tPos) - newIndex--; - - if (draggedTab.pinned) { - if (newIndex >= this.tabbrowser._numPinnedTabs) - this.tabbrowser.unpinTab(draggedTab); - } else { - if (newIndex <= this.tabbrowser._numPinnedTabs - 1) - this.tabbrowser.pinTab(draggedTab); - } - - this.tabbrowser.moveTabTo(draggedTab, newIndex); - } - } else if (draggedTab) { - // swap the dropped tab with a new one we create and then close - // it in the other window (making it seem to have moved between - // windows) - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.addTab("about:blank"); - let newBrowser = this.tabbrowser.getBrowserForTab(newTab); - // Stop the about:blank load - newBrowser.stop(); - // make sure it has a docshell - newBrowser.docShell; - - this.tabbrowser.moveTabTo(newTab, newIndex); - - this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab); - - // We need to select the tab after we've done - // swapBrowsersAndCloseOther, so that the updateCurrentBrowser - // it triggers will correctly update our URL bar. - this.tabbrowser.selectedTab = newTab; - } else { - let url = browserDragAndDrop.drop(event, { }); - - // valid urls don't contain spaces ' '; if we have a space it isn't a valid url. - // Also disallow dropping javascript: or data: urls--bail out - if (!url || !url.length || url.indexOf(" ", 0) != -1 || - /^\s*(javascript|data):/.test(url)) - return; - - let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); - - if (event.shiftKey) - bgLoad = !bgLoad; - - let tab = this._getDragTargetTab(event); - if (!tab || dropEffect == "copy") { - // We're adding a new tab. - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.loadOneTab(getShortcutOrURI(url), {inBackground: bgLoad}); - this.tabbrowser.moveTabTo(newTab, newIndex); - } else { - // Load in an existing tab. - try { - this.tabbrowser.getBrowserForTab(tab).loadURI(getShortcutOrURI(url)); - if (!bgLoad) - this.selectedItem = tab; - } catch(ex) { - // Just ignore invalid urls - } - } - } - - // these offsets are only used in dragend, but we need to free them here - // as well - delete draggedTab._dragOffsetX; - delete draggedTab._dragOffsetY; - ]]> - - wX && eX < (wX + window.outerWidth)) { - let bo = this.mTabstrip.boxObject; - // also avoid detaching if the the tab was dropped too close to - // the tabbar (half a tab) - let endScreenY = bo.screenY + 1.5 * bo.height; - if (eY < endScreenY && eY > window.screenY) - return; - } - - var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); - // screen.availLeft et. al. only check the screen that this window is on, - // but we want to look at the screen the tab is being dropped onto. - var sX = {}, sY = {}, sWidth = {}, sHeight = {}; - Cc["@mozilla.org/gfx/screenmanager;1"] - .getService(Ci.nsIScreenManager) - .screenForRect(eX, eY, 1, 1) - .GetAvailRect(sX, sY, sWidth, sHeight); - // ensure new window entirely within screen - var winWidth = Math.min(window.outerWidth, sWidth.value); - var winHeight = Math.min(window.outerHeight, sHeight.value); - var left = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value), - sX.value + sWidth.value - winWidth); - var top = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value), - sY.value + sHeight.value - winHeight); - - delete draggedTab._dragOffsetX; - delete draggedTab._dragOffsetY; - - if (this.tabbrowser.tabs.length == 1) { - // resize _before_ move to ensure the window fits the new screen. if - // the window is too large for its screen, the window manager may do - // automatic repositioning. - window.resizeTo(winWidth, winHeight); - window.moveTo(left, top); - window.focus(); - } else { - this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left, - screenY: top, -#ifndef XP_WIN - outerWidth: winWidth, - outerHeight: winHeight -#endif - }); - } - event.stopPropagation(); ]]> false null - false false diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 03f8e54652da..85f84d1b75a5 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -42,8 +42,6 @@ // Services = object with smart getters for common XPCOM services Components.utils.import("resource://gre/modules/Services.jsm"); -var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; - var gBidiUI = false; function getBrowserURL() diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index 4f349d3af2ff..651a7447872c 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -1600,6 +1600,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- } /* Tab drag and drop */ +.tab-drag-label { + padding: 2px; +} + .tab-drop-indicator { list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png); margin-bottom: -11px; diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css index bb88ba8c47d3..99a6f8af856c 100644 --- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -1560,6 +1560,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { height: 26px; } +.tab-drag-label, .tabbrowser-tab, .tabs-newtab-button { -moz-appearance: none; @@ -1837,6 +1838,19 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { * Tab Drag and Drop */ +.tab-drag-label { + background: -moz-linear-gradient(#eee, #ccc); + padding: 4px 8px; + border-radius: 4px; + box-shadow: inset 0 1px 0 rgba(255,255,255,.6); +} + +.tab-drag-panel:not([target]) > .tab-drag-label { + background: -moz-linear-gradient(#ddd, #bbb); + border-bottom: 1px solid #999; + border-radius: 3px 3px 0 0; +} + .tab-drop-indicator { list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png); margin-bottom: -8px; diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css index 9f2a76370506..38ef33a9eceb 100644 --- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -11,6 +11,7 @@ margin-top: 1px; } + .tab-drag-preview::before, #appmenu-button { border-width: 2px; -moz-border-left-colors: @appMenuButtonBorderColor@; @@ -21,6 +22,7 @@ 0 0 2px 1px rgba(255,255,255,.25) inset; } + #main-window[privatebrowsingmode=temporary] #tabbrowser-tabs > hbox > .tab-drag-panel > .tab-drag-preview::before, #main-window[privatebrowsingmode=temporary] #appmenu-button { -moz-border-left-colors: rgba(255,255,255,.5) rgba(43,8,65,.9); -moz-border-bottom-colors: rgba(255,255,255,.5) rgba(43,8,65,.9); @@ -55,6 +57,7 @@ -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@); } + .tab-drag-label, .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) { background-image: -moz-linear-gradient(white, @toolbarHighlight@ 50%), -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@); @@ -293,6 +296,31 @@ -moz-linear-gradient(rgba(255,255,255,0), #CCD9EA 200px, #C7D5E7); background-attachment: fixed; } + + .tab-drag-panel { + -moz-appearance: -moz-win-borderless-glass; + } + .tab-drag-label { + padding: 4px; + background-color: -moz-dialog; + border-radius: 3px; + } + .tab-drag-preview { + margin: 15px 7px 7px; + } + .tab-drag-panel:not([target]) > .tab-drag-preview { + display: block; + } + .tab-drag-preview::before { /* miniature appmenu button */ + content: ""; + display: block; + margin-top: -15px; + -moz-margin-start: -2px; + padding: 0; + width: 32px; + height: 7px; + border-radius: 0 0 3px 3px; + } } @media not all and (-moz-windows-compositor) { diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index 4abc6ca0e77b..554f3be59569 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -176,6 +176,7 @@ } %ifdef MOZ_OFFICIAL_BRANDING +.tab-drag-preview::before, #appmenu-button { background-image: -moz-linear-gradient(rgb(247,182,82), rgb(215,98,10) 95%); border-color: rgba(83,42,6,.9); @@ -199,6 +200,7 @@ } %else %if MOZ_UPDATE_CHANNEL == aurora +.tab-drag-preview::before, #appmenu-button { background-image: -moz-linear-gradient(hsl(208,99%,37%), hsl(214,90%,23%) 95%); border-color: hsla(214,89%,21%,.9); @@ -221,6 +223,7 @@ 0 1px 1px rgba(0,0,0,.2) inset; } %else +.tab-drag-preview::before, #appmenu-button { background-image: -moz-linear-gradient(hsl(211,33%,32%), hsl(209,53%,10%) 95%); border-color: hsla(210,59%,13%,.9); @@ -245,6 +248,7 @@ %endif %endif +#main-window[privatebrowsingmode=temporary] #tabbrowser-tabs > hbox > .tab-drag-panel > .tab-drag-preview::before, #main-window[privatebrowsingmode=temporary] #appmenu-button { background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%); border-color: rgba(43,8,65,.9); @@ -1806,7 +1810,25 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- outline: 1px dotted; } -/* Tab DnD indicator */ +/* Tab drag and drop */ +.tab-drag-panel { + border: 0 !important; +} + +.tab-drag-label { + margin: 0 !important; + padding: 5px; + border: 1px solid DimGray; +} + +.tab-drag-panel:not([target]) > .tab-drag-label { + display: none; +} + +.tab-drag-preview { + border: 1px solid rgba(0,0,0,.5); +} + .tab-drop-indicator { list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png); margin-bottom: -11px;