Bug 847872: Make reflow-on-zoom happen on double-tap only. [r=blassey]

This commit is contained in:
Scott Johnson 2013-05-10 11:37:52 -05:00
parent 1a61f5d09f
commit a8b7cd1231
3 changed files with 92 additions and 12 deletions

View File

@ -97,7 +97,7 @@
<!ENTITY pref_plugins_tap_to_play "Tap to play"> <!ENTITY pref_plugins_tap_to_play "Tap to play">
<!ENTITY pref_plugins_disabled "Disabled"> <!ENTITY pref_plugins_disabled "Disabled">
<!ENTITY pref_text_size "Text size"> <!ENTITY pref_text_size "Text size">
<!ENTITY pref_reflow_on_zoom2 "Pinch to reflow text"> <!ENTITY pref_reflow_on_zoom3 "Double tap to reflow text">
<!ENTITY pref_font_size_tiny "Tiny"> <!ENTITY pref_font_size_tiny "Tiny">
<!ENTITY pref_font_size_small "Small"> <!ENTITY pref_font_size_small "Small">
<!ENTITY pref_font_size_medium "Medium"> <!ENTITY pref_font_size_medium "Medium">

View File

@ -115,7 +115,7 @@
<string name="pref_font_size_set">&pref_font_size_set;</string> <string name="pref_font_size_set">&pref_font_size_set;</string>
<string name="pref_font_size_adjust_char">&pref_font_size_adjust_char;</string> <string name="pref_font_size_adjust_char">&pref_font_size_adjust_char;</string>
<string name="pref_font_size_preview_text">&pref_font_size_preview_text;</string> <string name="pref_font_size_preview_text">&pref_font_size_preview_text;</string>
<string name="pref_reflow_on_zoom">&pref_reflow_on_zoom2;</string> <string name="pref_reflow_on_zoom">&pref_reflow_on_zoom3;</string>
<string name="pref_show_product_announcements">&pref_show_product_announcements;</string> <string name="pref_show_product_announcements">&pref_show_product_announcements;</string>
<string name="pref_sync">&pref_sync;</string> <string name="pref_sync">&pref_sync;</string>
<string name="pref_search_suggestions">&pref_search_suggestions;</string> <string name="pref_search_suggestions">&pref_search_suggestions;</string>

View File

@ -179,6 +179,14 @@ function fuzzyEquals(a, b) {
return (Math.abs(a - b) < 1e-6); 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 #ifdef MOZ_CRASHREPORTER
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter", 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) { 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"); let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout");
if (gReflowPending) { if (gReflowPending) {
clearTimeout(gReflowPending); clearTimeout(gReflowPending);
} }
// We add in a bit of fudge just so that the end characters don't accidentally // We add in a bit of fudge just so that the end characters
// get clipped. 15px is an arbitrary choice. // don't accidentally get clipped. 15px is an arbitrary choice.
gReflowPending = setTimeout(doChangeMaxLineBoxWidth, gReflowPending = setTimeout(doChangeMaxLineBoxWidth,
reflozTimeout, reflozTimeout,
viewportWidth - 15); viewportWidth - 15);
@ -2913,7 +2950,21 @@ Tab.prototype = {
// Adjust the max line box width to be no more than the viewport width, but // Adjust the max line box width to be no more than the viewport width, but
// only if the reflow-on-zoom preference is enabled. // 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 && if (isZooming &&
BrowserEventHandler.mReflozPref && BrowserEventHandler.mReflozPref &&
BrowserApp.selectedTab._mReflozPoint && BrowserApp.selectedTab._mReflozPoint &&
@ -3812,10 +3863,15 @@ var BrowserEventHandler = {
}, },
resetMaxLineBoxWidth: function() { resetMaxLineBoxWidth: function() {
let webNav = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation); BrowserApp.selectedTab.probablyNeedRefloz = false;
let docShell = webNav.QueryInterface(Ci.nsIDocShell);
let docViewer = docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer); if (gReflowPending) {
docViewer.changeMaxLineBoxWidth(0); clearTimeout(gReflowPending);
}
let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout");
gReflowPending = setTimeout(doChangeMaxLineBoxWidth,
reflozTimeout, 0);
}, },
updateReflozPref: function() { updateReflozPref: function() {
@ -4046,6 +4102,18 @@ var BrowserEventHandler = {
onDoubleTap: function(aData) { onDoubleTap: function(aData) {
let data = JSON.parse(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 zoom = BrowserApp.selectedTab._zoom;
let element = ElementTouchHelper.anyElementFromPoint(data.x, data.y); let element = ElementTouchHelper.anyElementFromPoint(data.x, data.y);
if (!element) { if (!element) {
@ -4068,6 +4136,10 @@ var BrowserEventHandler = {
*/ */
_zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) { _zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) {
const margin = 15; const margin = 15;
// This is really only used for reflow-on-zoom.
let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement);
let rect = ElementTouchHelper.getBoundingContentRect(aElement); let rect = ElementTouchHelper.getBoundingContentRect(aElement);
let viewport = BrowserApp.selectedTab.getViewport(); let viewport = BrowserApp.selectedTab.getViewport();
@ -4077,12 +4149,20 @@ var BrowserEventHandler = {
rect.h); rect.h);
// constrict the rect to the screen's right edge // constrict the rect to the screen's right edge
bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x); 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 // 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. // 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(); this._zoomOut();
}
return; return;
} }