2012-05-30 22:06:25 +00:00
|
|
|
// screen.js:
|
|
|
|
// Set the screen size, pixel density and scaling of the b2g client screen
|
|
|
|
// based on the --screen command-line option, if there is one.
|
|
|
|
//
|
|
|
|
// TODO: support multiple device pixels per CSS pixel
|
|
|
|
//
|
|
|
|
|
2015-09-15 18:19:45 +00:00
|
|
|
var browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
|
|
|
var isMulet = "ResponsiveUI" in browserWindow;
|
2014-12-23 23:28:54 +00:00
|
|
|
Cu.import("resource://gre/modules/GlobalSimulatorScreen.jsm");
|
2014-08-12 06:43:00 +00:00
|
|
|
|
2015-09-04 18:12:53 +00:00
|
|
|
window.addEventListener('ContentStart', onStart);
|
|
|
|
window.addEventListener('SafeModeStart', onStart);
|
|
|
|
|
|
|
|
// We do this on ContentStart and SafeModeStart because querying the
|
|
|
|
// displayDPI fails otherwise.
|
|
|
|
function onStart() {
|
2012-05-30 22:06:25 +00:00
|
|
|
// This is the toplevel <window> element
|
|
|
|
let shell = document.getElementById('shell');
|
|
|
|
|
|
|
|
// The <browser> element inside it
|
2013-08-28 21:35:34 +00:00
|
|
|
let browser = document.getElementById('systemapp');
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
// Figure out the native resolution of the screen
|
|
|
|
let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
|
|
|
let hostDPI = windowUtils.displayDPI;
|
|
|
|
|
2014-03-19 12:38:59 +00:00
|
|
|
let DEFAULT_SCREEN = '320x480';
|
2012-06-25 18:14:15 +00:00
|
|
|
|
2012-05-30 22:06:25 +00:00
|
|
|
// This is a somewhat random selection of named screens.
|
|
|
|
// Add more to this list when we support more hardware.
|
|
|
|
// Data from: http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density
|
|
|
|
let screens = {
|
|
|
|
iphone: {
|
|
|
|
name: 'Apple iPhone', width:320, height:480, dpi:163
|
|
|
|
},
|
|
|
|
ipad: {
|
|
|
|
name: 'Apple iPad', width:1024, height:768, dpi:132
|
|
|
|
},
|
|
|
|
nexus_s: {
|
|
|
|
name: 'Samsung Nexus S', width:480, height:800, dpi:235
|
|
|
|
},
|
|
|
|
galaxy_s2: {
|
|
|
|
name: 'Samsung Galaxy SII (I9100)', width:480, height:800, dpi:219
|
|
|
|
},
|
|
|
|
galaxy_nexus: {
|
|
|
|
name: 'Samsung Galaxy Nexus', width:720, height:1280, dpi:316
|
|
|
|
},
|
|
|
|
galaxy_tab: {
|
|
|
|
name: 'Samsung Galaxy Tab 10.1', width:800, height:1280, dpi:149
|
|
|
|
},
|
|
|
|
wildfire: {
|
|
|
|
name: 'HTC Wildfire', width:240, height:320, dpi:125
|
|
|
|
},
|
|
|
|
tattoo: {
|
|
|
|
name: 'HTC Tattoo', width:240, height:320, dpi:143
|
|
|
|
},
|
|
|
|
salsa: {
|
|
|
|
name: 'HTC Salsa', width:320, height:480, dpi:170
|
|
|
|
},
|
|
|
|
chacha: {
|
|
|
|
name: 'HTC ChaCha', width:320, height:480, dpi:222
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
// Get the command line arguments that were passed to the b2g client
|
2014-04-10 07:38:00 +00:00
|
|
|
let args;
|
|
|
|
try {
|
2014-08-28 08:10:00 +00:00
|
|
|
let service = Cc["@mozilla.org/commandlinehandler/general-startup;1?type=b2gcmds"].getService(Ci.nsISupports);
|
|
|
|
args = service.wrappedJSObject.cmdLine;
|
2014-04-10 07:38:00 +00:00
|
|
|
} catch(e) {}
|
|
|
|
|
|
|
|
let screenarg = null;
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
// Get the --screen argument from the command line
|
|
|
|
try {
|
2014-04-10 07:38:00 +00:00
|
|
|
if (args) {
|
|
|
|
screenarg = args.handleFlagWithParam('screen', false);
|
|
|
|
}
|
2012-05-30 22:06:25 +00:00
|
|
|
|
2014-12-03 19:42:00 +00:00
|
|
|
// Override default screen size with a pref
|
|
|
|
if (screenarg === null && Services.prefs.prefHasUserValue('b2g.screen.size')) {
|
|
|
|
screenarg = Services.prefs.getCharPref('b2g.screen.size');
|
|
|
|
}
|
|
|
|
|
2012-06-25 18:14:15 +00:00
|
|
|
// If there isn't one, use the default screen
|
2012-05-30 22:06:25 +00:00
|
|
|
if (screenarg === null)
|
2012-06-25 18:14:15 +00:00
|
|
|
screenarg = DEFAULT_SCREEN;
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
// With no value, tell the user how to use it
|
|
|
|
if (screenarg == '')
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
catch(e) {
|
|
|
|
// If getting the argument value fails, its an error
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case --screen=full goes into fullscreen mode
|
|
|
|
if (screenarg === 'full') {
|
|
|
|
shell.setAttribute('sizemode', 'fullscreen');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-23 23:28:54 +00:00
|
|
|
let width, height, ratio = 1.0;
|
2016-02-02 22:52:00 +00:00
|
|
|
let lastResizedWidth;
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
if (screenarg in screens) {
|
|
|
|
// If this is a named screen, get its data
|
|
|
|
let screen = screens[screenarg];
|
|
|
|
width = screen.width;
|
|
|
|
height = screen.height;
|
2014-12-23 23:28:54 +00:00
|
|
|
ratio = screen.ratio;
|
2012-05-30 22:06:25 +00:00
|
|
|
} else {
|
|
|
|
// Otherwise, parse the resolution and density from the --screen value.
|
|
|
|
// The supported syntax is WIDTHxHEIGHT[@DPI]
|
2014-12-23 23:28:54 +00:00
|
|
|
let match = screenarg.match(/^(\d+)x(\d+)(@(\d+(\.\d+)?))?$/);
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
// Display usage information on syntax errors
|
|
|
|
if (match == null)
|
|
|
|
usage();
|
|
|
|
|
|
|
|
// Convert strings to integers
|
|
|
|
width = parseInt(match[1], 10);
|
|
|
|
height = parseInt(match[2], 10);
|
|
|
|
if (match[4])
|
2014-12-23 23:28:54 +00:00
|
|
|
ratio = parseFloat(match[4], 10);
|
2012-05-30 22:06:25 +00:00
|
|
|
|
|
|
|
// If any of the values came out 0 or NaN or undefined, display usage
|
2014-12-23 23:28:54 +00:00
|
|
|
if (!width || !height || !ratio) {
|
2012-05-30 22:06:25 +00:00
|
|
|
usage();
|
2014-12-23 23:28:54 +00:00
|
|
|
}
|
2012-05-30 22:06:25 +00:00
|
|
|
}
|
2014-03-19 12:38:59 +00:00
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
Services.prefs.setCharPref('layout.css.devPixelsPerPx',
|
|
|
|
ratio == 1 ? -1 : ratio);
|
|
|
|
let defaultOrientation = width < height ? 'portrait' : 'landscape';
|
|
|
|
GlobalSimulatorScreen.mozOrientation = GlobalSimulatorScreen.screenOrientation = defaultOrientation;
|
|
|
|
|
|
|
|
function resize() {
|
2014-03-19 12:38:59 +00:00
|
|
|
GlobalSimulatorScreen.width = width;
|
|
|
|
GlobalSimulatorScreen.height = height;
|
|
|
|
|
|
|
|
// Set the window width and height to desired size plus chrome
|
|
|
|
// Include the size of the toolbox displayed under the system app
|
|
|
|
let controls = document.getElementById('controls');
|
2015-03-12 06:12:00 +00:00
|
|
|
let controlsHeight = controls ? controls.getBoundingClientRect().height : 0;
|
|
|
|
|
2014-08-12 06:43:00 +00:00
|
|
|
if (isMulet) {
|
2015-01-20 05:57:00 +00:00
|
|
|
let tab = browserWindow.gBrowser.selectedTab;
|
|
|
|
let responsive = ResponsiveUIManager.getResponsiveUIForTab(tab);
|
2015-03-12 06:12:00 +00:00
|
|
|
responsive.setSize(width + 16*2,
|
|
|
|
height + controlsHeight + 61);
|
2014-08-12 06:43:00 +00:00
|
|
|
} else {
|
2015-03-12 06:12:00 +00:00
|
|
|
let chromewidth = window.outerWidth - window.innerWidth;
|
|
|
|
let chromeheight = window.outerHeight - window.innerHeight + controlsHeight;
|
2016-02-02 22:52:00 +00:00
|
|
|
|
|
|
|
if (lastResizedWidth == width) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
lastResizedWidth = width;
|
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
window.resizeTo(width + chromewidth,
|
|
|
|
height + chromeheight);
|
2014-08-12 06:43:00 +00:00
|
|
|
}
|
2014-03-19 12:38:59 +00:00
|
|
|
|
|
|
|
let frameWidth = width, frameHeight = height;
|
2015-03-12 06:12:00 +00:00
|
|
|
|
|
|
|
// If the current app doesn't supports the current screen orientation
|
|
|
|
// still resize the window, but rotate its frame so that
|
|
|
|
// it is displayed rotated on the side
|
|
|
|
let shouldFlip = GlobalSimulatorScreen.mozOrientation != GlobalSimulatorScreen.screenOrientation;
|
|
|
|
|
2014-03-19 12:38:59 +00:00
|
|
|
if (shouldFlip) {
|
|
|
|
frameWidth = height;
|
|
|
|
frameHeight = width;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the browser element to the full unscaled size of the screen
|
|
|
|
let style = browser.style;
|
|
|
|
style.transform = '';
|
2014-12-23 23:28:54 +00:00
|
|
|
style.height = 'calc(100% - ' + controlsHeight + 'px)';
|
|
|
|
style.bottom = controlsHeight;
|
2014-03-19 12:38:59 +00:00
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
style.width = frameWidth + "px";
|
|
|
|
style.height = frameHeight + "px";
|
|
|
|
|
2014-03-19 12:38:59 +00:00
|
|
|
if (shouldFlip) {
|
|
|
|
// Display the system app with a 90° clockwise rotation
|
2015-03-12 06:12:00 +00:00
|
|
|
let shift = Math.floor(Math.abs(frameWidth - frameHeight) / 2);
|
2014-03-19 12:38:59 +00:00
|
|
|
style.transform +=
|
|
|
|
' rotate(0.25turn) translate(-' + shift + 'px, -' + shift + 'px)';
|
|
|
|
}
|
2012-05-30 22:06:25 +00:00
|
|
|
}
|
|
|
|
|
2014-03-19 12:38:59 +00:00
|
|
|
// Resize on startup
|
2015-03-12 06:12:00 +00:00
|
|
|
resize();
|
2014-12-23 23:28:54 +00:00
|
|
|
|
|
|
|
// Catch manual resizes to update the internal device size.
|
|
|
|
window.onresize = function() {
|
2015-03-12 06:12:00 +00:00
|
|
|
let controls = document.getElementById('controls');
|
|
|
|
let controlsHeight = controls ? controls.getBoundingClientRect().height : 0;
|
|
|
|
|
|
|
|
width = window.innerWidth;
|
|
|
|
height = window.innerHeight - controlsHeight;
|
|
|
|
|
|
|
|
queueResize();
|
2014-12-23 23:28:54 +00:00
|
|
|
};
|
2014-03-19 12:38:59 +00:00
|
|
|
|
|
|
|
// Then resize on each rotation button click,
|
|
|
|
// or when the system app lock/unlock the orientation
|
|
|
|
Services.obs.addObserver(function orientationChangeListener(subject) {
|
|
|
|
let screen = subject.wrappedJSObject;
|
|
|
|
let { mozOrientation, screenOrientation } = screen;
|
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
// If we have an orientation different than the current one,
|
2014-03-19 12:38:59 +00:00
|
|
|
// we switch the sizes
|
|
|
|
if (screenOrientation != defaultOrientation) {
|
2015-03-12 06:12:00 +00:00
|
|
|
let w = width;
|
|
|
|
width = height;
|
|
|
|
height = w;
|
2014-03-19 12:38:59 +00:00
|
|
|
}
|
2015-03-12 06:12:00 +00:00
|
|
|
defaultOrientation = screenOrientation;
|
2014-03-19 12:38:59 +00:00
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
queueResize();
|
2014-03-19 12:38:59 +00:00
|
|
|
}, 'simulator-adjust-window-size', false);
|
2012-05-30 22:06:25 +00:00
|
|
|
|
2015-03-12 06:12:00 +00:00
|
|
|
// Queue resize request in order to prevent race and slowdowns
|
|
|
|
// by requesting resize multiple times per loop
|
|
|
|
let resizeTimeout;
|
|
|
|
function queueResize() {
|
|
|
|
if (resizeTimeout) {
|
|
|
|
clearTimeout(resizeTimeout);
|
|
|
|
}
|
|
|
|
resizeTimeout = setTimeout(function () {
|
|
|
|
resizeTimeout = null;
|
|
|
|
resize();
|
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
|
2012-05-30 22:06:25 +00:00
|
|
|
// A utility function like console.log() for printing to the terminal window
|
|
|
|
// Uses dump(), but enables it first, if necessary
|
|
|
|
function print() {
|
|
|
|
let dump_enabled =
|
|
|
|
Services.prefs.getBoolPref('browser.dom.window.dump.enabled');
|
|
|
|
|
2014-03-19 12:38:59 +00:00
|
|
|
if (!dump_enabled)
|
2012-05-30 22:06:25 +00:00
|
|
|
Services.prefs.setBoolPref('browser.dom.window.dump.enabled', true);
|
|
|
|
|
|
|
|
dump(Array.prototype.join.call(arguments, ' ') + '\n');
|
|
|
|
|
|
|
|
if (!dump_enabled)
|
|
|
|
Services.prefs.setBoolPref('browser.dom.window.dump.enabled', false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print usage info for --screen and exit
|
|
|
|
function usage() {
|
|
|
|
// Documentation for the --screen argument
|
|
|
|
let msg =
|
|
|
|
'The --screen argument specifies the desired resolution and\n' +
|
|
|
|
'pixel density of the simulated device screen. Use it like this:\n' +
|
|
|
|
'\t--screen=WIDTHxHEIGHT\t\t\t// E.g.: --screen=320x480\n' +
|
|
|
|
'\t--screen=WIDTHxHEIGHT@DOTS_PER_INCH\t// E.g.: --screen=480x800@250\n' +
|
|
|
|
'\t--screen=full\t\t\t\t// run in fullscreen mode\n' +
|
|
|
|
'\nYou can also specify certain device names:\n';
|
|
|
|
for(let p in screens)
|
|
|
|
msg += '\t--screen=' + p + '\t// ' + screens[p].name + '\n';
|
|
|
|
|
|
|
|
// Display the usage message
|
|
|
|
print(msg);
|
|
|
|
|
|
|
|
// Exit the b2g client
|
|
|
|
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
|
|
|
}
|
2015-09-04 18:12:53 +00:00
|
|
|
}
|