Bug 1387296 - Improve layerization and reduce invalidations in the tab bar. r?dao
MozReview-Commit-ID: H6UgWm4FNaZ
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -7331,18 +7331,20 @@
<resources>
<stylesheet src="chrome://browser/content/tabbrowser.css"/>
</resources>
<content context="tabContextMenu">
<xul:stack class="tab-stack" flex="1">
<xul:vbox xbl:inherits="selected=visuallyselected,fadein"
class="tab-background">
- <xul:hbox xbl:inherits="selected=visuallyselected"
- class="tab-line"/>
+ <xul:vbox class="tab-line-wrapper">
+ <xul:hbox xbl:inherits="selected=visuallyselected"
+ class="tab-line"/>
+ </xul:vbox>
<xul:spacer flex="1"/>
<xul:hbox class="tab-bottom-line"/>
</xul:vbox>
<xul:hbox xbl:inherits="pinned,selected=visuallyselected,titlechanged,attention"
class="tab-content" align="center">
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected"
class="tab-throbber"
role="presentation"
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -45,27 +45,31 @@
the navigation toolbar. */
.tabbrowser-tab[visuallyselected=true] {
position: relative;
z-index: 2;
}
.tab-content {
padding: 0 9px;
+ /* Set pointer-events:none on this element in order to work around a problem
+ with layerization, see bug 1387296. */
+ pointer-events: none;
}
.tab-content[pinned] {
padding: 0 12px;
}
.tab-throbber,
.tab-icon-image,
.tab-sharing-icon-overlay,
.tab-icon-sound,
.tab-close-button {
+ pointer-events: auto; /* counteract pointer-events: none on .tab-content */
margin-top: 1px;
}
.tab-throbber,
.tab-sharing-icon-overlay,
.tab-icon-image {
height: 16px;
width: 16px;
@@ -292,16 +296,20 @@
height: 2px;
}
/* Selected tab */
.tab-background {
border: 1px none transparent;
background-clip: padding-box;
+ /* This element has a purely visual purpose and does not contain interactive
+ elements.
+ Set pointer-events: none in order to achieve better layerization. */
+ pointer-events: none;
}
#toolbar-menubar:not([autohide=true]) ~ #TabsToolbar > #tabbrowser-tabs > .tabbrowser-tab > .tab-stack > .tab-background {
border-top-style: solid;
}
.tab-background[selected=true] {
border-left-style: solid;
@@ -337,29 +345,38 @@
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]) {
background-color: rgba(0,0,0,.1);
}
#TabsToolbar[brighttext] > #tabbrowser-tabs > .tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]) {
background-color: rgba(255,255,255,.1);
}
+.tab-line-wrapper {
+ /* Set overflow:hidden on this element so that the transform animation on
+ .tab-line does not cause unnecessary layers to be created during drawing.
+ This effectively tells layerization that .tab-line will never leave this
+ rectangle and that anything that does not intersect with this rectangle
+ can be merged into an existing layer under the tab line's layer. */
+ overflow: hidden;
+}
+
.tab-line:not([selected=true]) {
opacity: 0;
transform: scaleX(0);
transition: transform 250ms var(--animation-easing-function), opacity 250ms var(--animation-easing-function);
}
-.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-line:not([selected=true]) {
+.tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-line-wrapper > .tab-line:not([selected=true]) {
background-color: rgba(0,0,0,.2);
opacity: 1;
transform: none;
}
-#TabsToolbar[brighttext] > #tabbrowser-tabs > .tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-line:not([selected=true]) {
+#TabsToolbar[brighttext] > #tabbrowser-tabs > .tabbrowser-tab:hover > .tab-stack > .tab-background > .tab-line-wrapper > .tab-line:not([selected=true]) {
background-color: rgba(255,255,255,.2);
}
/* Pinned tabs */
/* Pinned tab separators need position: absolute when positioned (during overflow). */
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned]::before {
height: 100%;