Bug 590715 - Fullscreen video for Fennec [r=mfinkle]

This commit is contained in:
Matt Brubeck 2010-10-16 06:25:15 -07:00
Родитель 8d931cd756
Коммит 70f5847a73
11 изменённых файлов: 368 добавлений и 16 удалений

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.com>
* Matt Brubeck <mbrubeck@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -482,6 +483,7 @@ var BrowserUI = {
DownloadsView.init();
PreferencesView.init();
ConsoleView.init();
FullScreenVideo.init();
#ifdef MOZ_IPC
// Pre-start the content process
@ -2546,14 +2548,9 @@ var ContextCommands = {
SharingUI.show(ContextHelper.popupState.mediaURL, null);
},
playMedia: function cc_playVideo() {
sendCommand: function cc_playVideo(aCommand) {
let browser = ContextHelper.popupState.target;
browser.messageManager.sendAsyncMessage("Browser:MediaCommand", { command: "play"});
},
pauseMedia: function cc_playVideo() {
let browser = ContextHelper.popupState.target;
browser.messageManager.sendAsyncMessage("Browser:MediaCommand", { command: "pause" });
browser.messageManager.sendAsyncMessage("Browser:ContextCommand", { command: aCommand });
},
editBookmark: function cc_editBookmark() {
@ -2718,3 +2715,69 @@ var BadgeHandlers = {
return aValue;
}
};
var FullScreenVideo = {
browser: null,
init: function fsv_init() {
messageManager.addMessageListener("Browser:FullScreenVideo:Start", this.show.bind(this));
messageManager.addMessageListener("Browser:FullScreenVideo:Close", this.hide.bind(this));
},
show: function fsv_show() {
this.createBrowser();
window.fullScreen = true;
BrowserUI.pushPopup(this, this.browser);
},
hide: function fsv_hide() {
this.destroyBrowser();
window.fullScreen = false;
BrowserUI.popPopup();
},
createBrowser: function fsv_createBrowser() {
let browser = this.browser = document.createElement("browser");
browser.className = "window-width window-height full-screen";
browser.setAttribute("type", "content");
browser.setAttribute("remote", "true");
browser.setAttribute("src", "chrome://browser/content/fullscreen-video.xhtml");
document.getElementById("main-window").appendChild(browser);
let mm = browser.messageManager;
mm.loadFrameScript("chrome://browser/content/fullscreen-video.js", true);
browser.addEventListener("TapDown", this, true);
browser.addEventListener("TapSingle", this, false);
return browser;
},
destroyBrowser: function fsv_destroyBrowser() {
let browser = this.browser;
browser.removeEventListener("TapDown", this, false);
browser.removeEventListener("TapSingle", this, false);
browser.parentNode.removeChild(browser);
this.browser = null;
},
handleEvent: function fsv_handleEvent(aEvent) {
switch (aEvent.type) {
case "TapDown":
this._dispatchMouseEvent("Browser:MouseDown", aEvent.clientX, aEvent.clientY);
break;
case "TapSingle":
this._dispatchMouseEvent("Browser:MouseUp", aEvent.clientX, aEvent.clientY);
break;
}
},
_dispatchMouseEvent: function fsv_dispatchMouseEvent(aName, aX, aY) {
let pos = this.browser.transformClientToBrowser(aX, aY);
this.browser.messageManager.sendAsyncMessage(aName, {
x: pos.x,
y: pos.y,
messageId: null
});
}
};

Просмотреть файл

@ -165,8 +165,8 @@ function onDebugKeyPress(ev) {
}
var Browser = {
_tabs : [],
_selectedTab : null,
_tabs: [],
_selectedTab: null,
windowUtils: window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils),
controlsScrollbox: null,

Просмотреть файл

@ -564,12 +564,15 @@
<richlistitem class="context-command" id="context-share-image" type="image-shareable" onclick="ContextCommands.shareMedia();">
<label value="&contextShareImage.label;"/>
</richlistitem>
<richlistitem class="context-command" id="context-play-media" type="media-paused" onclick="ContextCommands.playMedia();">
<richlistitem class="context-command" id="context-play-media" type="media-paused" onclick="ContextCommands.sendCommand('play');">
<label value="&contextPlayMedia.label;"/>
</richlistitem>
<richlistitem class="context-command" id="context-pause-video" type="media-playing" onclick="ContextCommands.pauseMedia();">
<richlistitem class="context-command" id="context-pause-video" type="media-playing" onclick="ContextCommands.sendCommand('pause');">
<label value="&contextPauseMedia.label;"/>
</richlistitem>
<richlistitem class="context-command" id="context-fullscreen" type="video" onclick="ContextCommands.sendCommand('fullscreen');">
<label value="&contextFullScreen.label;"/>
</richlistitem>
<richlistitem class="context-command" id="context-save-video" type="video" onclick="ContextCommands.saveImage();">
<label value="&contextSaveVideo.label;"/>
</richlistitem>

Просмотреть файл

@ -656,7 +656,7 @@ var ContextHandler = {
init: function ch_init() {
addEventListener("contextmenu", this, false);
addEventListener("pagehide", this, false);
addMessageListener("Browser:MediaCommand", this, false);
addMessageListener("Browser:ContextCommand", this, false);
this.popupNode = null;
},
@ -735,10 +735,23 @@ var ContextHandler = {
},
receiveMessage: function ch_receiveMessage(aMessage) {
switch (aMessage.name) {
case "Browser:MediaCommand":
if (this.popupNode instanceof Ci.nsIDOMHTMLMediaElement)
this.popupNode[aMessage.json.command]();
let node = this.popupNode;
let command = aMessage.json.command;
switch (command) {
case "play":
case "pause":
if (node instanceof Ci.nsIDOMHTMLMediaElement)
node[command]();
break;
case "fullscreen":
if (node instanceof Ci.nsIDOMHTMLVideoElement) {
node.pause();
Cu.import("resource:///modules/video.jsm");
Video.fullScreenSourceElement = node;
sendAsyncMessage("Browser:FullScreenVideo:Start");
}
break;
}
},

Просмотреть файл

@ -0,0 +1,47 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Mobile Browser.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Matt Brubeck <mbrubeck@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function closeFullScreen() {
sendAsyncMessage("Browser:FullScreenVideo:Close");
}
addEventListener("click", function(aEvent) {
if (aEvent.target.id == "close")
closeFullScreen();
}, false);
addEventListener("CloseVideo", closeFullScreen, false);

Просмотреть файл

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<!--
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Dão Gottwald <dao@mozilla.com>
# Matt Brubeck <mbrubeck@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-->
<html xmlns="http://www.w3.org/1999/xhtml" accelerated="11">
<head>
<style type="text/css"><![CDATA[
html,
body,
video {
height: 100%;
}
body {
margin: 0;
background: black;
overflow: -moz-hidden-unscrollable;
}
body.userIdle {
cursor: none;
}
video {
width: 100%;
max-height: 100%;
}
body.loadingdata > video,
body.loadingdata > #close,
body.userIdle > #close {
visibility: hidden;
}
#close {
position: absolute;
top: 0;
right: 0;
width: 32px;
height: 32px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAB3RJTUUH2AUXDg4nBoBhWwAAAAlwSFlzAAAPYAAAD2ABenhFjQAAAARnQU1BAACxjwv8YQUAAAEYSURBVHjaY2BgYOAAYtXk5OQAEA3EnAzkAUYg5gFidahZikDMBpJQvXHjxqP/QHDhwoUHmpqarlCFpBou4OzsHH7nzp3XILOOHDlyHigmz1BQUBD5Hwlcu3bthYaGhhsJloANd3Jyinz8+PEnmDl//vz5Z2RkZAFSoAGzlQxLsBoOAidPnrwJlFMAKeIBeQ1dARGW4DQcpFdLS8sZFp94FeKwhBg93KRq4CFDLcmu4gViQXIMJ8oSJSWlIBsbmyRyDSdoCTCfvH/w4MFXCpM1fkuoYTiyJYLW1tbJ9+/f/4Zu+MWLF98pKysHQOMFJ2Aix2ZqAJoGEU0jmabJlKYZjaZFBc0LO5oX17StcOhRZdK20megcbMFAI0gGfYvgPhiAAAAAElFTkSuQmCC) center center no-repeat;
}
]]></style>
<script type="application/javascript;version=1.8"><![CDATA[
Components.utils.import("resource:///modules/video.jsm");
var contentVideo = Video.fullScreenSourceElement;
Video.fullScreenSourceElement = null;
var video;
function init() {
video = document.querySelector("video");
video.addEventListener("loadeddata", function () {
video.removeEventListener("loadeddata", arguments.callee, false);
video.volume = contentVideo.volume;
video.muted = contentVideo.muted;
video.poster = contentVideo.poster;
if (contentVideo.currentTime && !contentVideo.ended) {
video.addEventListener("seeked", function () {
video.removeEventListener("seeked", arguments.callee, false);
playbackStarts();
}, false);
video.currentTime = contentVideo.currentTime;
} else {
playbackStarts();
}
showUI();
resetIdleTimer();
video.controls = true;
video.play();
}, false);
// Automatically close this window when the playback ended, unless the user
// interacted with it.
video.addEventListener("ended", close, false);
window.addEventListener("click", cancelAutoClose, false);
window.addEventListener("keypress", cancelAutoClose, false);
video.addEventListener("seeked", hideUI, false);
video.addEventListener("seeking", showUI, false);
video.addEventListener("pause", showUI, false);
video.addEventListener("ended", showUI, false);
window.addEventListener("click", function () {
toggleUI();
resetIdleTimer();
}, false);
video.mozLoadFrom(contentVideo);
}
window.addEventListener("unload", function () {
if (video.currentSrc) {
contentVideo.currentTime = video.currentTime;
contentVideo.volume = video.volume;
contentVideo.muted = video.muted;
if (!video.paused && !video.ended) {
video.pause();
contentVideo.play();
}
}
}, false);
window.addEventListener("keypress", function (event) {
if (event.keyCode == event.DOM_VK_ESCAPE) {
close();
return;
}
resetIdleTimer();
if (!video.controls &&
String.fromCharCode(event.charCode) == " ")
video.pause();
}, false);
function playbackStarts() {
// Loading the data from the content video may take a second or two. We hide
// the video during that period.
document.body.classList.remove("loadingdata");
video.focus();
}
function close() {
let event = document.createEvent("Events");
event.initEvent("CloseVideo", true, true);
window.dispatchEvent(event);
}
function cancelAutoClose() {
video.removeEventListener("ended", close, false);
window.removeEventListener("click", cancelAutoClose, false);
window.removeEventListener("keypress", cancelAutoClose, false);
}
var idleTimer;
function resetIdleTimer() {
if (idleTimer) {
clearTimeout(idleTimer);
idleTimer = 0;
}
idleTimer = setTimeout(function () {
idleTimer = 0;
hideUI();
}, 5000);
}
var showingUI = false;
function toggleUI() {
if (showingUI)
hideUI();
else
showUI();
}
function showUI() {
showingUI = true;
document.body.classList.remove("userIdle");
}
function hideUI() {
showingUI = false;
document.body.classList.add("userIdle");
}
]]></script>
</head>
<body class="loadingdata" onload="init();">
<span id="close"/>
<video/>
</body>
</html>

Просмотреть файл

@ -59,5 +59,7 @@ chrome.jar:
content/sync.js (content/sync.js)
#endif
content/LoginManagerChild.js (content/LoginManagerChild.js)
content/fullscreen-video.js (content/fullscreen-video.js)
content/fullscreen-video.xhtml (content/fullscreen-video.xhtml)
% override chrome://global/content/config.xul chrome://browser/content/config.xul

Просмотреть файл

@ -96,6 +96,7 @@
<!ENTITY contextShareVideo.label "Share Video">
<!ENTITY contextPlayMedia.label "Play">
<!ENTITY contextPauseMedia.label "Pause">
<!ENTITY contextFullScreen.label "Full Screen">
<!ENTITY contextEditBookmark.label "Edit">
<!ENTITY contextRemoveBookmark.label "Remove">

Просмотреть файл

@ -44,6 +44,7 @@ include $(DEPTH)/config/autoconf.mk
EXTRA_JS_MODULES = \
linuxTypes.jsm \
video.jsm \
$(NULL)
EXTRA_PP_JS_MODULES = \

5
mobile/modules/video.jsm Normal file
Просмотреть файл

@ -0,0 +1,5 @@
var EXPORTED_SYMBOLS = ["Video"];
var Video = {
fullScreenSourceElement: null
};

Просмотреть файл

@ -1525,3 +1525,9 @@ echrome-select-option[disabled="true"] {
background: #8db8d8;
}
/* full-screen video ------------------------------------------------------- */
.full-screen {
position: absolute;
z-index: 500;
}