Bug 621888 - Fennec zoom to the wrong area when the search result is at the bottom of the page [r=mbrubeck]

This commit is contained in:
Vivien Nicolas 2010-12-29 16:40:51 +01:00
parent f2d25b0f36
commit 27801dd4a3
2 changed files with 59 additions and 60 deletions

View File

@ -448,6 +448,7 @@ var BrowserUI = {
tabs.addEventListener("TabOpen", NewTabPopup, true);
Elements.browsers.addEventListener("PanFinished", this, true);
Elements.browsers.addEventListener("SizeChanged", this, true);
// listen content messages
messageManager.addMessageListener("DOMLinkAdded", this);
@ -514,7 +515,6 @@ var BrowserUI = {
uninit: function() {
ExtensionsView.uninit();
ConsoleView.uninit();
FormHelperUI.uninit();
},
update: function(aState) {
@ -832,6 +832,10 @@ var BrowserUI = {
if (tabsVisibility == 0.0)
document.getElementById("tabs").removeClosedTab();
break;
case "SizeChanged":
if (aEvent.detail)
this.sizeControls(ViewableAreaObserver.height, ViewableAreaObserver.width);
break;
// Window events
case "keypress":
if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE)
@ -1841,26 +1845,11 @@ var FormHelperUI = {
return Services.prefs.getBoolPref("formhelper.enabled");
},
_visibleScreenArea: null,
get visibleScreenArea() {
let visibleRect = Rect.fromRect(this._currentBrowser.getBoundingClientRect());
let visibleScreenArea = visibleRect;
if (this._visibleScreenArea) {
visibleScreenArea = this._visibleScreenArea.clone();
visibleScreenArea.x = visibleRect.x;
visibleScreenArea.y = visibleRect.y;
visibleScreenArea.width = visibleRect.width;
visibleScreenArea.height = visibleRect.height - this._container.getBoundingClientRect().height;
}
return visibleScreenArea;
},
init: function formHelperInit() {
this._container = document.getElementById("content-navigator");
this._autofillContainer = document.getElementById("form-helper-autofill");
this._cmdPrevious = document.getElementById(this.commands.previous);
this._cmdNext = document.getElementById(this.commands.next);
this._visibleScreenArea = new Rect(0, 0, 0, 0);
// Listen for form assistant messages from content
messageManager.addMessageListener("FormAssist:Show", this);
@ -1874,17 +1863,12 @@ var FormHelperUI = {
tabs.addEventListener("TabSelect", this, true);
tabs.addEventListener("TabClose", this, true);
Elements.browsers.addEventListener("URLChanged", this, true);
Elements.browsers.addEventListener("SizeChanged", this, true);
window.addEventListener("resize", this, true);
// Listen for modal dialog to show/hide the UI
messageManager.addMessageListener("DOMWillOpenModalDialog", this);
messageManager.addMessageListener("DOMModalDialogClosed", this);
Services.obs.addObserver(this, "softkb-change", false);
},
uninit: function formHelperUninit() {
Services.obs.removeObserver(this, "softkb-change");
},
_currentBrowser: null,
@ -1931,6 +1915,9 @@ var FormHelperUI = {
this._open = false;
},
// for VKB that does not resize the window
_currentCaretRect: null,
_currentElementRect: null,
handleEvent: function formHelperHandleEvent(aEvent) {
if (!this._open)
return;
@ -1952,6 +1939,11 @@ var FormHelperUI = {
self._container.contentHasChanged();
}, 0, this);
break;
case "SizeChanged":
if (aEvent.detail)
this._zoom(this._currentElementRect, this._currentCaretRect);
break;
}
},
@ -2002,20 +1994,6 @@ var FormHelperUI = {
}
},
// for VKB that does not resize the window
_currentCaretRect: null,
_currentElementRect: null,
observe: function formHelperObserve(aSubject, aTopic, aData) {
let rect = Rect.fromRect(JSON.parse(aData));
rect.height = rect.bottom - rect.top;
rect.width = rect.right - rect.left;
this._visibleScreenArea = rect;
BrowserUI.sizeControls(rect.width, rect.height);
if (this.open)
this._zoom(this._currentElementRect, this._currentCaretRect);
},
goToPrevious: function formHelperGoToPrevious() {
this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:Previous", { });
},
@ -2123,8 +2101,8 @@ var FormHelperUI = {
/** Zoom and move viewport so that element is legible and touchable. */
_zoom: function _formHelperZoom(aElementRect, aCaretRect) {
let zoomRect = this.visibleScreenArea;
let browser = getBrowser();
let zoomRect = Rect.fromRect(browser.getBoundingClientRect());
// Zoom to a specified Rect
if (aElementRect && Browser.selectedTab.allowZoom && Services.prefs.getBoolPref("formhelper.autozoom")) {
@ -2132,7 +2110,7 @@ var FormHelperUI = {
// Zoom to an element by keeping the caret into view
let zoomLevel = Browser.selectedTab.clampZoomLevel(this._getZoomLevelForRect(aElementRect));
zoomRect = this._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, zoomLevel);
zoomRect = Browser._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, zoomLevel);
Browser.animatedZoomTo(zoomRect);
}
@ -2155,7 +2133,7 @@ var FormHelperUI = {
}
let browser = getBrowser();
let zoomRect = this.visibleScreenArea;
let zoomRect = Rect.fromRect(browser.getBoundingClientRect());
this._currentCaretRect = aCaretRect;
let caretRect = aCaretRect.scale(browser.scale, browser.scale);
@ -2193,26 +2171,9 @@ var FormHelperUI = {
Browser.pageScrollboxScroller.scrollTo(restore.pageScrollOffset.x, restore.pageScrollOffset.y);
},
_getZoomRectForPoint: function _getZoomRectForPoint(x, y, zoomLevel) {
let browser = getBrowser();
x = x * browser.scale;
y = y * browser.scale;
let vis = this.visibleScreenArea
zoomLevel = Math.min(ZoomManager.MAX, zoomLevel);
let oldScale = browser.scale;
let zoomRatio = zoomLevel / oldScale;
let newVisW = vis.width / zoomRatio, newVisH = vis.height / zoomRatio;
let result = new Rect(x - newVisW / 2, y - newVisH / 2, newVisW, newVisH);
// Make sure rectangle doesn't poke out of viewport
return result.translateInside(new Rect(0, 0, browser.contentDocumentWidth * oldScale,
browser.contentDocumentHeight * oldScale));
},
_getZoomLevelForRect: function _getZoomLevelForRect(aRect) {
const margin = 30;
let zoomLevel = this.visibleScreenArea.width / (aRect.width + margin);
let zoomLevel = getBrowser().getBoundingClientRect().width / (aRect.width + margin);
return Util.clamp(zoomLevel, kBrowserFormZoomLevelMin, kBrowserFormZoomLevelMax);
},

View File

@ -238,7 +238,7 @@ var Browser = {
pageScrollbox.customDragger = controlsScrollbox.customDragger;
let stylesheet = document.styleSheets[0];
for each (let style in ["window-width", "window-height", "toolbar-height"]) {
for each (let style in ["window-width", "window-height", "viewable-height", "viewable-width", "toolbar-height"]) {
let index = stylesheet.insertRule("." + style + " {}", stylesheet.cssRules.length);
this.styles[style] = stylesheet.cssRules[index].style;
}
@ -278,6 +278,7 @@ var Browser = {
Browser.styles["window-width"].width = w + "px";
Browser.styles["window-height"].height = h + "px";
Browser.styles["toolbar-height"].height = toolbarHeight + "px";
ViewableAreaObserver.update();
// Tell the UI to resize the browser controls
BrowserUI.sizeControls(w, h);
@ -348,6 +349,12 @@ var Browser = {
os.addObserver(MemoryObserver, "memory-pressure", false);
os.addObserver(BrowserSearch, "browser-search-engine-modified", false);
// Listens for change in the viewable area
os.addObserver(ViewableAreaObserver, "softkb-change", false);
Elements.contentNavigator.addEventListener("SizeChanged", function() {
ViewableAreaObserver.update();
}, false);
window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess();
Elements.browsers.addEventListener("DOMUpdatePageReport", PopupBlockerObserver.onUpdatePageReport, false);
@ -1235,8 +1242,10 @@ Browser.MainDragger.prototype = {
if (doffset.x > 0 && rect.left > 0)
x = Math.min(doffset.x, rect.left);
// XXX could we use getBrowser().getBoundingClientRect().height here?
let height = Elements.contentViewport.getBoundingClientRect().height;
height -= Elements.contentNavigator.getBoundingClientRect().height;
rect = Rect.fromRect(Browser.contentScrollbox.getBoundingClientRect()).map(Math.round);
if (doffset.y < 0 && rect.bottom < height)
y = Math.max(doffset.y, rect.bottom - height);
@ -2825,7 +2834,7 @@ Tab.prototype = {
// Create the browser using the current width the dynamically size the height
let browser = this._browser = document.createElement("browser");
browser.setAttribute("class", "window-width window-height");
browser.setAttribute("class", "viewable-width viewable-height");
this._chromeTab.linkedBrowser = browser;
browser.setAttribute("type", "content");
@ -3022,4 +3031,33 @@ function rendererFactory(aBrowser, aCanvas) {
}
return wrapper;
}
};
var ViewableAreaObserver = {
get width() {
return this._width || window.innerWidth;
},
get height() {
return this._height || window.innerHeight;
},
observe: function va_observe(aSubject, aTopic, aData) {
let rect = Rect.fromRect(JSON.parse(aData));
this._height = rect.bottom - rect.top;
this._width = rect.right - rect.left;
this._update(aIsVKB);
},
update: function va_update(aIsVKB) {
Browser.styles["viewable-height"].height = (this.height - Elements.contentNavigator.getBoundingClientRect().height) + "px";
Browser.styles["viewable-width"].width = this.width + "px";
// setTimeout 0 to ensure the resize event handler is well finished
setTimeout(function() {
let event = document.createEvent("UIEvents");
event.initUIEvent("SizeChanged", true, false, window, aIsVKB);
Elements.browsers.dispatchEvent(event);
}, 0);
}
};