bug 509764. Lift browser viewport state to tab level; restore state on tabswitch. r=stuart

This commit is contained in:
Roy Frostig 2009-08-11 13:51:13 -07:00
Родитель e2dabb32fc
Коммит 0d8f786bd4
2 изменённых файлов: 107 добавлений и 98 удалений

Просмотреть файл

@ -160,23 +160,16 @@ BrowserView.Util = {
return BrowserView.Util.clampZoomLevel(visibleRect.width / browserW);
},
seenBrowser: function seenBrowser(browser) {
return !!(browser.__BrowserView__vps);
},
initBrowserState: function initBrowserState(browser, visibleRect) {
createBrowserViewportState: function createBrowserViewportState(browser, visibleRect) {
let [browserW, browserH] = BrowserView.Util.getBrowserDimensions(browser);
let zoomLevel = BrowserView.Util.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);
return new BrowserView.BrowserViewportState(viewportRect,
visibleRect.x,
visibleRect.y,
zoomLevel);
},
getViewportStateFromBrowser: function getViewportStateFromBrowser(browser) {
@ -380,7 +373,14 @@ BrowserView.prototype = {
this._tileManager.endCriticalMove(cr, this.isRendering());
},
setBrowser: function setBrowser(browser, doZoom) {
/**
* Swap out the current browser and browser viewport state with a new pair.
*/
setBrowser: function setBrowser(browser, browserViewportState, doZoom) {
if (browser && !browserViewportState) {
throw "Cannot set non-null browser with null BrowserViewportState";
}
let currentBrowser = this._browser;
let browserChanged = (currentBrowser !== browser);
@ -393,13 +393,13 @@ BrowserView.prototype = {
currentBrowser.removeEventListener("FakeMozAfterSizeChange", this.handleMozAfterSizeChange, false);
// !!! --- RESIZE HACK END -------
this.discardAllBatchOperations();
currentBrowser.setAttribute("type", "content");
currentBrowser.docShell.isOffScreenBrowser = false;
}
this._restoreBrowser(browser);
this._browser = browser;
this._contentWindow = (browser) ? browser.contentWindow : null;
this._browserViewportState = browserViewportState;
if (browser) {
browser.setAttribute("type", "content-primary");
@ -548,21 +548,6 @@ BrowserView.prototype = {
// Private instance methods
//
_restoreBrowser: function _restoreBrowser(browser) {
let bvs = null;
if (browser) {
if (!BrowserView.Util.seenBrowser(browser))
BrowserView.Util.initBrowserState(browser, this.getVisibleRect());
bvs = BrowserView.Util.getViewportStateFromBrowser(browser);
}
this._browser = browser;
this._contentWindow = (browser) ? browser.contentWindow : null;
this._browserViewportState = bvs;
},
_viewportChanged: function _viewportChanged(viewportSizeChanged, dirtyAll) {
let bops = this._batchOps;

Просмотреть файл

@ -92,7 +92,7 @@ function debug() {
let cr = bv._tileManager._criticalRect;
dump('criticalRect from BV: ' + (cr ? cr.toString() : null) + endl);
dump('visibleRect from BV : ' + bv._visibleRect + endl);
dump('visibleRect from BV : ' + bv.getVisibleRect().toString() + endl);
dump('visibleRect from foo: ' + Browser.getVisibleRect().toString() + endl);
dump('bv batchops depth: ' + bv._batchOps.length + endl);
@ -534,7 +534,7 @@ var Browser = {
},
shutdown: function() {
this._browserView.setBrowser(null, false);
this._browserView.setBrowser(null, null, false);
BrowserUI.uninit();
@ -688,7 +688,21 @@ var Browser = {
this._selectedTab = tab;
bv.beginBatchOperation();
bv.setBrowser(this.selectedBrowser, true);
bv.setBrowser(tab.browser, tab.browserViewportState, false);
bv.forceContainerResize();
// XXX these should probably be computed less hackily so they don't
// potentially break if we change something in browser.xul
let offY = Math.round(document.getElementById("toolbar-container").getBoundingClientRect().height);
let restoreX = Math.max(0, tab.browserViewportState.visibleX);
let restoreY = Math.max(0, tab.browserViewportState.visibleY) + offY;
dump('Switch tab scrolls to: ' + restoreX
+ ', ' + restoreY + '\n');
Browser.contentScrollboxScroller.scrollTo(restoreX, restoreY);
document.getElementById("tabs").selectedItem = tab.chromeTab;
if (!firstTab) {
@ -696,7 +710,7 @@ var Browser = {
let securityUI = this.selectedBrowser.securityUI;
try {
tab._listener.onLocationChange(webProgress, null, this.selectedBrowser.currentURI);
tab._listener.onLocationChange(webProgress, null, tab.browser.currentURI);
if (securityUI)
tab._listener.onSecurityChange(webProgress, null, securityUI.state);
} catch (e) {
@ -708,7 +722,8 @@ var Browser = {
event.initEvent("TabSelect", true, false);
tab.chromeTab.dispatchEvent(event);
}
bv.commitBatchOperation(true);
bv.commitBatchOperation();
},
supportsCommand: function(cmd) {
@ -1224,18 +1239,6 @@ Browser.MainDragger = function MainDragger(browserView) {
};
Browser.MainDragger.prototype = {
_targetIsContent: function _targetIsContent(target) {
let tileBox = document.getElementById("tile-container");
while (target) {
if (target === window)
return false;
if (target === tileBox)
return true;
target = target.parentNode;
}
return false;
},
dragStart: function dragStart(clientX, clientY, target, scroller) {
this.draggedFrame = null;
@ -1256,45 +1259,6 @@ Browser.MainDragger.prototype = {
this.floatedWhileDragging = false;
},
_panFrame: function _panFrame(dx, dy) {
if (this.draggedFrame === null)
return false;
if (dx == 0 && dy == 0)
return true;
let panned = false;
let elem = this.draggedFrame;
// top-level window will have itself as its parent, so stop
// there to allow canvasbrowser/widgetstack to pan instead
// of doing scrolling
while (elem && elem !== elem.parent.document.defaultView) {
let windowUtils = elem.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let origX = {}, origY = {};
windowUtils.getScrollXY(false, origX, origY);
elem.scrollBy(dx, dy);
let newX = {}, newY = {};
windowUtils.getScrollXY(false, newX, newY);
panned = (origX.value != newX.value) || (origY.value != newY.value);
if (panned) {
// get critical area to redraw after we move frame
// NOTE: may need to rate limit these for performance
this.bv.renderNow();
break;
}
elem = elem.parent.document.defaultView;
}
return panned;
},
dragStop: function dragStop(dx, dy, scroller) {
let dx = this.dragMove(dx, dy, scroller, true);
@ -1311,8 +1275,7 @@ Browser.MainDragger.prototype = {
dragMove: function dragMove(dx, dy, scroller, doReturnDX) {
let outrv = 0;
// first see if we need to adjust internal IFRAME/FRAME
if (this._panFrame(dx, dy))
if (this._panFrame(dx, dy)) // first see if we need to adjust internal IFRAME/FRAME
return true;
if (this.scrollingOuterX) {
@ -1358,8 +1321,6 @@ Browser.MainDragger.prototype = {
if (realdx != dx) {
let restdx = dx - realdx;
dump("--> restdx: " + restdx + "\n");
this.scrollingOuterX = true;
this.dragMove(restdx, 0, scroller, doReturnDX);
}
@ -1380,7 +1341,60 @@ Browser.MainDragger.prototype = {
this.bv.onAfterVisibleMove(realdx, realdy);
return (doReturnDX) ? realdx : (realdx != 0 || realdy != 0);
},
_panFrame: function _panFrame(dx, dy) {
if (this.draggedFrame === null)
return false;
if (dx == 0 && dy == 0)
return true;
let panned = false;
let elem = this.draggedFrame;
// top-level window will have itself as its parent, so stop
// there to allow canvasbrowser/widgetstack to pan instead
// of doing scrolling
while (elem && elem !== elem.parent.document.defaultView) {
let windowUtils = elem.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let origX = {}, origY = {};
windowUtils.getScrollXY(false, origX, origY);
elem.scrollBy(dx, dy);
let newX = {}, newY = {};
windowUtils.getScrollXY(false, newX, newY);
panned = (origX.value != newX.value) || (origY.value != newY.value);
if (panned) {
// get critical area to redraw after we move frame
// NOTE: may need to rate limit these for performance
this.bv.renderNow();
break;
}
elem = elem.parent.document.defaultView;
}
return panned;
},
_targetIsContent: function _targetIsContent(target) {
let tileBox = document.getElementById("tile-container");
while (target) {
if (target === window)
return false;
if (target === tileBox)
return true;
target = target.parentNode;
}
return false;
}
};
function nsBrowserAccess()
@ -2181,21 +2195,25 @@ ProgressController.prototype = {
function Tab() {
this._id = null;
this._browser = null;
this._browserViewportState = null;
this._state = null;
this._listener = null;
this._loading = false;
this._chromeTab = null;
this.create();
}
Tab.prototype = {
_id: null,
_browser: null,
_state: null,
_listener: null,
_loading: false,
_chromeTab: null,
get browser() {
return this._browser;
},
get browserViewportState() {
return this._browserViewportState;
},
get chromeTab() {
return this._chromeTab;
},
@ -2250,6 +2268,12 @@ Tab.prototype = {
// stop about:blank from loading
browser.stop();
// Initialize a viewport state for BrowserView
let initVis = Browser.getVisibleRect();
initVis.x = 0;
initVis.y = 0;
this._browserViewportState = BrowserView.Util.createBrowserViewportState(browser, initVis);
// Attach a separate progress listener to the browser
this._listener = new ProgressController(this);
browser.addProgressListener(this._listener);