1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/metro/base/content/apzc.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,153 @@ 1.4 +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +let Cc = Components.classes; 1.10 +let Ci = Components.interfaces; 1.11 +let Cu = Components.utils; 1.12 +let Cr = Components.results; 1.13 + 1.14 +/** 1.15 + * Misc. front end utilities for apzc management. 1.16 + * the pref: layers.async-pan-zoom.enabled is true. 1.17 + */ 1.18 + 1.19 +var APZCObserver = { 1.20 + _debugEvents: false, 1.21 + _enabled: false, 1.22 + 1.23 + get enabled() { 1.24 + return this._enabled; 1.25 + }, 1.26 + 1.27 + init: function() { 1.28 + this._enabled = Services.prefs.getBoolPref(kAsyncPanZoomEnabled); 1.29 + if (!this._enabled) { 1.30 + return; 1.31 + } 1.32 + 1.33 + let os = Services.obs; 1.34 + os.addObserver(this, "apzc-transform-begin", false); 1.35 + 1.36 + Elements.tabList.addEventListener("TabSelect", this, true); 1.37 + Elements.browsers.addEventListener("pageshow", this, true); 1.38 + messageManager.addMessageListener("Content:ZoomToRect", this); 1.39 + }, 1.40 + 1.41 + shutdown: function shutdown() { 1.42 + if (!this._enabled) { 1.43 + return; 1.44 + } 1.45 + 1.46 + let os = Services.obs; 1.47 + os.removeObserver(this, "apzc-transform-begin"); 1.48 + 1.49 + Elements.tabList.removeEventListener("TabSelect", this, true); 1.50 + Elements.browsers.removeEventListener("pageshow", this, true); 1.51 + messageManager.removeMessageListener("Content:ZoomToRect", this); 1.52 + }, 1.53 + 1.54 + handleEvent: function APZC_handleEvent(aEvent) { 1.55 + switch (aEvent.type) { 1.56 + case 'TabSelect': 1.57 + this._resetDisplayPort(); 1.58 + break; 1.59 + 1.60 + case 'pageshow': 1.61 + if (aEvent.target != Browser.selectedBrowser.contentDocument) { 1.62 + break; 1.63 + } 1.64 + this._resetDisplayPort(); 1.65 + break; 1.66 + } 1.67 + }, 1.68 + 1.69 + observe: function ao_observe(aSubject, aTopic, aData) { 1.70 + if (aTopic == "apzc-transform-begin") { 1.71 + // When we're panning, hide the main scrollbars by setting imprecise 1.72 + // input (which sets a property on the browser which hides the scrollbar 1.73 + // via CSS). This reduces jittering from left to right. We may be able 1.74 + // to get rid of this once we implement axis locking in /gfx APZC. 1.75 + if (InputSourceHelper.isPrecise) { 1.76 + InputSourceHelper._imprecise(); 1.77 + } 1.78 + } 1.79 + }, 1.80 + 1.81 + receiveMessage: function(aMessage) { 1.82 + let json = aMessage.json; 1.83 + let browser = aMessage.target; 1.84 + switch (aMessage.name) { 1.85 + case "Content:ZoomToRect": { 1.86 + let { presShellId, viewId } = json; 1.87 + let rect = Rect.fromRect(json.rect); 1.88 + if (this.isRectZoomedIn(rect, browser.contentViewportBounds)) { 1.89 + // If we're already zoomed in, zoom out instead. 1.90 + rect = new Rect(0,0,0,0); 1.91 + } 1.92 + let data = [rect.x, rect.y, rect.width, rect.height, presShellId, viewId].join(","); 1.93 + Services.obs.notifyObservers(null, "apzc-zoom-to-rect", data); 1.94 + } 1.95 + } 1.96 + }, 1.97 + 1.98 + /** 1.99 + * Check to see if the area of the rect visible in the viewport is 1.100 + * approximately the max area of the rect we can show. 1.101 + * Based on code from BrowserElementPanning.js 1.102 + */ 1.103 + isRectZoomedIn: function (aRect, aViewport) { 1.104 + let overlap = aViewport.intersect(aRect); 1.105 + let overlapArea = overlap.width * overlap.height; 1.106 + let availHeight = Math.min(aRect.width * aViewport.height / aViewport.width, aRect.height); 1.107 + let showing = overlapArea / (aRect.width * availHeight); 1.108 + let ratioW = (aRect.width / aViewport.width); 1.109 + let ratioH = (aRect.height / aViewport.height); 1.110 + 1.111 + return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9)); 1.112 + }, 1.113 + 1.114 + _resetDisplayPort: function () { 1.115 + // Start off with something reasonable. The apzc will handle these 1.116 + // calculations once scrolling starts. 1.117 + let doc = Browser.selectedBrowser.contentDocument.documentElement; 1.118 + // While running tests, sometimes this can be null. If we don't have a 1.119 + // root document, there's no point in setting a scrollable display port. 1.120 + if (!doc) { 1.121 + return; 1.122 + } 1.123 + let win = Browser.selectedBrowser.contentWindow; 1.124 + let factor = 0.2; 1.125 + let portX = 0; 1.126 + let portY = 0; 1.127 + let portWidth = ContentAreaObserver.width; 1.128 + let portHeight = ContentAreaObserver.height; 1.129 + 1.130 + if (portWidth < doc.scrollWidth) { 1.131 + portWidth += ContentAreaObserver.width * factor; 1.132 + if (portWidth > doc.scrollWidth) { 1.133 + portWidth = doc.scrollWidth; 1.134 + } 1.135 + } 1.136 + if (portHeight < doc.scrollHeight) { 1.137 + portHeight += ContentAreaObserver.height * factor; 1.138 + if (portHeight > doc.scrollHeight) { 1.139 + portHeight = doc.scrollHeight; 1.140 + } 1.141 + } 1.142 + if (win.scrollX > 0) { 1.143 + portX -= ContentAreaObserver.width * factor; 1.144 + } 1.145 + if (win.scrollY > 0) { 1.146 + portY -= ContentAreaObserver.height * factor; 1.147 + } 1.148 + let cwu = Browser.selectedBrowser.contentWindow 1.149 + .QueryInterface(Ci.nsIInterfaceRequestor) 1.150 + .getInterface(Ci.nsIDOMWindowUtils); 1.151 + cwu.setDisplayPortForElement(portX, portY, 1.152 + portWidth, portHeight, 1.153 + Browser.selectedBrowser.contentDocument.documentElement, 1.154 + 0); 1.155 + } 1.156 +};