Bug 448909 - Need more controls WHATWG Video tag. r=mconnor, r=bz

This commit is contained in:
Justin Dolske 2008-10-01 01:00:22 -07:00
parent 5b263e95c7
commit a9f5276cf3
8 changed files with 255 additions and 265 deletions

View File

@ -600,29 +600,11 @@ input[type="file"] > input[type="text"] {
} }
video > xul|videocontrols { video > xul|videocontrols {
display: none;
}
video[controls] > xul|videocontrols {
display: -moz-box; display: -moz-box;
-moz-box-orient: vertical; -moz-box-orient: vertical;
-moz-binding: url("chrome://global/content/bindings/videocontrols.xml#videoControls"); -moz-binding: url("chrome://global/content/bindings/videocontrols.xml#videoControls");
} }
video[controls] > xul|videocontrols xul|button.controlbar {
visibility: hidden;
}
video[controls] > xul|videocontrols xul|button.centerplay {
visibility: visible;
}
video[controls] > xul|videocontrols.playing xul|button.centerplay {
visibility: hidden;
}
video[controls]:hover > xul|videocontrols.playing xul|button.controlbar {
visibility: visible;
}
%if OSARCH==OS2 %if OSARCH==OS2
input { input {
font: medium serif; font-family: inherit font: medium serif; font-family: inherit

View File

@ -1,9 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!--
SVG Icons from the BSD Licensed BlueSphere Icon Theme:
http://svgicons.sourceforge.net/
-->
<bindings id="videoContolBindings" <bindings id="videoContolBindings"
xmlns="http://www.mozilla.org/xbl" xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
@ -11,261 +7,221 @@
xmlns:svg="http://www.w3.org/2000/svg"> xmlns:svg="http://www.w3.org/2000/svg">
<binding id="videoControls"> <binding id="videoControls">
<content>
<xul:vbox flex="1"/> <resources>
<xul:hbox flex="0" pack="center"> <stylesheet src="chrome://global/skin/media/videocontrols.css"/>
<xul:button class="centerplay" flex="0" style="opacity:0.6;" vcattr="center-play" label="Play"> </resources>
<svg:svg
width="32px" <xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
height="32px" <spacer flex="1"/>
viewBox="0 0 508 508" <stack xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
xmlns="http://www.w3.org/2000/svg"> <hbox id="controlsBackground">
<defs> <image id="playButton"
<radialGradient onclick="this.parentNode.parentNode.parentNode.Utils.togglePause();"/>
cx="220" <box id="controlsMiddle" flex="1"/>
cy="220" <image id="muteButton"
r="151" onclick="this.parentNode.parentNode.parentNode.Utils.toggleMute();"/>
fx="220" </hbox>
fy="220" </stack>
gradientUnits="userSpaceOnUse" </xbl:content>
style="stroke:#000000;stroke-width:1;">
<stop
offset="0"
style="stop-color:#73ffff;stroke:#000000;stroke-width:1;" />
<stop
offset="0.28"
style="stop-color:#2EA6B9;stroke:#000000;stroke-width:1;" />
<stop
offset="1"
style="stop-color:#006b8b;stroke:#000000;stroke-width:1;" />
</radialGradient>
<linearGradient
id="gradient"
x1="0.380952"
y1="0.0859375"
x2="-0.111111"
y2="1.00781"
gradientUnits="objectBoundingBox"
spreadMethod="pad" />
</defs>
<g transform="translate(24,-1.6)">
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#a4c9ee;stroke-width:10.824;stroke-linejoin:round;stroke-opacity:0.701961;"
d="M 338.593 175.32 L 435.492 261.836 L 339.257 355.345 L 338.593 175.32 z "
transform="matrix(1.72603,0,0,1.94683,-397.314,-245.978)"
/>
<path
style="fill:url(#gradient);fill-opacity:0.992157;fill-rule:evenodd;stroke:#0c6671;stroke-width:9.60304;stroke-opacity:0.992157;"
d="M 355.635 183.469 L 437.887 259.936 L 355.817 342.102 L 355.635 183.469 z "
transform="matrix(1.67014,0,0,1.75639,-395.375,-194.413)"
/>
</g>
</svg:svg>
</xul:button>
</xul:hbox>
<xul:vbox flex="2" pack="end">
<xul:hbox flex="0" pack="center" style="opacity:0.6;">
<xul:button class="controlbar" flex="0" vcattr="pause" label="Pause">
<svg:svg
width="32px"
height="32px"
viewBox="0 0 508 508"
xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient
cx="220"
cy="220"
r="151"
fx="220"
fy="220"
gradientUnits="userSpaceOnUse"
style="stroke:#000000;stroke-width:1;">
<stop
offset="0"
style="stop-color:#73ffff;stroke:#000000;stroke-width:1;" />
<stop
offset="0.28"
style="stop-color:#2EA6B9;stroke:#000000;stroke-width:1;" />
<stop
offset="1"
style="stop-color:#006b8b;stroke:#000000;stroke-width:1;" />
</radialGradient>
<linearGradient
id="gradient"
x1="0.506276"
y1="0.046875"
x2="0.506276"
y2="0.984375"
gradientUnits="objectBoundingBox"
spreadMethod="pad" />
</defs>
<g transform="matrix(0,-1,1,0,-205,520)">
<rect
style="fill-rule:evenodd;stroke:#a4c9ee;stroke-width:16;stroke-opacity:0.701961;"
x="121"
y="297"
width="256"
height="147" />
<rect
style="fill:url(#gradient);fill-rule:evenodd;stroke:#0c6671;stroke-width:14;"
x="135"
y="308"
width="232"
height="125"/>
</g>
<g transform="matrix(0,-1,1,0,-22,520)">
<rect
style="fill-rule:evenodd;stroke:#a4c9ee;stroke-width:16;stroke-opacity:0.701961;"
x="121"
y="297"
width="256"
height="147"/>
<rect
style="fill:url(#gradient);fill-rule:evenodd;stroke:#0c6671;stroke-width:14;"
x="135"
y="308"
width="232"
height="125"/>
</g>
</svg:svg>
</xul:button>
<xul:button class="controlbar" flex="0" vcattr="stop" label="Stop">
<svg:svg
width="32px"
height="32px"
viewBox="0 0 508 508"
xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient
cx="220"
cy="220"
r="151"
fx="220"
fy="220"
gradientUnits="userSpaceOnUse"
style="stroke:#000000;stroke-width:1;">
<stop
offset="0"
style="stop-color:#73ffff;stroke:#000000;stroke-width:1;" />
<stop
offset="0.2809"
style="stop-color:#2EA6B9;stroke:#000000;stroke-width:1;" />
<stop
offset="1"
style="stop-color:#006b8b;stroke:#000000;stroke-width:1;" />
</radialGradient>
<linearGradient
id="gradient"
x1="0.506276"
y1="0.046875"
x2="0.506276"
y2="0.984375"
gradientUnits="objectBoundingBox"
spreadMethod="pad" />
</defs>
<g transform="matrix(0,-1,1.5,0,-340,497)">
<rect
style="fill-rule:evenodd;stroke:#a4c9ee;stroke-width:16;stroke-opacity:0.701961;"
x="121"
y="297"
width="256"
height="147"/>
<rect
style="fill:url(#gradient);fill-rule:evenodd;stroke:#0c6671;stroke-width:14;"
x="135"
y="308"
width="232"
height="125"/>
</g>
</svg:svg>
</xul:button>
</xul:hbox>
</xul:vbox>
</content>
<implementation implements="nsISecurityCheckedComponent"> <implementation implements="nsISecurityCheckedComponent">
<!-- nsISecurityCheckedComponent --> <!-- nsISecurityCheckedComponent -->
<method name="canCreateWrapper"> <method name="canCreateWrapper">
<parameter name="aIID"/> <parameter name="aIID"/>
<body> <body>
return "AllAccess"; return "AllAccess";
</body> </body>
</method> </method>
<method name="canCallMethod"> <method name="canCallMethod">
<parameter name="aIID"/> <parameter name="aIID"/>
<parameter name="aMethodName"/> <parameter name="aMethodName"/>
<body> <body>
return "AllAccess"; return "AllAccess";
</body> </body>
</method> </method>
<method name="canGetProperty"> <method name="canGetProperty">
<parameter name="aIID"/> <parameter name="aIID"/>
<parameter name="aPropertyName"/> <parameter name="aPropertyName"/>
<body> <body>
return "AllAccess"; return "AllAccess";
</body> </body>
</method> </method>
<method name="canSetProperty"> <method name="canSetProperty">
<parameter name="aIID"/> <parameter name="aIID"/>
<parameter name="aPropertyName"/> <parameter name="aPropertyName"/>
<body> <body>
return "AllAccess"; return "AllAccess";
</body> </body>
</method> </method>
<method name="QueryInterface"> <method name="QueryInterface">
<parameter name="aIID"/> <parameter name="aIID"/>
<body> <body>
<![CDATA[ <![CDATA[
if(!iid.equals(Components.interfaces.nsISecurityCheckedComponent)) if (!iid.equals(Components.interfaces.nsISecurityCheckedComponent))
throw Components.results.NS_ERROR_NO_INTERFACE; throw Components.results.NS_ERROR_NO_INTERFACE;
return this; return this;
]]> ]]>
</body> </body>
</method> </method>
<constructor> <constructor>
this.init(); <![CDATA[
</constructor> this.init();
]]>
</constructor>
<method name="init"> <field name="Utils">
<body> <![CDATA[ ({
<![CDATA[ debug : false,
video : null,
controls : null,
playButton : null,
muteButton : null,
animationSteps : 8,
animationStep : 0,
animationDirection : 1,
animationTimer : null,
onMediaEvent : function (aEvent) {
this.log("Got " + aEvent.type + " media event");
switch (aEvent.type) {
case "play":
this.playButton.setAttribute("paused", false);
break;
case "pause":
this.playButton.setAttribute("paused", true);
break;
case "volumechange":
this.muteButton.setAttribute("muted", this.video.muted);
break;
default:
this.log("!!! event " + aEvent.type + " not handled!");
}
return false;
},
fadeControls : function (self) {
self.log("fadeControls @" + self.animationStep);
self.animationStep += self.animationDirection;
if (self.animationStep <= 0) {
self.animationStep = 0;
clearInterval(self.animationTimer);
self.animationTimer = null;
} else if (self.animationStep >= self.animationSteps) {
self.animationStep = self.animationSteps;
clearInterval(self.animationTimer);
self.animationTimer = null;
}
// XXX might be good to do logarithmic steps, maybe use timer error too (for smoothness)?
self.controls.style.opacity = self.animationStep / self.animationSteps;
},
togglePause : function () {
if (this.video.paused)
this.video.play();
else
this.video.pause();
// We'll handle style changes in the event listener for
// the "play" and "pause" events, same as if content
// script was controlling video playback.
},
toggleMute : function () {
this.video.muted = !this.video.muted;
// We'll handle style changes in the event listener for
// the "volumechange" event, same as if content script was
// controlling volume.
},
isChildNode : function (node) {
while (node) {
if (node == this.controls)
break;
node = node.parentNode;
}
return (node == this);
},
log : function (msg) {
if (this.debug)
dump("videoctl: " + msg + "\n");
}
}) ]]>
</field>
<method name="init">
<body>
<![CDATA[
var self = this; var self = this;
var video = this.parentNode; var video = this.parentNode;
this.Utils.video = video;
this.Utils.controls = self;
var centerPlay = document.getAnonymousElementByAttribute(this, "vcattr", "center-play"); this.Utils.playButton = document.getAnonymousElementByAttribute(self, "id", "playButton");
video.addEventListener("play", function() { this.Utils.muteButton = document.getAnonymousElementByAttribute(self, "id", "muteButton");
self.setAttribute("class", "playing");
}, false); // Set initial state of play/pause button.
video.addEventListener("pause", function() { // XXX (force to a bool, due to bug 457964)
self.setAttribute("class", ""); this.Utils.playButton.setAttribute("paused", video.paused ? true : false);
}, false);
video.addEventListener("ended", function() { function eventBouncer(aEvent) {
self.setAttribute("class", ""); self.Utils.onMediaEvent(aEvent);
}, false); }
centerPlay.addEventListener("click", function() { this.style.opacity = 0;
video.play();
}, false); video.addEventListener("play", eventBouncer, false);
video.addEventListener("pause", eventBouncer, false);
video.addEventListener("volumechange", eventBouncer, false);
this.Utils.log("--- videocontrols initialized ---");
]]>
</body>
</method>
var pause = document.getAnonymousElementByAttribute(this, "vcattr", "pause");
pause.addEventListener("click", function() {
video.pause();
}, false);
var stop = document.getAnonymousElementByAttribute(this, "vcattr", "stop");
stop.addEventListener("click", function() {
video.pause();
video.currentTime = 0.0;
}, false);
]]>
</body>
</method>
<destructor>
</destructor>
</implementation> </implementation>
<handlers>
<handler event="mouseover">
<![CDATA[
// Ignore events caused by transitions between child nodes.
if (this.Utils.isChildNode(event.relatedTarget))
return;
// Don't show controls unless they're enabled
// XXX sucks that spec defaults to controls=false. :-(
// XXX add support for dynamically hiding controls w/o waiting for mouseout?
if (!this.Utils.video.controls)
return;
this.Utils.animationDirection = 1;
if (!this.Utils.animationTimer)
this.Utils.animationTimer = setInterval(this.Utils.fadeControls, 50, this.Utils);
]]>
</handler>
<handler event="mouseout">
<![CDATA[
// Ignore events caused by transitions between child nodes.
if (this.Utils.isChildNode(event.relatedTarget))
return;
this.Utils.animationDirection = -1;
if (!this.Utils.animationTimer)
this.Utils.animationTimer = setInterval(this.Utils.fadeControls, 50, this.Utils);
]]>
</handler>
</handlers>
</binding> </binding>
</bindings> </bindings>

View File

@ -169,6 +169,8 @@ classic.jar:
+ skin/classic/global/notification/critical-bar-background.png (notification/critical-bar-background.png) + skin/classic/global/notification/critical-bar-background.png (notification/critical-bar-background.png)
+ skin/classic/global/notification/info-bar-background.png (notification/info-bar-background.png) + skin/classic/global/notification/info-bar-background.png (notification/info-bar-background.png)
+ skin/classic/global/notification/warning-bar-background.png (notification/warning-bar-background.png) + skin/classic/global/notification/warning-bar-background.png (notification/warning-bar-background.png)
+ skin/classic/global/media/videocontrols.css (media/videocontrols.css)
+ skin/classic/global/media/videocontrols.png (media/videocontrols.png)
+ skin/classic/global/menu/menu-arrow-dis.gif (menu/menu-arrow-dis.gif) + skin/classic/global/menu/menu-arrow-dis.gif (menu/menu-arrow-dis.gif)
+ skin/classic/global/menu/menu-arrow-hov.gif (menu/menu-arrow-hov.gif) + skin/classic/global/menu/menu-arrow-hov.gif (menu/menu-arrow-hov.gif)
+ skin/classic/global/menu/menu-arrow.gif (menu/menu-arrow.gif) + skin/classic/global/menu/menu-arrow.gif (menu/menu-arrow.gif)

View File

@ -0,0 +1,23 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
#controlsBackground {
height: 24px;
background-color: #656363;
}
#playButton {
list-style-image: url(chrome://global/skin/media/videocontrols.png);
-moz-image-region: rect(0px, 48px, 24px, 24px);
}
#playButton[paused="true"] {
-moz-image-region: rect(0px, 24px, 24px, 0px);
}
#muteButton{
list-style-image: url(chrome://global/skin/media/videocontrols.png);
-moz-image-region: rect(24px, 24px, 48px, 0px);
}
#muteButton[muted="true"] {
-moz-image-region: rect(24px, 48px, 48px, 24px);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -144,6 +144,8 @@ classic.jar:
skin/classic/global/icons/warningBarIcon-16.png (icons/warningBarIcon-16.png) skin/classic/global/icons/warningBarIcon-16.png (icons/warningBarIcon-16.png)
skin/classic/global/icons/warningGhosted-64.png (icons/warningGhosted-64.png) skin/classic/global/icons/warningGhosted-64.png (icons/warningGhosted-64.png)
skin/classic/global/icons/wrap.png (icons/wrap.png) skin/classic/global/icons/wrap.png (icons/wrap.png)
skin/classic/global/media/videocontrols.css (media/videocontrols.css)
skin/classic/global/media/videocontrols.png (media/videocontrols.png)
skin/classic/global/radio/radio-check.gif (radio/radio-check.gif) skin/classic/global/radio/radio-check.gif (radio/radio-check.gif)
skin/classic/global/radio/radio-check-dis.gif (radio/radio-check-dis.gif) skin/classic/global/radio/radio-check-dis.gif (radio/radio-check-dis.gif)
skin/classic/global/scrollbar/slider.gif (scrollbar/slider.gif) skin/classic/global/scrollbar/slider.gif (scrollbar/slider.gif)
@ -308,6 +310,8 @@ classic.jar:
skin/classic/aero/global/icons/warningBarIcon-16.png (icons/warningBarIcon-16-aero.png) skin/classic/aero/global/icons/warningBarIcon-16.png (icons/warningBarIcon-16-aero.png)
skin/classic/aero/global/icons/warningGhosted-64.png (icons/warningGhosted-64-aero.png) skin/classic/aero/global/icons/warningGhosted-64.png (icons/warningGhosted-64-aero.png)
skin/classic/aero/global/icons/wrap.png (icons/wrap-aero.png) skin/classic/aero/global/icons/wrap.png (icons/wrap-aero.png)
skin/classic/aero/global/media/videocontrols.css (media/videocontrols.css)
skin/classic/aero/global/media/videocontrols.png (media/videocontrols.png)
skin/classic/aero/global/radio/radio-check.gif (radio/radio-check.gif) skin/classic/aero/global/radio/radio-check.gif (radio/radio-check.gif)
skin/classic/aero/global/radio/radio-check-dis.gif (radio/radio-check-dis.gif) skin/classic/aero/global/radio/radio-check-dis.gif (radio/radio-check-dis.gif)
skin/classic/aero/global/scrollbar/slider.gif (scrollbar/slider.gif) skin/classic/aero/global/scrollbar/slider.gif (scrollbar/slider.gif)

View File

@ -0,0 +1,23 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
#controlsBackground {
height: 24px;
background-color: #656363;
}
#playButton {
list-style-image: url(chrome://global/skin/media/videocontrols.png);
-moz-image-region: rect(0px, 48px, 24px, 24px);
}
#playButton[paused="true"] {
-moz-image-region: rect(0px, 24px, 24px, 0px);
}
#muteButton{
list-style-image: url(chrome://global/skin/media/videocontrols.png);
-moz-image-region: rect(24px, 24px, 48px, 0px);
}
#muteButton[muted="true"] {
-moz-image-region: rect(24px, 48px, 48px, 24px);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B