Bug 1444489 - Part VIII, Transition the visibility property instead of using transitionend event
Fades out all the UIs by applying CSS transition on opacity and visibility.
Stop relying on transitionend event to set the hidden state.
This removes a source of intermittent failure and while making sure UIs are
hidden.
MozReview-Commit-ID: FR7JQn4eO3X
--- a/toolkit/content/tests/widgets/test_videocontrols_error.html
+++ b/toolkit/content/tests/widgets/test_videocontrols_error.html
@@ -27,33 +27,31 @@
});
add_task(async function check_normal_status() {
await new Promise(resolve => {
video.src = "seek_with_sound.ogg";
video.addEventListener("loadedmetadata", () => SimpleTest.executeSoon(resolve));
});
- // Wait for the fade out transition to complete in case the throbber
- // shows up on slower platforms.
- await SimpleTest.promiseWaitForCondition(() => statusOverlay.hidden,
+ await SimpleTest.promiseWaitForCondition(() => statusOverlay.hasAttribute("fadeout") || statusOverlay.hidden,
"statusOverlay should not present without error");
ok(!statusOverlay.hasAttribute("error"), "statusOverlay should not in error state");
isnot(statusIcon.getAttribute("type"), "error", "should not show error icon");
});
add_task(async function invalid_source() {
const errorType = "errorNoSource";
await new Promise(resolve => {
video.src = "invalid_source.ogg";
video.addEventListener("error", () => SimpleTest.executeSoon(resolve));
});
- ok(!statusOverlay.hidden, `statusOverlay should show when ${errorType}`);
+ ok(!statusOverlay.hidden && !statusOverlay.hasAttribute("fadeout"), `statusOverlay should show when ${errorType}`);
is(statusOverlay.getAttribute("error"), errorType, `statusOverlay should have correct error state: ${errorType}`);
is(statusIcon.getAttribute("type"), "error", `should show error icon when ${errorType}`);
});
</script>
</pre>
</body>
</html>
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -1015,32 +1015,16 @@
element.setAttribute("fadeout", true);
if (element.classList.contains("controlBar") && !this.hasError() &&
document.mozFullScreenElement == this.video) {
this.controlsSpacer.setAttribute("hideCursor", true);
}
}
},
- onTransitionEnd(event) {
- // Ignore events for things other than opacity changes.
- if (event.propertyName != "opacity") {
- return;
- }
-
- var element = event.originalTarget;
-
- // Nothing to do when a fade *in* finishes.
- if (!element.hasAttribute("fadeout")) {
- return;
- }
-
- element.hidden = true;
- },
-
_triggeredByControls: false,
startPlay() {
this._triggeredByControls = true;
this.hideClickToPlay();
this.video.play();
},
@@ -1769,17 +1753,16 @@
// On touch videocontrols, tapping controlsSpacer should show/hide
// the control bar, instead of playing the video or toggle fullscreen.
if (!this.videocontrols.isTouchControls) {
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
addListener(this.controlsSpacer, "dblclick", this.toggleFullscreen);
}
addListener(this.videocontrols, "resizevideocontrols", this.adjustControlSize);
- addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
addListener(this.controlBar, "transitionend", this.onControlBarTransitioned);
// See comment at onFullscreenChange on bug 718107.
// addListener(this.video.ownerDocument, "fullscreenchange", this.onFullscreenChange);
addListener(this.video, "keypress", this.keyHandler, {capture: true});
// Prevent any click event within media controls from dispatching through to video.
addListener(this.videocontrols, "click", function(event) {
event.stopPropagation();
}, {mozSystemGroup: false});
--- a/toolkit/themes/shared/media/videocontrols.css
+++ b/toolkit/themes/shared/media/videocontrols.css
@@ -437,60 +437,55 @@ audio > xul|videocontrols {
.controlsSpacerStack:hover > .clickToPlay,
.clickToPlay:hover {
opacity: 0.55;
}
.controlsSpacerStack:hover > .clickToPlay[fadeout] {
opacity: 0;
+ visibility: hidden;
}
.controlBar[fullscreen-unavailable] .fullscreenButton {
display: none;
}
/* CSS Transitions */
-.clickToPlay {
- transition-property: transform, opacity;
- transition-duration: 400ms, 400ms;
-}
-
-.controlsSpacer[fadeout] {
- opacity: 0;
+.clickToPlay:not([immediate]) {
+ transition-property: transform, opacity, visibility;
+ transition-duration: 400ms, 400ms, 400ms;
}
.clickToPlay[fadeout] {
transform: scale(3);
opacity: 0;
+ visibility: hidden;
+}
+
+.controlBar:not([immediate]) {
+ transition-property: opacity, visibility;
+ transition-duration: 200ms, 200ms;
}
-.clickToPlay[fadeout][immediate] {
- transition-property: opacity, background-size;
- transition-duration: 0s, 0s;
-}
-.controlBar:not([immediate]) {
- transition-property: opacity;
- transition-duration: 200ms;
-}
.controlBar[fadeout] {
opacity: 0;
-}
-.volumeStack:not([immediate]) {
- transition-property: opacity, margin-top;
- transition-duration: 200ms, 200ms;
+ visibility: hidden;
}
+
.statusOverlay:not([immediate]) {
- transition-property: opacity;
- transition-duration: 300ms;
- transition-delay: 750ms;
+ transition-property: opacity, visibility;
+ transition-duration: 300ms, 300ms;
+ transition-delay: 750ms, 750ms;
}
+
.statusOverlay[fadeout],
.statusOverlay[error] + .controlsOverlay > .controlsSpacerStack {
opacity: 0;
+ visibility: hidden;
}
/* Error description formatting */
.errorLabel {
padding: 0 10px;
text-align: center;
font: message-box;
font-size: 14px;