mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Commit the Fennec tile testapp from Stuart for testing
This commit is contained in:
parent
d125f2e7bb
commit
ecb4b6a7b9
11
toolkit/content/tests/fennec-tile-testapp/application.ini
Normal file
11
toolkit/content/tests/fennec-tile-testapp/application.ini
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[App]
|
||||||
|
Vendor=venderr
|
||||||
|
Name=tile
|
||||||
|
Version=1.0
|
||||||
|
BuildID=20060101
|
||||||
|
Copyright=Copyright (c) 2006 Mark Finkle
|
||||||
|
ID=xulapp@starkravingfinkle.org
|
||||||
|
|
||||||
|
[Gecko]
|
||||||
|
MinVersion=1.8
|
||||||
|
MaxVersion=1.9.2.*
|
@ -0,0 +1 @@
|
|||||||
|
content tile file:content/
|
@ -0,0 +1,736 @@
|
|||||||
|
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Mobile Browser.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Mozilla Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Roy Frostig <rfrostig@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
// --- REMOVE ---
|
||||||
|
let noop = function() {};
|
||||||
|
let endl = '\n';
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
function BrowserView(container, visibleRect) {
|
||||||
|
bindAll(this);
|
||||||
|
this.init(container, visibleRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A BrowserView maintains state of the viewport (browser, zoom level,
|
||||||
|
* dimensions) and the visible rectangle into the viewport, for every
|
||||||
|
* browser it is given (cf setBrowser()). In updates to the viewport state,
|
||||||
|
* a BrowserView (using its TileManager) renders parts of the page quasi-
|
||||||
|
* intelligently, with guarantees of having rendered and appended all of the
|
||||||
|
* visible browser content (aka the "critical rectangle").
|
||||||
|
*
|
||||||
|
* State is characterized in large part by two rectangles (and an implicit third):
|
||||||
|
* - Viewport: Always rooted at the origin, ie with (left, top) at (0, 0). The
|
||||||
|
* width and height (right and bottom) of this rectangle are that of the
|
||||||
|
* current viewport, which corresponds more or less to the transformed
|
||||||
|
* browser content (scaled by zoom level).
|
||||||
|
* - Visible: Corresponds to the client's viewing rectangle in viewport
|
||||||
|
* coordinates. Has (top, left) corresponding to position, and width & height
|
||||||
|
* corresponding to the clients viewing dimensions. Take note that the top
|
||||||
|
* and left of the visible rect are per-browser state, but that the width
|
||||||
|
* and height persist across setBrowser() calls. This is best explained by
|
||||||
|
* a simple example: user views browser A, pans to position (x0, y0), switches
|
||||||
|
* to browser B, where she finds herself at position (x1, y1), tilts her
|
||||||
|
* device so that visible rectangle's width and height change, and switches
|
||||||
|
* back to browser A. She expects to come back to position (x0, y0), but her
|
||||||
|
* device remains tilted.
|
||||||
|
* - Critical (the implicit one): The critical rectangle is the (possibly null)
|
||||||
|
* intersection of the visible and viewport rectangles. That is, it is that
|
||||||
|
* region of the viewport which is visible to the user. We care about this
|
||||||
|
* because it tells us which region must be rendered as soon as it is dirtied.
|
||||||
|
* The critical rectangle is mostly state that we do not keep in BrowserView
|
||||||
|
* but that our TileManager maintains.
|
||||||
|
*
|
||||||
|
* Example rectangle state configurations:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* +-------------------------------+
|
||||||
|
* |A |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | +----------------+ |
|
||||||
|
* | |B,C | |
|
||||||
|
* | | | |
|
||||||
|
* | | | |
|
||||||
|
* | | | |
|
||||||
|
* | +----------------+ |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* +-------------------------------+
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* A = viewport ; at (0, 0)
|
||||||
|
* B = visible ; at (x, y) where x > 0, y > 0
|
||||||
|
* C = critical ; at (x, y)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* +-------------------------------+
|
||||||
|
* |A |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* +----+-----------+ |
|
||||||
|
* |B .C | |
|
||||||
|
* | . | |
|
||||||
|
* | . | |
|
||||||
|
* | . | |
|
||||||
|
* +----+-----------+ |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* +-------------------------------+
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* A = viewport ; at (0, 0)
|
||||||
|
* B = visible ; at (x, y) where x < 0, y > 0
|
||||||
|
* C = critical ; at (0, y)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Maintaining per-browser state is a little bit of a hack involving attaching
|
||||||
|
* an object as the obfuscated dynamic JS property of the browser object, that
|
||||||
|
* hopefully no one but us will touch. See getViewportStateFromBrowser() for
|
||||||
|
* the property name.
|
||||||
|
*/
|
||||||
|
BrowserView.prototype = (
|
||||||
|
function() {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Privates
|
||||||
|
//
|
||||||
|
|
||||||
|
const kZoomLevelMin = 0.2;
|
||||||
|
const kZoomLevelMax = 4.0;
|
||||||
|
const kZoomLevelPrecision = 10000;
|
||||||
|
|
||||||
|
function visibleRectToCriticalRect(visibleRect, browserViewportState) {
|
||||||
|
return visibleRect.intersect(browserViewportState.viewportRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clampZoomLevel(zl) {
|
||||||
|
let bounded = Math.min(Math.max(kZoomLevelMin, zl), kZoomLevelMax);
|
||||||
|
return Math.round(bounded * kZoomLevelPrecision) / kZoomLevelPrecision;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pageZoomLevel(visibleRect, browserW, browserH) {
|
||||||
|
return clampZoomLevel(visibleRect.width / browserW);
|
||||||
|
}
|
||||||
|
|
||||||
|
function seenBrowser(browser) {
|
||||||
|
return !!(browser.__BrowserView__vps);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initBrowserState(browser, visibleRect) {
|
||||||
|
let [browserW, browserH] = getBrowserDimensions(browser);
|
||||||
|
|
||||||
|
let zoomLevel = pageZoomLevel(visibleRect, browserW, browserH);
|
||||||
|
let viewportRect = (new wsRect(0, 0, browserW, browserH)).scale(zoomLevel, zoomLevel);
|
||||||
|
|
||||||
|
dump('--- initing browser to ---' + endl);
|
||||||
|
browser.__BrowserView__vps = new BrowserView.BrowserViewportState(viewportRect,
|
||||||
|
visibleRect.x,
|
||||||
|
visibleRect.y,
|
||||||
|
zoomLevel);
|
||||||
|
dump(browser.__BrowserView__vps.toString() + endl);
|
||||||
|
dump('--------------------------' + endl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getViewportStateFromBrowser(browser) {
|
||||||
|
return browser.__BrowserView__vps;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBrowserDimensions(browser) {
|
||||||
|
let cdoc = browser.contentDocument;
|
||||||
|
|
||||||
|
// These might not exist yet depending on page load state
|
||||||
|
let body = cdoc.body || {};
|
||||||
|
let html = cdoc.documentElement || {};
|
||||||
|
let w = Math.max(body.scrollWidth || 0, html.scrollWidth);
|
||||||
|
let h = Math.max(body.scrollHeight || 0, html.scrollHeight);
|
||||||
|
|
||||||
|
return [w, h];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentScrollValues(browser) {
|
||||||
|
let cwu = getBrowserDOMWindowUtils(browser);
|
||||||
|
let scrollX = {};
|
||||||
|
let scrollY = {};
|
||||||
|
cwu.getScrollXY(false, scrollX, scrollY);
|
||||||
|
|
||||||
|
return [scrollX.value, scrollY.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBrowserDOMWindowUtils(browser) {
|
||||||
|
return browser.contentWindow
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNewBatchOperationState() {
|
||||||
|
return {
|
||||||
|
viewportSizeChanged: false,
|
||||||
|
dirtyAll: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function clampViewportWH(width, height, visibleRect) {
|
||||||
|
let minW = visibleRect.width;
|
||||||
|
let minH = visibleRect.height;
|
||||||
|
return [Math.max(width, minW), Math.max(height, minH)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function initContainer(container, visibleRect) {
|
||||||
|
container.style.width = visibleRect.width + 'px';
|
||||||
|
container.style.height = visibleRect.height + 'px';
|
||||||
|
container.style.overflow = '-moz-hidden-unscrollable';
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeContainerToViewport(container, viewportRect) {
|
||||||
|
container.style.width = viewportRect.width + 'px';
|
||||||
|
container.style.height = viewportRect.height + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
function simulateMozAfterSizeChange(browser, width, height) {
|
||||||
|
let ev = document.createElement("MouseEvents");
|
||||||
|
ev.initEvent("FakeMozAfterSizeChange", false, false, window, 0, width, height);
|
||||||
|
browser.dispatchEvent(ev);
|
||||||
|
}
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
// --- Change of coordinates functions --- //
|
||||||
|
|
||||||
|
|
||||||
|
// The following returned object becomes BrowserView.prototype
|
||||||
|
return {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Public instance methods
|
||||||
|
//
|
||||||
|
|
||||||
|
init: function init(container, visibleRect) {
|
||||||
|
this._batchOps = [];
|
||||||
|
this._container = container;
|
||||||
|
this._browserViewportState = null;
|
||||||
|
this._renderMode = 0;
|
||||||
|
this._tileManager = new TileManager(this._appendTile, this._removeTile, this);
|
||||||
|
this.setVisibleRect(visibleRect);
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// remove this eventually
|
||||||
|
this._resizeHack = {
|
||||||
|
maxSeenW: 0,
|
||||||
|
maxSeenH: 0
|
||||||
|
};
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
},
|
||||||
|
|
||||||
|
setVisibleRect: function setVisibleRect(r) {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
let vr = this._visibleRect;
|
||||||
|
|
||||||
|
if (!vr)
|
||||||
|
this._visibleRect = vr = r.clone();
|
||||||
|
else
|
||||||
|
vr.copyFrom(r);
|
||||||
|
|
||||||
|
if (bvs) {
|
||||||
|
bvs.visibleX = vr.left;
|
||||||
|
bvs.visibleY = vr.top;
|
||||||
|
|
||||||
|
// reclamp minimally to the new visible rect
|
||||||
|
//this.setViewportDimensions(bvs.viewportRect.right, bvs.viewportRect.bottom);
|
||||||
|
} else
|
||||||
|
this._viewportChanged(false, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
getVisibleRect: function getVisibleRect() {
|
||||||
|
return this._visibleRect.clone();
|
||||||
|
},
|
||||||
|
|
||||||
|
getVisibleRectX: function getVisibleRectX() { return this._visibleRect.x; },
|
||||||
|
getVisibleRectY: function getVisibleRectY() { return this._visibleRect.y; },
|
||||||
|
getVisibleRectWidth: function getVisibleRectWidth() { return this._visibleRect.width; },
|
||||||
|
getVisibleRectHeight: function getVisibleRectHeight() { return this._visibleRect.height; },
|
||||||
|
|
||||||
|
setViewportDimensions: function setViewportDimensions(width, height, causedByZoom) {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
let vis = this._visibleRect;
|
||||||
|
|
||||||
|
if (!bvs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//[width, height] = clampViewportWH(width, height, vis);
|
||||||
|
bvs.viewportRect.right = width;
|
||||||
|
bvs.viewportRect.bottom = height;
|
||||||
|
|
||||||
|
// XXX we might not want the user's page to disappear from under them
|
||||||
|
// at this point, which could happen if the container gets resized such
|
||||||
|
// that visible rect becomes entirely outside of viewport rect. might
|
||||||
|
// be wise to define what UX should be in this case, like a move occurs.
|
||||||
|
// then again, we could also argue this is the responsibility of the
|
||||||
|
// caller who would do such a thing...
|
||||||
|
|
||||||
|
this._viewportChanged(true, !!causedByZoom);
|
||||||
|
},
|
||||||
|
|
||||||
|
setZoomLevel: function setZoomLevel(zl) {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
|
||||||
|
if (!bvs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let newZL = clampZoomLevel(zl);
|
||||||
|
|
||||||
|
if (newZL != bvs.zoomLevel) {
|
||||||
|
let browserW = this.viewportToBrowser(bvs.viewportRect.right);
|
||||||
|
let browserH = this.viewportToBrowser(bvs.viewportRect.bottom);
|
||||||
|
bvs.zoomLevel = newZL; // side-effect: now scale factor in transformations is newZL
|
||||||
|
this.setViewportDimensions(this.browserToViewport(browserW),
|
||||||
|
this.browserToViewport(browserH));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getZoomLevel: function getZoomLevel() {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
if (!bvs)
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
return bvs.zoomLevel;
|
||||||
|
},
|
||||||
|
|
||||||
|
beginBatchOperation: function beginBatchOperation() {
|
||||||
|
this._batchOps.push(getNewBatchOperationState());
|
||||||
|
this.pauseRendering();
|
||||||
|
},
|
||||||
|
|
||||||
|
commitBatchOperation: function commitBatchOperation() {
|
||||||
|
let bops = this._batchOps;
|
||||||
|
|
||||||
|
if (bops.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let opState = bops.pop();
|
||||||
|
this._viewportChanged(opState.viewportSizeChanged, opState.dirtyAll);
|
||||||
|
this.resumeRendering();
|
||||||
|
},
|
||||||
|
|
||||||
|
discardBatchOperation: function discardBatchOperation() {
|
||||||
|
let bops = this._batchOps;
|
||||||
|
bops.pop();
|
||||||
|
this.resumeRendering();
|
||||||
|
},
|
||||||
|
|
||||||
|
discardAllBatchOperations: function discardAllBatchOperations() {
|
||||||
|
let bops = this._batchOps;
|
||||||
|
while (bops.length > 0)
|
||||||
|
this.discardBatchOperation();
|
||||||
|
},
|
||||||
|
|
||||||
|
moveVisibleBy: function moveVisibleBy(dx, dy) {
|
||||||
|
let vr = this._visibleRect;
|
||||||
|
let vs = this._browserViewportState;
|
||||||
|
|
||||||
|
this.onBeforeVisibleMove(dx, dy);
|
||||||
|
this.onAfterVisibleMove(dx, dy);
|
||||||
|
},
|
||||||
|
|
||||||
|
moveVisibleTo: function moveVisibleTo(x, y) {
|
||||||
|
let visibleRect = this._visibleRect;
|
||||||
|
let dx = x - visibleRect.x;
|
||||||
|
let dy = y - visibleRect.y;
|
||||||
|
this.moveBy(dx, dy);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls to this function need to be one-to-one with calls to
|
||||||
|
* resumeRendering()
|
||||||
|
*/
|
||||||
|
pauseRendering: function pauseRendering() {
|
||||||
|
this._renderMode++;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls to this function need to be one-to-one with calls to
|
||||||
|
* pauseRendering()
|
||||||
|
*/
|
||||||
|
resumeRendering: function resumeRendering(renderNow) {
|
||||||
|
if (this._renderMode > 0)
|
||||||
|
this._renderMode--;
|
||||||
|
|
||||||
|
if (renderNow || this._renderMode == 0)
|
||||||
|
this._tileManager.criticalRectPaint();
|
||||||
|
},
|
||||||
|
|
||||||
|
isRendering: function isRendering() {
|
||||||
|
return (this._renderMode == 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dx Guess delta to destination x coordinate
|
||||||
|
* @param dy Guess delta to destination y coordinate
|
||||||
|
*/
|
||||||
|
onBeforeVisibleMove: function onBeforeVisibleMove(dx, dy) {
|
||||||
|
let vs = this._browserViewportState;
|
||||||
|
let vr = this._visibleRect;
|
||||||
|
|
||||||
|
let destCR = visibleRectToCriticalRect(vr.clone().translate(dx, dy), vs);
|
||||||
|
|
||||||
|
this._tileManager.beginCriticalMove(destCR);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dx Actual delta to destination x coordinate
|
||||||
|
* @param dy Actual delta to destination y coordinate
|
||||||
|
*/
|
||||||
|
onAfterVisibleMove: function onAfterVisibleMove(dx, dy) {
|
||||||
|
let vs = this._browserViewportState;
|
||||||
|
let vr = this._visibleRect;
|
||||||
|
|
||||||
|
vr.translate(dx, dy);
|
||||||
|
vs.visibleX = vr.left;
|
||||||
|
vs.visibleY = vr.top;
|
||||||
|
|
||||||
|
let cr = visibleRectToCriticalRect(vr, vs);
|
||||||
|
|
||||||
|
this._tileManager.endCriticalMove(cr, this.isRendering());
|
||||||
|
},
|
||||||
|
|
||||||
|
setBrowser: function setBrowser(browser, skipZoom) {
|
||||||
|
let currentBrowser = this._browser;
|
||||||
|
|
||||||
|
let browserChanged = (currentBrowser !== browser);
|
||||||
|
|
||||||
|
if (currentBrowser) {
|
||||||
|
currentBrowser.removeEventListener("MozAfterPaint", this.handleMozAfterPaint, false);
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// change to the real event type and perhaps refactor the handler function name
|
||||||
|
currentBrowser.removeEventListener("FakeMozAfterSizeChange", this.handleMozAfterSizeChange, false);
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
this.discardAllBatchOperations();
|
||||||
|
|
||||||
|
currentBrowser.setAttribute("type", "content");
|
||||||
|
currentBrowser.docShell.isOffScreenBrowser = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._restoreBrowser(browser);
|
||||||
|
|
||||||
|
browser.setAttribute("type", "content-primary");
|
||||||
|
|
||||||
|
this.beginBatchOperation();
|
||||||
|
|
||||||
|
browser.addEventListener("MozAfterPaint", this.handleMozAfterPaint, false);
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// change to the real event type and perhaps refactor the handler function name
|
||||||
|
browser.addEventListener("FakeMozAfterSizeChange", this.handleMozAfterSizeChange, false);
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
if (!skipZoom) {
|
||||||
|
browser.docShell.isOffScreenBrowser = true;
|
||||||
|
this.zoomToPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._viewportChanged(browserChanged, browserChanged);
|
||||||
|
|
||||||
|
this.commitBatchOperation();
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMozAfterPaint: function handleMozAfterPaint(ev) {
|
||||||
|
let browser = this._browser;
|
||||||
|
let tm = this._tileManager;
|
||||||
|
let vs = this._browserViewportState;
|
||||||
|
|
||||||
|
let [scrollX, scrollY] = getContentScrollValues(browser);
|
||||||
|
let clientRects = ev.clientRects;
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// remove this, cf explanation in loop below
|
||||||
|
let hack = this._resizeHack;
|
||||||
|
let hackSizeChanged = false;
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
let rects = [];
|
||||||
|
// loop backwards to avoid xpconnect penalty for .length
|
||||||
|
for (let i = clientRects.length - 1; i >= 0; --i) {
|
||||||
|
let e = clientRects.item(i);
|
||||||
|
let r = new wsRect(e.left + scrollX,
|
||||||
|
e.top + scrollY,
|
||||||
|
e.width, e.height);
|
||||||
|
|
||||||
|
this.browserToViewportRect(r);
|
||||||
|
r.round();
|
||||||
|
|
||||||
|
if (r.right < 0 || r.bottom < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// remove this. this is where we make 'lazy' calculations
|
||||||
|
// that hint at a browser size change and fake the size change
|
||||||
|
// event dispach
|
||||||
|
if (r.right > hack.maxW) {
|
||||||
|
hack.maxW = rect.right;
|
||||||
|
hackSizeChanged = true;
|
||||||
|
}
|
||||||
|
if (r.bottom > hack.maxH) {
|
||||||
|
hack.maxH = rect.bottom;
|
||||||
|
hackSizeChanged = true;
|
||||||
|
}
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
r.restrictTo(vs.viewportRect);
|
||||||
|
rects.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// remove this, cf explanation in loop above
|
||||||
|
if (hackSizeChanged)
|
||||||
|
simulateMozAfterSizeChange(browser, hack.maxW, hack.maxH);
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
tm.dirtyRects(rects, this.isRendering());
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMozAfterSizeChange: function handleMozAfterPaint(ev) {
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// get the correct properties off of the event, these are wrong because
|
||||||
|
// we're using a MouseEvent since it has an X and Y prop of some sort and
|
||||||
|
// we piggyback on that.
|
||||||
|
let w = ev.screenX;
|
||||||
|
let h = ev.screenY;
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
this.setViewportDimensions(w, h);
|
||||||
|
},
|
||||||
|
|
||||||
|
zoomToPage: function zoomToPage() {
|
||||||
|
let browser = this._browser;
|
||||||
|
|
||||||
|
if (!browser)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let [w, h] = getBrowserDimensions(browser);
|
||||||
|
this.setZoomLevel(pageZoomLevel(this._visibleRect, w, h));
|
||||||
|
},
|
||||||
|
|
||||||
|
zoom: function zoom(aDirection) {
|
||||||
|
if (aDirection == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var zoomDelta = 0.05; // 1/20
|
||||||
|
if (aDirection >= 0)
|
||||||
|
zoomDelta *= -1;
|
||||||
|
|
||||||
|
this.zoomLevel = this._zoomLevel + zoomDelta;
|
||||||
|
},
|
||||||
|
|
||||||
|
viewportToBrowser: function viewportToBrowser(x) {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
|
||||||
|
if (!bvs)
|
||||||
|
throw "No browser is set";
|
||||||
|
|
||||||
|
return x / bvs.zoomLevel;
|
||||||
|
},
|
||||||
|
|
||||||
|
browserToViewport: function browserToViewport(x) {
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
|
||||||
|
if (!bvs)
|
||||||
|
throw "No browser is set";
|
||||||
|
|
||||||
|
return x * bvs.zoomLevel;
|
||||||
|
},
|
||||||
|
|
||||||
|
viewportToBrowserRect: function viewportToBrowserRect(rect) {
|
||||||
|
let f = this.viewportToBrowser(1.0);
|
||||||
|
return rect.scale(f, f);
|
||||||
|
},
|
||||||
|
|
||||||
|
browserToViewportRect: function browserToViewportRect(rect) {
|
||||||
|
let f = this.browserToViewport(1.0);
|
||||||
|
return rect.scale(f, f);
|
||||||
|
},
|
||||||
|
|
||||||
|
browserToViewportCanvasContext: function browserToViewportCanvasContext(ctx) {
|
||||||
|
let f = this.browserToViewport(1.0);
|
||||||
|
ctx.scale(f, f);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Private instance methods
|
||||||
|
//
|
||||||
|
|
||||||
|
_restoreBrowser: function _restoreBrowser(browser) {
|
||||||
|
let vr = this._visibleRect;
|
||||||
|
|
||||||
|
if (!seenBrowser(browser))
|
||||||
|
initBrowserState(browser, vr);
|
||||||
|
|
||||||
|
let bvs = getViewportStateFromBrowser(browser);
|
||||||
|
|
||||||
|
this._contentWindow = browser.contentWindow;
|
||||||
|
this._browser = browser;
|
||||||
|
this._browserViewportState = bvs;
|
||||||
|
vr.left = bvs.visibleX;
|
||||||
|
vr.top = bvs.visibleY;
|
||||||
|
this._tileManager.setBrowser(browser);
|
||||||
|
},
|
||||||
|
|
||||||
|
_viewportChanged: function _viewportChanged(viewportSizeChanged, dirtyAll) {
|
||||||
|
let bops = this._batchOps;
|
||||||
|
|
||||||
|
if (bops.length > 0) {
|
||||||
|
let opState = bops[bops.length - 1];
|
||||||
|
|
||||||
|
if (viewportSizeChanged)
|
||||||
|
opState.viewportSizeChanged = viewportSizeChanged;
|
||||||
|
|
||||||
|
if (dirtyAll)
|
||||||
|
opState.dirtyAll = dirtyAll;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bvs = this._browserViewportState;
|
||||||
|
let vis = this._visibleRect;
|
||||||
|
|
||||||
|
// !!! --- RESIZE HACK BEGIN -----
|
||||||
|
// We want to uncomment this for perf, but we can't with the hack in place
|
||||||
|
// because the mozAfterPaint gives us rects that we use to create the
|
||||||
|
// fake mozAfterResize event, so we can't just clear things.
|
||||||
|
/*
|
||||||
|
if (dirtyAll) {
|
||||||
|
// We're about to mark the entire viewport dirty, so we can clear any
|
||||||
|
// queued afterPaint events that will cause redundant draws
|
||||||
|
getBrowserDOMWindowUtils(this._browser).clearMozAfterPaintEvents();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// !!! --- RESIZE HACK END -------
|
||||||
|
|
||||||
|
if (bvs) {
|
||||||
|
resizeContainerToViewport(this._container, bvs.viewportRect);
|
||||||
|
|
||||||
|
this._tileManager.viewportChangeHandler(bvs.viewportRect,
|
||||||
|
visibleRectToCriticalRect(vis, bvs),
|
||||||
|
viewportSizeChanged,
|
||||||
|
dirtyAll);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendTile: function _appendTile(tile) {
|
||||||
|
let canvas = tile.getContentImage();
|
||||||
|
|
||||||
|
/*
|
||||||
|
canvas.style.position = "absolute";
|
||||||
|
canvas.style.left = tile.x + "px";
|
||||||
|
canvas.style.top = tile.y + "px";
|
||||||
|
*/
|
||||||
|
|
||||||
|
canvas.setAttribute("style", "position: absolute; left: " + tile.boundRect.left + "px; " + "top: " + tile.boundRect.top + "px;");
|
||||||
|
|
||||||
|
this._container.appendChild(canvas);
|
||||||
|
|
||||||
|
//dump('++ ' + tile.toString(true) + endl);
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeTile: function _removeTile(tile) {
|
||||||
|
let canvas = tile.getContentImage();
|
||||||
|
|
||||||
|
this._container.removeChild(canvas);
|
||||||
|
|
||||||
|
//dump('-- ' + tile.toString(true) + endl);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
)();
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Helper structures
|
||||||
|
//
|
||||||
|
|
||||||
|
BrowserView.BrowserViewportState = function(viewportRect,
|
||||||
|
visibleX,
|
||||||
|
visibleY,
|
||||||
|
zoomLevel) {
|
||||||
|
|
||||||
|
this.init(viewportRect, visibleX, visibleY, zoomLevel);
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserView.BrowserViewportState.prototype = {
|
||||||
|
|
||||||
|
init: function init(viewportRect, visibleX, visibleY, zoomLevel) {
|
||||||
|
this.viewportRect = viewportRect;
|
||||||
|
this.visibleX = visibleX;
|
||||||
|
this.visibleY = visibleY;
|
||||||
|
this.zoomLevel = zoomLevel;
|
||||||
|
},
|
||||||
|
|
||||||
|
clone: function clone() {
|
||||||
|
return new BrowserView.BrowserViewportState(this.viewportRect,
|
||||||
|
this.visibleX,
|
||||||
|
this.visibleY,
|
||||||
|
this.zoomLevel);
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function toString() {
|
||||||
|
let props = ['\tviewportRect=' + this.viewportRect.toString(),
|
||||||
|
'\tvisibleX=' + this.visibleX,
|
||||||
|
'\tvisibleY=' + this.visibleY,
|
||||||
|
'\tzoomLevel=' + this.zoomLevel];
|
||||||
|
|
||||||
|
return '[BrowserViewportState] {\n' + props.join(',\n') + '\n}';
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,359 @@
|
|||||||
|
let noop = function() {};
|
||||||
|
Browser = {
|
||||||
|
updateViewportSize: noop
|
||||||
|
/*************************************************************
|
||||||
|
function
|
||||||
|
let browser = document.getElementById("googlenews");
|
||||||
|
let cdoc = browser.contentDocument;
|
||||||
|
|
||||||
|
// These might not exist yet depending on page load state
|
||||||
|
var body = cdoc.body || {};
|
||||||
|
var html = cdoc.documentElement || {};
|
||||||
|
|
||||||
|
var w = Math.max(body.scrollWidth || 0, html.scrollWidth);
|
||||||
|
var h = Math.max(body.scrollHeight || 0, html.scrollHeight);
|
||||||
|
|
||||||
|
window.tileManager.viewportHandler(new wsRect(0, 0, w, h),
|
||||||
|
window.innerWidth,
|
||||||
|
new wsRect(0, 0, window.innerWidth, window.innerHeight),
|
||||||
|
false);
|
||||||
|
*************************************************************/
|
||||||
|
};
|
||||||
|
let ws = {
|
||||||
|
beginUpdateBatch: noop,
|
||||||
|
panTo: noop,
|
||||||
|
endUpdateBatch: noop
|
||||||
|
};
|
||||||
|
let Ci = Components.interfaces;
|
||||||
|
let bv = null;
|
||||||
|
let endl = "\n";
|
||||||
|
|
||||||
|
|
||||||
|
function BrowserView() {
|
||||||
|
this.init();
|
||||||
|
bindAll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserView.prototype = {
|
||||||
|
|
||||||
|
// --- PROPERTIES ---
|
||||||
|
// public:
|
||||||
|
// init()
|
||||||
|
// getViewportInnerBoundsRect(dx, dy)
|
||||||
|
// tileManager
|
||||||
|
// scrollbox
|
||||||
|
//
|
||||||
|
// private:
|
||||||
|
// _scrollbox
|
||||||
|
// _leftbar
|
||||||
|
// _rightbar
|
||||||
|
// _topbar
|
||||||
|
// _browser
|
||||||
|
// _tileManager
|
||||||
|
// _viewportRect
|
||||||
|
// _viewportInnerBoundsRect
|
||||||
|
//
|
||||||
|
|
||||||
|
get tileManager() { return this._tileManager; },
|
||||||
|
get scrollbox() { return this._scrollbox; },
|
||||||
|
|
||||||
|
init: function init() {
|
||||||
|
let scrollbox = document.getElementById("scrollbox")
|
||||||
|
.boxObject
|
||||||
|
.QueryInterface(Components.interfaces.nsIScrollBoxObject);
|
||||||
|
this._scrollbox = scrollbox;
|
||||||
|
|
||||||
|
let leftbar = document.getElementById("left_sidebar");
|
||||||
|
let rightbar = document.getElementById("right_sidebar");
|
||||||
|
let topbar = document.getElementById("top_urlbar");
|
||||||
|
this._leftbar = leftbar;
|
||||||
|
this._rightbar = rightbar;
|
||||||
|
this._topbar = topbar;
|
||||||
|
|
||||||
|
scrollbox.scrollTo(Math.round(leftbar.getBoundingClientRect().right), 0);
|
||||||
|
|
||||||
|
let tileContainer = document.getElementById("tile_container");
|
||||||
|
tileContainer.addEventListener("mousedown", onMouseDown, true);
|
||||||
|
tileContainer.addEventListener("mouseup", onMouseUp, true);
|
||||||
|
tileContainer.addEventListener("mousemove", onMouseMove, true);
|
||||||
|
this._tileContainer = tileContainer;
|
||||||
|
|
||||||
|
let tileManager = new TileManager(this.appendTile, this.removeTile, window.innerWidth);
|
||||||
|
this._tileManager = tileManager;
|
||||||
|
|
||||||
|
let browser = document.getElementById("googlenews");
|
||||||
|
this.setCurrentBrowser(browser, false); // sets this._browser
|
||||||
|
|
||||||
|
let cdoc = browser.contentDocument;
|
||||||
|
|
||||||
|
// These might not exist yet depending on page load state
|
||||||
|
let body = cdoc.body || {};
|
||||||
|
let html = cdoc.documentElement || {};
|
||||||
|
|
||||||
|
let w = Math.max(body.scrollWidth || 0, html.scrollWidth);
|
||||||
|
let h = Math.max(body.scrollHeight || 0, html.scrollHeight);
|
||||||
|
|
||||||
|
let viewportRect = new wsRect(0, 0, w, h);
|
||||||
|
this._viewportRect = viewportRect;
|
||||||
|
|
||||||
|
let viewportInnerBoundsRect = this.getViewportInnerBoundsRect();
|
||||||
|
this._viewportInnerBoundsRect = viewportInnerBoundsRect;
|
||||||
|
|
||||||
|
tileManager.viewportHandler(viewportRect,
|
||||||
|
window.innerWidth,
|
||||||
|
viewportInnerBoundsRect,
|
||||||
|
true);
|
||||||
|
},
|
||||||
|
|
||||||
|
resizeTileContainer: function resizeTileContainer() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollboxToViewportRect: function scrollboxToViewportRect(rect, clip) {
|
||||||
|
let leftbar = this._leftbar.getBoundingClientRect();
|
||||||
|
let rightbar = this._rightbar.getBoundingClientRect();
|
||||||
|
let topbar = this._topbar.getBoundingClientRect();
|
||||||
|
|
||||||
|
let xtrans = -leftbar.width;
|
||||||
|
let ytrans = -topbar.height;
|
||||||
|
let x = rect.x + xtrans;
|
||||||
|
let y = rect.y + ytrans;
|
||||||
|
|
||||||
|
// XXX we're cheating --- this is not really a clip, but its the only
|
||||||
|
// way this function is used
|
||||||
|
rect.x = (clip) ? Math.max(x, 0) : x;
|
||||||
|
rect.y = (clip) ? Math.max(y, 0) : y;
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
},
|
||||||
|
|
||||||
|
getScrollboxPosition: function getScrollboxPosition() {
|
||||||
|
let x = {};
|
||||||
|
let y = {};
|
||||||
|
this._scrollbox.getPosition(x, y);
|
||||||
|
return [x.value, y.value];
|
||||||
|
},
|
||||||
|
|
||||||
|
getViewportInnerBoundsRect: function getViewportInnerBoundsRect(dx, dy) {
|
||||||
|
if (!dx) dx = 0;
|
||||||
|
if (!dy) dy = 0;
|
||||||
|
|
||||||
|
let w = window.innerWidth;
|
||||||
|
let h = window.innerHeight;
|
||||||
|
|
||||||
|
let leftbar = this._leftbar.getBoundingClientRect();
|
||||||
|
let rightbar = this._rightbar.getBoundingClientRect();
|
||||||
|
let topbar = this._topbar.getBoundingClientRect();
|
||||||
|
|
||||||
|
let leftinner = Math.max(leftbar.right - dx, 0);
|
||||||
|
let rightinner = Math.min(rightbar.left - dx, w);
|
||||||
|
let topinner = Math.max(topbar.bottom - dy, 0);
|
||||||
|
|
||||||
|
let [x, y] = this.getScrollboxPosition();
|
||||||
|
|
||||||
|
return this.scrollboxToViewportRect(new wsRect(x + dx, y + dy, rightinner - leftinner, h - topinner),
|
||||||
|
true);
|
||||||
|
},
|
||||||
|
|
||||||
|
appendTile: function appendTile(tile) {
|
||||||
|
let canvas = tile.contentImage;
|
||||||
|
|
||||||
|
canvas.style.position = "absolute";
|
||||||
|
canvas.style.left = tile.x + "px";
|
||||||
|
canvas.style.top = tile.y + "px";
|
||||||
|
|
||||||
|
let tileContainer = document.getElementById("tile_container");
|
||||||
|
tileContainer.appendChild(canvas);
|
||||||
|
|
||||||
|
dump('++ ' + tile.toString() + endl);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeTile: function removeTile(tile) {
|
||||||
|
let canvas = tile.contentImage;
|
||||||
|
|
||||||
|
let tileContainer = document.getElementById("tile_container");
|
||||||
|
tileContainer.removeChild(canvas);
|
||||||
|
|
||||||
|
dump('-- ' + tile.toString() + endl);
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollBy: function scrollBy(dx, dy) {
|
||||||
|
// TODO
|
||||||
|
this.onBeforeScroll();
|
||||||
|
this.onAfterScroll();
|
||||||
|
},
|
||||||
|
|
||||||
|
// x: current x
|
||||||
|
// y: current y
|
||||||
|
// dx: delta to get to x from current x
|
||||||
|
// dy: delta to get to y from current y
|
||||||
|
onBeforeScroll: function onBeforeScroll(x, y, dx, dy) {
|
||||||
|
this.tileManager.onBeforeScroll(this.getViewportInnerBoundsRect(dx, dy));
|
||||||
|
|
||||||
|
// shouldn't update margin if it doesn't need to be changed
|
||||||
|
let sidebars = document.getElementsByClassName("sidebar");
|
||||||
|
for (let i = 0; i < sidebars.length; i++) {
|
||||||
|
let sidebar = sidebars[i];
|
||||||
|
sidebar.style.margin = (y + dy) + "px 0px 0px 0px";
|
||||||
|
}
|
||||||
|
|
||||||
|
let urlbar = document.getElementById("top_urlbar");
|
||||||
|
urlbar.style.margin = "0px 0px 0px " + (x + dx) + "px";
|
||||||
|
},
|
||||||
|
|
||||||
|
onAfterScroll: function onAfterScroll(x, y, dx, dy) {
|
||||||
|
this.tileManager.onAfterScroll(this.getViewportInnerBoundsRect());
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentBrowser: function setCurrentBrowser(browser, skipZoom) {
|
||||||
|
let currentBrowser = this._browser;
|
||||||
|
if (currentBrowser) {
|
||||||
|
// backup state
|
||||||
|
currentBrowser.mZoomLevel = this.zoomLevel;
|
||||||
|
currentBrowser.mPanX = ws._viewingRect.x;
|
||||||
|
currentBrowser.mPanY = ws._viewingRect.y;
|
||||||
|
|
||||||
|
// stop monitor paint events for this browser
|
||||||
|
currentBrowser.removeEventListener("MozAfterPaint", this.handleMozAfterPaint, false);
|
||||||
|
currentBrowser.setAttribute("type", "content");
|
||||||
|
currentBrowser.docShell.isOffScreenBrowser = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.setAttribute("type", "content-primary");
|
||||||
|
if (!skipZoom)
|
||||||
|
browser.docShell.isOffScreenBrowser = true;
|
||||||
|
|
||||||
|
// start monitoring paint events for this browser
|
||||||
|
browser.addEventListener("MozAfterPaint", this.handleMozAfterPaint, false);
|
||||||
|
|
||||||
|
this._browser = browser;
|
||||||
|
|
||||||
|
// endLoading(and startLoading in most cases) calls zoom anyway
|
||||||
|
if (!skipZoom) {
|
||||||
|
this.zoomToPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("mZoomLevel" in browser) {
|
||||||
|
// restore last state
|
||||||
|
ws.beginUpdateBatch();
|
||||||
|
ws.panTo(browser.mPanX, browser.mPanY);
|
||||||
|
this.zoomLevel = browser.mZoomLevel;
|
||||||
|
ws.endUpdateBatch(true);
|
||||||
|
|
||||||
|
// drop the cache
|
||||||
|
delete browser.mZoomLevel;
|
||||||
|
delete browser.mPanX;
|
||||||
|
delete browser.mPanY;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tileManager.browser = browser;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMozAfterPaint: function handleMozAfterPaint(ev) {
|
||||||
|
this.tileManager.handleMozAfterPaint(ev);
|
||||||
|
},
|
||||||
|
|
||||||
|
zoomToPage: function zoomToPage() {
|
||||||
|
/********************************************************
|
||||||
|
let needToPanToTop = this._needToPanToTop;
|
||||||
|
// Ensure pages are panned at the top before zooming/painting
|
||||||
|
// combine the initial pan + zoom into a transaction
|
||||||
|
if (needToPanToTop) {
|
||||||
|
ws.beginUpdateBatch();
|
||||||
|
this._needToPanToTop = false;
|
||||||
|
ws.panTo(0, -BrowserUI.toolbarH);
|
||||||
|
}
|
||||||
|
// Adjust the zoomLevel to fit the page contents in our window width
|
||||||
|
let [contentW, ] = this._contentAreaDimensions;
|
||||||
|
let fakeW = this._fakeWidth;
|
||||||
|
|
||||||
|
if (contentW > fakeW)
|
||||||
|
this.zoomLevel = fakeW / contentW;
|
||||||
|
|
||||||
|
if (needToPanToTop)
|
||||||
|
ws.endUpdateBatch();
|
||||||
|
********************************************************/
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function onResize(e) {
|
||||||
|
let browser = document.getElementById("googlenews");
|
||||||
|
let cdoc = browser.contentDocument;
|
||||||
|
|
||||||
|
// These might not exist yet depending on page load state
|
||||||
|
var body = cdoc.body || {};
|
||||||
|
var html = cdoc.documentElement || {};
|
||||||
|
|
||||||
|
var w = Math.max(body.scrollWidth || 0, html.scrollWidth);
|
||||||
|
var h = Math.max(body.scrollHeight || 0, html.scrollHeight);
|
||||||
|
|
||||||
|
if (bv)
|
||||||
|
bv.tileManager.viewportHandler(new wsRect(0, 0, w, h),
|
||||||
|
window.innerWidth,
|
||||||
|
bv.getViewportInnerBoundsRect(),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseDown(e) {
|
||||||
|
window._isDragging = true;
|
||||||
|
window._dragStart = {x: e.clientX, y: e.clientY};
|
||||||
|
|
||||||
|
bv.tileManager.startPanning();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseUp() {
|
||||||
|
window._isDragging = false;
|
||||||
|
|
||||||
|
bv.tileManager.endPanning();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseMove(e) {
|
||||||
|
if (window._isDragging) {
|
||||||
|
let scrollbox = bv.scrollbox;
|
||||||
|
|
||||||
|
let x = {};
|
||||||
|
let y = {};
|
||||||
|
let w = {};
|
||||||
|
let h = {};
|
||||||
|
scrollbox.getPosition(x, y);
|
||||||
|
scrollbox.getScrolledSize(w, h);
|
||||||
|
|
||||||
|
let dx = window._dragStart.x - e.clientX;
|
||||||
|
let dy = window._dragStart.y - e.clientY;
|
||||||
|
|
||||||
|
// XXX if max(x, 0) > scrollwidth we shouldn't do anything (same for y/height)
|
||||||
|
let newX = Math.max(x.value + dx, 0);
|
||||||
|
let newY = Math.max(y.value + dy, 0);
|
||||||
|
|
||||||
|
if (newX < w.value || newY < h.value) {
|
||||||
|
// clip dx and dy to prevent us from going below 0
|
||||||
|
dx = Math.max(dx, -x.value);
|
||||||
|
dy = Math.max(dy, -y.value);
|
||||||
|
|
||||||
|
bv.onBeforeScroll(x.value, y.value, dx, dy);
|
||||||
|
|
||||||
|
/*dump("==========scroll==========" + endl);
|
||||||
|
dump("delta: " + dx + "," + dy + endl);
|
||||||
|
let xx = {};
|
||||||
|
let yy = {};
|
||||||
|
scrollbox.getPosition(xx, yy);
|
||||||
|
dump(xx.value + "," + yy.value + endl);*/
|
||||||
|
|
||||||
|
scrollbox.scrollBy(dx, dy);
|
||||||
|
|
||||||
|
/*scrollbox.getPosition(xx, yy);
|
||||||
|
dump(xx.value + "," + yy.value + endl);
|
||||||
|
dump("==========================" + endl);*/
|
||||||
|
|
||||||
|
bv.onAfterScroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window._dragStart = {x: e.clientX, y: e.clientY};
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoad() {
|
||||||
|
bv = new BrowserView();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?xml-stylesheet href="chrome://tile/skin/overlay.css" type="text/css"?>
|
||||||
|
<!DOCTYPE overlay SYSTEM "chrome://tile/locale/tile.dtd">
|
||||||
|
<overlay id="tile-overlay"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<script src="overlay.js"/>
|
||||||
|
<stringbundleset id="stringbundleset">
|
||||||
|
<stringbundle id="tile-strings" src="chrome://tile/locale/tile.properties"/>
|
||||||
|
</stringbundleset>
|
||||||
|
|
||||||
|
<menupopup id="menu_ToolsPopup">
|
||||||
|
<menuitem id="tile-hello" label="&tile.label;"
|
||||||
|
oncommand="tile.onMenuItemCommand(event);"/>
|
||||||
|
</menupopup>
|
||||||
|
</overlay>
|
469
toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
Normal file
469
toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
<window
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
onload="onAlmostLoad();"
|
||||||
|
style="background-color:white;"
|
||||||
|
width="800"
|
||||||
|
height="480"
|
||||||
|
onresize="onResize();"
|
||||||
|
onkeypress="onKeyPress(event);">
|
||||||
|
|
||||||
|
<script type="application/javascript" src="WidgetStack.js"/>
|
||||||
|
<script type="application/javascript" src="TileManager.js"/>
|
||||||
|
<script type="application/javascript" src="BrowserView.js"/>
|
||||||
|
<script type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
// We do not endorse the use of globals, but this is just a closed lab
|
||||||
|
// environment. What could possibly go wrong? ...
|
||||||
|
let bv = null;
|
||||||
|
let scrollbox = null;
|
||||||
|
let leftbar = null;
|
||||||
|
let rightbar = null;
|
||||||
|
let topbar = null;
|
||||||
|
|
||||||
|
function debug() {
|
||||||
|
let w = {};
|
||||||
|
let h = {};
|
||||||
|
scrollbox.getScrolledSize(w, h);
|
||||||
|
let container = document.getElementById("tile_container");
|
||||||
|
let [x, y] = getScrollboxPosition();
|
||||||
|
let [w, h] = [w.value, h.value];
|
||||||
|
if (bv) {
|
||||||
|
dump('----------------------DEBUG!-------------------------\n');
|
||||||
|
dump(bv._browserViewportState.toString() + endl);
|
||||||
|
|
||||||
|
dump(endl);
|
||||||
|
|
||||||
|
let cr = bv._tileManager._criticalRect;
|
||||||
|
dump('criticalRect from BV: ' + (cr ? cr.toString() : null) + endl);
|
||||||
|
dump('visibleRect from BV : ' + bv._visibleRect.toString() + endl);
|
||||||
|
dump('visibleRect from foo: ' + scrollboxToViewportRect(getVisibleRect()) + endl);
|
||||||
|
|
||||||
|
dump(endl);
|
||||||
|
|
||||||
|
dump('container width,height from BV: ' + bv._container.style.width + ', '
|
||||||
|
+ bv._container.style.height + endl);
|
||||||
|
dump('container width,height via DOM: ' + container.style.width + ', '
|
||||||
|
+ container.style.height + endl);
|
||||||
|
|
||||||
|
dump(endl);
|
||||||
|
|
||||||
|
dump('scrollbox position : ' + x + ', ' + y + endl);
|
||||||
|
dump('scrollbox scrolledsize: ' + w + ', ' + h + endl);
|
||||||
|
|
||||||
|
dump(endl);
|
||||||
|
|
||||||
|
dump('tilecache capacity: ' + bv._tileManager._tileCache.getCapacity() + endl);
|
||||||
|
dump('tilecache size : ' + bv._tileManager._tileCache.size + endl);
|
||||||
|
dump('tilecache numFree : ' + bv._tileManager._tileCache.numFree + endl);
|
||||||
|
dump('tilecache iBound : ' + bv._tileManager._tileCache.iBound + endl);
|
||||||
|
dump('tilecache jBound : ' + bv._tileManager._tileCache.jBound + endl);
|
||||||
|
dump('tilecache _lru : ' + bv._tileManager._tileCache._lru + endl);
|
||||||
|
|
||||||
|
dump('-----------------------------------------------------\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function debugTile(i, j) {
|
||||||
|
let tc = bv._tileManager._tileCache;
|
||||||
|
let t = tc.getTile(i, j);
|
||||||
|
|
||||||
|
dump('------ DEBUGGING TILE (' + i + ',' + j + ') --------\n');
|
||||||
|
|
||||||
|
dump('in bounds: ' + tc.inBounds(i, j) + endl);
|
||||||
|
dump('occupied : ' + tc._isOccupied(i, j) + endl);
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
dump('toString : ' + t.toString(true) + endl);
|
||||||
|
dump('free : ' + t.free + endl);
|
||||||
|
dump('dirtyRect: ' + t._dirtyTileCanvasRect + endl);
|
||||||
|
|
||||||
|
let len = tc._tilePool.length;
|
||||||
|
for (let k = 0; k < len; ++k)
|
||||||
|
if (tc._tilePool[k] === t)
|
||||||
|
dump('found in tilePool at index ' + k + endl);
|
||||||
|
}
|
||||||
|
|
||||||
|
dump('------------------------------------\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeyPress(e) {
|
||||||
|
const a = 97; // debug all critical tiles
|
||||||
|
const c = 99; // set tilecache capacity
|
||||||
|
const d = 100; // debug dump
|
||||||
|
const f = 102; // run noop() through forEachIntersectingRect (for timing)
|
||||||
|
const i = 105; // toggle info click mode
|
||||||
|
const l = 108; // restart lazy crawl
|
||||||
|
const m = 109; // fix mouseout
|
||||||
|
const t = 116; // debug given list of tiles separated by space
|
||||||
|
|
||||||
|
switch (e.charCode) {
|
||||||
|
case d:
|
||||||
|
debug();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case l:
|
||||||
|
bv._tileManager.restartLazyCrawl(bv._tileManager._criticalRect);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case c:
|
||||||
|
let cap = parseInt(window.prompt('new capacity'));
|
||||||
|
bv._tileManager._tileCache.setCapacity(cap);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case f:
|
||||||
|
let noop = function noop() { for (let i = 0; i < 10; ++i); };
|
||||||
|
bv._tileManager._tileCache.forEachIntersectingRect(bv._tileManager._criticalRect,
|
||||||
|
false, noop, window);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case t:
|
||||||
|
let ijstrs = window.prompt('row,col plz').split(' ');
|
||||||
|
for each (let ijstr in ijstrs) {
|
||||||
|
let [i, j] = ijstr.split(',').map(function (x) parseInt(x));
|
||||||
|
debugTile(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case a:
|
||||||
|
let cr = bv._tileManager._criticalRect;
|
||||||
|
dump('>>>>>> critical rect is ' + (cr ? cr.toString() : cr) + endl);
|
||||||
|
if (cr) {
|
||||||
|
let starti = cr.left >> kTileExponentWidth;
|
||||||
|
let endi = cr.right >> kTileExponentWidth;
|
||||||
|
|
||||||
|
let startj = cr.top >> kTileExponentHeight;
|
||||||
|
let endj = cr.bottom >> kTileExponentHeight;
|
||||||
|
|
||||||
|
for (var jj = startj; jj <= endj; ++jj)
|
||||||
|
for (var ii = starti; ii <= endi; ++ii)
|
||||||
|
debugTile(ii, jj);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case i:
|
||||||
|
window.infoMode = !window.infoMode;
|
||||||
|
break;
|
||||||
|
case m:
|
||||||
|
onMouseUp();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResize(e) {
|
||||||
|
if (bv) {
|
||||||
|
bv.beginBatchOperation();
|
||||||
|
bv.setVisibleRect(scrollboxToViewportRect(getVisibleRect()));
|
||||||
|
bv.zoomToPage();
|
||||||
|
bv.commitBatchOperation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseDown(e) {
|
||||||
|
if (window.infoMode) {
|
||||||
|
let [basex, basey] = getScrollboxPosition();
|
||||||
|
let [x, y] = scrollboxToViewportXY(basex + e.clientX, basey + e.clientY);
|
||||||
|
let i = x >> kTileExponentWidth;
|
||||||
|
let j = y >> kTileExponentHeight;
|
||||||
|
|
||||||
|
debugTile(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
window._isDragging = true;
|
||||||
|
window._dragStart = {x: e.clientX, y: e.clientY};
|
||||||
|
|
||||||
|
bv.pauseRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseUp() {
|
||||||
|
window._isDragging = false;
|
||||||
|
bv.resumeRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseMove(e) {
|
||||||
|
if (window._isDragging) {
|
||||||
|
let x = {};
|
||||||
|
let y = {};
|
||||||
|
let w = {};
|
||||||
|
let h = {};
|
||||||
|
scrollbox.getPosition(x, y);
|
||||||
|
scrollbox.getScrolledSize(w, h);
|
||||||
|
|
||||||
|
let dx = window._dragStart.x - e.clientX;
|
||||||
|
let dy = window._dragStart.y - e.clientY;
|
||||||
|
|
||||||
|
// XXX if max(x, 0) > scrollwidth we shouldn't do anything (same for y/height)
|
||||||
|
let newX = Math.max(x.value + dx, 0);
|
||||||
|
let newY = Math.max(y.value + dy, 0);
|
||||||
|
|
||||||
|
if (newX < w.value || newY < h.value) {
|
||||||
|
// clip dx and dy to prevent us from going below 0
|
||||||
|
dx = Math.max(dx, -x.value);
|
||||||
|
dy = Math.max(dy, -y.value);
|
||||||
|
|
||||||
|
let oldx = x.value;
|
||||||
|
let oldy = y.value;
|
||||||
|
|
||||||
|
bv.onBeforeVisibleMove(dx, dy);
|
||||||
|
|
||||||
|
updateBars(oldx, oldy, dx, dy);
|
||||||
|
scrollbox.scrollBy(dx, dy);
|
||||||
|
|
||||||
|
let [newx, newy] = getScrollboxPosition();
|
||||||
|
let realdx = newx - oldx;
|
||||||
|
let realdy = newy - oldy;
|
||||||
|
|
||||||
|
updateBars(oldx, oldy, realdx, realdy);
|
||||||
|
bv.onAfterVisibleMove(realdx, realdy);
|
||||||
|
}
|
||||||
|
window._dragStart = {x: e.clientX, y: e.clientY};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAlmostLoad() {
|
||||||
|
window._isDragging = false;
|
||||||
|
window.infoMode = false;
|
||||||
|
window.setTimeout(onLoad, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoad() {
|
||||||
|
// ----------------------------------------------------
|
||||||
|
scrollbox = document.getElementById("scrollbox")
|
||||||
|
.boxObject
|
||||||
|
.QueryInterface(Components.interfaces.nsIScrollBoxObject);
|
||||||
|
leftbar = document.getElementById("left_sidebar");
|
||||||
|
rightbar = document.getElementById("right_sidebar");
|
||||||
|
topbar = document.getElementById("top_urlbar");
|
||||||
|
// ----------------------------------------------------
|
||||||
|
|
||||||
|
let initX = Math.round(leftbar.getBoundingClientRect().right);
|
||||||
|
dump('scrolling to ' + initX + endl);
|
||||||
|
scrollbox.scrollTo(initX, 0);
|
||||||
|
let [x, y] = getScrollboxPosition();
|
||||||
|
dump(' scrolled to ' + x + ',' + y + endl);
|
||||||
|
|
||||||
|
let container = document.getElementById("tile_container");
|
||||||
|
container.addEventListener("mousedown", onMouseDown, true);
|
||||||
|
container.addEventListener("mouseup", onMouseUp, true);
|
||||||
|
container.addEventListener("mousemove", onMouseMove, true);
|
||||||
|
|
||||||
|
bv = new BrowserView(container, scrollboxToViewportRect(getVisibleRect()));
|
||||||
|
|
||||||
|
let browser = document.getElementById("googlenews");
|
||||||
|
bv.setBrowser(browser, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBars(x, y, dx, dy) {
|
||||||
|
return;
|
||||||
|
// shouldn't update margin if it doesn't need to be changed
|
||||||
|
let sidebars = document.getElementsByClassName("sidebar");
|
||||||
|
for (let i = 0; i < sidebars.length; i++) {
|
||||||
|
let sidebar = sidebars[i];
|
||||||
|
sidebar.style.margin = (y + dy) + "px 0px 0px 0px";
|
||||||
|
}
|
||||||
|
|
||||||
|
let urlbar = document.getElementById("top_urlbar");
|
||||||
|
urlbar.style.margin = "0px 0px 0px " + (x + dx) + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewportToScrollboxXY(x, y) {
|
||||||
|
return scrollboxToViewportXY(x, y, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollboxToViewportXY(x, y) {
|
||||||
|
if (!x) x = 0;
|
||||||
|
if (!y) y = 0;
|
||||||
|
|
||||||
|
// shield your eyes!
|
||||||
|
let direction = (arguments.length >= 3) ? arguments[2] : 1;
|
||||||
|
|
||||||
|
let leftbarcr = leftbar.getBoundingClientRect();
|
||||||
|
let rightbarcr = rightbar.getBoundingClientRect();
|
||||||
|
let topbarcr = topbar.getBoundingClientRect();
|
||||||
|
|
||||||
|
let xtrans = direction * (-leftbarcr.width);
|
||||||
|
let ytrans = direction * (-topbarcr.height);
|
||||||
|
x += xtrans;
|
||||||
|
y += ytrans;
|
||||||
|
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollboxToBrowserXY(browserView, x, y) {
|
||||||
|
[x, y] = scrollboxToViewportXY(x, y);
|
||||||
|
return [browserView.viewportToBrowser(x),
|
||||||
|
browserView.viewportToBrowser(y)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollboxToViewportRect(rect) {
|
||||||
|
let leftbarcr = leftbar.getBoundingClientRect();
|
||||||
|
let topbarcr = topbar.getBoundingClientRect();
|
||||||
|
|
||||||
|
let xtrans = -leftbarcr.width;
|
||||||
|
let ytrans = -topbarcr.height;
|
||||||
|
|
||||||
|
rect.translate(xtrans, ytrans);
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScrollboxPosition() {
|
||||||
|
let x = {};
|
||||||
|
let y = {};
|
||||||
|
scrollbox.getPosition(x, y);
|
||||||
|
return [x.value, y.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentScrollValues(browser) {
|
||||||
|
let cwu = getBrowserDOMWindowUtils(browser);
|
||||||
|
let scrollX = {};
|
||||||
|
let scrollY = {};
|
||||||
|
cwu.getScrollXY(false, scrollX, scrollY);
|
||||||
|
|
||||||
|
return [scrollX.value, scrollY.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBrowserDOMWindowUtils(browser) {
|
||||||
|
return browser.contentWindow
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBrowserClientRect(browser, el) {
|
||||||
|
let [scrollX, scrollY] = getContentScrollValues(browser);
|
||||||
|
let r = el.getBoundingClientRect();
|
||||||
|
|
||||||
|
return new wsRect(r.left + scrollX,
|
||||||
|
r.top + scrollY,
|
||||||
|
r.width, r.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToElement(browser, el) {
|
||||||
|
var elRect = getPagePosition(browser, el);
|
||||||
|
bv.browserToViewportRect(elRect);
|
||||||
|
elRect.round();
|
||||||
|
this.scrollTo(elRect.x, elRect.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
function zoomToElement(aElement) {
|
||||||
|
const margin = 15;
|
||||||
|
|
||||||
|
let elRect = getBrowserClientRect(browser, aElement);
|
||||||
|
let elWidth = elRect.width;
|
||||||
|
let vrWidth = bv.visibleRect.width;
|
||||||
|
/* Try to set zoom-level such that once zoomed element is as wide
|
||||||
|
* as the visible rect */
|
||||||
|
let zoomLevel = vrtWidth / (elWidth + (2 * margin));
|
||||||
|
|
||||||
|
bv.beginBatchOperation();
|
||||||
|
|
||||||
|
bv.setZoomLevel(zoomLevel);
|
||||||
|
|
||||||
|
/* If zoomLevel ends up clamped to less than asked for, calculate
|
||||||
|
* how many more screen pixels will fit horizontally in addition to
|
||||||
|
* element's width. This ensures that more of the webpage is
|
||||||
|
* showing instead of the navbar. Bug 480595. */
|
||||||
|
let xpadding = Math.max(margin, vrWidth - bv.browserToViewport(elWidth));
|
||||||
|
|
||||||
|
// XXX TODO these arguments are wrong, we still have to transform the coordinates
|
||||||
|
// from viewport to scrollbox before sending them to scrollTo
|
||||||
|
this.scrollTo(Math.floor(Math.max(bv.browserToViewport(elRect.x) - xpadding, 0)),
|
||||||
|
Math.floor(Math.max(bv.browserToViewport(elRect.y) - margin, 0)));
|
||||||
|
|
||||||
|
bv.commitBatchOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function zoomFromElement(browser, aElement) {
|
||||||
|
let elRect = getBrowserClientRect(browser, aElement);
|
||||||
|
|
||||||
|
bv.beginBatchOperation();
|
||||||
|
|
||||||
|
// pan to the element
|
||||||
|
// don't bother with x since we're zooming all the way out
|
||||||
|
bv.zoomToPage();
|
||||||
|
|
||||||
|
// XXX have this center the element on the page
|
||||||
|
// XXX TODO these arguments are wrong, we still have to transform the coordinates
|
||||||
|
// from viewport to scrollbox before sending them to scrollTo
|
||||||
|
this.scrollTo(0, Math.floor(Math.max(0, bv.browserToViewport(elRect.y))));
|
||||||
|
|
||||||
|
bv.commitBatchOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the content element for a given point in client coordinates
|
||||||
|
* (relative to the top left corner of the chrome window).
|
||||||
|
*/
|
||||||
|
function elementFromPoint(browser, browserView, x, y) {
|
||||||
|
[x, y] = scrollboxToBrowserXY(browserView, x, y);
|
||||||
|
let cwu = getBrowserDOMWindowUtils(browser);
|
||||||
|
return cwu.elementFromPoint(x, y,
|
||||||
|
true, /* ignore root scroll frame*/
|
||||||
|
false); /* don't flush layout */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensures that a given content element is visible */
|
||||||
|
function ensureElementIsVisible(browser, aElement) {
|
||||||
|
let elRect = getBrowserClientRect(browser, aElement);
|
||||||
|
|
||||||
|
bv.browserToViewportRect(elRect);
|
||||||
|
|
||||||
|
let curRect = bv.visibleRect;
|
||||||
|
let newx = curRect.x;
|
||||||
|
let newy = curRect.y;
|
||||||
|
|
||||||
|
if (elRect.x < curRect.x || elRect.width > curRect.width) {
|
||||||
|
newx = elRect.x;
|
||||||
|
} else if (elRect.x + elRect.width > curRect.x + curRect.width) {
|
||||||
|
newx = elRect.x - curRect.width + elRect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elRect.y < curRect.y || elRect.height > curRect.height) {
|
||||||
|
newy = elRect.y;
|
||||||
|
} else if (elRect.y + elRect.height > curRect.y + curRect.height) {
|
||||||
|
newy = elRect.y - curRect.height + elRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX TODO these arguments are wrong, we still have to transform the coordinates
|
||||||
|
// from viewport to scrollbox before sending them to scrollTo
|
||||||
|
this.scrollTo(newx, newy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a mehful way of getting the visible rect in scrollbox coordinates
|
||||||
|
// that we use in this here lab environment and hopefully nowhere in real fennec
|
||||||
|
function getVisibleRect() {
|
||||||
|
let w = window.innerWidth;
|
||||||
|
let h = window.innerHeight;
|
||||||
|
|
||||||
|
let [x, y] = getScrollboxPosition();
|
||||||
|
|
||||||
|
return new wsRect(x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<scrollbox id="scrollbox" style="-moz-box-orient: vertical; overflow: scroll;" flex="1">
|
||||||
|
<hbox id="top_urlbar" style="background-color: pink"><textbox flex="1"/></hbox>
|
||||||
|
<hbox style="position: relative">
|
||||||
|
<vbox id="left_sidebar" class="sidebar" style="background-color: red"><button label="left sidebar"/></vbox>
|
||||||
|
<box>
|
||||||
|
<html:div id="tile_container" style="position: relative; width: 800px; height: 480px; overflow: -moz-hidden-unscrollable;"/>
|
||||||
|
</box>
|
||||||
|
<vbox id="right_sidebar" class="sidebar" style="background-color: blue"><button label="right sidebar"/></vbox>
|
||||||
|
</hbox>
|
||||||
|
</scrollbox>
|
||||||
|
|
||||||
|
<box>
|
||||||
|
<html:div style="position: relative; overflow: hidden; max-width: 0px; max-height: 0px; visibility: hidden;">
|
||||||
|
<html:div id="browsers" style="position: absolute;">
|
||||||
|
<!-- <browser id="googlenews" src="http://www.webhamster.com/" type="content" style="width: 1024px; height: 614px"/> -->
|
||||||
|
<browser id="googlenews" src="http://news.google.com/" type="content" style="width: 1024px; height: 614px"/>
|
||||||
|
</html:div>
|
||||||
|
</html:div>
|
||||||
|
</box>
|
||||||
|
|
||||||
|
</window>
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||||
|
|
||||||
|
<window id="main" title="My App" width="300" height="300"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<caption label="Hello World"/>
|
||||||
|
</window>
|
@ -0,0 +1,15 @@
|
|||||||
|
var tile = {
|
||||||
|
onLoad: function() {
|
||||||
|
// initialization code
|
||||||
|
this.initialized = true;
|
||||||
|
this.strings = document.getElementById("tile-strings");
|
||||||
|
},
|
||||||
|
onMenuItemCommand: function(e) {
|
||||||
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIPromptService);
|
||||||
|
promptService.alert(window, this.strings.getString("helloMessageTitle"),
|
||||||
|
this.strings.getString("helloMessage"));
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
window.addEventListener("load", function(e) { tile.onLoad(e); }, false);
|
@ -0,0 +1 @@
|
|||||||
|
<!ENTITY tile.label "Your localized menuitem">
|
@ -0,0 +1,3 @@
|
|||||||
|
helloMessage=Hello World!
|
||||||
|
helloMessageTitle=Hello
|
||||||
|
prefMessage=Int Pref Value: %d
|
@ -0,0 +1,5 @@
|
|||||||
|
/* This is just an example. You shouldn't do this. */
|
||||||
|
#tile-hello
|
||||||
|
{
|
||||||
|
color: red ! important;
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
pref("toolkit.defaultChromeURI", "chrome://tile/content/foo.xul");
|
||||||
|
pref("javascript.options.jit.chrome", true);
|
||||||
|
pref("javascript.options.jit.content", false);
|
||||||
|
pref("browser.dom.window.dump.enabled", true);
|
17
toolkit/content/tests/fennec-tile-testapp/install.rdf
Normal file
17
toolkit/content/tests/fennec-tile-testapp/install.rdf
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||||
|
<Description about="urn:mozilla:install-manifest">
|
||||||
|
<em:id>tile@roy</em:id>
|
||||||
|
<em:name>tile</em:name>
|
||||||
|
<em:version>1.0</em:version>
|
||||||
|
<em:creator>Roy</em:creator>
|
||||||
|
<em:targetApplication>
|
||||||
|
<Description>
|
||||||
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
|
||||||
|
<em:minVersion>1.5</em:minVersion>
|
||||||
|
<em:maxVersion>3.5.*</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
</Description>
|
||||||
|
</RDF>
|
104
toolkit/content/tests/fennec-tile-testapp/logread.py
Normal file
104
toolkit/content/tests/fennec-tile-testapp/logread.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import re, sys
|
||||||
|
|
||||||
|
interesting_re = re.compile("(js_Execute|CallHook) ([^ ]+) ([^ ]+ )?([^ ]+ms)")
|
||||||
|
class Entry:
|
||||||
|
def __init__(self, kind, depth, file, linenum, func, timetaken):
|
||||||
|
self.kind = kind
|
||||||
|
self.depth = depth
|
||||||
|
self.file = file
|
||||||
|
self.linenum = linenum
|
||||||
|
self.func = func
|
||||||
|
self.timetaken = timetaken
|
||||||
|
self.calls = 0
|
||||||
|
self.duration = 0
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return " ".join(map(str,[self.kind, self.depth, self.file, self.linenum, self.func, self.timetaken]))
|
||||||
|
|
||||||
|
def id(self):
|
||||||
|
if self.kind == "js_Execute":
|
||||||
|
return self.file
|
||||||
|
else:
|
||||||
|
if self.file and self.linenum:
|
||||||
|
strout = "%s:%d" % (self.file, self.linenum)
|
||||||
|
if self.func:
|
||||||
|
strout = "%s %s" % (self.func, strout)
|
||||||
|
return strout
|
||||||
|
elif self.func:
|
||||||
|
return self.func
|
||||||
|
else:
|
||||||
|
print("No clue what my id is:"+self)
|
||||||
|
|
||||||
|
def call(self, timetaken):
|
||||||
|
self.calls += 1
|
||||||
|
self.duration += timetaken
|
||||||
|
|
||||||
|
def parse_line(line):
|
||||||
|
m = interesting_re.search(line)
|
||||||
|
if not m:
|
||||||
|
return None
|
||||||
|
|
||||||
|
ms_index = line.find("ms")
|
||||||
|
depth = m.start() - ms_index - 3
|
||||||
|
kind = m.group(1)
|
||||||
|
func = None
|
||||||
|
file = None
|
||||||
|
linenum = None
|
||||||
|
if kind == "CallHook":
|
||||||
|
func = m.group(2)
|
||||||
|
file = m.group(3)
|
||||||
|
colpos = file.rfind(":")
|
||||||
|
(file,linenum) = file[:colpos], file[colpos+1:-1]
|
||||||
|
if linenum == "0":
|
||||||
|
linenum = None
|
||||||
|
else:
|
||||||
|
linenum = int(linenum)
|
||||||
|
offset = 1
|
||||||
|
else:
|
||||||
|
file = m.group(3)
|
||||||
|
|
||||||
|
timetaken = None
|
||||||
|
try:
|
||||||
|
timetaken = float(m.group(4)[:-2])
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
return Entry(kind, depth, file, linenum, func, timetaken)
|
||||||
|
|
||||||
|
def compare(x,y):
|
||||||
|
diff = x[1].calls - y[1].calls
|
||||||
|
if diff == 0:
|
||||||
|
return int(x[1].duration - y[1].duration)
|
||||||
|
elif diff > 0:
|
||||||
|
return 1
|
||||||
|
elif diff < 0:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def frequency(ls):
|
||||||
|
dict = {}
|
||||||
|
for item in ls:
|
||||||
|
id = item.id()
|
||||||
|
stat = None
|
||||||
|
if not id in dict:
|
||||||
|
stat = dict[id] = item
|
||||||
|
else:
|
||||||
|
stat = dict[id]
|
||||||
|
stat.call(item.timetaken)
|
||||||
|
|
||||||
|
ls = dict.items()
|
||||||
|
ls.sort(compare)
|
||||||
|
ls = filter(lambda (_,item): item.duration > 20, ls)
|
||||||
|
# ls = filter(lambda (_,item): item.file and item.file.find("browser.js") != -1 and item.linenum <= 1223 and item.linenum >1067, ls)
|
||||||
|
for key, item in ls:
|
||||||
|
print(item.calls,key, str(item.duration)+"ms")
|
||||||
|
|
||||||
|
def go():
|
||||||
|
file = sys.argv[1]
|
||||||
|
|
||||||
|
ls = filter(lambda x: x != None, map(parse_line, open(file).readlines()))
|
||||||
|
|
||||||
|
frequency(ls)
|
||||||
|
print ls[0]
|
||||||
|
|
||||||
|
go()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user