Bug 941995 - Disable double-tapping and click delay on pages that are device-width or narrower. r=mbrubeck,wesj
| author | Kartikaya Gupta <kgupta@mozilla.com> |
| Mon, 24 Feb 2014 19:21:02 -0500 | |
| changeset 170286 | c0f13ab0740e3552744c1727e8c15cbebd182a39 |
| parent 170285 | a19e4c6dc2a95920c0a0a80a86833dbb7630e308 |
| child 170287 | ff2a1d3d39f2e74712b28460c6cd6f8d11007102 |
| push id | 40184 |
| push user | kgupta@mozilla.com |
| push date | Tue, 25 Feb 2014 00:23:08 +0000 |
| treeherder | mozilla-inbound@ff2a1d3d39f2 [default view] [failures only] |
| reviewers | mbrubeck, wesj |
| bugs | 941995 |
| milestone | 30.0a1 |
| first release with | nightly linux32 626d99c084cb / 30.0a1 / 20140226030202 / files nightly linux64 626d99c084cb / 30.0a1 / 20140226030202 / files nightly mac 626d99c084cb / 30.0a1 / 20140226030202 / files nightly win32 626d99c084cb / 30.0a1 / 20140226030202 / files nightly win64 626d99c084cb / 30.0a1 / 20140226030202 / files |
| last release without | nightly linux32 31113754db3b / 30.0a1 / 20140224030203 / files nightly linux64 31113754db3b / 30.0a1 / 20140224030203 / files nightly mac 31113754db3b / 30.0a1 / 20140224030203 / files nightly win32 31113754db3b / 30.0a1 / 20140224030203 / files nightly win64 31113754db3b / 30.0a1 / 20140224030203 / files |
Bug 941995 - Disable double-tapping and click delay on pages that are device-width or narrower. r=mbrubeck,wesj
--- a/mobile/android/base/ZoomConstraints.java +++ b/mobile/android/base/ZoomConstraints.java @@ -5,38 +5,45 @@ package org.mozilla.gecko; import org.json.JSONException; import org.json.JSONObject; public final class ZoomConstraints { private final boolean mAllowZoom; + private final boolean mAllowDoubleTapZoom; private final float mDefaultZoom; private final float mMinZoom; private final float mMaxZoom; public ZoomConstraints(boolean allowZoom) { mAllowZoom = allowZoom; + mAllowDoubleTapZoom = allowZoom; mDefaultZoom = 0.0f; mMinZoom = 0.0f; mMaxZoom = 0.0f; } ZoomConstraints(JSONObject message) throws JSONException { mAllowZoom = message.getBoolean("allowZoom"); + mAllowDoubleTapZoom = message.getBoolean("allowDoubleTapZoom"); mDefaultZoom = (float)message.getDouble("defaultZoom"); mMinZoom = (float)message.getDouble("minZoom"); mMaxZoom = (float)message.getDouble("maxZoom"); } public final boolean getAllowZoom() { return mAllowZoom; } + public final boolean getAllowDoubleTapZoom() { + return mAllowDoubleTapZoom; + } + public final float getDefaultZoom() { return mDefaultZoom; } public final float getMinZoom() { return mMinZoom; }
--- a/mobile/android/base/gfx/JavaPanZoomController.java +++ b/mobile/android/base/gfx/JavaPanZoomController.java @@ -1349,38 +1349,39 @@ class JavaPanZoomController @Override public void onLongPress(MotionEvent motionEvent) { sendPointToGecko("Gesture:LongPress", motionEvent); } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { - // When zooming is enabled, we wait to see if there's a double-tap. + // When double-tapping is allowed, we have to wait to see if this is + // going to be a double-tap. // However, if mMediumPress is true then we know there will be no // double-tap so we treat this as a click. - if (mMediumPress || !mTarget.getZoomConstraints().getAllowZoom()) { + if (mMediumPress || !mTarget.getZoomConstraints().getAllowDoubleTapZoom()) { sendPointToGecko("Gesture:SingleTap", motionEvent); } // return false because we still want to get the ACTION_UP event that triggers this return false; } @Override public boolean onSingleTapConfirmed(MotionEvent motionEvent) { // When zooming is disabled, we handle this in onSingleTapUp. - if (mTarget.getZoomConstraints().getAllowZoom()) { + if (mTarget.getZoomConstraints().getAllowDoubleTapZoom()) { sendPointToGecko("Gesture:SingleTap", motionEvent); } return true; } @Override public boolean onDoubleTap(MotionEvent motionEvent) { - if (mTarget.getZoomConstraints().getAllowZoom()) { + if (mTarget.getZoomConstraints().getAllowDoubleTapZoom()) { sendPointToGecko("Gesture:DoubleTap", motionEvent); } return true; } private void cancelTouch() { GeckoEvent e = GeckoEvent.createBroadcastEvent("Gesture:CancelTouch", ""); GeckoAppShell.sendEventToGecko(e);
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -4036,33 +4036,35 @@ Tab.prototype = { get metadata() { return ViewportHandler.getMetadataForDocument(this.browser.contentDocument); }, /** Update viewport when the metadata changes. */ updateViewportMetadata: function updateViewportMetadata(aMetadata, aInitialLoad) { if (Services.prefs.getBoolPref("browser.ui.zoom.force-user-scalable")) { aMetadata.allowZoom = true; + aMetadata.allowDoubleTapZoom = true; aMetadata.minZoom = aMetadata.maxZoom = NaN; } let scaleRatio = window.devicePixelRatio; if (aMetadata.defaultZoom > 0) aMetadata.defaultZoom *= scaleRatio; if (aMetadata.minZoom > 0) aMetadata.minZoom *= scaleRatio; if (aMetadata.maxZoom > 0) aMetadata.maxZoom *= scaleRatio; aMetadata.isRTL = this.browser.contentDocument.documentElement.dir == "rtl"; ViewportHandler.setMetadataForDocument(this.browser.contentDocument, aMetadata); + this.sendViewportMetadata(); + this.updateViewportSize(gScreenWidth, aInitialLoad); - this.sendViewportMetadata(); }, /** Update viewport when the metadata or the window size changes. */ updateViewportSize: function updateViewportSize(aOldScreenWidth, aInitialLoad) { // When this function gets called on window resize, we must execute // this.sendViewportUpdate() so that refreshDisplayPort is called. // Ensure that when making changes to this function that code path // is not accidentally removed (the call to sendViewportUpdate() is @@ -4177,30 +4179,42 @@ Tab.prototype = { // Avoid having the scroll position jump around after device rotation. let win = this.browser.contentWindow; this.userScrollPos.x = win.scrollX; this.userScrollPos.y = win.scrollY; this.sendViewportUpdate(); + if (metadata.allowZoom && !Services.prefs.getBoolPref("browser.ui.zoom.force-user-scalable")) { + // If the CSS viewport is narrower than the screen (i.e. width <= device-width) + // then we disable double-tap-to-zoom behaviour. + var oldAllowDoubleTapZoom = metadata.allowDoubleTapZoom; + var newAllowDoubleTapZoom = (viewportW > screenW / window.devicePixelRatio); + if (oldAllowDoubleTapZoom !== newAllowDoubleTapZoom) { + metadata.allowDoubleTapZoom = newAllowDoubleTapZoom; + this.sendViewportMetadata(); + } + } + // Store the page size that was used to calculate the viewport so that we // can verify it's changed when we consider remeasuring in updateViewportForPageSize let viewport = this.getViewport(); this.lastPageSizeAfterViewportRemeasure = { width: viewport.pageRight - viewport.pageLeft, height: viewport.pageBottom - viewport.pageTop }; }, sendViewportMetadata: function sendViewportMetadata() { let metadata = this.metadata; sendMessageToJava({ type: "Tab:ViewportMetadata", allowZoom: metadata.allowZoom, + allowDoubleTapZoom: metadata.allowDoubleTapZoom, defaultZoom: metadata.defaultZoom || window.devicePixelRatio, minZoom: metadata.minZoom || 0, maxZoom: metadata.maxZoom || 0, isRTL: metadata.isRTL, tabID: this.id }); }, @@ -5873,35 +5887,42 @@ var ViewportHandler = { let height = this.clamp(parseInt(heightStr), kViewportMinHeight, kViewportMaxHeight) || 0; // Allow zoom unless explicity disabled or minScale and maxScale are equal. // WebKit allows 0, "no", or "false" for viewport-user-scalable. // Note: NaN != NaN. Therefore if minScale and maxScale are undefined the clause has no effect. let allowZoomStr = windowUtils.getDocumentMetadata("viewport-user-scalable"); let allowZoom = !/^(0|no|false)$/.test(allowZoomStr) && (minScale != maxScale); + // Double-tap should always be disabled if allowZoom is disabled. So we initialize + // allowDoubleTapZoom to the same value as allowZoom and have additional conditions to + // disable it in updateViewportSize. + let allowDoubleTapZoom = allowZoom; + let autoSize = true; if (isNaN(scale) && isNaN(minScale) && isNaN(maxScale) && allowZoomStr == "" && widthStr == "" && heightStr == "") { // Only check for HandheldFriendly if we don't have a viewport meta tag let handheldFriendly = windowUtils.getDocumentMetadata("HandheldFriendly"); if (handheldFriendly == "true") { return new ViewportMetadata({ defaultZoom: 1, autoSize: true, - allowZoom: true + allowZoom: true, + allowDoubleTapZoom: false }); } let doctype = aWindow.document.doctype; if (doctype && /(WAP|WML|Mobile)/.test(doctype.publicId)) { return new ViewportMetadata({ defaultZoom: 1, autoSize: true, - allowZoom: true + allowZoom: true, + allowDoubleTapZoom: false }); } hasMetaViewport = false; let defaultZoom = Services.prefs.getIntPref("browser.viewport.defaultZoom"); if (defaultZoom >= 0) { scale = defaultZoom / 1000; autoSize = false; @@ -5923,16 +5944,17 @@ var ViewportHandler = { return new ViewportMetadata({ defaultZoom: scale, minZoom: minScale, maxZoom: maxScale, width: width, height: height, autoSize: autoSize, allowZoom: allowZoom, + allowDoubleTapZoom: allowDoubleTapZoom, isSpecified: hasMetaViewport, isRTL: isRTL }); }, clamp: function(num, min, max) { return Math.max(min, Math.min(max, num)); }, @@ -5966,39 +5988,42 @@ var ViewportHandler = { * An object which represents the page's preferred viewport properties: * width (int): The CSS viewport width in px. * height (int): The CSS viewport height in px. * defaultZoom (float): The initial scale when the page is loaded. * minZoom (float): The minimum zoom level. * maxZoom (float): The maximum zoom level. * autoSize (boolean): Resize the CSS viewport when the window resizes. * allowZoom (boolean): Let the user zoom in or out. + * allowDoubleTapZoom (boolean): Allow double-tap to zoom in. * isSpecified (boolean): Whether the page viewport is specified or not. */ function ViewportMetadata(aMetadata = {}) { this.width = ("width" in aMetadata) ? aMetadata.width : 0; this.height = ("height" in aMetadata) ? aMetadata.height : 0; this.defaultZoom = ("defaultZoom" in aMetadata) ? aMetadata.defaultZoom : 0; this.minZoom = ("minZoom" in aMetadata) ? aMetadata.minZoom : 0; this.maxZoom = ("maxZoom" in aMetadata) ? aMetadata.maxZoom : 0; this.autoSize = ("autoSize" in aMetadata) ? aMetadata.autoSize : false; this.allowZoom = ("allowZoom" in aMetadata) ? aMetadata.allowZoom : true; + this.allowDoubleTapZoom = ("allowDoubleTapZoom" in aMetadata) ? aMetadata.allowDoubleTapZoom : true; this.isSpecified = ("isSpecified" in aMetadata) ? aMetadata.isSpecified : false; this.isRTL = ("isRTL" in aMetadata) ? aMetadata.isRTL : false; Object.seal(this); } ViewportMetadata.prototype = { width: null, height: null, defaultZoom: null, minZoom: null, maxZoom: null, autoSize: null, allowZoom: null, + allowDoubleTapZoom: null, isSpecified: null, isRTL: null, }; /** * Handler for blocked popups, triggered by DOMUpdatePageReport events in browser.xml */