Fixing touch scrolling support for devices that support it natively. Our current touch support overrides native touch scrolling on tablets, which breaks touch scrolling.
Review at http://gwt-code-reviews.appspot.com/1369809
Review by: pdr@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9852 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/event/dom/DomEvent.gwt.xml b/user/src/com/google/gwt/event/dom/DomEvent.gwt.xml
index 1e761c5..12d921e 100644
--- a/user/src/com/google/gwt/event/dom/DomEvent.gwt.xml
+++ b/user/src/com/google/gwt/event/dom/DomEvent.gwt.xml
@@ -1,5 +1,6 @@
<module>
- <inherits name="com.google.gwt.event.EventBase" />
- <inherits name="com.google.gwt.dom.DOM" />
+ <inherits name="com.google.gwt.dom.DOM" />
+ <inherits name="com.google.gwt.event.EventBase" />
+ <inherits name="com.google.gwt.event.dom.TouchEvent" />
<source path="client"/>
</module>
diff --git a/user/src/com/google/gwt/event/dom/TouchEvent.gwt.xml b/user/src/com/google/gwt/event/dom/TouchEvent.gwt.xml
new file mode 100644
index 0000000..e2beb0b
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/TouchEvent.gwt.xml
@@ -0,0 +1,37 @@
+<!-- -->
+<!-- Copyright 2011 Google Inc. -->
+<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
+<!-- may not use this file except in compliance with the License. You may -->
+<!-- may obtain a copy of the License at -->
+<!-- -->
+<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
+<!-- -->
+<!-- Unless required by applicable law or agreed to in writing, software -->
+<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
+<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -->
+<!-- implied. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+<module>
+ <inherits name="com.google.gwt.user.User" />
+
+ <!-- Define the support property -->
+ <define-property name="touchEventSupport" values="maybe,no" />
+
+ <!--
+ Modern browsers either support touch events or will probably add touch
+ support in the future.
+ -->
+ <set-property name="touchEventSupport" value="maybe" />
+
+ <!-- Older browsers do not support touch events. -->
+ <set-property name="touchEventSupport" value="no">
+ <any>
+ <when-property-is name="user.agent" value="ie6" />
+ </any>
+ </set-property>
+
+ <replace-with class="com.google.gwt.event.dom.TouchEvent.TouchSupportDetectorNo">
+ <when-type-is class="com.google.gwt.event.dom.TouchEvent.TouchSupportDetector" />
+ <when-property-is name="touchEventSupport" value="no" />
+ </replace-with>
+</module>
diff --git a/user/src/com/google/gwt/event/dom/client/TouchEvent.java b/user/src/com/google/gwt/event/dom/client/TouchEvent.java
index e59c69d..556c3cb 100644
--- a/user/src/com/google/gwt/event/dom/client/TouchEvent.java
+++ b/user/src/com/google/gwt/event/dom/client/TouchEvent.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.shared.EventHandler;
@@ -29,6 +30,53 @@
extends HumanInputEvent<H> {
/**
+ * Dectector for browser support for touch events.
+ */
+ private static class TouchSupportDetector {
+
+ private final boolean isSupported = detectTouchSupport();
+
+ public boolean isSupported() {
+ return isSupported;
+ }
+
+ private native boolean detectTouchSupport() /*-{
+ var elem = document.createElement('div');
+ elem.setAttribute('ontouchstart', 'return;');
+ return (typeof elem.ontouchstart) == "function";
+ }-*/;
+ }
+
+ /**
+ * Detector for browsers that do not support touch events.
+ */
+ @SuppressWarnings("unused")
+ private static class TouchSupportDetectorNo extends TouchSupportDetector {
+ @Override
+ public boolean isSupported() {
+ return false;
+ }
+ }
+
+ /**
+ * The implementation singleton.
+ */
+ private static TouchSupportDetector impl;
+
+ /**
+ * Runtime check for whether touch scrolling is supported in this browser. Returns true if touch
+ * events are supported but touch based scrolling is not natively supported.
+ *
+ * @return true if touch events are supported, false if not
+ */
+ public static boolean isSupported() {
+ if (impl == null) {
+ impl = GWT.create(TouchSupportDetector.class);
+ }
+ return impl.isSupported();
+ }
+
+ /**
* Get an array of {@link Touch touches} which have changed since the last
* touch event fired. Note, that for {@link TouchEndEvent touch end events},
* the touch which has just ended will not be present in the array. Moreover,
diff --git a/user/src/com/google/gwt/touch/Touch.gwt.xml b/user/src/com/google/gwt/touch/Touch.gwt.xml
index 959061d..4e27ae4 100644
--- a/user/src/com/google/gwt/touch/Touch.gwt.xml
+++ b/user/src/com/google/gwt/touch/Touch.gwt.xml
@@ -13,25 +13,5 @@
<!-- limitations under the License. -->
<module>
<inherits name="com.google.gwt.user.User" />
-
- <!-- Define the support property -->
- <define-property name="touchEventSupport" values="maybe,no" />
-
- <!--
- Modern browsers either support touch events or will probably add touch
- support in the future.
- -->
- <set-property name="touchEventSupport" value="maybe" />
-
- <!-- Older browsers do not support touch events. -->
- <set-property name="touchEventSupport" value="no">
- <any>
- <when-property-is name="user.agent" value="ie6" />
- </any>
- </set-property>
-
- <replace-with class="com.google.gwt.touch.client.TouchScroller.TouchSupportDetectorNo">
- <when-type-is class="com.google.gwt.touch.client.TouchScroller.TouchSupportDetector" />
- <when-property-is name="touchEventSupport" value="no" />
- </replace-with>
+ <source path="client"/>
</module>
diff --git a/user/src/com/google/gwt/touch/client/TouchScroller.java b/user/src/com/google/gwt/touch/client/TouchScroller.java
index fd9967a..5c05a36 100644
--- a/user/src/com/google/gwt/touch/client/TouchScroller.java
+++ b/user/src/com/google/gwt/touch/client/TouchScroller.java
@@ -16,7 +16,6 @@
package com.google.gwt.touch.client;
import com.google.gwt.core.client.Duration;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
@@ -43,6 +42,11 @@
/**
* Adds touch based scrolling to a scroll panel.
+ *
+ * <p>
+ * Touch based scrolling is only supported on devices that support touch events
+ * and do not implement native touch based scrolling.
+ * </p>
*/
@PartialSupport
public class TouchScroller {
@@ -138,35 +142,6 @@
}
/**
- * Dectector for browser support for touch events.
- */
- private static class TouchSupportDetector {
-
- private final boolean isSupported = detectTouchSupport();
-
- public boolean isSupported() {
- return isSupported;
- }
-
- private native boolean detectTouchSupport() /*-{
- var elem = document.createElement('div');
- elem.setAttribute('ontouchstart', 'return;');
- return (typeof elem.ontouchstart) == "function";
- }-*/;
- }
-
- /**
- * Detector for browsers that do not support touch events.
- */
- @SuppressWarnings("unused")
- private static class TouchSupportDetectorNo extends TouchSupportDetector {
- @Override
- public boolean isSupported() {
- return false;
- }
- }
-
- /**
* The number of frames per second the animation should run at.
*/
private static final double FRAMES_PER_SECOND = 60;
@@ -193,9 +168,10 @@
private static final int MS_PER_FRAME = (int) (1000 / FRAMES_PER_SECOND);
/**
- * The implementation singleton.
+ * A cached boolean indicating whether or not touch scrolling is supported.
+ * Set to a non-null value the first time {@link #isSupported()} is called.
*/
- private static TouchSupportDetector impl;
+ private static Boolean isSupported;
/**
* Return a new {@link TouchScroller}.
@@ -222,25 +198,35 @@
}
/**
- * Runtime check for whether touch events are supported in this browser.
+ * Runtime check for whether touch scrolling is supported in this browser.
+ * Returns true if touch events are supported but touch based scrolling is not
+ * natively supported.
*
- * @return true if touch events are is supported, false it not
+ * @return true if touch scrolling is supported, false if not
*/
public static boolean isSupported() {
- return impl().isSupported();
+ if (isSupported == null) {
+ /*
+ * Android 3.0 devices support touch scrolling natively.
+ *
+ * TODO(jlabanca): Find a more reliable way to detect if native touch
+ * scrolling is supported.
+ */
+ isSupported = TouchEvent.isSupported() && !isAndroid3();
+ }
+ return isSupported;
}
/**
- * Get the implementation of this widget.
+ * Check if the user agent is android 3.0 or greater.
*
- * @return the implementation
+ * @return true if android 3.0+
+ *
*/
- private static TouchSupportDetector impl() {
- if (impl == null) {
- impl = GWT.create(TouchSupportDetector.class);
- }
- return impl;
- }
+ private static native boolean isAndroid3() /*-{
+ var ua = navigator.userAgent.toLowerCase();
+ return /android ([3-9]+)\.([0-9]+)/.exec(ua) != null;
+ }-*/;
/**
* The registration for the preview handler used to bust click events.
diff --git a/user/test/com/google/gwt/touch/client/TouchScrollTest.java b/user/test/com/google/gwt/touch/client/TouchScrollTest.java
index 6b07f39..bcf035a 100644
--- a/user/test/com/google/gwt/touch/client/TouchScrollTest.java
+++ b/user/test/com/google/gwt/touch/client/TouchScrollTest.java
@@ -257,7 +257,7 @@
public void testCreateIfSupported() {
// createIfSupported()
TouchScroller scroller = TouchScroller.createIfSupported();
- if (isTouchSupported()) {
+ if (TouchScroller.isSupported()) {
assertNotNull("TouchScroll not created, but touch is supported", scroller);
assertNull(scroller.getTargetWidget());
@@ -268,7 +268,7 @@
// createIfSupported(HasScrolling)
HasScrolling target = new ScrollPanel();
scroller = TouchScroller.createIfSupported(target);
- if (isTouchSupported()) {
+ if (TouchScroller.isSupported()) {
assertNotNull("TouchScroll not created, but touch is supported", scroller);
assertEquals(target, scroller.getTargetWidget());
@@ -511,10 +511,4 @@
scrollPanel = null;
scroller = null;
}
-
- private native boolean isTouchSupported() /*-{
- var elem = document.createElement('div');
- elem.setAttribute('ontouchstart', 'return;');
- return (typeof elem.ontouchstart) == "function";
- }-*/;
}