Bug 1271765 - Part 2: Desktop media control visual refresh. r=jaws

MozReview-Commit-ID: 1GfyGmrhgCs

--HG--
extra : rebase_source : e3b49788ddac0537281c8e2fb33c66b31e631db3
This commit is contained in:
Ray Lin 2016-10-12 13:31:32 +08:00
parent 461915d273
commit 8c3d97d3bc
34 changed files with 1005 additions and 539 deletions

View File

@ -1151,7 +1151,7 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
if (controls) {
controlBar = controls.ownerDocument.getAnonymousElementByAttribute(
controls, "class", "controlBar");
controls, "anonid", "controlBar");
controlBarShown = controlBar ? !!controlBar.clientHeight : false;
}

View File

@ -46,6 +46,7 @@
// for time=0, immediately update the value to show or hide the hours.
// It's less intrusive to do it now than when the user clicks play and
// is looking right next to the thumb.
if (!this.timeLabel) return;
var displayedTime = this.timeLabel.getAttribute("value");
if (val && displayedTime == "0:00")
this.timeLabel.setAttribute("value", "0:00:00");
@ -131,7 +132,11 @@
this.Utils.positionLabel.setAttribute("value", this.thumb.timeLabel.value);
// Update the value bar to match the thumb position.
let percent = newValue / this.max;
this.valueBar.value = Math.round(percent * 10000); // has max=10000
if (!isNaN(percent) && percent != Infinity) {
this.valueBar.value = Math.round(percent * 10000); // has max=10000
} else {
this.valueBar.removeAttribute("value");
}
}
// The value of userChanged is true when changing the position with the mouse,
@ -203,61 +208,67 @@
<stylesheet src="chrome://global/skin/media/videocontrols.css"/>
</resources>
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="mediaControlsFrame">
<stack flex="1">
<vbox flex="1" class="statusOverlay" hidden="true">
<box class="statusIcon"/>
<label class="errorLabel" anonid="errorAborted">&error.aborted;</label>
<label class="errorLabel" anonid="errorNetwork">&error.network;</label>
<label class="errorLabel" anonid="errorDecode">&error.decode;</label>
<label class="errorLabel" anonid="errorSrcNotSupported">&error.srcNotSupported;</label>
<label class="errorLabel" anonid="errorNoSource">&error.noSource2;</label>
<label class="errorLabel" anonid="errorGeneric">&error.generic;</label>
</vbox>
<xbl:content xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns="http://www.w3.org/1999/xhtml" class="mediaControlsFrame">
<div anonid="controlsContainer" class="controlsContainer" role="none">
<div anonid="statusOverlay" class="statusOverlay stackItem" hidden="true">
<div anonid="statusIcon" class="statusIcon"></div>
<span class="errorLabel" anonid="errorAborted">&error.aborted;</span>
<span class="errorLabel" anonid="errorNetwork">&error.network;</span>
<span class="errorLabel" anonid="errorDecode">&error.decode;</span>
<span class="errorLabel" anonid="errorSrcNotSupported">&error.srcNotSupported;</span>
<span class="errorLabel" anonid="errorNoSource">&error.noSource2;</span>
<span class="errorLabel" anonid="errorGeneric">&error.generic;</span>
</div>
<vbox class="controlsOverlay">
<stack flex="1">
<spacer class="controlsSpacer" flex="1"/>
<box class="clickToPlay" hidden="true" flex="1"/>
<vbox class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></vbox>
</stack>
<hbox class="controlBar" hidden="true">
<button class="playButton"
<div anonid="controlsOverlay" class="controlsOverlay stackItem">
<div class="controlsSpacerStack" aria-hideen="true">
<div anonid="controlsSpacer" class="controlsSpacer stackItem" role="none"></div>
<div anonid="clickToPlay" class="clickToPlay" hidden="true"></div>
</div>
<div anonid="controlBar" class="controlBar" hidden="true">
<button anonid="playButton"
class="playButton"
playlabel="&playButton.playLabel;"
pauselabel="&playButton.pauseLabel;"/>
<stack class="scrubberStack" flex="1">
<box class="backgroundBar"/>
<progressmeter class="bufferBar"/>
<progressmeter class="progressBar" max="10000"/>
<scale class="scrubber" movetoclick="true"/>
</stack>
<vbox class="durationBox">
<label class="positionLabel" role="presentation"/>
<label class="durationLabel" role="presentation"/>
</vbox>
<button class="muteButton"
<div anonid="scrubberStack" class="scrubberStack progressContainer" role="none">
<div class="progressBackgroundBar stackItem" role="none">
<div class="progressStack" role="none">
<progress anonid="bufferBar" class="bufferBar" value="0" max="100"></progress>
<progress anonid="progressBar" class="progressBar" value="0" max="100"></progress>
</div>
</div>
<input type="range" anonid="scrubber" class="scrubber"/>
</div>
<span anonid="positionLabel" class="positionLabel" role="presentation"></span>
<span anonid="durationLabel" class="durationLabel" role="presentation"></span>
<div anonid="positionDurationBox" class="positionDurationBox" role="none">
&positionAndDuration.nameFormat;
</div>
<div anonid="controlBarSpacer" class="controlBarSpacer" hidden="true" role="none"></div>
<button anonid="muteButton"
class="muteButton"
mutelabel="&muteButton.muteLabel;"
unmutelabel="&muteButton.unmuteLabel;"/>
<stack class="volumeStack">
<box class="volumeBackground"/>
<box class="volumeForeground" anonid="volumeForeground"/>
<scale class="volumeControl" movetoclick="true"/>
</stack>
<button class="closedCaptionButton"/>
<button class="fullscreenButton"
<div anonid="volumeStack" class="volumeStack progressContainer" role="none">
<input type="range" anonid="volumeControl" class="volumeControl" min="0" max="100" step="1"/>
</div>
<button anonid="closedCaptionButton" class="closedCaptionButton"/>
<button anonid="fullscreenButton"
class="fullscreenButton"
enterfullscreenlabel="&fullscreenButton.enterfullscreenlabel;"
exitfullscreenlabel="&fullscreenButton.exitfullscreenlabel;"/>
</hbox>
</vbox>
</stack>
</div>
<div anonid="textTrackList" class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></div>
</div>
</div>
</xbl:content>
<implementation>
<constructor>
<![CDATA[
this.isTouchControl = false;
this.isTouchControls = false;
this.randomID = 0;
this.Utils = {
@ -270,7 +281,6 @@
volumeControl : null,
durationLabel : null,
positionLabel : null,
scrubberThumb : null,
scrubber : null,
progressBar : null,
bufferBar : null,
@ -293,6 +303,7 @@
firstFrameShown : false,
timeUpdateCount : 0,
maxCurrentTimeSeen : 0,
isPausedByDragging: false,
_isAudioOnly : false,
get isAudioOnly() { return this._isAudioOnly; },
set isAudioOnly(val) {
@ -302,7 +313,7 @@
if (!this.isTopLevelSyntheticDocument)
return;
if (this._isAudioOnly) {
this.video.style.height = this._controlBarHeight + "px";
this.video.style.height = this.controlBar.minHeight + "px";
this.video.style.width = "66%";
} else {
this.video.style.removeProperty("height");
@ -366,6 +377,7 @@
this.log("Initial playback position is at " + currentTime + " of " + duration);
// It would be nice to retain maxCurrentTimeSeen, but it would be difficult
// to determine if the media source changed while we were detached.
this.initPositionDurationBox();
this.maxCurrentTimeSeen = currentTime;
this.showPosition(currentTime, duration);
@ -396,11 +408,11 @@
// We can't determine the exact buffering status, but do know if it's
// fully loaded. (If it's still loading, it will fire a progress event
// and we'll figure out the exact state then.)
this.bufferBar.setAttribute("max", 100);
this.bufferBar.max = 100;
if (this.video.readyState >= this.video.HAVE_METADATA)
this.showBuffered();
else
this.bufferBar.setAttribute("value", 0);
this.bufferBar.value = 0;
// Set the current status icon.
if (this.hasError()) {
@ -412,15 +424,66 @@
// An event handler for |onresize| should be added when bug 227495 is fixed.
this.controlBar.hidden = false;
this._playButtonWidth = this.playButton.clientWidth;
this._durationLabelWidth = this.durationLabel.clientWidth;
this._muteButtonWidth = this.muteButton.clientWidth;
this._volumeControlWidth = this.volumeControl.clientWidth;
this._closedCaptionButtonWidth = this.closedCaptionButton.clientWidth;
this._fullscreenButtonWidth = this.fullscreenButton.clientWidth;
this._controlBarHeight = this.controlBar.clientHeight;
this.controlBar.hidden = true;
let layoutControls = [
...this.controlBar.children,
this.durationSpan,
this.controlBar,
this.clickToPlay
];
for (let control of layoutControls) {
if (!control) {
break;
}
Object.defineProperties(control, {
minWidth: {
value: control.clientWidth,
writable: true
},
minHeight: {
value: control.clientHeight,
writable: true
},
isAdjustableControl: {
value: true
},
isWanted: {
value: true,
writable: true
},
hideByAdjustment: {
set: (v) => {
if (v) {
control.setAttribute("hidden", "true");
} else {
control.removeAttribute("hidden");
}
control._isHiddenByAdjustment = v;
},
get: () => control._isHiddenByAdjustment
},
_isHiddenByAdjustment: {
value: false,
writable: true
}
});
}
// Cannot get minimal width of flexible scrubber and clickToPlay.
// Rewrite to empirical value for now.
this.controlBar.minHeight = 40;
this.scrubberStack.minWidth = 64;
this.volumeControl.minWidth = 48;
this.clickToPlay.minWidth = 48;
if (this.positionDurationBox) {
this.positionDurationBox.minWidth -= this.durationSpan.minWidth;
}
this.adjustControlSize();
this.controlBar.hidden = true;
// Can only update the volume controls once we've computed
// _volumeControlWidth, since the volume slider implementation
@ -443,8 +506,10 @@
(this.video.paused &&
!(this.video.autoplay && this.video.mozAutoplayEnabled));
// Hide the overlay if the video time is non-zero or if an error occurred to workaround bug 718107.
this.startFade(this.clickToPlay, shouldShow && !this.isAudioOnly &&
this.video.currentTime == 0 && !this.hasError(), true);
let shouldClickToPlayShow = shouldShow && !this.isAudioOnly &&
this.video.currentTime == 0 && !this.hasError();
this.startFade(this.clickToPlay, shouldClickToPlayShow, true);
this.startFade(this.controlsSpacer, shouldClickToPlayShow, true);
this.startFade(this.controlBar, shouldShow, true);
},
@ -464,12 +529,16 @@
return enabled;
},
updateVolume() {
const volume = this.volumeControl.value;
this.setVolume(volume / 100);
},
updateVolumeControls() {
var volume = this.video.muted ? 0 : this.video.volume;
var volumePercentage = Math.round(volume * 100);
this.updateMuteButtonState();
this.volumeControl.value = volumePercentage;
this.volumeForeground.style.paddingRight = (1 - volume) * this._volumeControlWidth + "px";
},
handleEvent : function(aEvent) {
@ -486,7 +555,7 @@
case "play":
this.setPlayButtonState(false);
this.setupStatusFader();
if (!this._triggeredByControls && this.dynamicControls && this.videocontrols.isTouchControl)
if (!this._triggeredByControls && this.dynamicControls && this.videocontrols.isTouchControls)
this.startFadeOut(this.controlBar);
if (!this._triggeredByControls)
this.clickToPlay.hidden = true;
@ -585,10 +654,11 @@
// If the user is dragging the scrubber ignore the delayed seek
// responses (don't yank the thumb away from the user)
if (this.scrubber.isDragging)
if (this.scrubber.isDragging || this.scrubber.startToDrag)
return;
this.showPosition(currentTime, duration);
this.showBuffered();
break;
case "emptied":
this.bufferBar.value = 0;
@ -744,6 +814,37 @@
return timeString;
},
initPositionDurationBox : function() {
if (this.videocontrols.isTouchControls) {
return;
}
const positionTextNode = Array.prototype.find.call(
this.positionDurationBox.childNodes, (n) => !!~n.textContent.search("#1"));
const durationSpan = this.durationSpan;
const durationFormat = durationSpan.textContent;
const positionFormat = positionTextNode.textContent;
durationSpan.classList.add("duration");
durationSpan.setAttribute("role", "none");
Object.defineProperties(this.positionDurationBox, {
durationSpan: {
value: durationSpan
},
position: {
set: (v) => {
positionTextNode.textContent = positionFormat.replace("#1", v);
}
},
duration: {
set: (v) => {
durationSpan.textContent = v ? durationFormat.replace("#2", v) : "";
}
}
});
},
showDuration : function(duration) {
let isInfinite = (duration == Infinity);
this.log("Duration is " + duration + "ms.\n");
@ -753,14 +854,17 @@
// Format the duration as "h:mm:ss" or "m:ss"
let timeString = isInfinite ? "" : this.formatTime(duration);
this.durationLabel.setAttribute("value", timeString);
if (this.videocontrols.isTouchControls) {
this.durationLabel.setAttribute("value", timeString);
} else {
this.positionDurationBox.duration = timeString;
}
// "durationValue" property is used by scale binding to
// generate accessible name.
this.scrubber.durationValue = timeString;
// If the duration is over an hour, thumb should show h:mm:ss instead of mm:ss
this.scrubberThumb.showHours = (duration >= 3600000);
this.scrubber.max = duration;
// XXX Can't set increment here, due to bug 473103. Also, doing so causes
@ -769,6 +873,51 @@
this.scrubber.pageIncrement = Math.round(duration / 10);
},
pauseVideoDuringDragging: function() {
if (!this.video.paused &&
!this.isPausedByDragging &&
this.scrubber.isDragging) {
this.isPausedByDragging = true;
this.video.pause();
}
},
onScrubberInput: function(e) {
const duration = Math.round(this.video.duration * 1000); // in ms
let time = this.scrubber.value;
if (!this.scrubber.startToDrag || this.scrubber.isDragging) {
this.seekToPosition(time);
this.showPosition(time, duration);
}
this.scrubber.startToDrag = true;
},
onScrubberChange: function(e) {
this.scrubber.startToDrag = false;
this.scrubber.isDragging = false;
if (this.isPausedByDragging) {
this.video.play();
this.isPausedByDragging = false;
}
},
updateScrubberProgress() {
if (this.videocontrols.isTouchControls) {
return;
}
const positionPercent = this.scrubber.value / this.scrubber.max * 100;
if (!isNaN(positionPercent) && positionPercent != Infinity) {
this.progressBar.value = positionPercent;
} else {
this.progressBar.value = 0;
}
},
seekToPosition : function(newPosition) {
newPosition /= 1000; // convert from ms
this.log("+++ seeking to " + newPosition);
@ -798,8 +947,15 @@
this.log("time update @ " + currentTime + "ms of " + duration + "ms");
this.positionLabel.setAttribute("value", this.formatTime(currentTime));
let positionTime = this.formatTime(currentTime);
this.scrubber.value = currentTime;
if (this.videocontrols.isTouchControls) {
this.positionLabel.setAttribute("value", positionTime);
} else {
this.positionDurationBox.position = positionTime;
this.updateScrubberProgress();
}
},
showBuffered : function() {
@ -831,8 +987,9 @@
}
var duration = Math.round(this.video.duration * 1000);
if (isNaN(duration))
if (isNaN(duration) || duration == Infinity) {
duration = this.maxCurrentTimeSeen;
}
// Find the range that the current play position is in and use that
// range for bufferBar. At some point we may support multiple ranges
@ -870,8 +1027,9 @@
HIDE_CONTROLS_TIMEOUT_MS : 2000,
onMouseMove : function(event) {
// Pause playing video when the mouse is dragging over the control bar.
if (this.scrubber.isDragging) {
this.scrubber.pauseVideoDuringDragging();
if (this.scrubber.startToDrag) {
this.scrubber.isDragging = true;
this.pauseVideoDuringDragging();
}
// If the controls are static, don't change anything.
@ -959,7 +1117,11 @@
// so our dependent state (eg, timestamp in the thumb) will be stale.
// As a workaround, update it manually when it first becomes unhidden.
if (element.hidden)
if (this.videocontrols.isTouchControls) {
this.scrubber.valueChanged("curpos", this.video.currentTime * 1000, false);
} else {
this.scrubber.value = this.video.currentTime * 1000;
}
}
if (immediate)
@ -967,7 +1129,7 @@
else
element.removeAttribute("immediate");
if (fadeIn) {
if (fadeIn && !(element.isAdjustableControl && element.hideByAdjustment)) {
element.hidden = false;
// force style resolution, so that transition begins
// when we remove the attribute.
@ -995,7 +1157,9 @@
if (!element.hasAttribute("fadeout"))
return;
this.scrubber.dragStateChanged(false);
if (this.videocontrols.isTouchControls) {
this.scrubber.dragStateChanged(false);
}
element.hidden = true;
},
@ -1102,14 +1266,17 @@
// shows the animation unless the video is too small
// to show 2/3 of the animation.
let animationScale = 2;
if (this._overlayPlayButtonHeight * animationScale > (videoHeight - this._controlBarHeight) ||
this._overlayPlayButtonWidth * animationScale > videoWidth) {
this.clickToPlay.setAttribute("immediate", "true");
this.clickToPlay.hidden = true;
let animationMinSize = this.clickToPlay.minWidth * animationScale;
if (animationMinSize > videoWidth ||
animationMinSize > (videoHeight - this.controlBar.minHeight)) {
this.clickToPlay.setAttribute("immediate", "true");
this.clickToPlay.hidden = true;
} else {
this.clickToPlay.removeAttribute("immediate");
}
this.clickToPlay.setAttribute("fadeout", "true");
this.controlsSpacer.setAttribute("fadeout", "true");
},
setPlayButtonState : function(aPaused) {
@ -1253,6 +1420,10 @@
textTrack.kind == "captions";
},
get isClosedCaptionAvailable() {
return this.overlayableTextTracks.length && !this.videocontrols.isTouchControls;
},
get overlayableTextTracks() {
return Array.prototype.filter.call(this.video.textTracks, this.isSupportedTextTrack);
},
@ -1268,7 +1439,7 @@
},
setClosedCaptionButtonState : function() {
if (!this.overlayableTextTracks.length || this.videocontrols.isTouchControl) {
if (!this.isClosedCaptionAvailable) {
this.closedCaptionButton.setAttribute("hidden", "true");
return;
}
@ -1280,6 +1451,7 @@
} else {
this.closedCaptionButton.removeAttribute("enabled");
}
this.adjustControlSize();
let ttItems = this.textTrackList.childNodes;
@ -1353,33 +1525,11 @@
},
toggleClosedCaption : function() {
if (this.overlayableTextTracks.length === 1) {
const lastTTIdx = this.overlayableTextTracks[0].index;
this.changeTextTrack(this.isClosedCaptionOn() ? 0 : lastTTIdx);
return;
}
if (this.textTrackList.hasAttribute("hidden")) {
this.textTrackList.removeAttribute("hidden");
} else {
this.textTrackList.setAttribute("hidden", "true");
}
let maxButtonWidth = 0;
for (let tti of this.textTrackList.childNodes) {
if (tti.clientWidth > maxButtonWidth) {
maxButtonWidth = tti.clientWidth;
}
}
if (maxButtonWidth > this.video.clientWidth) {
maxButtonWidth = this.video.clientWidth;
}
for (let tti of this.textTrackList.childNodes) {
tti.style.width = maxButtonWidth + "px";
}
},
onTextTrackAdd : function(trackEvent) {
@ -1414,6 +1564,11 @@
},
initTextTracks : function() {
if (!this.isClosedCaptionAvailable) {
this.closedCaptionButton.setAttribute("hidden", "true");
return;
}
const offLabel = this.textTrackList.getAttribute("offlabel");
this.addNewTextTrack({
@ -1451,108 +1606,146 @@
return doc.mozSyntheticDocument && win === win.top;
},
_playButtonWidth : 0,
_durationLabelWidth : 0,
_muteButtonWidth : 0,
_volumeControlWidth : 0,
_closedCaptionButtonWidth : 0,
_fullscreenButtonWidth : 0,
_controlBarHeight : 0,
_overlayPlayButtonHeight : 64,
_overlayPlayButtonWidth : 64,
_controlBarPaddingEnd: 8,
adjustControlSize : function adjustControlSize() {
let doc = this.video.ownerDocument;
if (!this.controlBar.minWidth || this.videocontrols.isTouchControls) {
return;
}
// The scrubber has |flex=1|, therefore |minScrubberWidth|
// was generated by empirical testing.
let minScrubberWidth = 25;
let minWidthAllControls = this._playButtonWidth +
minScrubberWidth +
this._durationLabelWidth +
this._muteButtonWidth +
this._volumeControlWidth +
this._closedCaptionButtonWidth +
this._fullscreenButtonWidth;
let videoWidth = this.video.clientWidth;
let videoHeight = this.video.clientHeight;
const minControlBarPaddingWidth = 18;
let isFullscreenUnavailable = this.controlBar.hasAttribute("fullscreen-unavailable");
if (isFullscreenUnavailable) {
// When the fullscreen button is hidden we add margin-end to the volume stack.
minWidthAllControls -= this._fullscreenButtonWidth - this._controlBarPaddingEnd;
if (this.video.readyState >= this.video.HAVE_METADATA) {
if (!this.isAudioOnly && this.video.videoWidth && this.video.videoHeight) {
let rect = this.video.getBoundingClientRect();
let widthRatio = rect.width / this.video.videoWidth;
let heightRatio = rect.height / this.video.videoHeight;
let resizedWidth = this.video.videoWidth * Math.min(widthRatio, heightRatio);
this.controlsContainer.style.width = `${resizedWidth}px`;
this.controlsContainer.style.left = `${(videoWidth - resizedWidth) / 2}px`;
videoWidth = resizedWidth;
} else {
this.controlsContainer.style.width = "";
this.controlsContainer.style.left = "";
}
}
// Hide and show control in order.
const prioritizedControls = [
this.playButton,
this.muteButton,
this.fullscreenButton,
this.closedCaptionButton,
this.positionDurationBox,
this.scrubberStack,
this.durationSpan,
this.volumeStack
];
if (this.controlBar.hasAttribute("fullscreen-unavailable")) {
this.fullscreenButton.isWanted = false;
}
if (!this.isClosedCaptionAvailable) {
this.closedCaptionButton.isWanted = false;
}
if (this.muteButton.hasAttribute("noAudio")) {
this.volumeStack.isWanted = false;
}
let widthUsed = minControlBarPaddingWidth;
let preventAppendControl = false;
for (let control of prioritizedControls) {
if (!control.isWanted) {
control.hideByAdjustment = true;
continue;
}
let minHeightForControlBar = this._controlBarHeight;
let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
control.hideByAdjustment = preventAppendControl ||
widthUsed + control.minWidth > videoWidth;
let isAudioOnly = this.isAudioOnly;
let videoHeight = isAudioOnly ? minHeightForControlBar : this.video.clientHeight;
let videoWidth = isAudioOnly ? minWidthAllControls : this.video.clientWidth;
// Adapt the size of the controls to the size of the video
if (this.video.readyState >= this.video.HAVE_METADATA) {
if (!this.isAudioOnly && this.video.videoWidth && this.video.videoHeight) {
var rect = this.video.getBoundingClientRect();
var widthRatio = rect.width / this.video.videoWidth;
var heightRatio = rect.height / this.video.videoHeight;
var width = this.video.videoWidth * Math.min(widthRatio, heightRatio);
this.controlsOverlay.setAttribute("scaled", true);
this.controlsOverlay.style.width = width + "px";
this.controlsSpacer.style.width = width + "px";
this.controlBar.style.width = width + "px";
} else {
this.controlsOverlay.removeAttribute("scaled");
this.controlsOverlay.style.width = "";
this.controlsSpacer.style.width = "";
this.controlBar.style.width = "";
}
if (control.hideByAdjustment) {
preventAppendControl = true;
} else {
widthUsed += control.minWidth;
}
}
if ((this._overlayPlayButtonHeight + this._controlBarHeight) > videoHeight ||
this._overlayPlayButtonWidth > videoWidth) {
this.clickToPlay.hidden = true;
} else if (this.clickToPlay.hidden &&
!this.video.played.length &&
this.video.paused) {
// Check this.video.paused to handle when a video is
// playing but hasn't processed any frames yet
this.clickToPlay.hidden = false;
if (this.durationSpan.hideByAdjustment) {
this.positionDurationBox.setAttribute("positionOnly", "true");
} else {
this.positionDurationBox.removeAttribute("positionOnly");
}
if (videoHeight < this.controlBar.minHeight ||
widthUsed === minControlBarPaddingWidth) {
this.controlBar.setAttribute("size", "hidden");
this.controlBar.hideByAdjustment = true;
} else {
this.controlBar.removeAttribute("size");
this.controlBar.hideByAdjustment = false;
}
// Use flexible spacer to separate controls when scrubber is hidden.
// As long as muteButton hidden, which means only play button presents,
// hide spacer and make playButton centered.
this.controlBarSpacer.hidden = !this.scrubberStack.hidden || this.muteButton.hidden;
// Adjust clickToPlayButton size.
const minVideoSideLength = Math.min(videoWidth, videoHeight);
const clickToPlayViewRatio = 0.15;
const clickToPlayScaledSize = Math.max(
this.clickToPlay.minWidth, minVideoSideLength * clickToPlayViewRatio);
if (clickToPlayScaledSize >= videoWidth ||
(clickToPlayScaledSize + this.controlBar.minHeight / 2 >= videoHeight / 2 )) {
this.clickToPlay.hideByAdjustment = true;
} else {
if (this.clickToPlay.hidden && !this.video.played.length && this.video.paused) {
this.clickToPlay.hideByAdjustment = false;
}
let size = "normal";
if (videoHeight < minHeightForControlBar)
size = "hidden";
else if (videoWidth < minWidthOnlyPlayPause)
size = "hidden";
else if (videoWidth < minWidthAllControls)
size = "small";
this.controlBar.setAttribute("size", size);
this.clickToPlay.style.width = `${clickToPlayScaledSize}px`;
this.clickToPlay.style.height = `${clickToPlayScaledSize}px`;
}
},
init : function(binding) {
this.video = binding.parentNode;
this.videocontrols = binding;
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.progressBar = document.getAnonymousElementByAttribute(binding, "class", "progressBar");
this.bufferBar = document.getAnonymousElementByAttribute(binding, "class", "bufferBar");
this.scrubber = document.getAnonymousElementByAttribute(binding, "class", "scrubber");
this.scrubberThumb = document.getAnonymousElementByAttribute(this.scrubber, "class", "scale-thumb");
this.durationLabel = document.getAnonymousElementByAttribute(binding, "class", "durationLabel");
this.positionLabel = document.getAnonymousElementByAttribute(binding, "class", "positionLabel");
this.statusOverlay = document.getAnonymousElementByAttribute(binding, "class", "statusOverlay");
this.controlsOverlay = document.getAnonymousElementByAttribute(binding, "class", "controlsOverlay");
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.closedCaptionButton = document.getAnonymousElementByAttribute(binding, "class", "closedCaptionButton");
this.textTrackList = document.getAnonymousElementByAttribute(binding, "class", "textTrackList");
this.controlsContainer = document.getAnonymousElementByAttribute(binding, "anonid", "controlsContainer");
this.statusIcon = document.getAnonymousElementByAttribute(binding, "anonid", "statusIcon");
this.controlBar = document.getAnonymousElementByAttribute(binding, "anonid", "controlBar");
this.playButton = document.getAnonymousElementByAttribute(binding, "anonid", "playButton");
this.controlBarSpacer = document.getAnonymousElementByAttribute(binding, "anonid", "controlBarSpacer");
this.muteButton = document.getAnonymousElementByAttribute(binding, "anonid", "muteButton");
this.volumeStack = document.getAnonymousElementByAttribute(binding, "anonid", "volumeStack");
this.volumeControl = document.getAnonymousElementByAttribute(binding, "anonid", "volumeControl");
this.progressBar = document.getAnonymousElementByAttribute(binding, "anonid", "progressBar");
this.bufferBar = document.getAnonymousElementByAttribute(binding, "anonid", "bufferBar");
this.scrubberStack = document.getAnonymousElementByAttribute(binding, "anonid", "scrubberStack");
this.scrubber = document.getAnonymousElementByAttribute(binding, "anonid", "scrubber");
this.durationLabel = document.getAnonymousElementByAttribute(binding, "anonid", "durationLabel");
this.positionLabel = document.getAnonymousElementByAttribute(binding, "anonid", "positionLabel");
this.positionDurationBox = document.getAnonymousElementByAttribute(binding, "anonid", "positionDurationBox");
this.statusOverlay = document.getAnonymousElementByAttribute(binding, "anonid", "statusOverlay");
this.controlsOverlay = document.getAnonymousElementByAttribute(binding, "anonid", "controlsOverlay");
this.controlsSpacer = document.getAnonymousElementByAttribute(binding, "anonid", "controlsSpacer");
this.clickToPlay = document.getAnonymousElementByAttribute(binding, "anonid", "clickToPlay");
this.fullscreenButton = document.getAnonymousElementByAttribute(binding, "anonid", "fullscreenButton");
this.closedCaptionButton = document.getAnonymousElementByAttribute(binding, "anonid", "closedCaptionButton");
this.textTrackList = document.getAnonymousElementByAttribute(binding, "anonid", "textTrackList");
if (this.positionDurationBox) {
this.durationSpan = this.positionDurationBox.getElementsByTagName("span")[0];
}
// XXX controlsContainer is a desktop only element. To determine whether
// isTouchControls or not during the whole initialization process, get
// this state overridden here.
this.videocontrols.isTouchControls = !this.controlsContainer;
this.isAudioOnly = (this.video instanceof HTMLAudioElement);
this.setupInitialState();
this.setupNewLoadState();
@ -1579,10 +1772,10 @@
elem.addEventListener(eventName, boundFunc, { mozSystemGroup: true });
}
addListener(this.muteButton, "command", this.toggleMute);
addListener(this.closedCaptionButton, "command", this.toggleClosedCaption);
addListener(this.muteButton, "click", this.toggleMute);
addListener(this.closedCaptionButton, "click", this.toggleClosedCaption);
addListener(this.fullscreenButton, "click", this.toggleFullscreen);
addListener(this.playButton, "click", this.clickToPlayClickHandler);
addListener(this.fullscreenButton, "command", this.toggleFullscreen);
addListener(this.clickToPlay, "click", this.clickToPlayClickHandler);
addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
addListener(this.controlsSpacer, "dblclick", this.toggleFullscreen);
@ -1590,19 +1783,26 @@
addListener(this.videocontrols, "resizevideocontrols", this.adjustControlSize);
addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
addListener(this.video.ownerDocument, "mozfullscreenchange", this.onFullscreenChange);
addListener(this.videocontrols, "transitionend", this.onControlBarTransitioned);
addListener(this.controlBar, "transitionend", this.onControlBarTransitioned);
addListener(this.video.ownerDocument, "fullscreenchange", this.onFullscreenChange);
addListener(this.video, "keypress", this.keyHandler);
addListener(this.video.textTracks, "addtrack", this.onTextTrackAdd);
addListener(this.video.textTracks, "removetrack", this.onTextTrackRemove);
addListener(this.videocontrols, "dragstart", function(event) {
event.preventDefault(); // prevent dragging of controls image (bug 517114)
});
if (!this.videocontrols.isTouchControls) {
addListener(this.scrubber, "input", this.onScrubberInput);
addListener(this.scrubber, "change", this.onScrubberChange);
addListener(this.volumeControl, "input", this.updateVolume);
addListener(this.video.textTracks, "addtrack", this.onTextTrackAdd);
addListener(this.video.textTracks, "removetrack", this.onTextTrackRemove);
}
this.log("--- videocontrols initialized ---");
}
};
this.Utils.init(this);
]]>
</constructor>
@ -1621,15 +1821,15 @@
<handlers>
<handler event="mouseover">
if (!this.isTouchControl)
if (!this.isTouchControls)
this.Utils.onMouseInOut(event);
</handler>
<handler event="mouseout">
if (!this.isTouchControl)
if (!this.isTouchControls)
this.Utils.onMouseInOut(event);
</handler>
<handler event="mousemove">
if (!this.isTouchControl)
if (!this.isTouchControls)
this.Utils.onMouseMove(event);
</handler>
</handlers>
@ -1639,8 +1839,8 @@
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" class="mediaControlsFrame">
<stack flex="1">
<vbox flex="1" class="statusOverlay" hidden="true">
<box class="statusIcon"/>
<vbox anonid="statusOverlay" flex="1" class="statusOverlay" hidden="true">
<box anonid="statusIcon" class="statusIcon"/>
<label class="errorLabel" anonid="errorAborted">&error.aborted;</label>
<label class="errorLabel" anonid="errorNetwork">&error.network;</label>
<label class="errorLabel" anonid="errorDecode">&error.decode;</label>
@ -1649,38 +1849,41 @@
<label class="errorLabel" anonid="errorGeneric">&error.generic;</label>
</vbox>
<vbox class="controlsOverlay">
<spacer class="controlsSpacer" flex="1"/>
<vbox anonid="controlsOverlay" class="controlsOverlay">
<spacer anonid="controlsSpacer" class="controlsSpacer" flex="1"/>
<box flex="1" hidden="true">
<box class="clickToPlay" hidden="true" flex="1"/>
<vbox class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></vbox>
<box anonid="clickToPlay" class="clickToPlay" hidden="true" flex="1"/>
<vbox anonid="textTrackList" class="textTrackList" hidden="true" offlabel="&closedCaption.off;"></vbox>
</box>
<vbox class="controlBar" hidden="true">
<vbox anonid="controlBar" class="controlBar" hidden="true">
<hbox class="buttonsBar">
<button class="playButton"
<button anonid="playButton"
class="playButton"
playlabel="&playButton.playLabel;"
pauselabel="&playButton.pauseLabel;"/>
<label class="positionLabel" role="presentation"/>
<stack class="scrubberStack">
<label anonid="positionLabel" class="positionLabel" role="presentation"/>
<stack anonid="scrubberStack" class="scrubberStack">
<box class="backgroundBar"/>
<progressmeter class="flexibleBar" value="100"/>
<progressmeter class="bufferBar"/>
<progressmeter class="progressBar" max="10000"/>
<scale class="scrubber" movetoclick="true"/>
<progressmeter anonid="bufferBar" class="bufferBar"/>
<progressmeter anonid="progressBar" class="progressBar" max="10000"/>
<scale anonid="scrubber" class="scrubber" movetoclick="true"/>
</stack>
<label class="durationLabel" role="presentation"/>
<button class="muteButton"
<label anonid="durationLabel" class="durationLabel" role="presentation"/>
<button anonid="muteButton"
class="muteButton"
mutelabel="&muteButton.muteLabel;"
unmutelabel="&muteButton.unmuteLabel;"/>
<stack class="volumeStack">
<box class="volumeBackground"/>
<box class="volumeForeground" anonid="volumeForeground"/>
<scale class="volumeControl" movetoclick="true"/>
<stack anonid="volumeStack" class="volumeStack">
<box anonid="volumeBackground" class="volumeBackground"/>
<box anonid="volumeForeground" class="volumeForeground"/>
<scale anonid="volumeControl" class="volumeControl" movetoclick="true"/>
</stack>
<button class="castingButton" hidden="true"
<button anonid="castingButton" class="castingButton" hidden="true"
aria-label="&castingButton.castingLabel;"/>
<button class="closedCaptionButton" hidden="true"/>
<button class="fullscreenButton"
<button anonid="closedCaptionButton" class="closedCaptionButton" hidden="true"/>
<button anonid="fullscreenButton"
class="fullscreenButton"
enterfullscreenlabel="&fullscreenButton.enterfullscreenlabel;"
exitfullscreenlabel="&fullscreenButton.exitfullscreenlabel;"/>
</hbox>
@ -1690,10 +1893,9 @@
</xbl:content>
<implementation>
<constructor>
<![CDATA[
this.isTouchControl = true;
this.isTouchControls = true;
this.TouchUtils = {
videocontrols: null,
video: null,
@ -1828,7 +2030,7 @@
}, false);
this.Utils.muteButton.addEventListener("click", function() { self.delayHideControls(self.controlsTimeout); }, false);
this.castingButton = document.getAnonymousElementByAttribute(binding, "class", "castingButton");
this.castingButton = document.getAnonymousElementByAttribute(binding, "anonid", "castingButton");
this.castingButton.addEventListener("command", function() {
self.startCasting();
}, false);
@ -1858,7 +2060,8 @@
}
}
};
this.TouchUtils.init(this);
this.TouchUtils.init(this)
this.dispatchEvent(new CustomEvent("VideoBindingAttached"));
]]>
</constructor>

View File

@ -37,3 +37,13 @@ the 5 minute mark in a 6 hour long video, #1 would be "5:00" and #2 would be
"6:00:00", result string would be "5:00 of 6:00:00 elapsed".
-->
<!ENTITY scrubberScale.nameFormat "#1 of #2 elapsed">
<!-- LOCALIZATION NOTE (positionAndDuration.nameFormat): the #1 string is the current
media position, and the #2 string is the total duration. For example, when at
the 5 minute mark in a 6 hour long video, #1 would be "5:00" and #2 would be
"6:00:00", result string would be "5:00 / 6:00:00".
Note that #2 is not always avaiable. For example, when at the 5 minute mark in an
unknown duration video, #1 would be "5:00" and string which is surrounded by <span>
would be deleted, result string would be "5:00".
-->
<!ENTITY positionAndDuration.nameFormat "#1<span> / #2</span>">

View File

@ -64,31 +64,14 @@ toolkit.jar:
skin/classic/global/media/imagedoc-lightnoise.png (../../shared/media/imagedoc-lightnoise.png)
skin/classic/global/media/imagedoc-darknoise.png (../../shared/media/imagedoc-darknoise.png)
* skin/classic/global/media/videocontrols.css (../../shared/media/videocontrols.css)
skin/classic/global/media/pauseButton.png (../../shared/media/pauseButton.png)
skin/classic/global/media/pauseButton@2x.png (../../shared/media/pauseButton@2x.png)
skin/classic/global/media/playButton.png (../../shared/media/playButton.png)
skin/classic/global/media/playButton@2x.png (../../shared/media/playButton@2x.png)
skin/classic/global/media/muteButton.png (../../shared/media/muteButton.png)
skin/classic/global/media/muteButton@2x.png (../../shared/media/muteButton@2x.png)
skin/classic/global/media/unmuteButton.png (../../shared/media/unmuteButton.png)
skin/classic/global/media/unmuteButton@2x.png (../../shared/media/unmuteButton@2x.png)
skin/classic/global/media/noAudio.png (../../shared/media/noAudio.png)
skin/classic/global/media/noAudio@2x.png (../../shared/media/noAudio@2x.png)
skin/classic/global/media/closeCaptionButton.png (../../shared/media/closeCaptionButton.png)
skin/classic/global/media/closeCaptionButton@2x.png (../../shared/media/closeCaptionButton@2x.png)
skin/classic/global/media/fullscreenButton.png (../../shared/media/fullscreenButton.png)
skin/classic/global/media/fullscreenButton@2x.png (../../shared/media/fullscreenButton@2x.png)
skin/classic/global/media/scrubberThumb.png (../../shared/media/scrubberThumb.png)
skin/classic/global/media/scrubberThumb@2x.png (../../shared/media/scrubberThumb@2x.png)
skin/classic/global/media/scrubberThumbWide.png (../../shared/media/scrubberThumbWide.png)
skin/classic/global/media/scrubberThumbWide@2x.png (../../shared/media/scrubberThumbWide@2x.png)
skin/classic/global/media/pauseButton.svg (../../shared/media/pauseButton.svg)
skin/classic/global/media/playButton.svg (../../shared/media/playButton.svg)
skin/classic/global/media/muteButton.svg (../../shared/media/muteButton.svg)
skin/classic/global/media/closedCaptionButton.svg (../../shared/media/closedCaptionButton.svg)
skin/classic/global/media/fullscreenButton.svg (../../shared/media/fullscreenButton.svg)
skin/classic/global/media/error.png (../../shared/media/error.png)
skin/classic/global/media/throbber.png (../../shared/media/throbber.png)
skin/classic/global/media/stalled.png (../../shared/media/stalled.png)
skin/classic/global/media/volume-empty.png (../../shared/media/volume-empty.png)
skin/classic/global/media/volume-empty@2x.png (../../shared/media/volume-empty@2x.png)
skin/classic/global/media/volume-full.png (../../shared/media/volume-full.png)
skin/classic/global/media/volume-full@2x.png (../../shared/media/volume-full@2x.png)
skin/classic/global/media/clicktoplay-bgtexture.png (../../shared/media/clicktoplay-bgtexture.png)
skin/classic/global/media/videoClickToPlayButton.svg (../../shared/media/videoClickToPlayButton.svg)
#ifdef MOZ_PLACES

View File

@ -8,5 +8,6 @@ body {
}
video {
box-shadow: 0 0 15px #000;
border: 1px #000000 solid;
box-shadow: 0 0 5px rgba(0,0,0,0.6);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ffffff;
}
use[id$="-hover"] {
fill: #48a0f7;
}
use[id$="-active"] {
fill: #2d89e6;
}
use[id$="-focus"] {
fill: #48a0f7;
}
use[id$="-disabled"] {
fill: #ffffff;
}
</style>
<symbol id="cc-off-shape">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.531,16.107H5.267l1.982-2H15c0.6,0,1-0.4,1-1V5.274
l1.946-1.964C17.963,3.399,18,3.483,18,3.576v11.031C18,15.407,17.331,16.107,16.531,16.107z M14.016,8.506h-1.218l1.005-1.014
C13.913,7.789,13.984,8.128,14.016,8.506z M11.786,12.361c-0.828,0-1.476-0.326-1.913-0.902l1.09-1.101
c0.136,0.323,0.374,0.541,0.796,0.541c0.514,0,0.695-0.44,0.756-1.014h1.535C13.908,11.43,13.071,12.361,11.786,12.361z
M1.496,16.106C0.697,16.104,0,15.406,0,14.607V3.576c0-0.8,0.7-1.5,1.5-1.5h12.846L16.299,0l1.316,1.283L2.615,17.13L1.496,16.106
z M3,4.107c-0.6,0-1,0.4-1,1v8c0,0.6,0.4,1,1,1h0.029l2.031-2.16c-0.757-0.503-1.191-1.457-1.191-2.744
c0-1.936,1.069-3.14,2.428-3.14c1.357,0,2.136,0.76,2.361,2.059l3.777-4.016H3z M8.298,8.506H7.355
c-0.047-0.623-0.49-1.23-0.99-1.23c-0.561,0-1.337,0.84-1.337,1.995c0,0.674,0.381,1.427,0.95,1.702L8.298,8.506z"/>
</symbol>
<symbol id="cc-shape">
<path d="M16.531,1.984H1.5c-0.8,0-1.5,0.7-1.5,1.5v11.031c0,0.8,0.7,1.5,1.5,1.5h15.031
c0.8,0,1.469-0.7,1.469-1.5V3.484C18,2.684,17.331,1.984,16.531,1.984z M16,13.016c0,0.6-0.4,1-1,1H3c-0.6,0-1-0.4-1-1v-8
c0-0.6,0.4-1,1-1h12c0.6,0,1,0.4,1,1V13.016z M6.426,10.807c-0.811,0-0.96-0.789-0.96-1.628c0-1.155,0.338-1.745,0.899-1.745
c0.5,0,0.818,0.357,0.866,0.98h1.484C8.585,6.877,7.785,5.972,6.297,5.972c-1.359,0-2.428,1.205-2.428,3.14
c0,1.944,0.974,3.157,2.583,3.157c1.285,0,2.153-0.93,2.295-2.476H7.244C7.183,10.367,6.94,10.807,6.426,10.807z M11.759,10.807
c-0.811,0-0.96-0.789-0.96-1.628c0-1.155,0.338-1.745,0.899-1.745c0.5,0,0.756,0.357,0.803,0.98h1.515
c-0.129-1.537-0.898-2.443-2.385-2.443c-1.359,0-2.396,1.205-2.396,3.14c0,1.944,0.943,3.157,2.552,3.157
c1.285,0,2.122-0.93,2.264-2.476h-1.535C12.454,10.367,12.273,10.807,11.759,10.807z"/>
</symbol>
<use id="cc" xlink:href="#cc-shape"/>
<use id="cc-hover" xlink:href="#cc-shape"/>
<use id="cc-active" xlink:href="#cc-shape"/>
<use id="cc-focus" xlink:href="#cc-shape"/>
<use id="cc-disabled" xlink:href="#cc-shape"/>
<use id="cc-off" xlink:href="#cc-off-shape"/>
<use id="cc-off-hover" xlink:href="#cc-off-shape"/>
<use id="cc-off-active" xlink:href="#cc-off-shape"/>
<use id="cc-off-focus" xlink:href="#cc-off-shape"/>
<use id="cc-off-disabled" xlink:href="#cc-off-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ffffff;
}
use[id$="-hover"] {
fill: #48a0f7;
}
use[id$="-active"] {
fill: #2d89e6;
}
use[id$="-focus"] {
fill: #48a0f7;
}
use[id$="-disabled"] {
fill: #ffffff;
}
</style>
<symbol id="fullscreen-shape">
<path d="M6.728,10.188l-3.235,3.094l0.017-2.267l-1.513-0.016l0,5l4.987-0.008l0.011-1.537l-2.281-0.022
l3.097-3.158L6.728,10.188z M14.453,11.004l-0.022,2.281l-3.158-3.097l-1.086,1.083l3.094,3.235l-2.267-0.017l-0.016,1.514l5,0
l-0.008-4.988L14.453,11.004z M11.015,2.01l-0.011,1.537l2.281,0.022l-3.097,3.158l1.083,1.086l3.235-3.094L14.49,6.986
l1.513,0.016v-5L11.015,2.01z M6.986,3.511l0.016-1.514l-5,0L2.01,6.985l1.537,0.011l0.022-2.281l3.158,3.097l1.086-1.083
L4.718,3.494L6.986,3.511z"/>
</symbol>
<symbol id="unfullscreen-shape">
<path d="M2.047,11.135l-0.011,1.537l2.281,0.022L1.22,15.851l1.083,1.086l3.235-3.094l-0.017,2.268l1.513,0.016
l0-5L2.047,11.135z M13.781,12.587l2.267,0.017l0.016-1.514l-5,0l0.008,4.988l1.537,0.011l0.022-2.281l3.158,3.097l1.086-1.083
L13.781,12.587z M16.058,5.578l-2.281-0.021l3.097-3.158l-1.083-1.086l-3.235,3.094l0.017-2.267L11.06,2.123v5l4.988-0.008
L16.058,5.578z M5.516,2.098L5.494,4.379L2.336,1.283L1.25,2.365L4.344,5.6L2.077,5.583L2.06,7.097l5,0L7.053,2.109L5.516,2.098z"/>
</symbol>
<use id="fullscreen" xlink:href="#fullscreen-shape"/>
<use id="fullscreen-hover" xlink:href="#fullscreen-shape"/>
<use id="fullscreen-active" xlink:href="#fullscreen-shape"/>
<use id="fullscreen-focus" xlink:href="#fullscreen-shape"/>
<use id="fullscreen-disabled" xlink:href="#fullscreen-shape"/>
<use id="unfullscreen" xlink:href="#unfullscreen-shape"/>
<use id="unfullscreen-hover" xlink:href="#unfullscreen-shape"/>
<use id="unfullscreen-active" xlink:href="#unfullscreen-shape"/>
<use id="unfullscreen-focus" xlink:href="#unfullscreen-shape"/>
<use id="unfullscreen-disabled" xlink:href="#unfullscreen-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 619 B

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ffffff;
}
use[id$="-hover"] {
fill: #48a0f7;
}
use[id$="-active"] {
fill: #2d89e6;
}
use[id$="-focus"] {
fill: #48a0f7;
}
use[id$="-disabled"] {
fill: #ffffff;
}
</style>
<symbol id="unmute-shape">
<path d="M3.52,5.367c-1.332,0-2.422,1.09-2.422,2.422v2.422c0,1.332,1.09,2.422,2.422,2.422h1.516l4.102,3.633
V1.735L5.035,5.367H3.52z M12.059,9c0-0.727-0.484-1.211-1.211-1.211v2.422C11.574,10.211,12.059,9.727,12.059,9z M14.48,9
c0-1.695-1.211-3.148-2.785-3.512l-0.363,1.09C12.422,6.82,13.27,7.789,13.27,9c0,1.211-0.848,2.18-1.938,2.422l0.484,1.09
C13.27,12.148,14.48,10.695,14.48,9z M12.543,3.188l-0.484,1.09C14.238,4.883,15.691,6.82,15.691,9c0,2.18-1.453,4.117-3.512,4.601
l0.484,1.09c2.422-0.605,4.238-2.906,4.238-5.691C16.902,6.215,15.086,3.914,12.543,3.188z"/>
</symbol>
<symbol id="mute-shape">
<path d="M3.52,5.367c-1.332,0-2.422,1.09-2.422,2.422v2.422c0,1.332,1.09,2.422,2.422,2.422h1.516l4.102,3.633
V1.735L5.035,5.367H3.52z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.155,12.066l-1.138-1.138l4.872-4.872l1.138,1.138
L12.155,12.066z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.998,7.204l1.138-1.138l4.872,4.872l-1.138,1.138L10.998,7.204
z"/>
</symbol>
<symbol id="noaudio-shape">
<path d="M14.901,3.571l-4.412,3.422V1.919L6.286,5.46H4.869c-1.298,0-2.36,1.062-2.36,2.36v2.36
c0,1.062,0.708,1.888,1.652,2.242l-2.242,1.77l1.18,1.416L16.081,4.987L14.901,3.571z M10.489,16.081V11.36l-2.669,2.36
L10.489,16.081z"/>
</symbol>
<use id="unmute" xlink:href="#unmute-shape"/>
<use id="unmute-hover" xlink:href="#unmute-shape"/>
<use id="unmute-active" xlink:href="#unmute-shape"/>
<use id="unmute-focus" xlink:href="#unmute-shape"/>
<use id="unmute-disabled" xlink:href="#unmute-shape"/>
<use id="mute" xlink:href="#mute-shape"/>
<use id="mute-hover" xlink:href="#mute-shape"/>
<use id="mute-active" xlink:href="#mute-shape"/>
<use id="mute-focus" xlink:href="#mute-shape"/>
<use id="mute-disabled" xlink:href="#mute-shape"/>
<use id="noaudio" xlink:href="#noaudio-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 B

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ffffff;
}
use[id$="-hover"] {
fill: #48a0f7;
}
use[id$="-active"] {
fill: #2d89e6;
}
use[id$="-focus"] {
fill: #48a0f7;
}
use[id$="-disabled"] {
fill: #ffffff;
}
</style>
<symbol id="pause-shape">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.002,1.953C5.172,1.953,4.5,2.626,4.5,3.455v11.08
c0,0.83,0.672,1.502,1.502,1.502c0.829,0,1.502-0.672,1.502-1.502V3.455C7.504,2.626,6.831,1.953,6.002,1.953z M12,1.953
c-0.828,0-1.5,0.672-1.5,1.5v11.094c0,0.828,0.672,1.5,1.5,1.5s1.5-0.672,1.5-1.5V3.453C13.5,2.625,12.828,1.953,12,1.953z"/>
</symbol>
<use id="pause" xlink:href="#pause-shape"/>
<use id="pause-hover" xlink:href="#pause-shape"/>
<use id="pause-active" xlink:href="#pause-shape"/>
<use id="pause-focus" xlink:href="#pause-shape"/>
<use id="pause-disalbed" xlink:href="#pause-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18px" height="18px" viewBox="0 0 18 18">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ffffff;
}
use[id$="-hover"] {
fill: #48a0f7;
}
use[id$="-active"] {
fill: #2d89e6;
}
use[id$="-focus"] {
fill: #48a0f7;
}
use[id$="-disabled"] {
fill: #ffffff;
}
use[id$="-clicktoplay"] {
fill: #000000;
}
</style>
<symbol id="play-shape">
<path d="M3.243,15.155c0,0.845,0.593,1.157,1.317,0.707l9.659-6.041c0.727-0.453,0.722-1.193,0-1.645L4.556,2.137
C3.827,1.682,3.237,2.014,3.237,2.844v12.312H3.243z"/>
</symbol>
<use id="play" xlink:href="#play-shape"/>
<use id="play-hover" xlink:href="#play-shape"/>
<use id="play-active" xlink:href="#play-shape"/>
<use id="play-focus" xlink:href="#play-shape"/>
<use id="play-clicktoplay" xlink:href="#play-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

