From a8b7cd1231a8f35c61f024146a6a8234f81f9436 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Fri, 10 May 2013 11:37:52 -0500 Subject: [PATCH] Bug 847872: Make reflow-on-zoom happen on double-tap only. [r=blassey] --- .../base/locales/en-US/android_strings.dtd | 2 +- mobile/android/base/strings.xml.in | 2 +- mobile/android/chrome/content/browser.js | 100 ++++++++++++++++-- 3 files changed, 92 insertions(+), 12 deletions(-) diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index 3051bd51ec4..f960c6cdff5 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -97,7 +97,7 @@ - + diff --git a/mobile/android/base/strings.xml.in b/mobile/android/base/strings.xml.in index 84609f35a34..95fade33d9e 100644 --- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -115,7 +115,7 @@ &pref_font_size_set; &pref_font_size_adjust_char; &pref_font_size_preview_text; - &pref_reflow_on_zoom2; + &pref_reflow_on_zoom3; &pref_show_product_announcements; &pref_sync; &pref_search_suggestions; diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 5f5b484dfa5..b07f35eca45 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -179,6 +179,14 @@ function fuzzyEquals(a, b) { return (Math.abs(a - b) < 1e-6); } +/** + * Convert a font size from CSS pixels (px) to twenteiths-of-a-point + * (twips). + */ +function convertFromPxToTwips(aSize) { + return (20.0 * 12.0 * (aSize/16.0)); +} + #ifdef MOZ_CRASHREPORTER Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter", @@ -2549,16 +2557,45 @@ Tab.prototype = { } }, + /** + * Retrieves the font size in twips for a given element. + */ + getFontSizeInTwipsFor: function(aElement) { + // GetComputedStyle should always give us CSS pixels for a font size. + let fontSizeStr = this.window.getComputedStyle(aElement)['fontSize']; + let fontSize = fontSizeStr.slice(0, -2); + // This is in px, so we want to convert it to points then to twips. + return convertFromPxToTwips(fontSize); + }, + + /** + * This returns the zoom necessary to match the font size of an element to + * the minimum font size specified by the browser.zoom.reflowOnZoom.minFontSizeTwips + * preference. + */ + getZoomToMinFontSize: function(aElement) { + let currentZoom = this._zoom; + let minFontSize = Services.prefs.getIntPref("browser.zoom.reflowZoom.minFontSizeTwips"); + let curFontSize = this.getFontSizeInTwipsFor(aElement); + if (!fuzzyEquals(curFontSize*(currentZoom), minFontSize)) { + return 1.0 + minFontSize / curFontSize; + } + + return 1.0; + }, + performReflowOnZoom: function(aViewport) { - let viewportWidth = gScreenWidth / aViewport.zoom; + let zoom = this._drawZoom ? this._drawZoom : aViewport.zoom; + + let viewportWidth = gScreenWidth / zoom; let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout"); if (gReflowPending) { clearTimeout(gReflowPending); } - // We add in a bit of fudge just so that the end characters don't accidentally - // get clipped. 15px is an arbitrary choice. + // We add in a bit of fudge just so that the end characters + // don't accidentally get clipped. 15px is an arbitrary choice. gReflowPending = setTimeout(doChangeMaxLineBoxWidth, reflozTimeout, viewportWidth - 15); @@ -2913,7 +2950,21 @@ Tab.prototype = { // Adjust the max line box width to be no more than the viewport width, but // only if the reflow-on-zoom preference is enabled. - let isZooming = Math.abs(aViewport.zoom - this._zoom) >= 1e-6; + let isZooming = !fuzzyEquals(aViewport.zoom, this._zoom); + if (BrowserApp.selectedTab.reflozPinchSeen && + isZooming && aViewport.zoom < 1.0) { + // In this case, we want to restore the max line box width, + // because we are pinch-zooming to zoom out. + BrowserEventHandler.resetMaxLineBoxWidth(); + BrowserApp.selectedTab.reflozPinchSeen = false; + } else if (BrowserApp.selectedTab.reflozPinchSeen && + isZooming) { + // In this case, the user pinch-zoomed in, so we don't want to + // preserve position as we would with reflow-on-zoom. + BrowserApp.selectedTab.probablyNeedRefloz = false; + BrowserApp.selectedTab._mReflozPoint = null; + } + if (isZooming && BrowserEventHandler.mReflozPref && BrowserApp.selectedTab._mReflozPoint && @@ -3812,10 +3863,15 @@ var BrowserEventHandler = { }, resetMaxLineBoxWidth: function() { - let webNav = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation); - let docShell = webNav.QueryInterface(Ci.nsIDocShell); - let docViewer = docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); - docViewer.changeMaxLineBoxWidth(0); + BrowserApp.selectedTab.probablyNeedRefloz = false; + + if (gReflowPending) { + clearTimeout(gReflowPending); + } + + let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout"); + gReflowPending = setTimeout(doChangeMaxLineBoxWidth, + reflozTimeout, 0); }, updateReflozPref: function() { @@ -4046,6 +4102,18 @@ var BrowserEventHandler = { onDoubleTap: function(aData) { let data = JSON.parse(aData); + // We only want to do this if reflow-on-zoom is enabled. + if (BrowserEventHandler.mReflozPref && + !BrowserApp.selectedTab._mReflozPoint) { + let data = JSON.parse(aData); + let zoomPointX = data.x; + let zoomPointY = data.y; + + BrowserApp.selectedTab._mReflozPoint = { x: zoomPointX, y: zoomPointY, + range: BrowserApp.selectedBrowser.contentDocument.caretPositionFromPoint(zoomPointX, zoomPointY) }; + BrowserApp.selectedTab.probablyNeedRefloz = true; + } + let zoom = BrowserApp.selectedTab._zoom; let element = ElementTouchHelper.anyElementFromPoint(data.x, data.y); if (!element) { @@ -4068,6 +4136,10 @@ var BrowserEventHandler = { */ _zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) { const margin = 15; + + // This is really only used for reflow-on-zoom. + let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement); + let rect = ElementTouchHelper.getBoundingContentRect(aElement); let viewport = BrowserApp.selectedTab.getViewport(); @@ -4077,12 +4149,20 @@ var BrowserEventHandler = { rect.h); // constrict the rect to the screen's right edge bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x); + if (BrowserEventHandler.mReflozPref) { + bRect.width = zoomFactor == 1.0 ? bRect.width : gScreenWidth / zoomFactor; + bRect.height = zoomFactor == 1.0 ? bRect.height : bRect.height / zoomFactor; + } // if the rect is already taking up most of the visible area and is stretching the // width of the page, then we want to zoom out instead. - if (this._isRectZoomedIn(bRect, viewport)) { - if (aCanZoomOut) + + if ((BrowserEventHandler.mReflozPref && zoomFactor == 1.0) || + this._isRectZoomedIn(bRect, viewport)) { + if (aCanZoomOut) { this._zoomOut(); + } + return; }