draw filtered if dragging but not moving after a 100ms delay
Some artifacts show up when dragging, but since the screen is in motion, they're usually go unnoticed. If one quits moving, the artifacts are more visible. Some devices generate fractional movement data while the screen is touched and held steady; others do not. Also, mouse-based implementations will not generate random fractional movements. If the device generates movements, invalidate the screen to transition once from unfiltered to filtered drawing. For the case that the device does not generate movements, fire a timer when the screen is drawn and a drag is in progress to detect that there is no drag motion. The timer fires if the dragged screen is unmoved for 100 ms, then invalidates so the next redraw uses filtering to remove the artifacts, and starts a continuous timer to keep the scrollbar awake until the drag ends or there is more drag motion. When detecting that there is no effective movement on a noisy device, use the original fractional deltas instead of the integer ones to detect sub 1 pixel differences. This was tested on the emulator (no noise) and a sapphire (noise) to make sure that events load the queue only when required. fixes http://b/issue?id=2092446
This commit is contained in:
@@ -390,6 +390,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
private static final int LONG_PRESS_TIMEOUT = 1000;
|
private static final int LONG_PRESS_TIMEOUT = 1000;
|
||||||
// needed to avoid flinging after a pause of no movement
|
// needed to avoid flinging after a pause of no movement
|
||||||
private static final int MIN_FLING_TIME = 250;
|
private static final int MIN_FLING_TIME = 250;
|
||||||
|
// draw unfiltered after drag is held without movement
|
||||||
|
private static final int MOTIONLESS_TIME = 100;
|
||||||
// The time that the Zoom Controls are visible before fading away
|
// The time that the Zoom Controls are visible before fading away
|
||||||
private static final long ZOOM_CONTROLS_TIMEOUT =
|
private static final long ZOOM_CONTROLS_TIMEOUT =
|
||||||
ViewConfiguration.getZoomControlsTimeout();
|
ViewConfiguration.getZoomControlsTimeout();
|
||||||
@@ -427,6 +429,10 @@ public class WebView extends AbsoluteLayout
|
|||||||
private Scroller mScroller;
|
private Scroller mScroller;
|
||||||
|
|
||||||
private boolean mWrapContent;
|
private boolean mWrapContent;
|
||||||
|
private static final int MOTIONLESS_FALSE = 0;
|
||||||
|
private static final int MOTIONLESS_PENDING = 1;
|
||||||
|
private static final int MOTIONLESS_TRUE = 2;
|
||||||
|
private int mHeldMotionless;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private message ids
|
* Private message ids
|
||||||
@@ -438,6 +444,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
private static final int RELEASE_SINGLE_TAP = 5;
|
private static final int RELEASE_SINGLE_TAP = 5;
|
||||||
private static final int REQUEST_FORM_DATA = 6;
|
private static final int REQUEST_FORM_DATA = 6;
|
||||||
private static final int RESUME_WEBCORE_UPDATE = 7;
|
private static final int RESUME_WEBCORE_UPDATE = 7;
|
||||||
|
private static final int DRAG_HELD_MOTIONLESS = 8;
|
||||||
|
private static final int AWAKEN_SCROLL_BARS = 9;
|
||||||
|
|
||||||
//! arg1=x, arg2=y
|
//! arg1=x, arg2=y
|
||||||
static final int SCROLL_TO_MSG_ID = 10;
|
static final int SCROLL_TO_MSG_ID = 10;
|
||||||
@@ -468,9 +476,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
"SWITCH_TO_LONGPRESS", // = 4;
|
"SWITCH_TO_LONGPRESS", // = 4;
|
||||||
"RELEASE_SINGLE_TAP", // = 5;
|
"RELEASE_SINGLE_TAP", // = 5;
|
||||||
"REQUEST_FORM_DATA", // = 6;
|
"REQUEST_FORM_DATA", // = 6;
|
||||||
"SWITCH_TO_CLICK", // = 7;
|
"RESUME_WEBCORE_UPDATE", // = 7;
|
||||||
"RESUME_WEBCORE_UPDATE", // = 8;
|
"DRAG_HELD_MOTIONLESS", // = 8;
|
||||||
"9",
|
"AWAKEN_SCROLL_BARS", // = 9;
|
||||||
"SCROLL_TO_MSG_ID", // = 10;
|
"SCROLL_TO_MSG_ID", // = 10;
|
||||||
"SCROLL_BY_MSG_ID", // = 11;
|
"SCROLL_BY_MSG_ID", // = 11;
|
||||||
"SPAWN_SCROLL_TO_MSG_ID", // = 12;
|
"SPAWN_SCROLL_TO_MSG_ID", // = 12;
|
||||||
@@ -2870,8 +2878,22 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean animateZoom = mZoomScale != 0;
|
boolean animateZoom = mZoomScale != 0;
|
||||||
boolean animateScroll = !mScroller.isFinished()
|
boolean animateScroll = (!mScroller.isFinished()
|
||||||
|| mVelocityTracker != null;
|
|| mVelocityTracker != null)
|
||||||
|
&& (mTouchMode != TOUCH_DRAG_MODE ||
|
||||||
|
mHeldMotionless != MOTIONLESS_TRUE);
|
||||||
|
if (mTouchMode == TOUCH_DRAG_MODE) {
|
||||||
|
if (mHeldMotionless == MOTIONLESS_PENDING) {
|
||||||
|
mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
|
||||||
|
mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
|
||||||
|
mHeldMotionless = MOTIONLESS_FALSE;
|
||||||
|
}
|
||||||
|
if (mHeldMotionless == MOTIONLESS_FALSE) {
|
||||||
|
mPrivateHandler.sendMessageDelayed(mPrivateHandler
|
||||||
|
.obtainMessage(DRAG_HELD_MOTIONLESS), MOTIONLESS_TIME);
|
||||||
|
mHeldMotionless = MOTIONLESS_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (animateZoom) {
|
if (animateZoom) {
|
||||||
float zoomScale;
|
float zoomScale;
|
||||||
int interval = (int) (SystemClock.uptimeMillis() - mZoomStart);
|
int interval = (int) (SystemClock.uptimeMillis() - mZoomStart);
|
||||||
@@ -3726,8 +3748,10 @@ public class WebView extends AbsoluteLayout
|
|||||||
mLastSentTouchTime = eventTime;
|
mLastSentTouchTime = eventTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
int deltaX = (int) (mLastTouchX - x);
|
float fDeltaX = mLastTouchX - x;
|
||||||
int deltaY = (int) (mLastTouchY - y);
|
float fDeltaY = mLastTouchY - y;
|
||||||
|
int deltaX = (int) fDeltaX;
|
||||||
|
int deltaY = (int) fDeltaY;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_DOWN: {
|
case MotionEvent.ACTION_DOWN: {
|
||||||
@@ -3853,13 +3877,27 @@ public class WebView extends AbsoluteLayout
|
|||||||
|
|
||||||
// do pan
|
// do pan
|
||||||
int newScrollX = pinLocX(mScrollX + deltaX);
|
int newScrollX = pinLocX(mScrollX + deltaX);
|
||||||
deltaX = newScrollX - mScrollX;
|
int newDeltaX = newScrollX - mScrollX;
|
||||||
|
if (deltaX != newDeltaX) {
|
||||||
|
deltaX = newDeltaX;
|
||||||
|
fDeltaX = (float) newDeltaX;
|
||||||
|
}
|
||||||
int newScrollY = pinLocY(mScrollY + deltaY);
|
int newScrollY = pinLocY(mScrollY + deltaY);
|
||||||
deltaY = newScrollY - mScrollY;
|
int newDeltaY = newScrollY - mScrollY;
|
||||||
|
if (deltaY != newDeltaY) {
|
||||||
|
deltaY = newDeltaY;
|
||||||
|
fDeltaY = (float) newDeltaY;
|
||||||
|
}
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
if (deltaX == 0 && deltaY == 0) {
|
boolean keepScrollBarsVisible = false;
|
||||||
done = true;
|
if (Math.abs(fDeltaX) < 1.0f && Math.abs(fDeltaY) < 1.0f) {
|
||||||
|
keepScrollBarsVisible = done = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (mHeldMotionless != MOTIONLESS_FALSE) {
|
||||||
|
mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
|
||||||
|
mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
|
||||||
|
mHeldMotionless = MOTIONLESS_FALSE;
|
||||||
|
}
|
||||||
if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
|
if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
|
||||||
int ax = Math.abs(deltaX);
|
int ax = Math.abs(deltaX);
|
||||||
int ay = Math.abs(deltaY);
|
int ay = Math.abs(deltaY);
|
||||||
@@ -3899,8 +3937,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (deltaX == 0) {
|
if (deltaX == 0) {
|
||||||
// keep the scrollbar on the screen even there is no
|
// keep the scrollbar on the screen even there is no
|
||||||
// scroll
|
// scroll
|
||||||
awakenScrollBars(ViewConfiguration
|
keepScrollBarsVisible = true;
|
||||||
.getScrollDefaultDelay(), false);
|
|
||||||
} else {
|
} else {
|
||||||
scrollBy(deltaX, 0);
|
scrollBy(deltaX, 0);
|
||||||
}
|
}
|
||||||
@@ -3910,8 +3947,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (deltaY == 0) {
|
if (deltaY == 0) {
|
||||||
// keep the scrollbar on the screen even there is no
|
// keep the scrollbar on the screen even there is no
|
||||||
// scroll
|
// scroll
|
||||||
awakenScrollBars(ViewConfiguration
|
keepScrollBarsVisible = true;
|
||||||
.getScrollDefaultDelay(), false);
|
|
||||||
} else {
|
} else {
|
||||||
scrollBy(0, deltaY);
|
scrollBy(0, deltaY);
|
||||||
}
|
}
|
||||||
@@ -3938,13 +3974,17 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done) {
|
if (keepScrollBarsVisible) {
|
||||||
|
if (mHeldMotionless != MOTIONLESS_TRUE) {
|
||||||
|
mHeldMotionless = MOTIONLESS_TRUE;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
// keep the scrollbar on the screen even there is no scroll
|
// keep the scrollbar on the screen even there is no scroll
|
||||||
awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(),
|
awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(),
|
||||||
false);
|
false);
|
||||||
// return false to indicate that we can't pan out of the
|
// return false to indicate that we can't pan out of the
|
||||||
// view space
|
// view space
|
||||||
return false;
|
return !done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3997,6 +4037,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOUCH_DRAG_MODE:
|
case TOUCH_DRAG_MODE:
|
||||||
|
mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
|
||||||
|
mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
|
||||||
|
mHeldMotionless = MOTIONLESS_TRUE;
|
||||||
// redraw in high-quality, as we're done dragging
|
// redraw in high-quality, as we're done dragging
|
||||||
invalidate();
|
invalidate();
|
||||||
// if the user waits a while w/o moving before the
|
// if the user waits a while w/o moving before the
|
||||||
@@ -4036,6 +4079,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
|
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
|
||||||
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||||
|
mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
|
||||||
|
mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
|
||||||
|
mHeldMotionless = MOTIONLESS_TRUE;
|
||||||
mTouchMode = TOUCH_DONE_MODE;
|
mTouchMode = TOUCH_DONE_MODE;
|
||||||
nativeHideCursor();
|
nativeHideCursor();
|
||||||
break;
|
break;
|
||||||
@@ -5203,6 +5249,21 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DRAG_HELD_MOTIONLESS:
|
||||||
|
mHeldMotionless = MOTIONLESS_TRUE;
|
||||||
|
invalidate();
|
||||||
|
// fall through to keep scrollbars awake
|
||||||
|
|
||||||
|
case AWAKEN_SCROLL_BARS:
|
||||||
|
if (mTouchMode == TOUCH_DRAG_MODE
|
||||||
|
&& mHeldMotionless == MOTIONLESS_TRUE) {
|
||||||
|
awakenScrollBars(ViewConfiguration
|
||||||
|
.getScrollDefaultDelay(), false);
|
||||||
|
mPrivateHandler.sendMessageDelayed(mPrivateHandler
|
||||||
|
.obtainMessage(AWAKEN_SCROLL_BARS),
|
||||||
|
ViewConfiguration.getScrollDefaultDelay());
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user