]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fixed touch scrolling issue in Surface and WP devices (#18737) 7.7.5
authorJohannes Tuikkala <johannes@vaadin.com>
Mon, 14 Nov 2016 07:46:32 +0000 (09:46 +0200)
committerVaadin Code Review <review@vaadin.com>
Tue, 22 Nov 2016 09:07:44 +0000 (09:07 +0000)
Fixed by using pointerevents instead of touchevents when the browser is IE11,
or Edge. Also added touch-action: none; css rules into escalator.css to prevent
default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers,
behaviour on those will stay the same as before the fix.

No new unit tests since we do not have automatic touch testing possibilities yet.
Please test manually with Surface: IE11 and Edge, use for example uitest:
com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics

Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703

client/src/main/java/com/vaadin/client/widgets/Escalator.java
themes/src/main/themes/VAADIN/themes/base/escalator/escalator.scss

index 9eaa7ddd3671adf43c356a865bb3316b1f671fae..39f996aa8418df26bd6993d61ea6495321a61369 100644 (file)
@@ -308,6 +308,8 @@ public class Escalator extends Widget
     static class JsniUtil {
         public static class TouchHandlerBundle {
 
+            public static final String POINTER_EVENT_TYPE_TOUCH = "touch";
+
             /**
              * A <a href=
              * "http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsOverlay.html"
@@ -340,6 +342,11 @@ public class Escalator extends Widget
                 /*-{
                     return this.targetTouches[0].pageY;
                 }-*/;
+
+                public native String getPointerType()
+                /*-{
+                    return this.pointerType;
+                }-*/;
             }
 
             private final Escalator escalator;
@@ -457,6 +464,15 @@ public class Escalator extends Widget
                 }
 
                 int pagePosition(CustomTouchEvent event) {
+                    // Use native event's screen x and y for IE11 and Edge
+                    // since there is no touches for these browsers (#18737)
+                    if (isCurrentBrowserIE11OrEdge()) {
+                        return vertical
+                                ? event.getNativeEvent().getClientY()
+                                + Window.getScrollTop()
+                                : event.getNativeEvent().getClientX()
+                                + Window.getScrollLeft();
+                    }
                     JsArray<Touch> a = event.getNativeEvent().getTouches();
                     return vertical ? a.get(0).getPageY() : a.get(0).getPageX();
                 }
@@ -496,7 +512,7 @@ public class Escalator extends Widget
             };
 
             public void touchStart(final CustomTouchEvent event) {
-                if (event.getNativeEvent().getTouches().length() == 1) {
+                if (allowTouch(event)) {
                     if (yMov == null) {
                         yMov = new Movement(true);
                         xMov = new Movement(false);
@@ -544,6 +560,18 @@ public class Escalator extends Widget
                 }
             }
 
+            // Allow touchStart for IE11 and Edge even though there is no touch
+            // (#18737),
+            // otherwise allow touch only if there is a single touch in the
+            // event
+            private boolean allowTouch(final TouchHandlerBundle.CustomTouchEvent event) {
+                if (isCurrentBrowserIE11OrEdge()) {
+                    return (POINTER_EVENT_TYPE_TOUCH.equals(event.getPointerType()));
+                } else {
+                    return (event.getNativeEvent().getTouches().length() == 1);
+                }
+            }
+
             private double easingInOutCos(double val, double max) {
                 return 0.5 - 0.5 * Math.cos(Math.PI * Math.signum(val)
                         * Math.min(Math.abs(val), max) / max);
@@ -901,7 +929,7 @@ public class Escalator extends Widget
 
         public native void detachScrollListener(Element element)
         /*
-         * Attaching events with JSNI instead of the GWT event mechanism because
+         * Detaching events with JSNI instead of the GWT event mechanism because
          * GWT didn't provide enough details in events, or triggering the event
          * handlers with GWT bindings was unsuccessful. Maybe, with more time
          * and skill, it could be done with better success. JavaScript overlay
@@ -996,6 +1024,50 @@ public class Escalator extends Widget
             }
         }-*/;
 
+        /**
+         * Using pointerdown, pointermove, pointerup, and pointercancel for IE11 and Edge instead of
+         * touch* listeners (#18737)
+         *
+         * @param element
+         */
+        public native void attachPointerEventListeners(Element element)
+        /*
+         * Attaching events with JSNI instead of the GWT event mechanism because
+         * GWT didn't provide enough details in events, or triggering the event
+         * handlers with GWT bindings was unsuccessful. Maybe, with more time
+         * and skill, it could be done with better success. JavaScript overlay
+         * types might work. This might also get rid of the JsniWorkaround
+         * class.
+         */
+        /*-{
+            element.addEventListener("pointerdown", this.@com.vaadin.client.widgets.JsniWorkaround::touchStartFunction);
+            element.addEventListener("pointermove", this.@com.vaadin.client.widgets.JsniWorkaround::touchMoveFunction);
+            element.addEventListener("pointerup", this.@com.vaadin.client.widgets.JsniWorkaround::touchEndFunction);
+            element.addEventListener("pointercancel", this.@com.vaadin.client.widgets.JsniWorkaround::touchEndFunction);
+        }-*/;
+
+        /**
+         * Using pointerdown, pointermove, pointerup, and pointercancel for IE11 and Edge instead of
+         * touch* listeners (#18737)
+         *
+         * @param element
+         */
+        public native void detachPointerEventListeners(Element element)
+        /*
+         * Detaching events with JSNI instead of the GWT event mechanism because
+         * GWT didn't provide enough details in events, or triggering the event
+         * handlers with GWT bindings was unsuccessful. Maybe, with more time
+         * and skill, it could be done with better success. JavaScript overlay
+         * types might work. This might also get rid of the JsniWorkaround
+         * class.
+         */
+        /*-{
+            element.removeEventListener("pointerdown", this.@com.vaadin.client.widgets.JsniWorkaround::touchStartFunction);
+            element.removeEventListener("pointermove", this.@com.vaadin.client.widgets.JsniWorkaround::touchMoveFunction);
+            element.removeEventListener("pointerup", this.@com.vaadin.client.widgets.JsniWorkaround::touchEndFunction);
+            element.removeEventListener("pointercancel", this.@com.vaadin.client.widgets.JsniWorkaround::touchEndFunction);
+        }-*/;
+
         public void scrollToColumn(final int columnIndex,
                 final ScrollDestination destination, final int padding) {
             assert columnIndex >= columnConfiguration.frozenColumns : "Can't scroll to a frozen column";
@@ -5772,7 +5844,13 @@ public class Escalator extends Widget
         scroller.attachScrollListener(verticalScrollbar.getElement());
         scroller.attachScrollListener(horizontalScrollbar.getElement());
         scroller.attachMousewheelListener(getElement());
-        scroller.attachTouchListeners(getElement());
+
+        if (isCurrentBrowserIE11OrEdge()) {
+            // Touch listeners doesn't work for IE11 and Edge (#18737)
+            scroller.attachPointerEventListeners(getElement());
+        } else {
+            scroller.attachTouchListeners(getElement());
+        }
     }
 
     @Override
@@ -5781,7 +5859,13 @@ public class Escalator extends Widget
         scroller.detachScrollListener(verticalScrollbar.getElement());
         scroller.detachScrollListener(horizontalScrollbar.getElement());
         scroller.detachMousewheelListener(getElement());
-        scroller.detachTouchListeners(getElement());
+
+        if (isCurrentBrowserIE11OrEdge()) {
+            // Touch listeners doesn't work for IE11 and Edge (#18737)
+            scroller.detachPointerEventListeners(getElement());
+        } else {
+            scroller.detachTouchListeners(getElement());
+        }
 
         /*
          * We can call paintRemoveRows here, because static ranges are simple to
@@ -6838,4 +6922,12 @@ public class Escalator extends Widget
     double getMinCellWidth(int colIndex) {
         return columnConfiguration.getMinCellWidth(colIndex);
     }
+
+    /**
+     * Internal method for checking whether the browser is IE11 or Edge
+     * @return true only if the current browser is IE11, or Edge
+     */
+    private static boolean isCurrentBrowserIE11OrEdge() {
+        return BrowserInfo.get().isIE11() || BrowserInfo.get().isEdge();
+    }
 }
index 2d5ad729fcc8a2e8ca7978dedfed3b65777148f1..7758ebe6e80938faac3885fad4951dc5fbf89273 100644 (file)
@@ -75,6 +75,8 @@
   }
 
   .#{$primaryStyleName}-body {
+    -ms-touch-action: none;
+    touch-action: none;
     z-index: 0;
     top: 0;