From 61422459a563662c77673e0d96c25db7574216f4 Mon Sep 17 00:00:00 2001 From: Gavin Sharp Date: Fri, 19 Dec 2008 18:04:16 -0500 Subject: [PATCH] Bug 466280: fix WidgetStack to support resizes, and use that support to enable panning the full range of content at smaller-than-default window sizes, r=vlad/stuart --- mobile/chrome/content/CanvasBrowser.js | 4 + mobile/chrome/content/WidgetStack.js | 111 ++++++++++++++++--------- mobile/chrome/content/browser.js | 32 ++++--- mobile/chrome/content/browser.xul | 6 +- mobile/chrome/skin/browser.css | 4 + 5 files changed, 100 insertions(+), 57 deletions(-) diff --git a/mobile/chrome/content/CanvasBrowser.js b/mobile/chrome/content/CanvasBrowser.js index 0a1abe597f25..62a273dcbf31 100644 --- a/mobile/chrome/content/CanvasBrowser.js +++ b/mobile/chrome/content/CanvasBrowser.js @@ -442,6 +442,10 @@ CanvasBrowser.prototype = { clickOffsetY - cwin.scrollY]; }, + get _effectiveContentAreaDimensions() { + return this._contentAreaDimensions.map(this._pageToScreen, this); + }, + get _contentAreaDimensions() { var cdoc = this._browser.contentDocument; diff --git a/mobile/chrome/content/WidgetStack.js b/mobile/chrome/content/WidgetStack.js index 42ef379f19b8..60733c1c81fd 100644 --- a/mobile/chrome/content/WidgetStack.js +++ b/mobile/chrome/content/WidgetStack.js @@ -61,6 +61,17 @@ function logbase() { } } +function dumpJSStack(stopAtNamedFunction) { + let caller = Components.stack.caller; + dump("\tStack: " + caller.name); + while ((caller = caller.caller)) { + dump(" <- " + caller.name); + if (stopAtNamedFunction && caller.name != "anonymous") + break; + } + dump("\n"); +} + function log() { return; logbase.apply(window, arguments); @@ -371,11 +382,11 @@ WidgetStack.prototype = { // panBy: pan the entire set of widgets by the given x and y amounts. // This does the same thing as if the user dragged by the given amount. // If this is called with an outstanding drag, weirdness might happen, - // but it also might work, so not isabling that. + // but it also might work, so not disabling that. // // if ignoreBarriers is true, then barriers are ignored for the pan. - panBy: function (dx, dy, ignoreBarriers) { - let needsDragWrap = !this._dragging(); + panBy: function panBy(dx, dy, ignoreBarriers) { + let needsDragWrap = !this._dragging; //log2("tlc rect.x start", this._widgetState['tab-list-container'].rect.x, needsDragWrap); @@ -475,7 +486,7 @@ WidgetStack.prototype = { // // setViewportBounds will move all the viewport-relative widgets into // place based on the new viewport bounds. - setViewportBounds: function () { + setViewportBounds: function setViewportBounds() { let oldBounds = this._viewportBounds.clone(); let oldInner = this._viewport.viewportInnerBounds.clone(); @@ -561,18 +572,7 @@ WidgetStack.prototype = { log2("viewingRect old", this._viewingRect.toString()); - if (!this._pannableBounds.contains(this._viewingRect)) { - let dx = dright - dleft; - let dy = dbottom - dtop; - - //console.log("panBy: ", -dx, -dy); - - this._rectSanityCheck = false; - - this.panBy(-dx, -dy, true); - - this._rectSanityCheck = true; - } + this._adjustViewingRect(); log2("viewingRect new", this._viewingRect.toString()); log2("finished, inner bounds old:", oldInner, " new:", this._viewport.viewportInnerBounds); @@ -648,7 +648,7 @@ WidgetStack.prototype = { dragStop: function () { log("(dragStop)"); - if (!this._dragging()) + if (!this._dragging) return; if (this._viewportUpdateTimeout != -1) @@ -661,8 +661,8 @@ WidgetStack.prototype = { }, // dragMove: process a mouse move to clientX,clientY for an ongoing drag - dragMove: function (clientX, clientY) { - if (!this._dragging()) + dragMove: function dragStop(clientX, clientY) { + if (!this._dragging) return; log("(dragMove)", clientX, clientY); @@ -681,16 +681,13 @@ WidgetStack.prototype = { // updateSize: tell the WidgetStack to update its size, because it // was either resized or some other event took place. - updateSize: function() { - let rect = this._el.getBoundingClientRect(); - let oldw = this._viewingRect.width; - let oldh = this._viewingRect.height; - let width = rect.right - rect.left; - let height = rect.bottom - rect.top; - + updateSize: function updateSize() { // XXX assumes we can only be resized from the bottom left/bottom right - this._viewingRect.width = width; - this._viewingRect.height = height; + let rect = this._el.getBoundingClientRect(); + this._viewingRect.width = rect.width; + this._viewingRect.height = rect.height; + + this._adjustViewingRect(); // If the viewport changed size (the only thing that's allowed to for now), // update its internal sizes @@ -701,8 +698,8 @@ WidgetStack.prototype = { let newViewportRect = this._viewport.widget.getBoundingClientRect(); - let w = newViewportRect.right - newViewportRect.left; - let h = newViewportRect.bottom - newViewportRect.top; + let w = newViewportRect.width; + let h = newViewportRect.height; if (this._viewport.widget.hasAttribute("widgetwidth") && this._viewport.widget.hasAttribute("widgetheight")) @@ -796,6 +793,39 @@ WidgetStack.prototype = { // Internal code // + _dumpRects: function () { + dump("WidgetStack:\n"); + //dump("\tthis._viewportBounds: " + this._viewportBounds + "\n"); + dump("\tthis._viewingRect: " + this._viewingRect + "\n"); + dump("\tthis._viewport.viewportInnerBounds: " + this._viewport.viewportInnerBounds + "\n"); + dump("\tthis._viewport.rect: " + this._viewport.rect + "\n"); + //dump("\tthis._pannableBounds: " + this._pannableBounds + "\n"); + }, + + // Ensures that _viewingRect is within _pannableBounds (call this when either + // one is resized) + _adjustViewingRect: function _adjustViewingRect() { + + if (this._pannableBounds.contains(this._viewingRect)) + return; // nothing to do here + + this._rectSanityCheck = false; + + let vr = this._viewingRect; + let pb = this._pannableBounds; + if (vr.right > pb.right) + this.panBy(pb.right - vr.right, 0, true); + else if (vr.left < pb.left) + this.panBy(pb.left - vr.left, 0, true); + + if (vr.bottom > pb.bottom) + this.panBy(0, pb.bottom - vr.bottom, true); + else if(vr.top < pb.top) + this.panBy(0, pb.top - vr.top, true); + + this._rectSanityCheck = true; + }, + _getState: function (wid) { if (!(wid in this._widgetState)) throw "Unknown widget id '" + wid + "'; widget not in stack"; @@ -831,25 +861,25 @@ WidgetStack.prototype = { }, _onMouseMove: function (ev) { - if (!this._dragging()) + if (!this._dragging) return; this._dragCoordsFromClient(ev.screenX, ev.screenY); - if (!this._dragging() && this._dragState.outerDistSquared > 100) + if (!this._dragging && this._dragState.outerDistSquared > 100) this._delayedDragStart(); this.dragMove(ev.screenX, ev.screenY); }, - _dragging: function () { + get _dragging() { return this._dragState && this._dragState.dragging; }, // dragStart: a drag was started, either by distance or by time. _delayedDragStart: function () { log("(dragStart)"); - if (this._dragging()) + if (this._dragging) return; if (this._dragState.dragStartTimeout != -1) @@ -888,7 +918,7 @@ WidgetStack.prototype = { return [ioffsetx, ioffsety]; }, - _viewportUpdate: function (force) { + _viewportUpdate: function _viewportUpdate(force) { if (!this._viewport) return; @@ -901,13 +931,12 @@ WidgetStack.prototype = { // log2("viewportUpdate start", vws.rect.toString(), this._viewingRect.toString(), vws.originX, vws.originY); - let ioffsetx, ioffsety; - [ioffsetx, ioffsety] = this._panRegionOffsets(); + let [ioffsetx, ioffsety] = this._panRegionOffsets(); // recover the amount the inner bounds moved by the amount the viewport widget moved. // the rects are in screen space though, so we have to convert them to the virtual // coordinate space. - if (this._dragging()) { + if (this._dragging) { let idx = (vws.dragStartRect.x - vws.dragStartOffsets[0]) - (vws.rect.x - ioffsetx); let idy = (vws.dragStartRect.y - vws.dragStartOffsets[1]) - (vws.rect.y - ioffsety); @@ -933,8 +962,8 @@ WidgetStack.prototype = { } // if we're dragging, update this so that we can call this function again - // durig the same drag and get the right values. - if (this._dragging()) { + // during the same drag and get the right values. + if (this._dragging) { vws.dragStartOffsets = [ioffsetx, ioffsety]; vws.dragStartRect = vws.rect.clone(); } @@ -1106,7 +1135,7 @@ WidgetStack.prototype = { return [dx, dy]; }, - _panBy: function (dx, dy, ignoreBarriers) { + _panBy: function _panBy(dx, dy, ignoreBarriers) { // initially we work in viewingRect coords, so the direction // of the move is opposite from the direction of the pan dx = -dx; diff --git a/mobile/chrome/content/browser.js b/mobile/chrome/content/browser.js index fc8bed725a77..1c6e886e8c1e 100644 --- a/mobile/chrome/content/browser.js +++ b/mobile/chrome/content/browser.js @@ -79,7 +79,8 @@ var Browser = { this._canvasBrowser = new CanvasBrowser(document.getElementById("browser-canvas")); // initialize the WidgetStack - ws = new WidgetStack(document.getElementById("browser-container")); + let browserContainer = document.getElementById("browser-container"); + ws = new WidgetStack(browserContainer); ws.setViewportBounds({ top: 0, left: 0, right: 800, bottom: 480 }); // XXX this should live elsewhere @@ -98,11 +99,9 @@ var Browser = { } gSidebarVisible = visibleNow; - // deal with checkerboard - /* + // move checkerboard let stack = document.getElementById("browser-container"); stack.style.backgroundPosition = -vr.left + "px " + -vr.top + "px"; - */ // this is really only necessary for maemo, where we don't // always repaint fast enough @@ -111,10 +110,20 @@ var Browser = { ws.setPanHandler(panHandler); - function resizeHandler() { ws.updateSize(); } - window.addEventListener("resize", resizeHandler, false); + function resizeHandler(e) { + if (e.target != window) + return; - setTimeout(resizeHandler, 0); + // resize our container... + let w = window.innerWidth; + let h = window.innerHeight; + let containerStyle = browserContainer.style; + containerStyle.width = containerStyle.maxWidth = w + "px"; + containerStyle.height = containerStyle.maxHeight = h + "px"; + + ws.updateSize(); + } + window.addEventListener("resize", resizeHandler, false); function viewportHandler(b, ob) { self._canvasBrowser.viewportHandler(b, ob); } ws.setViewportHandler(viewportHandler); @@ -231,12 +240,11 @@ var Browser = { }, updateViewportSize: function() { - // XXX make sure this is right, and then add a better function for it. - var [w,h] = this._canvasBrowser._contentAreaDimensions; - w = Math.ceil(this._canvasBrowser._pageToScreen(w)); - h = Math.ceil(this._canvasBrowser._pageToScreen(h)); + var [w, h] = this._canvasBrowser._effectiveContentAreaDimensions.map(Math.ceil); - if (!this._currentViewportBounds || w != this._currentViewportBounds.width || h != this._currentViewportBounds.height) { + if (!this._currentViewportBounds || + w != this._currentViewportBounds.width || + h != this._currentViewportBounds.height) { this._currentViewportBounds = {width: w, height: h}; let bounds = { top: 0, left: 0, right: Math.max(800, w), bottom: Math.max(480, h) } //dump("setViewportBounds: " + bounds.toSource() + "\n"); diff --git a/mobile/chrome/content/browser.xul b/mobile/chrome/content/browser.xul index e7a482ebc110..add84f04a52b 100644 --- a/mobile/chrome/content/browser.xul +++ b/mobile/chrome/content/browser.xul @@ -178,11 +178,11 @@ - + diff --git a/mobile/chrome/skin/browser.css b/mobile/chrome/skin/browser.css index 8203818fede2..52cb8b1274f0 100644 --- a/mobile/chrome/skin/browser.css +++ b/mobile/chrome/skin/browser.css @@ -65,6 +65,10 @@ richlistitem { font-size: 16.75pt !important; } +#browser-container { + background-image: url('chrome://browser/content/checkerboard.png'); +} + /* main toolbar (URL bar) -------------------------------------------------- */ #toolbar-main { -moz-appearance: none;