Skip to content

Commit

Permalink
Fixed touch scrolling issue in Surface and WP devices (#18737)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
johannest authored and Vaadin Code Review committed Nov 22, 2016
1 parent 3145ab0 commit 92b5c38
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 4 deletions.
100 changes: 96 additions & 4 deletions client/src/main/java/com/vaadin/client/widgets/Escalator.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -340,6 +342,11 @@ public native int getPageY()
/*-{
return this.targetTouches[0].pageY;
}-*/;

public native String getPointerType()
/*-{
return this.pointerType;
}-*/;
}

private final Escalator escalator;
Expand Down Expand Up @@ -457,6 +464,15 @@ void stepAnimation(double progress) {
}

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();
}
Expand Down Expand Up @@ -496,7 +512,7 @@ public void run(int duration) {
};

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);
Expand Down Expand Up @@ -544,6 +560,18 @@ public void touchEnd(final CustomTouchEvent event) {
}
}

// 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);
Expand Down Expand Up @@ -901,7 +929,7 @@ public native void attachScrollListener(Element element)

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
Expand Down Expand Up @@ -996,6 +1024,50 @@ public native void detachTouchListeners(Element element)
}
}-*/;

/**
* 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";
Expand Down Expand Up @@ -5772,7 +5844,13 @@ public void execute() {
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
Expand All @@ -5781,7 +5859,13 @@ protected void onUnload() {
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
Expand Down Expand Up @@ -6838,4 +6922,12 @@ private void logWarning(String message) {
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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
}

.#{$primaryStyleName}-body {
-ms-touch-action: none;
touch-action: none;
z-index: 0;
top: 0;

Expand Down

0 comments on commit 92b5c38

Please sign in to comment.