browser/metro/base/content/apzc.js

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

mercurial