Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
223 lines
7.3 KiB
JavaScript
223 lines
7.3 KiB
JavaScript
/* global Service, AttentionWindow */
|
|
'use strict';
|
|
|
|
(function(exports) {
|
|
/**
|
|
* LayoutManager gathers all external events which would affect
|
|
* the layout of the windows and redirect the event to AppWindowManager.
|
|
*
|
|
*
|
|
* The height of the windows would be affected by some global factor:
|
|
*
|
|
*
|
|
* * The height of Statusbar.
|
|
* * The existence of Software Home Button.
|
|
* * The existence of Keyboard.
|
|
*
|
|
*
|
|
* When the size state of one of them is changed, LayoutManager
|
|
* would send <code>system-resize</code> event.
|
|
*
|
|
* 
|
|
*
|
|
* @class LayoutManager
|
|
* @requires SoftwareButtonManager
|
|
* @requires Service
|
|
*/
|
|
var LayoutManager = function LayoutManager() {};
|
|
|
|
LayoutManager.prototype = {
|
|
DEBUG: false,
|
|
CLASS_NAME: 'LayoutManager',
|
|
name: 'LayoutManager',
|
|
/** @lends LayoutManager */
|
|
|
|
get clientWidth() {
|
|
if (this._clientWidth) {
|
|
return this._clientWidth;
|
|
}
|
|
|
|
this._clientWidth = document.documentElement.clientWidth;
|
|
return this._clientWidth;
|
|
},
|
|
|
|
/**
|
|
* Gives the possible height for a window.
|
|
*
|
|
* @memberOf LayoutManager
|
|
*/
|
|
height: function() {
|
|
var activeApp = Service.query('getTopMostWindow');
|
|
var isFullScreenLayout = activeApp && activeApp.isFullScreenLayout();
|
|
var softwareButtonHeight = Service.query('locked') || isFullScreenLayout ?
|
|
0 : (Service.query('SoftwareButtonManager.height') || 0);
|
|
var keyboardHeight = this.keyboardEnabled ?
|
|
(Service.query('InputWindowManager.getHeight') || 0) : 0;
|
|
var height = window.innerHeight - keyboardHeight - softwareButtonHeight;
|
|
|
|
// Normalizing the height so that it always translates to an integral
|
|
// number of device pixels
|
|
var dpx = window.devicePixelRatio;
|
|
if ((height * dpx) % 1 !== 0) {
|
|
height = Math.ceil(height * dpx) / dpx;
|
|
}
|
|
|
|
return height;
|
|
},
|
|
|
|
/**
|
|
* Gives the possible width for a normal window.
|
|
*
|
|
* @memberOf LayoutManager
|
|
*/
|
|
width: function() {
|
|
return window.innerWidth -
|
|
((Service.query('getTopMostWindow') &&
|
|
Service.query('getTopMostWindow').isFullScreenLayout()) ?
|
|
0 : (Service.query('SoftwareButtonManager.width') || 0));
|
|
},
|
|
|
|
getHeightFor: function(currentWindow, ignoreKeyboard) {
|
|
if (currentWindow instanceof AttentionWindow) {
|
|
var keyboardHeight = this.keyboardEnabled && !ignoreKeyboard ?
|
|
(Service.query('InputWindowManager.getHeight') || 0) : 0;
|
|
var height = window.innerHeight - keyboardHeight -
|
|
(Service.query('SoftwareButtonManager.height') || 0);
|
|
|
|
// Normalizing the height so that it always translates to an integral
|
|
// number of device pixels
|
|
var dpx = window.devicePixelRatio;
|
|
if ((height * dpx) % 1 !== 0) {
|
|
height = Math.ceil(height * dpx) / dpx;
|
|
}
|
|
|
|
return height;
|
|
}
|
|
if (ignoreKeyboard) {
|
|
return this.height() +
|
|
(Service.query('InputWindowManager.getHeight') || 0);
|
|
} else {
|
|
return this.height();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Match the given size with current layout.
|
|
* @param {Number} width The matched width.
|
|
* @param {Number} height The matched height.
|
|
* @return {Boolean} Matches current layout or not.
|
|
*
|
|
* @memberOf LayoutManager
|
|
*/
|
|
match: function lm_match(width, height) {
|
|
return (this.width() === width && this.height() === height);
|
|
},
|
|
|
|
/**
|
|
* Record the keyboard is enabled now or not.
|
|
* @type {Boolean}
|
|
* @memberOf LayoutManager
|
|
*/
|
|
keyboardEnabled: false,
|
|
|
|
/**
|
|
* The orientation we keep each time we encounter resize event.
|
|
* @type {String}
|
|
* @memberOf LayoutManager
|
|
*/
|
|
_lastOrientation: undefined,
|
|
|
|
/**
|
|
* Startup. Adds all event listeners needed.
|
|
* @return {LayoutManager} this object
|
|
* @memberOf LayoutManager
|
|
*/
|
|
start: function lm_start() {
|
|
window.addEventListener('resize', this);
|
|
window.addEventListener('keyboardchange', this);
|
|
window.addEventListener('keyboardhide', this);
|
|
window.addEventListener('mozfullscreenchange', this);
|
|
window.addEventListener('software-button-enabled', this);
|
|
window.addEventListener('software-button-disabled', this);
|
|
window.addEventListener('attentionwindowmanager-deactivated', this);
|
|
window.addEventListener('lockscreen-appclosed', this);
|
|
|
|
this._lastOrientation = screen.mozOrientation;
|
|
Service.registerState('getHeightFor', this);
|
|
Service.registerState('width', this);
|
|
Service.registerState('height', this);
|
|
Service.registerState('keyboardEnabled', this);
|
|
Service.registerState('match', this);
|
|
},
|
|
|
|
handleEvent: function lm_handleEvent(evt) {
|
|
this.debug('resize event got: ', evt.type);
|
|
|
|
// The instance should be available on the evt.detail of
|
|
// the system-resize event. Additionally, if the original event caused
|
|
// the resize has a waitUntil() function, we would need the user of the
|
|
// system-resize event to have access to that too.
|
|
var systemResizeEventDetail = Object.create(this);
|
|
if (evt.detail && typeof evt.detail.waitUntil === 'function') {
|
|
systemResizeEventDetail.waitUntil = function(p) {
|
|
return evt.detail.waitUntil(p);
|
|
};
|
|
}
|
|
|
|
switch (evt.type) {
|
|
case 'keyboardchange':
|
|
if (document.mozFullScreen) {
|
|
document.mozCancelFullScreen();
|
|
}
|
|
this.keyboardEnabled = true;
|
|
/**
|
|
* Fired when layout needs to be adjusted.
|
|
* @event LayoutManager#system-resize
|
|
*/
|
|
this.publish('system-resize', systemResizeEventDetail);
|
|
break;
|
|
case 'resize':
|
|
// bug 1073806: do not publish |system-resize| if keyboard is showing
|
|
// and we've just changed orientation: |keyboardchange| will trigger
|
|
// later and we'll resize then.
|
|
if (!(screen.mozOrientation !== this._lastOrientation &&
|
|
this.keyboardEnabled)) {
|
|
this.publish('system-resize', systemResizeEventDetail);
|
|
}
|
|
this.publish('appwindow-orientationchange');
|
|
this._lastOrientation = screen.mozOrientation;
|
|
break;
|
|
case 'lockscreen-appclosed':
|
|
// If the software button is enabled it will be un-hidden when
|
|
// the lockscreen is closed and trigger a system level resize.
|
|
if (Service.query('SoftwareButtonManager.enabled')) {
|
|
this.publish('system-resize', systemResizeEventDetail);
|
|
}
|
|
break;
|
|
default:
|
|
if (evt.type === 'keyboardhide') {
|
|
this.keyboardEnabled = false;
|
|
}
|
|
this.publish('system-resize', systemResizeEventDetail);
|
|
break;
|
|
}
|
|
},
|
|
|
|
publish: function lm_publish(event, detail) {
|
|
var evt = document.createEvent('CustomEvent');
|
|
evt.initCustomEvent(event, true, false, detail || this);
|
|
|
|
this.debug('publish: ' + event);
|
|
window.dispatchEvent(evt);
|
|
},
|
|
|
|
debug: function lm_debug() {
|
|
if (this.DEBUG) {
|
|
console.log('[' + this.CLASS_NAME + ']' +
|
|
'[' + Service.currentTime() + '] ' +
|
|
Array.slice(arguments).concat());
|
|
}
|
|
}
|
|
};
|
|
exports.LayoutManager = LayoutManager;
|
|
}(window));
|