Bug 462117 - Reducing the number of visible controls when the video is too small. r=dolske
☠☠ backed out by ef520743354a ☠ ☠
authorJared Wein <jwein@mozilla.com>
Thu, 22 Sep 2011 16:19:52 -0700
changeset 78701 49678dad20f0128cfb4748d702496c06edb88de9
parent 78700 bf900e375add310511e301f9b86c061b13968f5a
child 78702 ef520743354a661a7089db386a8e607bf17b7019
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdolske
bugs462117
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 462117 - Reducing the number of visible controls when the video is too small. r=dolske
toolkit/content/widgets/videocontrols.css
toolkit/content/widgets/videocontrols.xml
--- a/toolkit/content/widgets/videocontrols.css
+++ b/toolkit/content/widgets/videocontrols.css
@@ -48,8 +48,23 @@
 .statusOverlay:not([immediate]) {
   -moz-transition-property: opacity;
   -moz-transition-duration: 1ms;
   -moz-transition-delay: 750ms;
 }
 .statusOverlay[fadeout] {
   opacity: 0;
 }
+
+.controlBar[size="hidden"],
+.controlBar[size="small"] .durationBox,
+.controlBar[size="small"] .durationLabel,
+.controlBar[size="small"] .positionLabel {
+  visibility: collapse;
+}
+
+.controlBar[size="small"] .scrubberStack {
+  visibility: hidden;
+}
+
+.controlBar[size="small"] .scrubberStack > * {
+  visibility: hidden;
+}
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -338,16 +338,27 @@
                     // Set the current status icon.
                     if (this.video.error || this.video.networkState == this.video.NETWORK_NO_SOURCE) {
                         this.statusIcon.setAttribute("type", "error");
                         this.setupStatusFader(true);
                     } else {
                         this.statusIcon.setAttribute("type", "throbber");
                         this.setupStatusFader();
                     }
+
+                    // An event handler for |onresize| should be added when bug 227495 is fixed.
+                    let controlBarWasHidden = this.controlBar.getAttribute("hidden") == "true";
+                    this.controlBar.removeAttribute("hidden");
+                    this._playButtonWidth = this.playButton.clientWidth;
+                    this._durationLabelWidth = this.durationLabel.clientWidth;
+                    this._muteButtonWidth = this.muteButton.clientWidth;
+                    this._controlBarHeight = this.controlBar.clientHeight;
+                    if (controlBarWasHidden)
+                      this.controlBar.setAttribute("hidden", "true");
+                    this.adjustControlSize();
                 },
 
                 get dynamicControls() {
                     // Don't fade controls for <audio> elements.
                     var enabled = !this.isAudioOnly;
 
                     // Allow tests to explicitly suppress the fading of controls.
                     if (this.video.hasAttribute("mozNoDynamicControls"))
@@ -395,16 +406,17 @@
                             this.setupStatusFader();
                             break;
                         case "volumechange":
                             var volume = this.video.muted ? 0 : Math.round(this.video.volume * 100);
                             this.setMuteButtonState(this.video.muted);
                             this.volumeControl.value = volume;
                             break;
                         case "loadedmetadata":
+                            this.adjustControlSize();
                             // If a <video> doesn't have any video data, treat it as <audio>
                             // and show the controls (they won't fade back out)
                             if (this.video instanceof HTMLVideoElement &&
                                 (this.video.videoWidth == 0 || this.video.videoHeight == 0)) {
                                 this.isAudioOnly = true;
                                 this.startFadeIn(this.controlBar);
                             }
                             this.showDuration(Math.round(this.video.duration * 1000));
@@ -649,16 +661,19 @@
 
                     // Suppress fading out the controls until the video has rendered
                     // its first frame. But since autoplay videos start off with no
                     // controls, let them fade-out so the controls don't get stuck on.
                     if (!this.firstFrameShown && !isMouseOver &&
                         !(this.video.autoplay && this.video.mozAutoplayEnabled))
                         return;
 
+                    if (!isMouseOver)
+                        this.adjustControlSize();
+
                     this.startFade(this.controlBar, isMouseOver);
                 },
 
                 startFadeIn : function (element, immediate) {
                     this.startFade(element, true, immediate);
                 },
 
                 startFadeOut : function (element, immediate) {
@@ -856,16 +871,44 @@
                     return isDescendant(event.target) && isDescendant(event.relatedTarget);
                 },
 
                 log : function (msg) {
                     if (this.debug)
                         dump("videoctl: " + msg + "\n");
                 },
 
+                _playButtonWidth : 0,
+                _durationLabelWidth : 0,
+                _muteButtonWidth : 0,
+                _controlBarHeight : 0,
+                adjustControlSize : function adjustControlSize() {
+                    let videoHeight = this.video.clientHeight;
+                    let videoWidth = this.video.clientWidth;
+
+                    // The scrubber has |flex=1|, therefore |minScrubberWidth|
+                    // was generated by empirical testing.
+                    let minScrubberWidth = 25;
+                    let minWidthAllControls = this._playButtonWidth +
+                                              minScrubberWidth +
+                                              this._durationLabelWidth +
+                                              this._muteButtonWidth;
+                    let minHeightForControlBar = this._controlBarHeight;
+                    let minWidthOnlyPlayPause = this._playButtonWidth + this._muteButtonWidth;
+
+                    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);
+                },
+
                 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");
@@ -874,17 +917,17 @@
                     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");
                     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.controlsSpacer = document.getAnonymousElementByAttribute(binding, "class", "controlsSpacer")
+                    this.controlsSpacer = document.getAnonymousElementByAttribute(binding, "class", "controlsSpacer");
 
                     this.setupInitialState();
 
                     // videocontrols.css hides the control bar by default, because if script
                     // is disabled our binding's script is disabled too (bug 449358). Thus,
                     // the controls are broken and we don't want them shown. But if script is
                     // enabled, the code here will run and can explicitly unhide the controls.
                     //