VulpesOS/gaia/tv_apps/smart-system/js/homescreen_window_manager.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

366 lines
13 KiB
JavaScript
Executable file

/* global homescreenLauncher, Service, FtuLauncher, LandingAppLauncher,
AppWindowManager, focusManager */
'use strict';
(function(exports) {
/**
* HomescreenWindowManager manages the show/hide of HomescreenWindow,
* HomescreenLauncher instances, LandingAppWindow and LandingAppLauncher.
*
* @class HomescreenWindowManager
* @requires HomescreenLauncher
* @requires LandingAppLauncher
* @requires Service
*/
function HomescreenWindowManager() {}
HomescreenWindowManager.prototype = {
DEBUG: false,
_ftuDone: false,
_activityCount: 0,
CLASS_NAME: 'HomescreenWindowManager',
/**
* Homescreen Window Manager depends on the ready state of homescreen
* launcher. It is ready only when all of the homescreen launchers are
* ready.
*
* @access public
* @memberOf HomescreenWindowManager.prototype
* @type {boolean}
*/
get ready() {
return homescreenLauncher.ready && this.landingAppLauncher &&
this.landingAppLauncher.ready;
},
debug: function hwm_debug() {
if (this.DEBUG) {
console.log('[' + this.CLASS_NAME + ']' +
'[' + Service.currentTime() + ']' +
Array.slice(arguments).concat());
}
},
/**
* HomescreenWindowManager starts to listen the event it cares.
*
* @memberOf HomescreenWindowManager.prototype
*/
start: function hwm_start() {
this.landingAppLauncher = new LandingAppLauncher();
this.landingAppLauncher.start();
window.addEventListener('appswitching', this);
window.addEventListener('ftuskip', this);
window.addEventListener('open-app', this);
window.addEventListener('webapps-launch', this);
window.addEventListener('appopened', this);
window.addEventListener('appterminated', this);
window.addEventListener('activityopened', this);
window.addEventListener('homescreenopened', this);
window.addEventListener('homescreenclosed', this);
window.addEventListener('home', this);
window.addEventListener('launchapp', this);
// The removal of the followings will be at the ready event.
window.addEventListener('homescreen-ready', this);
window.addEventListener('landing-app-ready', this);
},
/**
* HomescreenWindowManager stop to listen the event it cares.
*
* @memberOf HomescreenWindowManager.prototype
*/
stop: function hwm_stop() {
this.landingAppLauncher.stop();
window.removeEventListener('appswitching', this);
window.removeEventListener('ftuskip', this);
window.removeEventListener('open-app', this);
window.removeEventListener('webapps-launch', this);
window.removeEventListener('appopened', this);
window.removeEventListener('appterminated', this);
window.removeEventListener('activityopened', this);
window.removeEventListener('homescreenopened', this);
window.removeEventListener('launchapp', this);
window.removeEventListener('home', this);
},
handleEvent: function hwm_handleEvent(evt) {
var detail;
switch(evt.type) {
case 'appswitching':
this.getHomescreen().showFadeOverlay();
this.getHomescreen().fadeOut();
break;
case 'ftuskip':
this._ftuSkipped = true;
if (this.ready) {
this.getHomescreen().setVisible(true);
}
break;
case 'open-app':
case 'webapps-launch':
detail = evt.detail;
if (detail.manifestURL === homescreenLauncher.manifestURL ||
detail.manifestURL === this.landingAppLauncher.manifestURL) {
this.launchHomescreen(evt, detail.manifestURL);
evt.stopPropagation();
evt.stopImmediatePropagation();
evt.preventDefault();
}
break;
case 'appopened':
detail = evt.detail;
if (detail.manifestURL === FtuLauncher.getFtuManifestURL()) {
// we don't need to set activeHome as anything if it is ftu.
break;
} else if (detail.isHomescreen) {
this._activeHome = ('LandingAppWindow' === detail.CLASS_NAME) ?
this.landingAppLauncher : homescreenLauncher;
} else if (detail.manifest && detail.manifest.role === 'search') {
// XXX: Bug 1124112 - Seamlessly launch search app from home
// We have to ensure that the search app is fully rendered before
// closing the home app so defer it by "setTimeout".
setTimeout(this.closeHomeApp.bind(this));
} else {
this.closeHomeApp();
}
break;
case 'appterminated':
if (this._underlayApp &&
evt.detail.manifestURL === this._underlayApp.manifestURL) {
this._underlayApp = null;
}
break;
case 'homescreenclosed':
if (this._underlayApp) {
// If we have _underlayApp but another app is launching, we need to
// close the _underlayApp.
if (this._underlayApp.manifestURL ===
AppWindowManager.getActiveApp().manifestURL) {
this.publish('homescreen-underlayopened', this._underlayApp);
focusManager.focus();
} else {
this._underlayApp.close('immediate');
}
this._underlayApp = null;
}
break;
case 'launchapp':
if (this._underlayApp &&
evt.detail.manifestURL === this._underlayApp.manifestURL &&
!evt.detail.stayBackground) {
// The 'appopened' event will not be fired in this case because this
// app is already opened. AppWindowManager will change the active
// app to the opening app and trying to close homescreen app through
// launchapp event. AppTransitionController may find the app is
// already opened. So, it doesn't dispatch appopened and focus the
// appWindow.
//
// In this case, HomescreenWindowManager will not close and reset
// _activeHome. We should call closeHomeApp to reset the variable
// and focus back. switchApp in app window manager will handle
// home close.
this._activeHome = null;
}
break;
case 'homescreenopened':
detail = evt.detail;
// Landing app is also a homescreen. We need to which one is opened
// and show/hide the correct homescreen
if (detail.CLASS_NAME === 'LandingAppWindow') {
this.setHomescreenVisible(homescreenLauncher, false);
this.setHomescreenVisible(this.landingAppLauncher, true);
} else if (this.landingAppLauncher.hasLandingApp) {
this.setHomescreenVisible(this.landingAppLauncher, false);
this.setHomescreenVisible(homescreenLauncher, true);
}
break;
case 'activityopened':
if (this._activeHome) {
this._activityCount++;
}
break;
case 'activityclosed':
if (this._activeHome) {
this._activityCount--;
}
break;
case 'home':
if (this._underlayApp && !this.landingAppLauncher.hasLandingApp) {
// If we don't have landing app, pressing home key should switch
// between underlayApp and homescreen.
AppWindowManager.display(this._underlayApp);
}
else {
this.showHomeApp();
}
break;
case 'landing-app-ready':
case 'homescreen-ready':
if (this.ready) {
// remove ready listener when we are ready.
window.removeEventListener('homescreen-ready', this);
window.removeEventListener('landing-app-ready', this);
this.publish('homescreenwindowmanager-ready');
// The first activeHome is landing app.
this._activeHome = this.landingAppLauncher.hasLandingApp ?
this.landingAppLauncher : homescreenLauncher;
if (this._ftuSkipped && this.landingAppLauncher.hasLandingApp) {
// If ftu skipped already got, we need to set landing app as
// visible
this.setHomescreenVisible(homescreenLauncher, false);
this.setHomescreenVisible(this.landingAppLauncher, true);
}
}
break;
}
},
closeHomeApp: function hwm_closeHomeApp(nextApp) {
if (!this._activeHome) {
return;
}
this._activeHome.getHomescreen().ensure(true);
this._activeHome.getHomescreen().setVisible(false);
this._activeHome.getHomescreen().close('immediate');
this._activeHome = null;
},
showHomeApp: function hwm_showHomeApp() {
var originApp = AppWindowManager.getActiveApp();
var homeApp = this.getHomescreen(true);
if (originApp.instanceID === homeApp.instanceID) {
// If we open an activity at home and press home, the originApp is home
// app and the next app is also home app. In this case, we don't need
// to reopen it again.
focusManager.focus();
return;
}
homeApp.ready((function() {
if (originApp.isHomescreen) {
if (this._underlayApp) {
this._underlayApp.close('immediate');
this._underlayApp = null;
}
originApp.close('immediate');
homeApp.open();
} else {
this._underlayApp = originApp;
homeApp.open();
}
}).bind(this));
},
setHomescreenVisible: function hwm_hideActiveHome(launcher, visible) {
launcher.getHomescreen().ensure(true);
// We need to show/hide fade overlay to have wallpaper shown correctly.
if (visible) {
launcher.getHomescreen().showFadeOverlay();
} else {
launcher.getHomescreen().hideFadeOverlay();
}
launcher.getHomescreen().setVisible(visible);
},
publish: function awm_publish(event, detail) {
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, true, false, detail || this);
this.debug('publish: ' + event);
window.dispatchEvent(evt);
},
launchHomescreen: function launchHomescreen(evt, manifestURL) {
if (!this.landingAppLauncher.hasLandingApp) {
// cal getHomescreen to ensure it.
this.getHomescreen();
this.publish('home');
return;
}
if (this._activeHome) {
if (this._activeHome.manifestURL !== manifestURL) {
// in homeA trying to switch to homeB
this.publish('home');
} else {
// cal getHomescreen to ensure it.
this.getHomescreen();
}
} else if (homescreenLauncher.manifestURL === manifestURL) {
// in appX trying to switch to home
this.publish('home');
} else if (this.landingAppLauncher.manifestURL === manifestURL) {
// We set the activeHome as normal home and use home event to switch to
// landing app
this._activeHome = homescreenLauncher;
this.publish('home');
}
},
handleHomeEvent: function handleHomeEvent() {
// If press home when one home app active, we need to swap the
// launcher.
if (this._activityCount > 0) {
// If we have activity on top of home, we need to ensure it to close
// all of them.
this._activeHome.getHomescreen().ensure(true);
if (this._activeHome === this.landingAppLauncher) {
this._activeHome.getHomescreen().setVisible(false);
this._activeHome.getHomescreen().close('immediate');
this._activeHome = homescreenLauncher;
}
this._activityCount = 0;
} else {
this._activeHome.getHomescreen().setVisible(false);
this._activeHome.getHomescreen().close('immediate');
// If we have activity on top of home, we always normal home
this._activeHome = this._activeHome === this.landingAppLauncher ?
homescreenLauncher : this.landingAppLauncher;
}
},
/**
* getHomescreen returns the homescreen app window based on if it is
* triggered by home event.
*
* @memberOf HomescreenWindowManager.prototype
*/
getHomescreen: function getHomescreen(isHomeEvent) {
if ((!exports.homescreenLauncher || !exports.homescreenLauncher.ready) &&
(!this.landingAppLauncher || !this.landingAppLauncher.ready)) {
return null;
}
if (this.landingAppLauncher.hasLandingApp) {
// use landing app launcher as first home launcher
if (!this._activeHome) {
// If this._activeHome is null, the active app is normal app. We need
// to show normal homescreen app.
this._activeHome = homescreenLauncher;
} else if (isHomeEvent) {
this.handleHomeEvent();
}
} else if (!this._activeHome) {
// If we don't have landing app, we need to initialize active home as
// homescreen launcher.
this._activeHome = homescreenLauncher;
}
var home = this._activeHome.getHomescreen(true);
if (isHomeEvent) {
home.ensure(true);
}
return home;
}
};
exports.HomescreenWindowManager = HomescreenWindowManager;
}(window));