Bug 732564 - Ensure that for all possible combinations of CSS viewport and screen size changing, we do the "right thing". r=Cwiiis
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 12 Mar 2012 12:03:39 -0400
changeset 89336 e3798e9069175d40b1ba8058bcafef8b2c6cedc0
parent 89335 d8326d63c320c5b8a6c7458569e73d02e8e722dc
child 89337 d2340d74fc1960bdd407cc25b7619de9cd9d3cd3
push id22242
push userkgupta@mozilla.com
push dateWed, 14 Mar 2012 15:19:09 +0000
treeherdermozilla-central@936ef50fa498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCwiiis
bugs732564
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 732564 - Ensure that for all possible combinations of CSS viewport and screen size changing, we do the "right thing". r=Cwiiis
mobile/android/chrome/content/browser.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -85,16 +85,19 @@ const kElementsReceivingInput = {
     select: true,
     textarea: true,
     video: true
 };
 
 // Whether we're using GL layers.
 const kUsingGLLayers = true;
 
+const kDefaultCSSViewportWidth = 980;
+const kDefaultCSSViewportHeight = 480;
+
 function dump(a) {
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
 }
 
 function getBridge() {
   return Cc["@mozilla.org/android/bridge;1"].getService(Ci.nsIAndroidBridge);
 }
 
@@ -1456,17 +1459,17 @@ Tab.prototype = {
   create: function(aURL, aParams) {
     if (this.browser)
       return;
 
     aParams = aParams || {};
 
     this.browser = document.createElement("browser");
     this.browser.setAttribute("type", "content-targetable");
-    this.setBrowserSize(980, 480);
+    this.setBrowserSize(kDefaultCSSViewportWidth, kDefaultCSSViewportHeight);
     BrowserApp.deck.appendChild(this.browser);
 
     this.browser.stop();
 
     let frameLoader = this.browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
     if (kUsingGLLayers) {
         frameLoader.renderMode = Ci.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL;
         frameLoader.clampScrollPosition = false;
@@ -2062,16 +2065,17 @@ Tab.prototype = {
     // at the very end).
 
     if (window.outerWidth == 0 || window.outerHeight == 0) {
         // this happens sometimes when starting up fennec. we don't want zero
         // values corrupting our viewport numbers, so ignore this one.
         return;
     }
 
+    let oldScreenWidth = gScreenWidth;
     gScreenWidth = window.outerWidth;
     gScreenHeight = window.outerHeight;
 
     let browser = this.browser;
     if (!browser)
       return;
 
     let screenW = gScreenWidth;
@@ -2113,29 +2117,33 @@ Tab.prototype = {
     let oldBrowserWidth = this.browserWidth;
     this.setBrowserSize(viewportW, viewportH);
 
     // Avoid having the scroll position jump around after device rotation.
     let win = this.browser.contentWindow;
     this.userScrollPos.x = win.scrollX;
     this.userScrollPos.y = win.scrollY;
 
-    this.setResolution(oldBrowserWidth * this._zoom / viewportW, false);
+    // This change to the zoom accounts for all types of changes I can conceive:
+    // 1. screen size changes, CSS viewport does not (pages with no meta viewport
+    //    or a fixed size viewport)
+    // 2. screen size changes, CSS viewport also does (pages with a device-width
+    //    viewport)
+    // 3. screen size remains constant, but CSS viewport changes (meta viewport
+    //    tag is added or removed)
+    // 4. neither screen size nor CSS viewport changes
+    //
+    // In all of these cases, we maintain how much actual content is visible
+    // within the screen width. Note that "actual content" may be different
+    // with respect to CSS pixels because of the CSS viewport size changing.
+    let zoomScale = (screenW * oldBrowserWidth) / (oldScreenWidth * viewportW);
+    this.setResolution(this._zoom * zoomScale, false);
     this.sendViewportUpdate();
   },
 
-  getDefaultZoomLevel: function getDefaultZoomLevel() {
-    let md = this.metadata;
-    if ("defaultZoom" in md && md.defaultZoom)
-      return md.defaultZoom;
-
-    dump("### getDefaultZoomLevel gScreenWidth=" + gScreenWidth);
-    return gScreenWidth / this.browserWidth;
-  },
-
   getPageZoomLevel: function getPageZoomLevel() {
     // This may get called during a Viewport:Change message while the document
     // has not loaded yet.
     if (!this.browser.contentDocument || !this.browser.contentDocument.body)
       return 1.0;
 
     return gScreenWidth / this.browser.contentDocument.body.clientWidth;
   },
@@ -2173,17 +2181,20 @@ Tab.prototype = {
   },
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "before-first-paint":
         // Is it on the top level?
         let contentDocument = aSubject;
         if (contentDocument == this.browser.contentDocument) {
-          this.setResolution(this.getDefaultZoomLevel(), false);
+          // reset CSS viewport and zoom to default on new page
+          this.setBrowserSize(kDefaultCSSViewportWidth, kDefaultCSSViewportHeight);
+          this.setResolution(gScreenWidth / this.browserWidth, false);
+          // and then use the metadata to figure out how it needs to be updated
           ViewportHandler.updateMetadata(this);
 
           // The document element must have a display port on it whenever we are about to
           // paint. This is the point just before the first paint, so we set the display port
           // to a default value here. Once Java is aware of this document it will overwrite
           // it with a better-calculated display port.
           this.setDisplayPort(0, 0, {left: 0, top: 0, right: gScreenWidth, bottom: gScreenHeight });