browser/metro/base/content/apzc.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 let Cc = Components.classes;
michael@0 7 let Ci = Components.interfaces;
michael@0 8 let Cu = Components.utils;
michael@0 9 let Cr = Components.results;
michael@0 10
michael@0 11 /**
michael@0 12 * Misc. front end utilities for apzc management.
michael@0 13 * the pref: layers.async-pan-zoom.enabled is true.
michael@0 14 */
michael@0 15
michael@0 16 var APZCObserver = {
michael@0 17 _debugEvents: false,
michael@0 18 _enabled: false,
michael@0 19
michael@0 20 get enabled() {
michael@0 21 return this._enabled;
michael@0 22 },
michael@0 23
michael@0 24 init: function() {
michael@0 25 this._enabled = Services.prefs.getBoolPref(kAsyncPanZoomEnabled);
michael@0 26 if (!this._enabled) {
michael@0 27 return;
michael@0 28 }
michael@0 29
michael@0 30 let os = Services.obs;
michael@0 31 os.addObserver(this, "apzc-transform-begin", false);
michael@0 32
michael@0 33 Elements.tabList.addEventListener("TabSelect", this, true);
michael@0 34 Elements.browsers.addEventListener("pageshow", this, true);
michael@0 35 messageManager.addMessageListener("Content:ZoomToRect", this);
michael@0 36 },
michael@0 37
michael@0 38 shutdown: function shutdown() {
michael@0 39 if (!this._enabled) {
michael@0 40 return;
michael@0 41 }
michael@0 42
michael@0 43 let os = Services.obs;
michael@0 44 os.removeObserver(this, "apzc-transform-begin");
michael@0 45
michael@0 46 Elements.tabList.removeEventListener("TabSelect", this, true);
michael@0 47 Elements.browsers.removeEventListener("pageshow", this, true);
michael@0 48 messageManager.removeMessageListener("Content:ZoomToRect", this);
michael@0 49 },
michael@0 50
michael@0 51 handleEvent: function APZC_handleEvent(aEvent) {
michael@0 52 switch (aEvent.type) {
michael@0 53 case 'TabSelect':
michael@0 54 this._resetDisplayPort();
michael@0 55 break;
michael@0 56
michael@0 57 case 'pageshow':
michael@0 58 if (aEvent.target != Browser.selectedBrowser.contentDocument) {
michael@0 59 break;
michael@0 60 }
michael@0 61 this._resetDisplayPort();
michael@0 62 break;
michael@0 63 }
michael@0 64 },
michael@0 65
michael@0 66 observe: function ao_observe(aSubject, aTopic, aData) {
michael@0 67 if (aTopic == "apzc-transform-begin") {
michael@0 68 // When we're panning, hide the main scrollbars by setting imprecise
michael@0 69 // input (which sets a property on the browser which hides the scrollbar
michael@0 70 // via CSS). This reduces jittering from left to right. We may be able
michael@0 71 // to get rid of this once we implement axis locking in /gfx APZC.
michael@0 72 if (InputSourceHelper.isPrecise) {
michael@0 73 InputSourceHelper._imprecise();
michael@0 74 }
michael@0 75 }
michael@0 76 },
michael@0 77
michael@0 78 receiveMessage: function(aMessage) {
michael@0 79 let json = aMessage.json;
michael@0 80 let browser = aMessage.target;
michael@0 81 switch (aMessage.name) {
michael@0 82 case "Content:ZoomToRect": {
michael@0 83 let { presShellId, viewId } = json;
michael@0 84 let rect = Rect.fromRect(json.rect);
michael@0 85 if (this.isRectZoomedIn(rect, browser.contentViewportBounds)) {
michael@0 86 // If we're already zoomed in, zoom out instead.
michael@0 87 rect = new Rect(0,0,0,0);
michael@0 88 }
michael@0 89 let data = [rect.x, rect.y, rect.width, rect.height, presShellId, viewId].join(",");
michael@0 90 Services.obs.notifyObservers(null, "apzc-zoom-to-rect", data);
michael@0 91 }
michael@0 92 }
michael@0 93 },
michael@0 94
michael@0 95 /**
michael@0 96 * Check to see if the area of the rect visible in the viewport is
michael@0 97 * approximately the max area of the rect we can show.
michael@0 98 * Based on code from BrowserElementPanning.js
michael@0 99 */
michael@0 100 isRectZoomedIn: function (aRect, aViewport) {
michael@0 101 let overlap = aViewport.intersect(aRect);
michael@0 102 let overlapArea = overlap.width * overlap.height;
michael@0 103 let availHeight = Math.min(aRect.width * aViewport.height / aViewport.width, aRect.height);
michael@0 104 let showing = overlapArea / (aRect.width * availHeight);
michael@0 105 let ratioW = (aRect.width / aViewport.width);
michael@0 106 let ratioH = (aRect.height / aViewport.height);
michael@0 107
michael@0 108 return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9));
michael@0 109 },
michael@0 110
michael@0 111 _resetDisplayPort: function () {
michael@0 112 // Start off with something reasonable. The apzc will handle these
michael@0 113 // calculations once scrolling starts.
michael@0 114 let doc = Browser.selectedBrowser.contentDocument.documentElement;
michael@0 115 // While running tests, sometimes this can be null. If we don't have a
michael@0 116 // root document, there's no point in setting a scrollable display port.
michael@0 117 if (!doc) {
michael@0 118 return;
michael@0 119 }
michael@0 120 let win = Browser.selectedBrowser.contentWindow;
michael@0 121 let factor = 0.2;
michael@0 122 let portX = 0;
michael@0 123 let portY = 0;
michael@0 124 let portWidth = ContentAreaObserver.width;
michael@0 125 let portHeight = ContentAreaObserver.height;
michael@0 126
michael@0 127 if (portWidth < doc.scrollWidth) {
michael@0 128 portWidth += ContentAreaObserver.width * factor;
michael@0 129 if (portWidth > doc.scrollWidth) {
michael@0 130 portWidth = doc.scrollWidth;
michael@0 131 }
michael@0 132 }
michael@0 133 if (portHeight < doc.scrollHeight) {
michael@0 134 portHeight += ContentAreaObserver.height * factor;
michael@0 135 if (portHeight > doc.scrollHeight) {
michael@0 136 portHeight = doc.scrollHeight;
michael@0 137 }
michael@0 138 }
michael@0 139 if (win.scrollX > 0) {
michael@0 140 portX -= ContentAreaObserver.width * factor;
michael@0 141 }
michael@0 142 if (win.scrollY > 0) {
michael@0 143 portY -= ContentAreaObserver.height * factor;
michael@0 144 }
michael@0 145 let cwu = Browser.selectedBrowser.contentWindow
michael@0 146 .QueryInterface(Ci.nsIInterfaceRequestor)
michael@0 147 .getInterface(Ci.nsIDOMWindowUtils);
michael@0 148 cwu.setDisplayPortForElement(portX, portY,
michael@0 149 portWidth, portHeight,
michael@0 150 Browser.selectedBrowser.contentDocument.documentElement,
michael@0 151 0);
michael@0 152 }
michael@0 153 };

mercurial