View File

@ -2,283 +2,375 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
@namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace url("http://www.w3.org/1999/xhtml");
video > xul|videocontrols,
audio > xul|videocontrols {
writing-mode: horizontal-tb;
width: 100%;
height: 100%;
display: inline-block;
}
.controlsContainer [hidden="true"],
.controlBar[hidden] {
display: none;
}
.controlBar[size="hidden"] {
display: none;
}
.controlsContainer,
.progressContainer {
position: relative;
height: 100%;
}
.stackItem {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.statusOverlay {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgb(80,80,80);
}
.controlsOverlay {
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
.controlsSpacerStack {
display: flex;
flex-direction: column;
flex-grow: 1;
justify-content: center;
align-items: center;
}
.controlsSpacer {
background-color: rgba(255,255,255,.4);
}
.controlBar {
height: 28px;
background-color: rgba(35,31,32,.74);
position: relative;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
height: 40px;
padding: 0 9px;
background-color: rgba(26,26,26,.8);
}
.playButton,
.muteButton,
.closedCaptionButton,
.fullscreenButton {
height: 100%;
min-height: 30px;
min-width: 30px;
padding: 6px;
border: 0;
margin: 0;
background-color: transparent;
background-repeat: no-repeat;
background-position: center;
-moz-appearance: none; /* Remove the native button appearance and styling */
margin: 0;
padding: 0;
min-height: 28px;
min-width: 28px;
border: none;
opacity: 0.7;
}
.playButton:hover,
.muteButton:hover,
.closedCaptionButton:hover,
.fullscreenButton:hover {
opacity: 1;
}
.playButton:hover:active,
.muteButton:hover:active,
.closedCaptionButton:hover:active,
.fullscreenButton:hover:active {
opacity: 0.4;
background-origin: content-box;
background-clip: content-box;
}
.playButton {
background-image: url(chrome://global/skin/media/pauseButton.png);
margin-right: -22px; /* 1/2 of scrubber thumb width, for overhang. */
position: relative; /* Trick to work around negative margin interfering with clicking on the button. */
background-image: url(chrome://global/skin/media/pauseButton.svg#pause);
}
.playButton:hover {
background-image: url(chrome://global/skin/media/pauseButton.svg#pause-hover);
}
.playButton:hover:active {
background-image: url(chrome://global/skin/media/pauseButton.svg#pause-active);
}
.playButton[paused] {
background-image: url(chrome://global/skin/media/playButton.png);
background-image: url(chrome://global/skin/media/playButton.svg#play);
}
.playButton[paused]:hover {
background-image: url(chrome://global/skin/media/playButton.svg#play-hover);
}
.playButton[paused]:hover:active {
background-image: url(chrome://global/skin/media/playButton.svg#play-active);
}
.muteButton {
background-image: url(chrome://global/skin/media/muteButton.png);
min-width: 33px;
background-image: url(chrome://global/skin/media/muteButton.svg#unmute);
}
.muteButton:hover {
background-image: url(chrome://global/skin/media/muteButton.svg#unmute-hover);
}
.muteButton:hover:active {
background-image: url(chrome://global/skin/media/muteButton.svg#unmute-active);
}
.muteButton[muted] {
background-image: url(chrome://global/skin/media/unmuteButton.png);
background-image: url(chrome://global/skin/media/muteButton.svg#mute);
}
.muteButton[noAudio] {
background-image: url(chrome://global/skin/media/noAudio.png);
.muteButton[muted]:hover {
background-image: url(chrome://global/skin/media/muteButton.svg#mute-hover);
}
.muteButton[muted]:hover:active {
background-image: url(chrome://global/skin/media/muteButton.svg#mute-active);
}
.muteButton[noAudio],
.muteButton[noAudio]:hover,
.muteButton[noAudio]:hover:active {
background-image: url(chrome://global/skin/media/muteButton.svg#noaudio);
}
.muteButton[noAudio] + .volumeStack {
display: none;
}
.closedCaptionButton {
background-image: url(chrome://global/skin/media/closeCaptionButton.png);
background-position: 4px;
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc-off);
}
.closedCaptionButton:hover {
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc-off-hover);
}
.closedCaptionButton:hover:active {
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc-off-active);
}
.closedCaptionButton[enabled] {
opacity: 1;
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc);
}
.closedCaptionButton[hidden] {
display: none;
.closedCaptionButton[enabled]:hover {
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc-hover);
}
.closedCaptionButton[enabled]:hover:active {
background-image: url(chrome://global/skin/media/closedCaptionButton.svg#cc-active);
}
.fullscreenButton {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 16, 16, 0);
background-image: url(chrome://global/skin/media/fullscreenButton.svg#fullscreen);
}
.fullscreenButton:hover {
background-image: url(chrome://global/skin/media/fullscreenButton.svg#fullscreen-hover);
}
.fullscreenButton:hover:active {
background-image: url(chrome://global/skin/media/fullscreenButton.svg#fullscreen-active);
}
.fullscreenButton[fullscreened] {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton.png"), 0, 32, 16, 16);
background-image: url(chrome://global/skin/media/fullscreenButton.svg#unfullscreen);
}
.fullscreenButton[fullscreened]:hover {
background-image: url(chrome://global/skin/media/fullscreenButton.svg#unfullscreen-hover);
}
.fullscreenButton[fullscreened]:hover:active {
background-image: url(chrome://global/skin/media/fullscreenButton.svg#unfullscreen-active);
}
.volumeControl {
width: 32px;
opacity: 0;
.controlBarSpacer {
flex-grow: 1;
}
.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;
}
.textTrackList {
display: -moz-box;
-moz-appearance: none;
-moz-box-pack: end;
-moz-box-align: end;
padding: 0;
}
.textTrackList[hidden] {
display: none;
}
.textTrackList > html|*.textTrackItem {
-moz-appearance: none;
-moz-box-align: start;
text-align: start;
overflow: hidden;
margin: 0;
padding: 2px 10px;
-moz-margin-end: 10px;
.volumeControl::-moz-range-thumb,
.scrubber::-moz-range-thumb {
height: 13px;
width: 13px;
border: none;
color: rgba(255,255,255,.5);
background-color: rgba(35,31,32,.74);
white-space: nowrap;
border-radius: 50%;
background-color: #ffffff;
filter: drop-shadow(0px 0px 5px rgba(0,0,0,0.65));
}
.textTrackList > html|*.textTrackItem[on] {
color: white;
background-color: black;
.volumeControl::-moz-focus-outer,
.scrubber::-moz-focus-outer {
border: 0;
}
.textTrackList > html|*.textTrackItem:hover {
background-color: rgba(0,0,0,.55);
.progressBackgroundBar {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.controlBar[fullscreen-unavailable] {
/* This value is duplicated in the videocontrols.xml adjustControlSize function. */
padding-inline-end: 8px;
.progressStack {
position: relative;
width: 100%;
height: 5px;
}
.volumeControl .scale-thumb {
min-width: 0;
opacity: 0;
.scrubberStack {
min-width: 48px;
flex-basis: 48px;
flex-grow: 2;
flex-shrink: 0;
margin: 0 9px;
}
.durationBox {
-moz-box-pack: center;
}
.durationLabel {
margin-left: -22px; /* 1/2 of scrubber thumb width, for overhang. */
padding-left: 8px; /* don't bump into the scrubber bar */
color: rgba(255,255,255,.75);
font: message-box;
font-size: 11px;
}
%ifdef XP_MACOSX
.durationLabel {
padding-top: 2px; /* center vertically with scrubber bar */
}
%else
.durationLabel {
padding-top: 0; /* center vertically with scrubber bar */
}
%endif
.positionLabel {
display: none;
}
.backgroundBar {
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px;
background-color: rgba(255,255,255,.5);
border-radius: 2.5px;
.volumeStack {
max-width: 60px;
min-width: 48px;
flex-grow: 1;
flex-shrink: 0;
margin-right: 6px;
margin-left: 4px;
}
.bufferBar,
.progressBar {
/* margin top/bottom: make bar 8px tall (control height = 28, minus 2 * 10 margin) */
/* margin left/right: 1/2 of scrubber thumb width, for overhang. */
margin: 10px 22px;
-moz-appearance: none;
border: none;
background-color: transparent;
min-width: 0;
min-height: 0;
}
/* .progress-bar is an element inside the <progressmeter> implementation. */
.bufferBar .progress-bar {
/*
* Note that this is drawn on top of the .backgroundBar. So although this
* has the same background-color specified, the semitransparent
* compositing gives it a different visual appearance.
*/
background-color: rgba(255,255,255,.5);
.progressBar,
.scrubber,
.volumeBackground,
.volumeControl {
bottom: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
padding: 0;
border: 0;
border-radius: 2.5px;
-moz-appearance: none;
}
.progressBar .progress-bar {
background-color: white;
border-radius: 2.5px;
-moz-appearance: none;
}
/* .scale-slider is an element inside the <scale> implementation. */
.scrubber .scale-slider,
.volumeControl .scale-slider {
/* Hide the default horizontal bar. */
-moz-appearance: none;
background: none;
margin: 0;
background: none;
background-color: transparent;
}
.scrubber .scale-slider {
/* abs(margin-top) + margin-bottom + bar height == timeThumb height */
margin-top: -10px;
margin-bottom: 10px;
.bufferBar,
.volumeBackground {
background-color: rgba(0,0,0,0.7);
}
/* .scale-thumb is an element inside the <scale> implementation. */
.scrubber .scale-thumb,
.volumeControl .scale-thumb {
/* Override the default thumb appearance with a custom image. */
-moz-appearance: none;
background: transparent;
.bufferBar::-moz-progress-bar,
.progressBar::-moz-progress-bar,
.volumeBackground::-moz-meter-bar {
height: 100%;
padding: 0;
margin: 0;
border: 0;
border-radius: 2.5px;
background: none;
}
.scrubber:hover::-moz-range-thumb,
.volumeControl:hover::-moz-range-thumb {
background-color: #48a0f7;
}
.scrubber:active::-moz-range-thumb,
.volumeControl:active::-moz-range-thumb {
background-color: #2d89e6;
}
.scrubber::-moz-range-track,
.scrubber::-moz-range-progress {
background-color: transparent;
}
.volumeControl::-moz-range-progress,
.volumeControl::-moz-range-track {
height: 5px;
border-radius: 2.5px;
}
.volumeControl::-moz-range-progress {
background-color: #ffffff;
}
.volumeControl::-moz-range-track {
background-color: rgba(0,0,0,0.7);
}
.bufferBar::-moz-progress-bar {
background-color: rgba(255,255,255,0.3);
border-radius: 2.5px;
}
.progressBar::-moz-progress-bar {
background-color: #00b6f0;
}
.textTrackList {
position: absolute;
right: 5px;
bottom: 45px;
max-width: 80%;
border: 1px solid #000000;
border-radius: 2.5px;
padding: 5px 0;
vertical-align: middle;
font-size: 12px;
background-color: #000000;
opacity: 0.7;
}
.textTrackList > .textTrackItem {
display: block;
width: 100%;
height: 30px;
padding: 2px 10px;
border: none;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-align: left;
text-overflow: ellipsis;
color: #ffffff;
background-color: transparent;
}
.timeThumb {
background: url(chrome://global/skin/media/scrubberThumb.png) no-repeat center;
min-width: 45px;
min-height: 28px;
-moz-box-pack: center;
.textTrackList > .textTrackItem:hover {
background-color: #444444;
}
.timeThumb[showhours="true"] {
background-image: url(chrome://global/skin/media/scrubberThumbWide.png);
.textTrackList > .textTrackItem[on] {
color: #00b6f0;
}
.timeLabel {
color: rgba(255,255,255,.75);
.positionLabel,
.durationLabel {
display: none;
}
.positionDurationBox {
min-width: 9ch;
text-align: center;
padding-inline-start: 1px;
padding-inline-end: 9px;
white-space: nowrap;
font: message-box;
font-size: 10px;
text-shadow: rgba(0,0,0,.3) 0 1px;
padding-top: 7px;
font-size: 13px;
font-size-adjust: 0.6;
color: #ffffff;
}
.positionDurationBox[positionOnly] {
min-width: 4ch;
}
%ifdef XP_MACOSX
.timeLabel {
padding-top: 7px; /* center vertically with scrubber bar */
}
%else
.timeLabel {
padding-top: 5px; /* center vertically with scrubber bar */
.positionDurationBox {
font-size-adjust: unset;
}
%endif
.statusOverlay {
-moz-box-align: center;
-moz-box-pack: center;
background-color: rgba(0,0,0,.55);
.duration {
display: inline-block;
white-space: pre;
color: #929292;
}
.statusIcon {
margin-bottom: 28px; /* same height as .controlBar, to keep icon centered above it */
width: 36px;
height: 36px;
margin-bottom: 20px;
}
.statusIcon[type="throbber"] {
@ -290,61 +382,55 @@
}
.statusIcon[type="error"] {
min-width: 70px;
min-height: 60px;
background: url(chrome://global/skin/media/error.png) no-repeat center;
background-size: contain;
}
/* Overlay Play button */
.clickToPlay {
width: 64px;
height: 64px;
-moz-box-pack: center;
-moz-box-align: center;
opacity: 0.7;
background-image: url(chrome://global/skin/media/clicktoplay-bgtexture.png),
url(chrome://global/skin/media/videoClickToPlayButton.svg);
background-repeat: repeat, no-repeat;
background-position: center, center;
background-size: auto, 64px 64px;
background-color: hsla(0,0%,10%,.5);
}
.clickToPlay:hover {
opacity: 1;
min-width: 48px;
min-height: 48px;
border-radius: 50%;
background-image: url(chrome://global/skin/media/playButton.svg#play);
background-repeat: no-repeat;
background-position: 54% 50%;
background-size: 40% 40%;
background-color: #1a1a1a;
opacity: 0.8;
position: relative;
top: 20px;
}
/* Statistics formatting */
html|*.statsDiv {
position: relative;
.controlsSpacerStack:hover > .clickToPlay,
.clickToPlay:hover {
opacity: 0.55;
}
html|td {
height: 1em;
max-height: 1em;
padding: 0 2px;
.controlsSpacerStack:hover > .clickToPlay[fadeout] {
opacity: 0;
}
html|table {
font-family: Helvetica, Arial, sans-serif;
font-size: 11px;
color: white;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
min-width: 100%;
background: rgba(68,68,68,.7);
table-layout: fixed;
border-collapse: collapse;
position: absolute;
.controlBar[fullscreen-unavailable] .fullscreenButton {
display: none;
}
/* CSS Transitions */
.clickToPlay {
transition-property: opacity, background-size;
transition-property: transform, opacity;
transition-duration: 400ms, 400ms;
}
.clickToPlay[fadeout] {
background-size: auto, 192px 192px;
.controlsSpacer[fadeout] {
opacity: 0;
}
.clickToPlay[fadeout] {
transform: scale(3);
opacity: 0;
}
.clickToPlay[fadeout][immediate] {
transition-property: opacity, background-size;
transition-duration: 0s, 0s;
@ -360,10 +446,6 @@ html|table {
transition-property: opacity, margin-top;
transition-duration: 200ms, 200ms;
}
.volumeStack[fadeout] {
opacity: 0;
margin-top: 0;
}
.statusOverlay:not([immediate]) {
transition-property: opacity;
transition-duration: 300ms;
@ -375,66 +457,22 @@ html|table {
/* Error description formatting */
.errorLabel {
font-family: Helvetica, Arial, sans-serif;
font-size: 11px;
color: #bbb;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
padding: 0 10px;
text-align: center;
font: message-box;
font-size: 14px;
color: #ffffff;
}
@media (min-resolution: 2dppx) {
.playButton {
background-image: url(chrome://global/skin/media/pauseButton@2x.png);
background-size: 28px 28px;
}
.playButton[paused] {
background-image: url(chrome://global/skin/media/playButton@2x.png);
background-size: 28px 28px;
}
.volumeBackground {
background-image: url(chrome://global/skin/media/volume-empty@2x.png);
background-size: 32px 16px;
}
.volumeForeground {
background-image: url(chrome://global/skin/media/volume-full@2x.png);
background-size: 32px 16px;
}
.muteButton {
background-image: url(chrome://global/skin/media/muteButton@2x.png);
background-size: 33px 28px;
}
.muteButton[muted] {
background-image: url(chrome://global/skin/media/unmuteButton@2x.png);
background-size: 33px 28px;
}
.muteButton[noAudio] {
background-image: url(chrome://global/skin/media/noAudio@2x.png);
background-size: 33px 28px;
}
.closedCaptionButton {
background-image: url(chrome://global/skin/media/closeCaptionButton@2x.png);
background-position: 4px;
background-size: 28px 28px;
}
.fullscreenButton {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton@2x.png"), 0, 32, 32, 0);
background-size: 16px 16px;
}
.fullscreenButton[fullscreened] {
background-image: -moz-image-rect(url("chrome://global/skin/media/fullscreenButton@2x.png"), 0, 64, 32, 32);
background-size: 16px 16px;
}
.timeThumb {
background-image: url(chrome://global/skin/media/scrubberThumb@2x.png);
background-size: 33px 28px;
}
.timeThumb[showhours="true"] {
background-image: url(chrome://global/skin/media/scrubberThumbWide@2x.png);
background-size: 45px 28px;
}
.errorLabel {
display: none;
}
[error="errorAborted"] > [anonid="errorAborted"],
[error="errorNetwork"] > [anonid="errorNetwork"],
[error="errorDecode"] > [anonid="errorDecode"],
[error="errorSrcNotSupported"] > [anonid="errorSrcNotSupported"],
[error="errorNoSource"] > [anonid="errorNoSource"],
[error="errorGeneric"] > [anonid="errorGeneric"] {
display: inline;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B