Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
366 lines
13 KiB
JavaScript
Executable file
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));
|