Bug 649490 - Switch the volume slider on the media controls to be horizontal and always visible. r=Gijs

--HG--
extra : rebase_source : 90a0865e71b87dbaddf44c4805f78f709e5d80de
This commit is contained in:
Jared Wein 2013-11-27 10:31:39 -05:00
parent b28b41c00c
commit 78680ed96d
18 changed files with 113 additions and 108 deletions

View File

@ -65,7 +65,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
var audioElm = getAccessible("audio");
var playBtn = audioElm.firstChild;
var scrubber = playBtn.nextSibling.nextSibling.nextSibling;
var muteBtn = audioElm.lastChild;
var muteBtn = audioElm.lastChild.previousSibling;
var actions = [
{

View File

@ -49,7 +49,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=483573
role: ROLE_PUSHBUTTON,
name: "Mute",
children: []
}
},
{ // slider of volume bar
role: ROLE_SLIDER,
children: []
},
]
};
testAccessibleTree("audio", accTree);

View File

@ -54,7 +54,7 @@
* is hidden by videocontrols.xml, and that alters the position of the
* play button. This workaround moves it back to center.
*/
.controlBar.audio .playButton {
.controlBar.audio-only .playButton {
transform: translateX(28px);
}

View File

@ -54,7 +54,7 @@
* is hidden by videocontrols.xml, and that alters the position of the
* play button. This workaround moves it back to center.
*/
.controlBar.audio .playButton {
.controlBar.audio-only .playButton {
transform: translateX(28px);
}

View File

@ -30,14 +30,15 @@ const muteButtonWidth = 33;
const muteButtonHeight = 28;
const durationWidth = 34;
const fullscreenButtonWidth = document.mozFullScreenEnabled ? 28 : 0;
const scrubberWidth = videoWidth - playButtonWidth - muteButtonWidth - durationWidth - fullscreenButtonWidth;
const volumeSliderWidth = 32;
const scrubberWidth = videoWidth - playButtonWidth - durationWidth - muteButtonWidth - volumeSliderWidth - fullscreenButtonWidth;
const scrubberHeight = 28;
// Play button is on the bottom-left
const playButtonCenterX = 0 + Math.round(playButtonWidth / 2);
const playButtonCenterY = videoHeight - Math.round(playButtonHeight / 2);
// Mute button is on the bottom-right before the full screen button
const muteButtonCenterX = videoWidth - Math.round(muteButtonWidth / 2) - fullscreenButtonWidth;
// Mute button is on the bottom-right before the full screen button and volume slider
const muteButtonCenterX = videoWidth - Math.round(muteButtonWidth / 2) - volumeSliderWidth - fullscreenButtonWidth;
const muteButtonCenterY = videoHeight - Math.round(muteButtonHeight / 2);
// Scrubber bar is between the play and mute buttons. We don't need it's
// X center, just the offset of its box.

View File

@ -92,7 +92,8 @@ html|span.statActivity[seeking] > html|span.statActivitySeeking {
.controlBar[size="hidden"],
.controlBar[size="small"] .durationBox,
.controlBar[size="small"] .durationLabel,
.controlBar[size="small"] .positionLabel {
.controlBar[size="small"] .positionLabel,
.controlBar[size="small"] .volumeStack {
visibility: collapse;
}

View File

@ -287,9 +287,10 @@
<button class="muteButton"
mutelabel="&muteButton.muteLabel;"
unmutelabel="&muteButton.unmuteLabel;"/>
<stack class="volumeStack" hidden="true" fadeout="true">
<box class="volumeBackgroundBar"/>
<scale class="volumeControl" orient="vertical" dir="reverse" movetoclick="true"/>
<stack class="volumeStack">
<box class="volumeBackground"/>
<box class="volumeForeground" anonid="volumeForeground"/>
<scale class="volumeControl" movetoclick="true"/>
</stack>
<button class="fullscreenButton"
enterfullscreenlabel="&fullscreenButton.enterfullscreenlabel;"
@ -313,7 +314,6 @@
controlBar : null,
playButton : null,
muteButton : null,
volumeStack : null,
volumeControl : null,
durationLabel : null,
positionLabel : null,
@ -342,6 +342,13 @@
get isAudioOnly() { return this._isAudioOnly; },
set isAudioOnly(val) {
this._isAudioOnly = val;
if (this._isAudioOnly) {
this.controlBar.setAttribute("audio-only", true);
} else {
this.controlBar.removeAttribute("audio-only");
}
this.adjustControlSize();
if (!this.isTopLevelSyntheticDocument)
return;
if (this._isAudioOnly) {
@ -462,6 +469,7 @@
this._playButtonWidth = this.playButton.clientWidth;
this._durationLabelWidth = this.durationLabel.clientWidth;
this._muteButtonWidth = this.muteButton.clientWidth;
this._volumeControlWidth = this.volumeControl.clientWidth;
this._fullscreenButtonWidth = this.fullscreenButton.clientWidth;
this._controlBarHeight = this.controlBar.clientHeight;
this.controlBar.hidden = true;
@ -554,9 +562,11 @@
this.setupStatusFader();
break;
case "volumechange":
var volume = this.video.muted ? 0 : Math.round(this.video.volume * 100);
var volume = this.video.muted ? 0 : this.video.volume;
var volumePercentage = Math.round(volume * 100);
this.setMuteButtonState(this.video.muted);
this.volumeControl.value = volume;
this.volumeControl.value = volumePercentage;
this.volumeForeground.style.paddingRight = (1 - volume) * this._volumeControlWidth + "px";
break;
case "loadedmetadata":
this.adjustControlSize();
@ -854,21 +864,6 @@
this.bufferBar.value = endTime;
},
onVolumeMouseInOut : function (event) {
let doc = this.video.ownerDocument;
let win = doc.defaultView;
if (this.isVideoWithoutAudioTrack() ||
(this.isAudioOnly && this.isTopLevelSyntheticDocument)) {
return;
}
// Ignore events caused by transitions between mute button and volumeStack,
// or between nodes inside these two elements.
if (this.isEventWithin(event, this.muteButton, this.volumeStack))
return;
var isMouseOver = (event.type == "mouseover");
this.startFade(this.volumeStack, isMouseOver);
},
_controlsHiddenByTimeout : false,
_showControlsTimeout : 0,
SHOW_CONTROLS_TIMEOUT_MS: 500,
@ -1360,15 +1355,14 @@
_playButtonWidth : 0,
_durationLabelWidth : 0,
_muteButtonWidth : 0,
_volumeControlWidth : 0,
_fullscreenButtonWidth : 0,
_controlBarHeight : 0,
_overlayPlayButtonHeight : 64,
_overlayPlayButtonWidth : 64,
_volumeStackMarginEnd : 8,
adjustControlSize : function adjustControlSize() {
let doc = this.video.ownerDocument;
let isAudioOnly = this.isAudioOnly;
if (isAudioOnly && !this.isTopLevelSyntheticDocument)
return;
// The scrubber has |flex=1|, therefore |minScrubberWidth|
// was generated by empirical testing.
@ -1377,7 +1371,15 @@
minScrubberWidth +
this._durationLabelWidth +
this._muteButtonWidth +
this._volumeControlWidth +
this._fullscreenButtonWidth;
let isAudioOnly = this.isAudioOnly;
if (isAudioOnly) {
// When the fullscreen button is hidden we add margin-end to the volume stack.
minWidthAllControls -= this._fullscreenButtonWidth - this._volumeStackMarginEnd;
}
let minHeightForControlBar = this._controlBarHeight;
let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
@ -1400,14 +1402,12 @@
init : function (binding) {
this.video = binding.parentNode;
this.videocontrols = binding;
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
this.statusIcon = document.getAnonymousElementByAttribute(binding, "class", "statusIcon");
this.controlBar = document.getAnonymousElementByAttribute(binding, "class", "controlBar");
this.playButton = document.getAnonymousElementByAttribute(binding, "class", "playButton");
this.muteButton = document.getAnonymousElementByAttribute(binding, "class", "muteButton");
this.volumeControl = document.getAnonymousElementByAttribute(binding, "class", "volumeControl");
this.volumeStack = document.getAnonymousElementByAttribute(binding, "class", "volumeStack");
this.progressBar = document.getAnonymousElementByAttribute(binding, "class", "progressBar");
this.bufferBar = document.getAnonymousElementByAttribute(binding, "class", "bufferBar");
this.scrubber = document.getAnonymousElementByAttribute(binding, "class", "scrubber");
@ -1419,6 +1419,7 @@
this.controlsSpacer = document.getAnonymousElementByAttribute(binding, "class", "controlsSpacer");
this.clickToPlay = document.getAnonymousElementByAttribute(binding, "class", "clickToPlay");
this.fullscreenButton = document.getAnonymousElementByAttribute(binding, "class", "fullscreenButton");
this.volumeForeground = document.getAnonymousElementByAttribute(binding, "anonid", "volumeForeground");
this.statsTable = document.getAnonymousElementByAttribute(binding, "class", "statsTable");
this.stats.filename = document.getAnonymousElementByAttribute(binding, "class", "statFilename");
@ -1432,6 +1433,7 @@
this.stats.framesPresented = document.getAnonymousElementByAttribute(binding, "class", "statFramesPresented");
this.stats.framesPainted = document.getAnonymousElementByAttribute(binding, "class", "statFramesPainted");
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
this.setupInitialState();
this.setupNewLoadState();
@ -1459,15 +1461,6 @@
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
addListener(this.controlsSpacer, "dblclick", this.toggleFullscreen);
if (this.isAudioOnly) {
this.controlBar.classList.add("audio");
} else {
addListener(this.muteButton, "mouseover", this.onVolumeMouseInOut);
addListener(this.muteButton, "mouseout", this.onVolumeMouseInOut);
addListener(this.volumeStack, "mouseover", this.onVolumeMouseInOut);
addListener(this.volumeStack, "mouseout", this.onVolumeMouseInOut);
}
addListener(this.videocontrols, "resizevideocontrols", this.adjustControlSize);
addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
addListener(this.video.ownerDocument, "mozfullscreenchange", this.onFullscreenChange);
@ -1539,11 +1532,12 @@
<button class="muteButton"
mutelabel="&muteButton.muteLabel;"
unmutelabel="&muteButton.unmuteLabel;"/>
<stack class="volumeStack" hidden="true" fadeout="true">
<box class="volumeBackgroundBar"/>
<scale class="volumeControl" orient="vertical" dir="reverse" movetoclick="true"/>
<stack class="volumeStack">
<box class="volumeBackground"/>
<box class="volumeForeground" anonid="volumeForeground"/>
<scale class="volumeControl" movetoclick="true"/>
</stack>
</hbox>
</hbox>
<stack class="scrubberStack" flex="1">
<box class="backgroundBar"/>
<progressmeter class="bufferBar"/>

View File

@ -174,8 +174,8 @@ toolkit.jar:
skin/classic/global/media/error.png (media/error.png)
skin/classic/global/media/throbber.png (media/throbber.png)
skin/classic/global/media/stalled.png (media/stalled.png)
skin/classic/global/media/volumeThumb.png (media/volumeThumb.png)
skin/classic/global/media/volumeThumb@2x.png (media/volumeThumb@2x.png)
skin/classic/global/media/volume-empty.png (media/volume-empty.png)
skin/classic/global/media/volume-full.png (media/volume-full.png)
skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
skin/classic/global/menu/menu-arrow.png (menu/menu-arrow.png)

View File

@ -59,6 +59,10 @@
background-image: url(chrome://global/skin/media/noAudio.png);
}
.muteButton[noAudio] + .volumeStack {
display: none;
}
.fullscreenButton {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 16, 16, 0);
}
@ -67,36 +71,35 @@
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 32, 16, 16);
}
.volumeStack {
width: 28px;
height: 70px;
background-color: rgba(35,31,32,.74);
/* use negative margin to place stack over the mute button to its left. */
margin: -70px 3px 28px -31px;
overflow: hidden; /* crop it when sliding down, don't grow the control bar */
position: relative; /* Trick to work around negative margin interfering with dragging the thumb. */
padding-top: 6px;
}
.volumeControl {
min-height: 64px;
width: 32px;
opacity: 0;
}
.volumeBackground,
.volumeForeground {
background-repeat: no-repeat;
background-position: center;
width: 32px;
}
.volumeBackground {
background-image: url(chrome://global/skin/media/volume-empty.png);
}
.volumeForeground {
background-image: url(chrome://global/skin/media/volume-full.png);
background-clip: content-box;
}
.controlBar[audio-only] > .volumeStack {
/* This value is duplicated in the videocontrols.xml adjustControlSize function. */
-moz-margin-end: 8px;
}
/* .scale-thumb is an element inside the <scale> implementation. */
.volumeControl .scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center;
border: none;
min-width: 20px;
min-height: 10px;
}
.volumeBackgroundBar {
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
margin: 0 10px;
background-color: rgba(255,255,255,.75);
border-radius: 2.5px;
min-width: 0;
opacity: 0;
}
.durationBox {
@ -337,10 +340,6 @@ html|table {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton@2x.png"), 0, 64, 32, 32);
background-size: 16px 16px;
}
.volumeControl .scale-thumb {
background-image: url(chrome://global/skin/media/volumeThumb@2x.png);
background-size: 20px 10px;
}
.timeThumb {
background-image: url(chrome://global/skin/media/scrubberThumb@2x.png);
background-size: 33px 28px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

View File

@ -163,7 +163,8 @@ toolkit.jar:
skin/classic/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
skin/classic/global/media/throbber.png (media/throbber.png)
skin/classic/global/media/stalled.png (media/stalled.png)
skin/classic/global/media/volumeThumb.png (media/volumeThumb.png)
skin/classic/global/media/volume-empty.png (media/volume-empty.png)
skin/classic/global/media/volume-full.png (media/volume-full.png)
skin/classic/global/media/error.png (media/error.png)
skin/classic/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
skin/classic/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)
@ -344,7 +345,8 @@ toolkit.jar:
skin/classic/aero/global/media/scrubberThumbWide.png (media/scrubberThumbWide.png)
skin/classic/aero/global/media/throbber.png (media/throbber.png)
skin/classic/aero/global/media/stalled.png (media/stalled.png)
skin/classic/aero/global/media/volumeThumb.png (media/volumeThumb.png)
skin/classic/aero/global/media/volume-empty.png (media/volume-empty.png)
skin/classic/aero/global/media/volume-full.png (media/volume-full.png)
skin/classic/aero/global/media/error.png (media/error.png)
skin/classic/aero/global/media/clicktoplay-bgtexture.png (media/clicktoplay-bgtexture.png)
skin/classic/aero/global/media/videoClickToPlayButton.svg (media/videoClickToPlayButton.svg)

View File

@ -59,6 +59,10 @@
background-image: url(chrome://global/skin/media/noAudio.png);
}
.muteButton[noAudio] + .volumeStack {
display: none;
}
.fullscreenButton {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 16, 16, 0);
}
@ -67,36 +71,35 @@
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 32, 16, 16);
}
.volumeStack {
width: 28px;
height: 70px;
background-color: rgba(35,31,32,.74);
/* use negative margin to place stack over the mute button to its left. */
margin: -70px 3px 28px -31px;
overflow: hidden; /* crop it when sliding down, don't grow the control bar */
position: relative; /* Trick to work around negative margin interfering with dragging the thumb. */
padding-top: 6px;
}
.volumeControl {
min-height: 64px;
width: 32px;
opacity: 0;
}
.volumeBackground,
.volumeForeground {
background-repeat: no-repeat;
background-position: center;
width: 32px;
}
.volumeBackground {
background-image: url(chrome://global/skin/media/volume-empty.png);
}
.volumeForeground {
background-image: url(chrome://global/skin/media/volume-full.png);
background-clip: content-box;
}
.controlBar[audio-only] > .volumeStack {
/* This value is duplicated in the videocontrols.xml adjustControlSize function. */
-moz-margin-end: 8px;
}
/* .scale-thumb is an element inside the <scale> implementation. */
.volumeControl .scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: url(chrome://global/skin/media/volumeThumb.png) no-repeat center;
border: none;
min-width: 20px;
min-height: 10px;
}
.volumeBackgroundBar {
/* margin left/right: make bar 8px wide (control width = 28, minus 2 * 10 margin) */
margin: 0 10px;
background-color: rgba(255,255,255,.75);
border-radius: 2.5px;
min-width: 0;
opacity: 0;
}
.durationBox {
@ -170,7 +173,8 @@
}
/* .scale-thumb is an element inside the <scale> implementation. */
.scrubber .scale-thumb {
.scrubber .scale-thumb,
.volumeControl .scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: transparent;

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B