summaryrefslogtreecommitdiffstats
path: root/browser/base/content/browser-fullScreenAndPointerLock.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/browser-fullScreenAndPointerLock.js')
-rw-r--r--browser/base/content/browser-fullScreenAndPointerLock.js673
1 files changed, 0 insertions, 673 deletions
diff --git a/browser/base/content/browser-fullScreenAndPointerLock.js b/browser/base/content/browser-fullScreenAndPointerLock.js
deleted file mode 100644
index 497e51121..000000000
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ /dev/null
@@ -1,673 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-var PointerlockFsWarning = {
-
- _element: null,
- _origin: null,
-
- init: function() {
- this.Timeout.prototype = {
- start: function() {
- this.cancel();
- this._id = setTimeout(() => this._handle(), this._delay);
- },
- cancel: function() {
- if (this._id) {
- clearTimeout(this._id);
- this._id = 0;
- }
- },
- _handle: function() {
- this._id = 0;
- this._func();
- },
- get delay() {
- return this._delay;
- }
- };
- },
-
- /**
- * Timeout object for managing timeout request. If it is started when
- * the previous call hasn't finished, it would automatically cancelled
- * the previous one.
- */
- Timeout: function(func, delay) {
- this._id = 0;
- this._func = func;
- this._delay = delay;
- },
-
- showPointerLock: function(aOrigin) {
- if (!document.fullscreen) {
- let timeout = gPrefService.getIntPref("pointer-lock-api.warning.timeout");
- this.show(aOrigin, "pointerlock-warning", timeout, 0);
- }
- },
-
- showFullScreen: function(aOrigin) {
- let timeout = gPrefService.getIntPref("full-screen-api.warning.timeout");
- let delay = gPrefService.getIntPref("full-screen-api.warning.delay");
- this.show(aOrigin, "fullscreen-warning", timeout, delay);
- },
-
- // Shows a warning that the site has entered fullscreen or
- // pointer lock for a short duration.
- show: function(aOrigin, elementId, timeout, delay) {
-
- if (!this._element) {
- this._element = document.getElementById(elementId);
- // Setup event listeners
- this._element.addEventListener("transitionend", this);
- window.addEventListener("mousemove", this, true);
- // The timeout to hide the warning box after a while.
- this._timeoutHide = new this.Timeout(() => {
- this._state = "hidden";
- }, timeout);
- // The timeout to show the warning box when the pointer is at the top
- this._timeoutShow = new this.Timeout(() => {
- this._state = "ontop";
- this._timeoutHide.start();
- }, delay);
- }
-
- // Set the strings on the warning UI.
- if (aOrigin) {
- this._origin = aOrigin;
- }
- let uri = BrowserUtils.makeURI(this._origin);
- let host = null;
- try {
- host = uri.host;
- } catch (e) { }
- let textElem = this._element.querySelector(".pointerlockfswarning-domain-text");
- if (!host) {
- textElem.setAttribute("hidden", true);
- } else {
- textElem.removeAttribute("hidden");
- let hostElem = this._element.querySelector(".pointerlockfswarning-domain");
- // Document's principal's URI has a host. Display a warning including it.
- let utils = {};
- Cu.import("resource://gre/modules/DownloadUtils.jsm", utils);
- hostElem.textContent = utils.DownloadUtils.getURIHost(uri.spec)[0];
- }
-
- this._element.dataset.identity =
- gIdentityHandler.pointerlockFsWarningClassName;
-
- // User should be allowed to explicitly disable
- // the prompt if they really want.
- if (this._timeoutHide.delay <= 0) {
- return;
- }
-
- // Explicitly set the last state to hidden to avoid the warning
- // box being hidden immediately because of mousemove.
- this._state = "onscreen";
- this._lastState = "hidden";
- this._timeoutHide.start();
- },
-
- close: function() {
- if (!this._element) {
- return;
- }
- // Cancel any pending timeout
- this._timeoutHide.cancel();
- this._timeoutShow.cancel();
- // Reset state of the warning box
- this._state = "hidden";
- this._element.setAttribute("hidden", true);
- // Remove all event listeners
- this._element.removeEventListener("transitionend", this);
- window.removeEventListener("mousemove", this, true);
- // Clear fields
- this._element = null;
- this._timeoutHide = null;
- this._timeoutShow = null;
-
- // Ensure focus switches away from the (now hidden) warning box.
- // If the user clicked buttons in the warning box, it would have
- // been focused, and any key events would be directed at the (now
- // hidden) chrome document instead of the target document.
- gBrowser.selectedBrowser.focus();
- },
-
- // State could be one of "onscreen", "ontop", "hiding", and
- // "hidden". Setting the state to "onscreen" and "ontop" takes
- // effect immediately, while setting it to "hidden" actually
- // turns the state to "hiding" before the transition finishes.
- _lastState: null,
- _STATES: ["hidden", "ontop", "onscreen"],
- get _state() {
- for (let state of this._STATES) {
- if (this._element.hasAttribute(state)) {
- return state;
- }
- }
- return "hiding";
- },
- set _state(newState) {
- let currentState = this._state;
- if (currentState == newState) {
- return;
- }
- if (currentState != "hiding") {
- this._lastState = currentState;
- this._element.removeAttribute(currentState);
- }
- if (newState != "hidden") {
- if (currentState != "hidden") {
- this._element.setAttribute(newState, true);
- } else {
- // When the previous state is hidden, the display was none,
- // thus no box was constructed. We need to wait for the new
- // display value taking effect first, otherwise, there won't
- // be any transition. Since requestAnimationFrame callback is
- // generally triggered before any style flush and layout, we
- // should wait for the second animation frame.
- requestAnimationFrame(() => {
- requestAnimationFrame(() => {
- if (this._element) {
- this._element.setAttribute(newState, true);
- }
- });
- });
- }
- }
- },
-
- handleEvent: function(event) {
- switch (event.type) {
- case "mousemove": {
- let state = this._state;
- if (state == "hidden") {
- // If the warning box is currently hidden, show it after
- // a short delay if the pointer is at the top.
- if (event.clientY != 0) {
- this._timeoutShow.cancel();
- } else if (this._timeoutShow.delay >= 0) {
- this._timeoutShow.start();
- }
- } else {
- let elemRect = this._element.getBoundingClientRect();
- if (state == "hiding" && this._lastState != "hidden") {
- // If we are on the hiding transition, and the pointer
- // moved near the box, restore to the previous state.
- if (event.clientY <= elemRect.bottom + 50) {
- this._state = this._lastState;
- this._timeoutHide.start();
- }
- } else if (state == "ontop" || this._lastState != "hidden") {
- // State being "ontop" or the previous state not being
- // "hidden" indicates this current warning box is shown
- // in response to user's action. Hide it immediately when
- // the pointer leaves that area.
- if (event.clientY > elemRect.bottom + 50) {
- this._state = "hidden";
- this._timeoutHide.cancel();
- }
- }
- }
- break;
- }
- case "transitionend": {
- if (this._state == "hiding") {
- this._element.setAttribute("hidden", true);
- }
- break;
- }
- }
- }
-};
-
-var PointerLock = {
-
- init: function() {
- window.messageManager.addMessageListener("PointerLock:Entered", this);
- window.messageManager.addMessageListener("PointerLock:Exited", this);
- },
-
- receiveMessage: function(aMessage) {
- switch (aMessage.name) {
- case "PointerLock:Entered": {
- PointerlockFsWarning.showPointerLock(aMessage.data.originNoSuffix);
- break;
- }
- case "PointerLock:Exited": {
- PointerlockFsWarning.close();
- break;
- }
- }
- }
-};
-
-var FullScreen = {
- _MESSAGES: [
- "DOMFullscreen:Request",
- "DOMFullscreen:NewOrigin",
- "DOMFullscreen:Exit",
- "DOMFullscreen:Painted",
- ],
-
- init: function() {
- // called when we go into full screen, even if initiated by a web page script
- window.addEventListener("fullscreen", this, true);
- window.addEventListener("MozDOMFullscreen:Entered", this,
- /* useCapture */ true,
- /* wantsUntrusted */ false);
- window.addEventListener("MozDOMFullscreen:Exited", this,
- /* useCapture */ true,
- /* wantsUntrusted */ false);
- for (let type of this._MESSAGES) {
- window.messageManager.addMessageListener(type, this);
- }
-
- if (window.fullScreen)
- this.toggle();
- },
-
- uninit: function() {
- for (let type of this._MESSAGES) {
- window.messageManager.removeMessageListener(type, this);
- }
- this.cleanup();
- },
-
- toggle: function () {
- var enterFS = window.fullScreen;
-
- // Toggle the View:FullScreen command, which controls elements like the
- // fullscreen menuitem, and menubars.
- let fullscreenCommand = document.getElementById("View:FullScreen");
- if (enterFS) {
- fullscreenCommand.setAttribute("checked", enterFS);
- } else {
- fullscreenCommand.removeAttribute("checked");
- }
-
- if (AppConstants.platform == "macosx") {
- // Make sure the menu items are adjusted.
- document.getElementById("enterFullScreenItem").hidden = enterFS;
- document.getElementById("exitFullScreenItem").hidden = !enterFS;
- }
-
- if (!this._fullScrToggler) {
- this._fullScrToggler = document.getElementById("fullscr-toggler");
- this._fullScrToggler.addEventListener("mouseover", this._expandCallback, false);
- this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false);
- this._fullScrToggler.addEventListener("touchmove", this._expandCallback, {passive: true});
- }
-
- if (enterFS) {
- gNavToolbox.setAttribute("inFullscreen", true);
- document.documentElement.setAttribute("inFullscreen", true);
- if (!document.fullscreenElement && this.useLionFullScreen)
- document.documentElement.setAttribute("OSXLionFullscreen", true);
- } else {
- gNavToolbox.removeAttribute("inFullscreen");
- document.documentElement.removeAttribute("inFullscreen");
- document.documentElement.removeAttribute("OSXLionFullscreen");
- }
-
- if (!document.fullscreenElement)
- this._updateToolbars(enterFS);
-
- if (enterFS) {
- document.addEventListener("keypress", this._keyToggleCallback, false);
- document.addEventListener("popupshown", this._setPopupOpen, false);
- document.addEventListener("popuphidden", this._setPopupOpen, false);
- // In DOM fullscreen mode, we hide toolbars with CSS
- if (!document.fullscreenElement)
- this.hideNavToolbox(true);
- }
- else {
- this.showNavToolbox(false);
- // This is needed if they use the context menu to quit fullscreen
- this._isPopupOpen = false;
- this.cleanup();
- // In TabsInTitlebar._update(), we cancel the appearance update on
- // resize event for exiting fullscreen, since that happens before we
- // change the UI here in the "fullscreen" event. Hence we need to
- // call it here to ensure the appearance is properly updated. See
- // TabsInTitlebar._update() and bug 1173768.
- TabsInTitlebar.updateAppearance(true);
- }
-
- if (enterFS && !document.fullscreenElement) {
- Services.telemetry.getHistogramById("FX_BROWSER_FULLSCREEN_USED")
- .add(1);
- }
- },
-
- exitDomFullScreen : function() {
- document.exitFullscreen();
- },
-
- handleEvent: function (event) {
- switch (event.type) {
- case "fullscreen":
- this.toggle();
- break;
- case "MozDOMFullscreen:Entered": {
- // The event target is the element which requested the DOM
- // fullscreen. If we were entering DOM fullscreen for a remote
- // browser, the target would be `gBrowser` and the original
- // target would be the browser which was the parameter of
- // `remoteFrameFullscreenChanged` call. If the fullscreen
- // request was initiated from an in-process browser, we need
- // to get its corresponding browser here.
- let browser;
- if (event.target == gBrowser) {
- browser = event.originalTarget;
- } else {
- let topWin = event.target.ownerGlobal.top;
- browser = gBrowser.getBrowserForContentWindow(topWin);
- }
- TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
- this.enterDomFullscreen(browser);
- break;
- }
- case "MozDOMFullscreen:Exited":
- TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
- this.cleanupDomFullscreen();
- break;
- }
- },
-
- receiveMessage: function(aMessage) {
- let browser = aMessage.target;
- switch (aMessage.name) {
- case "DOMFullscreen:Request": {
- this._windowUtils.remoteFrameFullscreenChanged(browser);
- break;
- }
- case "DOMFullscreen:NewOrigin": {
- // Don't show the warning if we've already exited fullscreen.
- if (document.fullscreen) {
- PointerlockFsWarning.showFullScreen(aMessage.data.originNoSuffix);
- }
- break;
- }
- case "DOMFullscreen:Exit": {
- this._windowUtils.remoteFrameFullscreenReverted();
- break;
- }
- case "DOMFullscreen:Painted": {
- Services.obs.notifyObservers(window, "fullscreen-painted", "");
- TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
- break;
- }
- }
- },
-
- enterDomFullscreen : function(aBrowser) {
-
- if (!document.fullscreenElement) {
- return;
- }
-
- // If we have a current pointerlock warning shown then hide it
- // before transition.
- PointerlockFsWarning.close();
-
- // If it is a remote browser, send a message to ask the content
- // to enter fullscreen state. We don't need to do so if it is an
- // in-process browser, since all related document should have
- // entered fullscreen state at this point.
- // This should be done before the active tab check below to ensure
- // that the content document handles the pending request. Doing so
- // before the check is fine since we also check the activeness of
- // the requesting document in content-side handling code.
- if (this._isRemoteBrowser(aBrowser)) {
- aBrowser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
- }
-
- // If we've received a fullscreen notification, we have to ensure that the
- // element that's requesting fullscreen belongs to the browser that's currently
- // active. If not, we exit fullscreen since the "full-screen document" isn't
- // actually visible now.
- if (!aBrowser || gBrowser.selectedBrowser != aBrowser ||
- // The top-level window has lost focus since the request to enter
- // full-screen was made. Cancel full-screen.
- Services.focus.activeWindow != window) {
- // This function is called synchronously in fullscreen change, so
- // we have to avoid calling exitFullscreen synchronously here.
- setTimeout(() => document.exitFullscreen(), 0);
- return;
- }
-
- document.documentElement.setAttribute("inDOMFullscreen", true);
-
- if (gFindBarInitialized) {
- gFindBar.close(true);
- }
-
- // Exit DOM full-screen mode upon open, close, or change tab.
- gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
- gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen);
- gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen);
-
- // Add listener to detect when the fullscreen window is re-focused.
- // If a fullscreen window loses focus, we show a warning when the
- // fullscreen window is refocused.
- window.addEventListener("activate", this);
- },
-
- cleanup: function () {
- if (!window.fullScreen) {
- MousePosTracker.removeListener(this);
- document.removeEventListener("keypress", this._keyToggleCallback, false);
- document.removeEventListener("popupshown", this._setPopupOpen, false);
- document.removeEventListener("popuphidden", this._setPopupOpen, false);
- }
- },
-
- cleanupDomFullscreen: function () {
- window.messageManager
- .broadcastAsyncMessage("DOMFullscreen:CleanUp");
-
- PointerlockFsWarning.close();
- gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
- gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
- gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
- window.removeEventListener("activate", this);
-
- document.documentElement.removeAttribute("inDOMFullscreen");
- },
-
- _isRemoteBrowser: function (aBrowser) {
- return gMultiProcessBrowser && aBrowser.getAttribute("remote") == "true";
- },
-
- get _windowUtils() {
- return window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils);
- },
-
- getMouseTargetRect: function()
- {
- return this._mouseTargetRect;
- },
-
- // Event callbacks
- _expandCallback: function()
- {
- FullScreen.showNavToolbox();
- },
- onMouseEnter: function()
- {
- FullScreen.hideNavToolbox();
- },
- _keyToggleCallback: function(aEvent)
- {
- // if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we
- // should provide a way to collapse them too.
- if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
- FullScreen.hideNavToolbox();
- }
- // F6 is another shortcut to the address bar, but its not covered in OpenLocation()
- else if (aEvent.keyCode == aEvent.DOM_VK_F6)
- FullScreen.showNavToolbox();
- },
-
- // Checks whether we are allowed to collapse the chrome
- _isPopupOpen: false,
- _isChromeCollapsed: false,
- _safeToCollapse: function () {
- if (!gPrefService.getBoolPref("browser.fullscreen.autohide"))
- return false;
-
- // a popup menu is open in chrome: don't collapse chrome
- if (this._isPopupOpen)
- return false;
-
- // On OS X Lion we don't want to hide toolbars.
- if (this.useLionFullScreen)
- return false;
-
- // a textbox in chrome is focused (location bar anyone?): don't collapse chrome
- if (document.commandDispatcher.focusedElement &&
- document.commandDispatcher.focusedElement.ownerDocument == document &&
- document.commandDispatcher.focusedElement.localName == "input") {
- return false;
- }
-
- return true;
- },
-
- _setPopupOpen: function(aEvent)
- {
- // Popups should only veto chrome collapsing if they were opened when the chrome was not collapsed.
- // Otherwise, they would not affect chrome and the user would expect the chrome to go away.
- // e.g. we wouldn't want the autoscroll icon firing this event, so when the user
- // toggles chrome when moving mouse to the top, it doesn't go away again.
- if (aEvent.type == "popupshown" && !FullScreen._isChromeCollapsed &&
- aEvent.target.localName != "tooltip" && aEvent.target.localName != "window")
- FullScreen._isPopupOpen = true;
- else if (aEvent.type == "popuphidden" && aEvent.target.localName != "tooltip" &&
- aEvent.target.localName != "window") {
- FullScreen._isPopupOpen = false;
- // Try again to hide toolbar when we close the popup.
- FullScreen.hideNavToolbox(true);
- }
- },
-
- // Autohide helpers for the context menu item
- getAutohide: function(aItem)
- {
- aItem.setAttribute("checked", gPrefService.getBoolPref("browser.fullscreen.autohide"));
- },
- setAutohide: function()
- {
- gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide"));
- // Try again to hide toolbar when we change the pref.
- FullScreen.hideNavToolbox(true);
- },
-
- showNavToolbox: function(trackMouse = true) {
- this._fullScrToggler.hidden = true;
- gNavToolbox.removeAttribute("fullscreenShouldAnimate");
- gNavToolbox.style.marginTop = "";
-
- if (!this._isChromeCollapsed) {
- return;
- }
-
- // Track whether mouse is near the toolbox
- if (trackMouse && !this.useLionFullScreen) {
- let rect = gBrowser.mPanelContainer.getBoundingClientRect();
- this._mouseTargetRect = {
- top: rect.top + 50,
- bottom: rect.bottom,
- left: rect.left,
- right: rect.right
- };
- MousePosTracker.addListener(this);
- }
-
- this._isChromeCollapsed = false;
- },
-
- hideNavToolbox: function (aAnimate = false) {
- if (this._isChromeCollapsed || !this._safeToCollapse())
- return;
-
- this._fullScrToggler.hidden = false;
-
- if (aAnimate && gPrefService.getBoolPref("browser.fullscreen.animate")) {
- gNavToolbox.setAttribute("fullscreenShouldAnimate", true);
- // Hide the fullscreen toggler until the transition ends.
- let listener = () => {
- gNavToolbox.removeEventListener("transitionend", listener, true);
- if (this._isChromeCollapsed)
- this._fullScrToggler.hidden = false;
- };
- gNavToolbox.addEventListener("transitionend", listener, true);
- this._fullScrToggler.hidden = true;
- }
-
- gNavToolbox.style.marginTop =
- -gNavToolbox.getBoundingClientRect().height + "px";
- this._isChromeCollapsed = true;
- MousePosTracker.removeListener(this);
- },
-
- _updateToolbars: function (aEnterFS) {
- for (let el of document.querySelectorAll("toolbar[fullscreentoolbar=true]")) {
- if (aEnterFS) {
- // Give the main nav bar and the tab bar the fullscreen context menu,
- // otherwise remove context menu to prevent breakage
- el.setAttribute("saved-context", el.getAttribute("context"));
- if (el.id == "nav-bar" || el.id == "TabsToolbar")
- el.setAttribute("context", "autohide-context");
- else
- el.removeAttribute("context");
-
- // Set the inFullscreen attribute to allow specific styling
- // in fullscreen mode
- el.setAttribute("inFullscreen", true);
- } else {
- if (el.hasAttribute("saved-context")) {
- el.setAttribute("context", el.getAttribute("saved-context"));
- el.removeAttribute("saved-context");
- }
- el.removeAttribute("inFullscreen");
- }
- }
-
- ToolbarIconColor.inferFromText();
-
- // For Lion fullscreen, all fullscreen controls are hidden, don't
- // bother to touch them. If we don't stop here, the following code
- // could cause the native fullscreen button be shown unexpectedly.
- // See bug 1165570.
- if (this.useLionFullScreen) {
- return;
- }
-
- var fullscreenctls = document.getElementById("window-controls");
- var navbar = document.getElementById("nav-bar");
- var ctlsOnTabbar = window.toolbar.visible;
- if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) {
- fullscreenctls.removeAttribute("flex");
- document.getElementById("TabsToolbar").appendChild(fullscreenctls);
- }
- else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) {
- fullscreenctls.setAttribute("flex", "1");
- navbar.appendChild(fullscreenctls);
- }
- fullscreenctls.hidden = !aEnterFS;
- }
-};
-XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() {
- // We'll only use OS X Lion full screen if we're
- // * on OS X
- // * on Lion or higher (Darwin 11+)
- // * have fullscreenbutton="true"
- return AppConstants.isPlatformAndVersionAtLeast("macosx", 11) &&
- document.documentElement.getAttribute("fullscreenbutton") == "true";
-});