support for zoom (disabled)
authorBenjamin Stover <bstover@mozilla.com>
Fri, 27 Aug 2010 16:25:53 -0700
changeset 1965 4a71ba5c98a9689c9257d02a2bea025662af2a1f
parent 1964 20424865e08b3da1cfd7f4e85f58e79d05b14d8f
child 1966 b982249f3b69c112fbc9f7bf53458787292c8967
push id1714
push userdougt@mozilla.com
push dateThu, 16 Sep 2010 02:04:21 +0000
support for zoom (disabled)
chrome/content/BrowserView.js
chrome/content/bindings/browser.js
chrome/content/bindings/browser.xml
chrome/content/browser.js
--- a/chrome/content/BrowserView.js
+++ b/chrome/content/BrowserView.js
@@ -36,16 +36,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 let Ci = Components.interfaces;
 
+const kBrowserFormZoomLevelMin = 1.0;
+const kBrowserFormZoomLevelMax = 2.0;
+const kBrowserViewZoomLevelPrecision = 10000;
+
 function BrowserView(container, visibleRectFactory) {
   Util.bindAll(this);
   this.init(container, visibleRectFactory);
 }
 
 
 // -----------------------------------------------------------
 // Util/convenience functions.
@@ -69,67 +73,37 @@ BrowserView.prototype = {
 
   // -----------------------------------------------------------
   // Public instance methods
   //
 
   init: function init(container, visibleRectFactory) {
     this._container = container;
     this._browser = null;
-    this._browserViewportState = null;
     this._visibleRectFactory = visibleRectFactory;
     messageManager.addMessageListener("Browser:MozScrolledAreaChanged", this);
   },
 
   uninit: function uninit() {
   },
 
-  getVisibleRect: function getVisibleRect() {
-    return this._visibleRectFactory();
-  },
-
-  getCriticalRect: function getCriticalRect() {
-    let bvs = this._browserViewportState;
-    let vr = this.getVisibleRect();
-    return BrowserView.Util.visibleRectToCriticalRect(vr, bvs);
-  },
-
-  clampZoomLevel: function clampZoomLevel(zl) {
-    let bounded = Math.min(Math.max(ZoomManager.MIN, zl), ZoomManager.MAX);
-
-    let bvs = this._browserViewportState;
-    if (bvs) {
-      let md = bvs.metaData;
-      if (md && md.minZoom)
-        bounded = Math.max(bounded, md.minZoom);
-      if (md && md.maxZoom)
-        bounded = Math.min(bounded, md.maxZoom);
-
-      bounded = Math.max(bounded, this.getPageZoomLevel());
-    }
-
-    let rounded = Math.round(bounded * kBrowserViewZoomLevelPrecision) / kBrowserViewZoomLevelPrecision;
-    return rounded || 1.0;
-  },
-
   /**
    * Swap out the current browser and browser viewport state with a new pair.
    */
   setBrowser: function setBrowser(browser, browserViewportState) {
     let oldBrowser = this._browser;
     let browserChanged = (oldBrowser !== browser);
 
     if (oldBrowser) {
       oldBrowser.setAttribute("type", "content");
       oldBrowser.style.display = "none";
       oldBrowser.messageManager.sendAsyncMessage("Browser:Blur", {});
     }
 
     this._browser = browser;
-    this._browserViewportState = browserViewportState;
 
     if (browser) {
       browser.setAttribute("type", "content-primary");
       browser.style.display = "";
       browser.messageManager.sendAsyncMessage("Browser:Focus", {});
     }
   },
 
--- a/chrome/content/bindings/browser.js
+++ b/chrome/content/bindings/browser.js
@@ -56,16 +56,17 @@ let WebProgressListener = {
       windowId: aWebProgress.DOMWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID,
       documentURI: aWebProgress.DOMWindow.document.documentURIObject.spec,
       location: location,
       canGoBack: docShell.canGoBack,
       canGoForward: docShell.canGoForward
     };
     sendAsyncMessage("WebProgress:LocationChange", json);
 
+    let cwu = Util.getWindowUtils(content);
     let scrollOffset = Util.getScrollOffset(content);
     cwu.setDisplayport(scrollOffset.x - 200, scrollOffset.y - 400,
                        content.innerWidth + 400, content.innerHeight + 800);
   },
 
   onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
     let json = {
       windowId: aWebProgress.DOMWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID,
@@ -374,29 +375,29 @@ let ContentScroll =  {
     addMessageListener("Content:FastScrollTo", this);
     addMessageListener("Content:SetCssViewportSize", this);
   },
 
   receiveMessage: function(aMessage) {
     let json = aMessage.json;
     switch (aMessage.name) {
       case "Content:ScrollTo":
-        content.scrollTo(json.x, json.y);
+//        content.scrollTo(json.x, json.y);
         let cwu = Util.getWindowUtils(content);
-        let scrollOffset = Util.getScrollOffset(content);
-        cwu.setDisplayport(scrollOffset.x - 200, scrollOffset.y - 400,
+        cwu.setDisplayport(json.x - 200, json.y - 400,
                            content.innerWidth + 400, content.innerHeight + 800);
         break;
 
       case "Content:ScrollBy":
         content.scrollBy(json.dx, json.dy);
         break;
 
       case "Content:ZoomLevel":
-        // XXX not working yet
+        content.document.body.style.MozTransformOrigin = "top left";
+        content.document.body.style.MozTransform = "scale(" + json.zoomLevel + ")";
         break;
 
       case "Content:FastScrollTo": {
         try {
           let cwu = Util.getWindowUtils(content);
           cwu.setDisplayport(json.x - 200, json.y - 400,
                              content.innerWidth + 400, content.innerHeight + 800);
         } catch(e) {
--- a/chrome/content/bindings/browser.xml
+++ b/chrome/content/bindings/browser.xml
@@ -393,16 +393,24 @@
       <field name="_flushingFastScroll">false</field>
       <field name="_widthInDevicePx">0</field>
       <field name="_heightInDevicePx">0</field>
       <field name="_zoomLevel">1</field>
       <field name="_defaultZoomLevel">1</field>
       <field name="_pendingPixelsX">0</field>
       <field name="_pendingPixelsY">0</field>
 
+      <property name="widthInCssPx"
+                onget="return this._widthInDevicePx / this.zoomLevel;"
+                readonly="true"/>
+
+      <property name="heightInCssPx"
+                onget="return this._heightInDevicePx / this.zoomLevel;"
+                readonly="true"/>
+
       <property name="widthInDevicePx"
                 onget="return this._widthInDevicePx;"
                 readonly="true"/>
 
       <property name="heightInDevicePx"
                 onget="return this._heightInDevicePx;"
                 readonly="true"/>
 
@@ -413,29 +421,31 @@
       <property name="defaultZoomLevel"
                 onget="return this._defaultZoomLevel;"
                 onset="return this._setDefaultZoomLevel(val);"/>
 
       <method name="_setZoomLevel">
         <parameter name="zl"/>
         <body>
           <![CDATA[
-            throw "Not supported yet!";
+            return;
             if (zl <= 0) throw "Bad zoom level given.";
+
             this._zoomLevel = zl;
             this.messageManager.sendAsyncMessage("Content:ZoomLevel", { zoomLevel: zl });
           ]]>
         </body>
       </method>
 
       <method name="setCssViewportSize">
         <parameter name="width"/>
         <parameter name="height"/>
         <body>
           <![CDATA[
+            return;
             this.messageManager.sendAsyncMessage("Content:SetCssViewportSize", {
               width: width,
               height: height
             });
           ]]>
         </body>
       </method>
 
--- a/chrome/content/browser.js
+++ b/chrome/content/browser.js
@@ -239,17 +239,16 @@ var Browser = {
 
       Browser.styles["window-width"].width = w + "px";
       Browser.styles["window-height"].height = h + "px";
       Browser.styles["toolbar-height"].height = toolbarHeight + "px";
 
       // Tell the UI to resize the browser controls
       BrowserUI.sizeControls(w, h);
 
-//      bv.updateDefaultZoom();
       // XXX this should really only happen on browser startup, not every resize
       Browser.hideSidebars();
 
       for (let i = Browser.tabs.length - 1; i >= 0; i--)
         Browser.tabs[i].updateViewportSize();
 
       let curEl = document.activeElement;
       if (curEl && curEl.scrollIntoView)
@@ -620,17 +619,16 @@ var Browser = {
     let lastTab = this._selectedTab;
     this._selectedTab = tab;
 
     // Lock the toolbar if the new tab is still loading
     if (this._selectedTab.isLoading())
       BrowserUI.lockToolbar();
 
     bv.setBrowser(tab.browser, tab.browserViewportState);
-//    bv.updateDefaultZoom();
 
     document.getElementById("tabs").selectedTab = tab.chromeTab;
 
     if (!isFirstTab) {
       // Update all of our UI to reflect the new tab's location
       BrowserUI.updateURI();
       getIdentityHandler().checkIdentity();
 
@@ -2370,16 +2368,21 @@ Tab.prototype = {
     let flags = Ci.nsIWebProgress.NOTIFY_LOCATION |
                 Ci.nsIWebProgress.NOTIFY_SECURITY |
                 Ci.nsIWebProgress.NOTIFY_STATE_NETWORK |
                 Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT;
     this._listener = new ProgressController(this);
     browser.webProgress.addProgressListener(this._listener, flags);
 
     browser.setAttribute("src", aURI);
+
+    let self = this;
+    browser.messageManager.addMessageListener("MozScrolledAreaChanged", function() {
+      self.updateDefaultZoomLevel();
+    });
   },
 
   _destroyBrowser: function _destroyBrowser() {
     if (this._browser) {
       var browser = this._browser;
       browser.removeProgressListener(this._listener);
 
       this._browser = null;
@@ -2387,29 +2390,81 @@ Tab.prototype = {
       this._loading = false;
 
       Util.executeSoon(function() {
         document.getElementById("browsers").removeChild(browser);
       });
     }
   },
 
+  clampZoomLevel: function clampZoomLevel(zl) {
+    let browser = this._browser;
+    if (!browser.contentWindow) {
+      let bounded = Math.min(Math.max(ZoomManager.MIN, zl), ZoomManager.MAX);
+
+      let md = this.metaData;
+      if (md && md.minZoom)
+        bounded = Math.max(bounded, md.minZoom);
+      if (md && md.maxZoom)
+        bounded = Math.min(bounded, md.maxZoom);
+
+      bounded = Math.max(bounded, this.getPageZoomLevel());
+
+      let rounded = Math.round(bounded * kBrowserViewZoomLevelPrecision) / kBrowserViewZoomLevelPrecision;
+      return rounded || 1.0;
+    }
+    return 1;
+  },
+
   /**
-   * Set up the initial zoom level. While the bvs.defaultZoomLevel of a tab is
-   * equal to bvs.zoomLevel this mean that not user action has happended and
-   * we can safely alter the zoom on a window resize or on a page load
+   * XXX document me
    */
   resetZoomLevel: function resetZoomLevel() {
-    return;
-
-    let bvs = this._browserViewportState;
-    bvs.defaultZoomLevel = bvs.zoomLevel;
+    let browser = this._browser;
+    if (!browser.contentWindow)
+      this._defaultZoomLevel = browser.zoomLevel;
+  },
+
+  /**
+   * XXX document me
+   */
+  updateDefaultZoomLevel: function updateDefaultZoomLevel() {
+    let browser = this._browser;
+    if (!browser.contentWindow) {
+      let isDefault = (browser.zoomLevel == this._defaultZoomLevel);
+      this._defaultZoomLevel = this.getDefaultZoomLevel();
+      if (isDefault)
+        browser.zoomLevel = this._defaultZoomLevel;
+    }
+  },
+
+  getDefaultZoomLevel: function getDefaultZoomLevel() {
+    let md = this.metaData;
+    if (md && md.defaultZoom)
+      return this.clampZoomLevel(md.defaultZoom);
+
+    let pageZoom = this.getPageZoomLevel();
+
+    // If pageZoom is "almost" 100%, zoom in to exactly 100% (bug 454456).
+    let granularity = Services.prefs.getIntPref("browser.ui.zoom.pageFitGranularity");
+    let threshold = 1 - 1 / granularity;
+    if (threshold < pageZoom && pageZoom < 1)
+      pageZoom = 1;
+
+    return this.clampZoomLevel(pageZoom);
+  },
+
+  getPageZoomLevel: function getPageZoomLevel() {
+    let browserW = this._browser.widthInCssPx;
+    return this._browser.getBoundingClientRect().width / browserW;
   },
 
   updateThumbnail: function updateThumbnail() {
+    return;
+
     if (!this._browser)
       return;
 
     // XXX: We don't know the size of the browser at this time and we can't fallback
     // to contentWindow.innerWidth and .innerHeight. The viewport meta data is not
     // even set yet. So fallback to something sane for now.
     this._chromeTab.updateThumbnail(this._browser, 800, 500);
   },