mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
400 lines
10 KiB
JavaScript
400 lines
10 KiB
JavaScript
/* 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/. */
|
|
|
|
// Fired when the tabtray is displayed
|
|
const kContextUITabsShowEvent = "MozContextUITabsShow";
|
|
// add more as needed...
|
|
|
|
/*
|
|
* Manages context UI (navbar, tabbar, appbar) and track visibility. Also
|
|
* tracks events that summon and hide the context UI.
|
|
*/
|
|
var ContextUI = {
|
|
_expandable: true,
|
|
_hidingId: 0,
|
|
|
|
/*******************************************
|
|
* init
|
|
*/
|
|
|
|
init: function init() {
|
|
Elements.browsers.addEventListener('URLChanged', this, true);
|
|
Elements.browsers.addEventListener("AlertActive", this, true);
|
|
Elements.browsers.addEventListener("AlertClose", this, true);
|
|
Elements.tabList.addEventListener('TabSelect', this, true);
|
|
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
|
|
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
|
|
|
|
Elements.tray.addEventListener("mousemove", this, false);
|
|
Elements.tray.addEventListener("mouseleave", this, false);
|
|
|
|
window.addEventListener("touchstart", this, true);
|
|
window.addEventListener("mousedown", this, true);
|
|
window.addEventListener("MozEdgeUIStarted", this, true);
|
|
window.addEventListener("MozEdgeUICanceled", this, true);
|
|
window.addEventListener("MozEdgeUICompleted", this, true);
|
|
window.addEventListener("keypress", this, true);
|
|
window.addEventListener("KeyboardChanged", this, false);
|
|
window.addEventListener("MozFlyoutPanelShowing", this, false);
|
|
|
|
Elements.tray.addEventListener("transitionend", this, true);
|
|
|
|
Appbar.init();
|
|
},
|
|
|
|
/*******************************************
|
|
* Context UI state getters & setters
|
|
*/
|
|
|
|
// any visiblilty
|
|
get isVisible() {
|
|
return this.navbarVisible || this.tabbarVisible || this.contextAppbarVisible;
|
|
},
|
|
|
|
// navbar visiblilty
|
|
get navbarVisible() {
|
|
return (Elements.navbar.hasAttribute("visible") ||
|
|
Elements.navbar.hasAttribute("startpage"));
|
|
},
|
|
|
|
// tabbar visiblilty
|
|
get tabbarVisible() {
|
|
return Elements.tray.hasAttribute("expanded");
|
|
},
|
|
|
|
// appbar visiblilty
|
|
get contextAppbarVisible() {
|
|
return Elements.contextappbar.isShowing;
|
|
},
|
|
|
|
// currently not in use, for the always show tabs feature
|
|
get isExpandable() { return this._expandable; },
|
|
set isExpandable(aFlag) {
|
|
this._expandable = aFlag;
|
|
if (!this._expandable)
|
|
this.dismiss();
|
|
},
|
|
|
|
/*******************************************
|
|
* Public api
|
|
*/
|
|
|
|
/*
|
|
* Toggle the current nav UI state. Fires context ui events.
|
|
*/
|
|
toggleNavUI: function () {
|
|
// The navbar is forced open when the start page is visible. appbar.js
|
|
// controls the "visible" property, and browser-ui controls the "startpage"
|
|
// property. Hence we rely on the tabbar for current toggle state.
|
|
if (this.tabbarVisible) {
|
|
this.dismiss();
|
|
} else {
|
|
this.displayNavUI();
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Show the nav and tabs bar. Returns true if any non-visible UI
|
|
* was shown. Fires context ui events.
|
|
*/
|
|
displayNavUI: function () {
|
|
let shown = false;
|
|
|
|
if (!this.navbarVisible) {
|
|
BrowserUI.updateURI();
|
|
this.displayNavbar();
|
|
shown = true;
|
|
}
|
|
|
|
if (!this.tabbarVisible) {
|
|
this.displayTabs();
|
|
shown = true;
|
|
}
|
|
|
|
if (shown) {
|
|
ContentAreaObserver.updateContentArea();
|
|
}
|
|
|
|
return shown;
|
|
},
|
|
|
|
/*
|
|
* Dismiss any context UI currently visible. Returns true if any
|
|
* visible UI was dismissed. Fires context ui events.
|
|
*/
|
|
dismiss: function () {
|
|
let dismissed = false;
|
|
|
|
this._clearDelayedTimeout();
|
|
|
|
// No assurances this will hide the nav bar. It may have the
|
|
// 'startpage' property set. This removes the 'visible' property.
|
|
if (this.navbarVisible) {
|
|
BrowserUI.blurNavBar();
|
|
this.dismissNavbar();
|
|
dismissed = true;
|
|
}
|
|
if (this.tabbarVisible) {
|
|
this.dismissTabs();
|
|
dismissed = true;
|
|
}
|
|
if (Elements.contextappbar.isShowing) {
|
|
this.dismissContextAppbar();
|
|
dismissed = true;
|
|
}
|
|
|
|
if (dismissed) {
|
|
ContentAreaObserver.updateContentArea();
|
|
}
|
|
|
|
return dismissed;
|
|
},
|
|
|
|
/*
|
|
* Briefly show the tab bar and then hide it. Fires context ui events.
|
|
*/
|
|
peekTabs: function peekTabs(aDelay) {
|
|
if (!this.tabbarVisible)
|
|
this.displayTabs();
|
|
|
|
ContextUI.dismissTabsWithDelay(aDelay);
|
|
},
|
|
|
|
/*
|
|
* Dismiss tab bar after a delay. Fires context ui events.
|
|
*/
|
|
dismissTabsWithDelay: function (aDelay) {
|
|
aDelay = aDelay || kForegroundTabAnimationDelay;
|
|
this._clearDelayedTimeout();
|
|
this._lastTimeoutDelay = aDelay;
|
|
this._hidingId = setTimeout(function () {
|
|
ContextUI.dismissTabs();
|
|
}, aDelay);
|
|
},
|
|
|
|
/*
|
|
* Display the nav bar.
|
|
*
|
|
* @return false if we were already visible, and didn't do anything.
|
|
*/
|
|
displayNavbar: function () {
|
|
if (Elements.chromeState.getAttribute("navbar") == "visible") {
|
|
return false;
|
|
}
|
|
|
|
Elements.navbar.show();
|
|
Elements.chromeState.setAttribute("navbar", "visible");
|
|
ContentAreaObserver.updateContentArea();
|
|
return true;
|
|
},
|
|
|
|
// Display the tab tray
|
|
displayTabs: function () {
|
|
this._clearDelayedTimeout();
|
|
this._setIsExpanded(true);
|
|
},
|
|
|
|
// Dismiss the navbar if visible.
|
|
dismissNavbar: function dismissNavbar() {
|
|
if (!BrowserUI.isStartTabVisible) {
|
|
Elements.autocomplete.closePopup();
|
|
Elements.navbar.dismiss();
|
|
Elements.chromeState.removeAttribute("navbar");
|
|
ContentAreaObserver.updateContentArea();
|
|
}
|
|
},
|
|
|
|
// Dismiss the tabstray if visible.
|
|
dismissTabs: function dimissTabs() {
|
|
this._clearDelayedTimeout();
|
|
this._setIsExpanded(false);
|
|
},
|
|
|
|
// Dismiss the appbar if visible.
|
|
dismissContextAppbar: function dismissContextAppbar() {
|
|
Elements.contextappbar.dismiss();
|
|
},
|
|
|
|
/*******************************************
|
|
* Internal utils
|
|
*/
|
|
|
|
// tabtray state
|
|
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
|
|
// if the tray can't be expanded, don't expand it.
|
|
if (!this.isExpandable || this.tabbarVisible == aFlag)
|
|
return;
|
|
|
|
if (aFlag)
|
|
Elements.tray.setAttribute("expanded", "true");
|
|
else
|
|
Elements.tray.removeAttribute("expanded");
|
|
|
|
if (!setSilently)
|
|
this._fire(kContextUITabsShowEvent);
|
|
},
|
|
|
|
_clearDelayedTimeout: function _clearDelayedTimeout() {
|
|
if (this._hidingId) {
|
|
clearTimeout(this._hidingId);
|
|
this._hidingId = 0;
|
|
this._delayedHide = false;
|
|
}
|
|
},
|
|
|
|
_resetDelayedTimeout: function () {
|
|
this._hidingId = setTimeout(function () {
|
|
ContextUI.dismissTabs();
|
|
}, this._lastTimeoutDelay);
|
|
},
|
|
|
|
/*******************************************
|
|
* Events
|
|
*/
|
|
|
|
_onEdgeUIStarted: function(aEvent) {
|
|
this._hasEdgeSwipeStarted = true;
|
|
this._clearDelayedTimeout();
|
|
this.toggleNavUI();
|
|
},
|
|
|
|
_onEdgeUICanceled: function(aEvent) {
|
|
this._hasEdgeSwipeStarted = false;
|
|
this.dismiss();
|
|
},
|
|
|
|
_onEdgeUICompleted: function(aEvent) {
|
|
if (this._hasEdgeSwipeStarted) {
|
|
this._hasEdgeSwipeStarted = false;
|
|
return;
|
|
}
|
|
|
|
this._clearDelayedTimeout();
|
|
this.toggleNavUI();
|
|
},
|
|
|
|
onDownInput: function onDownInput(aEvent) {
|
|
if (!this.isVisible) {
|
|
return;
|
|
}
|
|
|
|
// Various ui element containers we do not update context ui for.
|
|
let whitelist = [
|
|
// Clicks on tab bar elements should not close the tab bar. the tabbar
|
|
// handles this.
|
|
Elements.tabs,
|
|
// Don't let a click on an infobar button dismiss the appbar or navbar.
|
|
// Note the notification box should always hover above these other two
|
|
// bars.
|
|
Browser.getNotificationBox()
|
|
];
|
|
|
|
if (whitelist.some(elem => elem.contains(aEvent.target))) {
|
|
return;
|
|
}
|
|
|
|
// If a start tab is visible only dismiss the tab bar.
|
|
if (BrowserUI.isStartTabVisible) {
|
|
ContextUI.dismissTabs();
|
|
return;
|
|
}
|
|
|
|
// content, dismiss anything visible
|
|
if (aEvent.target.ownerDocument.defaultView.top == getBrowser().contentWindow) {
|
|
this.dismiss();
|
|
return;
|
|
}
|
|
|
|
// dismiss tabs and context app bar if visible
|
|
this.dismissTabs();
|
|
this.dismissContextAppbar();
|
|
},
|
|
|
|
onMouseMove: function (aEvent) {
|
|
if (this._hidingId) {
|
|
this._clearDelayedTimeout();
|
|
this._delayedHide = true;
|
|
}
|
|
},
|
|
|
|
onMouseLeave: function (aEvent) {
|
|
if (this._delayedHide) {
|
|
this._delayedHide = false;
|
|
this._resetDelayedTimeout();
|
|
}
|
|
},
|
|
|
|
handleEvent: function handleEvent(aEvent) {
|
|
switch (aEvent.type) {
|
|
case "URLChanged":
|
|
// "aEvent.detail" is a boolean value that indicates whether actual URL
|
|
// has changed ignoring URL fragment changes.
|
|
if (aEvent.target == Browser.selectedBrowser && aEvent.detail) {
|
|
this.displayNavbar();
|
|
}
|
|
break;
|
|
case "MozEdgeUIStarted":
|
|
this._onEdgeUIStarted(aEvent);
|
|
break;
|
|
case "MozEdgeUICanceled":
|
|
this._onEdgeUICanceled(aEvent);
|
|
break;
|
|
case "MozEdgeUICompleted":
|
|
this._onEdgeUICompleted(aEvent);
|
|
break;
|
|
case "keypress":
|
|
if (String.fromCharCode(aEvent.which) == "z" &&
|
|
aEvent.getModifierState("Win"))
|
|
this.toggleNavUI();
|
|
break;
|
|
case "transitionend":
|
|
setTimeout(function () {
|
|
ContentAreaObserver.updateContentArea();
|
|
}, 0);
|
|
break;
|
|
case "KeyboardChanged":
|
|
this.dismissTabs();
|
|
break;
|
|
case "mousedown":
|
|
if (aEvent.button != 0) {
|
|
break;
|
|
}
|
|
this.onDownInput(aEvent);
|
|
break;
|
|
case "mousemove":
|
|
this.onMouseMove(aEvent);
|
|
break;
|
|
case "mouseleave":
|
|
this.onMouseLeave(aEvent);
|
|
break;
|
|
case "touchstart":
|
|
this.onDownInput(aEvent);
|
|
break;
|
|
case "ToolPanelShown":
|
|
case "ToolPanelHidden":
|
|
this.dismiss();
|
|
break;
|
|
case "AlertActive":
|
|
case "AlertClose":
|
|
case "TabSelect":
|
|
ContentAreaObserver.updateContentArea();
|
|
break;
|
|
case "MozFlyoutPanelShowing":
|
|
if (BrowserUI.isStartTabVisible) {
|
|
this.dismissTabs();
|
|
this.dismissContextAppbar();
|
|
} else {
|
|
this.dismiss();
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
_fire: function (name) {
|
|
let event = document.createEvent("Events");
|
|
event.initEvent(name, true, true);
|
|
window.dispatchEvent(event);
|
|
}
|
|
};
|