diff -r 000000000000 -r 6474c204b198 browser/metro/base/content/bindings/browser.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/metro/base/content/bindings/browser.xml Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,1303 @@ + + + + + + %findBarDTD; +]> + + + + + + + + binding. + this.removeEventListener("pageshow", this.onPageShow, true); + this.removeEventListener("pagehide", this.onPageHide, true); + this.removeEventListener("DOMPopupBlocked", this.onPopupBlocked, true); + + this.setAttribute("autoscrollpopup", "autoscrollerid"); + ]]> + + + [] + + + null + + + null + + null + + + Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + null + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + + + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + null + + + + null + + + + + + + + + + + + + + + + + + + + + + + true + + + + + ({}) + + + + + = this.kDieTime) + this._die(); + else + // This doesn't need to be exact, just be sure to clean up at some point. + this._timeout = setTimeout(this._dieIfOld.bind(this), this.kDieTime); + }, + + /** Cleanup after ourselves. */ + _die: function() { + let timeout = this._timeout; + if (timeout) { + clearTimeout(timeout); + this._timeout = null; + } + + if (this._contentView && Math.abs(this._pixelsPannedSinceRefresh) > 0) + this._updateCacheViewport(); + + // We expect contentViews to contain our ID. If not, something bad + // happened. + delete this.self._contentViews[this._id]; + }, + + /** + * Given the cache size and the viewport size, this determines where the cache + * should start relative to the scroll position. This adjusts the position based + * on which direction the user is panning, so that we use our cache as + * effectively as possible. + * + * @param aDirection Negative means user is panning to the left or above + * Zero means user did not pan + * Positive means user is panning to the right or below + * @param aViewportSize The width or height of the viewport + * @param aCacheSize The width or height of the displayport + */ + _getRelativeCacheStart: function(aDirection, aViewportSize, aCacheSize) { + // Remember that this is relative to the viewport scroll position. + // Let's assume we are thinking about the y-axis. + // The extreme cases: + // |0| would mean that there is no content available above + // |aViewportSize - aCacheSize| would mean no content available below + // + // Taking the average of the extremes puts equal amounts of cache on the + // top and bottom of the viewport. If we think of this like a weighted + // average, .5 is the sweet spot where equals amounts of content are + // above and below the visible area. + // + // This weight is therefore how much of the cache is above (or to the + // left) the visible area. + let cachedAbove = .5; + + // If panning down, leave only 25% of the non-visible cache above. + if (aDirection > 0) + cachedAbove = .25; + + // If panning up, Leave 75% of the non-visible cache above. + if (aDirection < 0) + cachedAbove = .75; + + return (aViewportSize - aCacheSize) * cachedAbove; + }, + + /** Determine size of the pixel cache. */ + _getCacheSize: function(viewportSize) { + let self = this.self; + let contentView = this._contentView; + + let cacheWidth = self._cacheRatioWidth * viewportSize.width; + let cacheHeight = self._cacheRatioHeight * viewportSize.height; + let contentSize = this._getContentSize(); + let contentWidth = contentSize.width; + let contentHeight = contentSize.height; + + // There are common cases, such as long skinny pages, where our cache size is + // bigger than our content size. In those cases, we take that sliver of leftover + // space and apply it to the other dimension. + if (contentWidth < cacheWidth) { + cacheHeight += (cacheWidth - contentWidth) * cacheHeight / cacheWidth; + cacheWidth = contentWidth; + } else if (contentHeight < cacheHeight) { + cacheWidth += (cacheHeight - contentHeight) * cacheWidth / cacheHeight; + cacheHeight = contentHeight; + } + + return { width: cacheWidth, height: cacheHeight }; + }, + + _sendDisplayportUpdate: function(scrollX, scrollY) { + let self = this.self; + if (!self.active) + return; + + let contentView = this._contentView; + let viewportSize = this._getViewportSize(); + let cacheSize = this._getCacheSize(viewportSize); + let cacheX = this._getRelativeCacheStart(this._pixelsPannedSinceRefresh.x, viewportSize.width, cacheSize.width) + contentView.scrollX; + let cacheY = this._getRelativeCacheStart(this._pixelsPannedSinceRefresh.y, viewportSize.height, cacheSize.height) + contentView.scrollY; + let contentSize = this._getContentSize(); + + // Use our pixels efficiently and don't try to cache things outside of content + // boundaries (The left bound can be negative because of RTL). + + let rootScale = self.scale; + let leftBound = self._contentDocumentLeft * rootScale; + let bounds = new Rect(leftBound, 0, contentSize.width, contentSize.height); + let displayport = new Rect(cacheX, cacheY, cacheSize.width, cacheSize.height); + displayport.translateInside(bounds); + + self.messageManager.sendAsyncMessage("Content:SetCacheViewport", { + scrollX: Math.round(scrollX) / rootScale, + scrollY: Math.round(scrollY) / rootScale, + x: Math.round(displayport.x) / rootScale, + y: Math.round(displayport.y) / rootScale, + w: Math.round(displayport.width) / rootScale, + h: Math.round(displayport.height) / rootScale, + scale: rootScale, + id: contentView.id + }); + + this._pixelsPannedSinceRefresh.x = 0; + this._pixelsPannedSinceRefresh.y = 0; + }, + + _updateCSSViewport: function() { + let contentView = this._contentView; + this._sendDisplayportUpdate(contentView.scrollX, + contentView.scrollY); + }, + + /** + * The cache viewport is what parts of content is cached in the parent process for + * fast scrolling. This syncs that up with the current projection viewport. + */ + _updateCacheViewport: function() { + // Do not update scroll values for content. + if (this.isRoot()) + this._sendDisplayportUpdate(-1, -1); + else { + let contentView = this._contentView; + this._sendDisplayportUpdate(contentView.scrollX, + contentView.scrollY); + } + }, + + _getContentSize: function() { + let self = this.self; + return { width: this._contentView.contentWidth, + height: this._contentView.contentHeight }; + }, + + _getViewportSize: function() { + let self = this.self; + if (this.isRoot()) { + let bcr = self.getBoundingClientRect(); + return { width: bcr.width, height: bcr.height }; + } else { + return { width: this._contentView.viewportWidth, + height: this._contentView.viewportHeight }; + } + }, + + init: function(contentView) { + let self = this.self; + + this._contentView = contentView; + this._id = contentView.id; + this._scale = 1; + self._contentViews[this._id] = this; + + if (!this.isRoot()) { + // Non-root content views are short lived. + this._timeout = setTimeout(this._dieIfOld.bind(this), this.kDieTime); + // This iframe may not have a display port yet, so build up a cache + // immediately. + this._updateCacheViewport(); + } + }, + + isRoot: function() { + return this.self._contentViewManager.rootContentView == this._contentView; + }, + + scrollBy: function(x, y) { + let self = this.self; + + // Bounding content rectangle is in device pixels + let contentView = this._contentView; + let viewportSize = this._getViewportSize(); + let contentSize = this._getContentSize(); + // Calculate document dimensions in device pixels + let scrollRangeX = contentSize.width - viewportSize.width; + let scrollRangeY = contentSize.height - viewportSize.height; + + let leftOffset = self._contentDocumentLeft * this._scale; + x = Math.floor(Math.max(leftOffset, Math.min(scrollRangeX + leftOffset, contentView.scrollX + x))) - contentView.scrollX; + y = Math.floor(Math.max(0, Math.min(scrollRangeY, contentView.scrollY + y))) - contentView.scrollY; + + if (x == 0 && y == 0) + return; + + contentView.scrollBy(x, y); + + this._lastPanTime = Date.now(); + + this._pixelsPannedSinceRefresh.x += x; + this._pixelsPannedSinceRefresh.y += y; + if (Math.abs(this._pixelsPannedSinceRefresh.x) > 20 || + Math.abs(this._pixelsPannedSinceRefresh.y) > 20) + this._updateCacheViewport(); + }, + + scrollTo: function(x, y) { + let contentView = this._contentView; + this.scrollBy(x - contentView.scrollX, y - contentView.scrollY); + }, + + _setScale: function _setScale(scale) { + this._scale = scale; + this._contentView.setScale(scale, scale); + }, + + getPosition: function() { + let contentView = this._contentView; + return { x: contentView.scrollX, y: contentView.scrollY }; + } + }) + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + + + + + + +