Merge "Better touch rects"

This commit is contained in:
John Reck
2011-08-26 15:31:16 -07:00
committed by Android (Google) Code Review
2 changed files with 98 additions and 61 deletions

View File

@@ -43,6 +43,7 @@ import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.graphics.RegionIterator;
import android.graphics.Shader; import android.graphics.Shader;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Proxy; import android.net.Proxy;
@@ -605,8 +606,9 @@ public class WebView extends AbsoluteLayout
// know to handle Shift and arrows natively first // know to handle Shift and arrows natively first
private boolean mAccessibilityScriptInjected; private boolean mAccessibilityScriptInjected;
static final boolean USE_WEBKIT_RINGS = true;
// the color used to highlight the touch rectangles // the color used to highlight the touch rectangles
private static final int mHightlightColor = 0x33000000; private static final int mHightlightColor = 0x6633b5e5;
// the round corner for the highlight path // the round corner for the highlight path
private static final float TOUCH_HIGHLIGHT_ARC = 5.0f; private static final float TOUCH_HIGHLIGHT_ARC = 5.0f;
// the region indicating where the user touched on the screen // the region indicating where the user touched on the screen
@@ -619,6 +621,7 @@ public class WebView extends AbsoluteLayout
private Paint mTouchCrossHairColor; private Paint mTouchCrossHairColor;
private int mTouchHighlightX; private int mTouchHighlightX;
private int mTouchHighlightY; private int mTouchHighlightY;
private long mTouchHighlightRequested;
// Basically this proxy is used to tell the Video to update layer tree at // Basically this proxy is used to tell the Video to update layer tree at
// SetBaseLayer time and to pause when WebView paused. // SetBaseLayer time and to pause when WebView paused.
@@ -3992,7 +3995,7 @@ public class WebView extends AbsoluteLayout
return super.drawChild(canvas, child, drawingTime); return super.drawChild(canvas, child, drawingTime);
} }
private void drawContent(Canvas canvas) { private void drawContent(Canvas canvas, boolean drawRings) {
// Update the buttons in the picture, so when we draw the picture // Update the buttons in the picture, so when we draw the picture
// to the screen, they are in the correct state. // to the screen, they are in the correct state.
// Tell the native side if user is a) touching the screen, // Tell the native side if user is a) touching the screen,
@@ -4004,7 +4007,8 @@ public class WebView extends AbsoluteLayout
nativeRecordButtons(hasFocus() && hasWindowFocus(), nativeRecordButtons(hasFocus() && hasWindowFocus(),
mTouchMode == TOUCH_SHORTPRESS_START_MODE mTouchMode == TOUCH_SHORTPRESS_START_MODE
|| mTrackballDown || mGotCenterDown, false); || mTrackballDown || mGotCenterDown, false);
drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); drawCoreAndCursorRing(canvas, mBackgroundColor,
mDrawCursorRing && drawRings);
} }
/** /**
@@ -4068,7 +4072,15 @@ public class WebView extends AbsoluteLayout
if (mTitleBar != null) { if (mTitleBar != null) {
canvas.translate(0, getTitleHeight()); canvas.translate(0, getTitleHeight());
} }
drawContent(canvas); boolean drawJavaRings = !mTouchHighlightRegion.isEmpty()
&& (mTouchMode == TOUCH_INIT_MODE
|| mTouchMode == TOUCH_SHORTPRESS_START_MODE
|| mTouchMode == TOUCH_SHORTPRESS_MODE);
boolean drawNativeRings = !drawJavaRings;
if (USE_WEBKIT_RINGS) {
drawNativeRings = !drawJavaRings && !isInTouchMode();
}
drawContent(canvas, drawNativeRings);
canvas.restoreToCount(saveCount); canvas.restoreToCount(saveCount);
if (AUTO_REDRAW_HACK && mAutoRedraw) { if (AUTO_REDRAW_HACK && mAutoRedraw) {
@@ -4081,16 +4093,22 @@ public class WebView extends AbsoluteLayout
} }
// paint the highlight in the end // paint the highlight in the end
if (!mTouchHighlightRegion.isEmpty()) { if (drawJavaRings) {
if (mTouchHightlightPaint == null) { long delay = System.currentTimeMillis() - mTouchHighlightRequested;
mTouchHightlightPaint = new Paint(); if (delay < ViewConfiguration.getTapTimeout()) {
mTouchHightlightPaint.setColor(mHightlightColor); Rect r = mTouchHighlightRegion.getBounds();
mTouchHightlightPaint.setAntiAlias(true); postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
mTouchHightlightPaint.setPathEffect(new CornerPathEffect( } else {
TOUCH_HIGHLIGHT_ARC)); if (mTouchHightlightPaint == null) {
mTouchHightlightPaint = new Paint();
mTouchHightlightPaint.setColor(mHightlightColor);
}
RegionIterator iter = new RegionIterator(mTouchHighlightRegion);
Rect r = new Rect();
while (iter.next(r)) {
canvas.drawRect(r, mTouchHightlightPaint);
}
} }
canvas.drawPath(mTouchHighlightRegion.getBoundaryPath(),
mTouchHightlightPaint);
} }
if (DEBUG_TOUCH_HIGHLIGHT) { if (DEBUG_TOUCH_HIGHLIGHT) {
if (getSettings().getNavDump()) { if (getSettings().getNavDump()) {
@@ -4113,11 +4131,10 @@ public class WebView extends AbsoluteLayout
} }
} }
private void removeTouchHighlight(boolean removePendingMessage) { private void removeTouchHighlight() {
if (removePendingMessage) { mWebViewCore.removeMessages(EventHub.GET_TOUCH_HIGHLIGHT_RECTS);
mWebViewCore.removeMessages(EventHub.GET_TOUCH_HIGHLIGHT_RECTS); mPrivateHandler.removeMessages(SET_TOUCH_HIGHLIGHT_RECTS);
} setTouchHighlightRects(null);
mWebViewCore.sendMessage(EventHub.REMOVE_TOUCH_HIGHLIGHT_RECTS);
} }
@Override @Override
@@ -5786,8 +5803,8 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY); mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
} else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) { } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP); mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
if (getSettings().supportTouchOnly()) { if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
removeTouchHighlight(true); removeTouchHighlight();
} }
if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) { if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
mTouchMode = TOUCH_DOUBLE_TAP_MODE; mTouchMode = TOUCH_DOUBLE_TAP_MODE;
@@ -5810,15 +5827,19 @@ public class WebView extends AbsoluteLayout
mWebViewCore.sendMessage( mWebViewCore.sendMessage(
EventHub.UPDATE_FRAME_CACHE_IF_LOADING); EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
} }
if (getSettings().supportTouchOnly()) { if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
TouchHighlightData data = new TouchHighlightData(); TouchHighlightData data = new TouchHighlightData();
data.mX = contentX; data.mX = contentX;
data.mY = contentY; data.mY = contentY;
data.mNativeLayerRect = new Rect();
data.mNativeLayer = nativeScrollableLayer(
contentX, contentY, data.mNativeLayerRect, null);
data.mSlop = viewToContentDimension(mNavSlop); data.mSlop = viewToContentDimension(mNavSlop);
mTouchHighlightRegion.setEmpty();
if (!mBlockWebkitViewMessages) { if (!mBlockWebkitViewMessages) {
mWebViewCore.sendMessageDelayed( mTouchHighlightRequested = System.currentTimeMillis();
EventHub.GET_TOUCH_HIGHLIGHT_RECTS, data, mWebViewCore.sendMessageAtFrontOfQueue(
ViewConfiguration.getTapTimeout()); EventHub.GET_TOUCH_HIGHLIGHT_RECTS, data);
} }
if (DEBUG_TOUCH_HIGHLIGHT) { if (DEBUG_TOUCH_HIGHLIGHT) {
if (getSettings().getNavDump()) { if (getSettings().getNavDump()) {
@@ -5905,8 +5926,8 @@ public class WebView extends AbsoluteLayout
if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) { if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mTouchMode = TOUCH_INIT_MODE; mTouchMode = TOUCH_INIT_MODE;
} }
if (getSettings().supportTouchOnly()) { if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
removeTouchHighlight(true); removeTouchHighlight();
} }
} }
// pass the touch events from UI thread to WebCore thread // pass the touch events from UI thread to WebCore thread
@@ -6487,8 +6508,8 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS); mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS); mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
if (getSettings().supportTouchOnly()) { if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
removeTouchHighlight(true); removeTouchHighlight();
} }
mHeldMotionless = MOTIONLESS_TRUE; mHeldMotionless = MOTIONLESS_TRUE;
mTouchMode = TOUCH_DONE_MODE; mTouchMode = TOUCH_DONE_MODE;
@@ -7140,8 +7161,20 @@ public class WebView extends AbsoluteLayout
int contentX = viewToContentX(mLastTouchX + mScrollX); int contentX = viewToContentX(mLastTouchX + mScrollX);
int contentY = viewToContentY(mLastTouchY + mScrollY); int contentY = viewToContentY(mLastTouchY + mScrollY);
int slop = viewToContentDimension(mNavSlop); int slop = viewToContentDimension(mNavSlop);
if (USE_WEBKIT_RINGS && !mTouchHighlightRegion.isEmpty()) {
// set mTouchHighlightRequested to 0 to cause an immediate
// drawing of the touch rings
mTouchHighlightRequested = 0;
invalidate(mTouchHighlightRegion.getBounds());
mPrivateHandler.postDelayed(new Runnable() {
@Override
public void run() {
removeTouchHighlight();
}
}, ViewConfiguration.getPressedStateDuration());
}
if (getSettings().supportTouchOnly()) { if (getSettings().supportTouchOnly()) {
removeTouchHighlight(false); removeTouchHighlight();
WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData(); WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
// use "0" as generation id to inform WebKit to use the same x/y as // use "0" as generation id to inform WebKit to use the same x/y as
// it used when processing GET_TOUCH_HIGHLIGHT_RECTS // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
@@ -8031,8 +8064,8 @@ public class WebView extends AbsoluteLayout
break; break;
} }
case SWITCH_TO_LONGPRESS: { case SWITCH_TO_LONGPRESS: {
if (getSettings().supportTouchOnly()) { if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
removeTouchHighlight(false); removeTouchHighlight();
} }
if (inFullScreenMode() || mDeferTouchProcess) { if (inFullScreenMode() || mDeferTouchProcess) {
TouchEventData ted = new TouchEventData(); TouchEventData ted = new TouchEventData();
@@ -8354,26 +8387,9 @@ public class WebView extends AbsoluteLayout
break; break;
case SET_TOUCH_HIGHLIGHT_RECTS: case SET_TOUCH_HIGHLIGHT_RECTS:
invalidate(mTouchHighlightRegion.getBounds()); @SuppressWarnings("unchecked")
mTouchHighlightRegion.setEmpty(); ArrayList<Rect> rects = (ArrayList<Rect>) msg.obj;
if (msg.obj != null) { setTouchHighlightRects(rects);
ArrayList<Rect> rects = (ArrayList<Rect>) msg.obj;
for (Rect rect : rects) {
Rect viewRect = contentToViewRect(rect);
// some sites, like stories in nytimes.com, set
// mouse event handler in the top div. It is not
// user friendly to highlight the div if it covers
// more than half of the screen.
if (viewRect.width() < getWidth() >> 1
|| viewRect.height() < getHeight() >> 1) {
mTouchHighlightRegion.union(viewRect);
invalidate(viewRect);
} else {
Log.w(LOGTAG, "Skip the huge selection rect:"
+ viewRect);
}
}
}
break; break;
case SAVE_WEBARCHIVE_FINISHED: case SAVE_WEBARCHIVE_FINISHED:
@@ -8410,6 +8426,28 @@ public class WebView extends AbsoluteLayout
} }
} }
private void setTouchHighlightRects(ArrayList<Rect> rects) {
invalidate(mTouchHighlightRegion.getBounds());
mTouchHighlightRegion.setEmpty();
if (rects != null) {
for (Rect rect : rects) {
Rect viewRect = contentToViewRect(rect);
// some sites, like stories in nytimes.com, set
// mouse event handler in the top div. It is not
// user friendly to highlight the div if it covers
// more than half of the screen.
if (viewRect.width() < getWidth() >> 1
|| viewRect.height() < getHeight() >> 1) {
mTouchHighlightRegion.union(viewRect);
} else {
Log.w(LOGTAG, "Skip the huge selection rect:"
+ viewRect);
}
}
invalidate(mTouchHighlightRegion.getBounds());
}
}
/** @hide Called by JNI when pages are swapped (only occurs with hardware /** @hide Called by JNI when pages are swapped (only occurs with hardware
* acceleration) */ * acceleration) */
protected void pageSwapCallback() { protected void pageSwapCallback() {

View File

@@ -801,6 +801,8 @@ public final class WebViewCore {
int mX; int mX;
int mY; int mY;
int mSlop; int mSlop;
int mNativeLayer;
Rect mNativeLayerRect;
} }
static class AutoFillData { static class AutoFillData {
@@ -1015,7 +1017,6 @@ public final class WebViewCore {
static final int REMOVE_PACKAGE_NAME = 186; static final int REMOVE_PACKAGE_NAME = 186;
static final int GET_TOUCH_HIGHLIGHT_RECTS = 187; static final int GET_TOUCH_HIGHLIGHT_RECTS = 187;
static final int REMOVE_TOUCH_HIGHLIGHT_RECTS = 188;
// accessibility support // accessibility support
static final int MODIFY_SELECTION = 190; static final int MODIFY_SELECTION = 190;
@@ -1577,6 +1578,10 @@ public final class WebViewCore {
case GET_TOUCH_HIGHLIGHT_RECTS: case GET_TOUCH_HIGHLIGHT_RECTS:
TouchHighlightData d = (TouchHighlightData) msg.obj; TouchHighlightData d = (TouchHighlightData) msg.obj;
if (d.mNativeLayer != 0) {
nativeScrollLayer(d.mNativeLayer,
d.mNativeLayerRect);
}
ArrayList<Rect> rects = nativeGetTouchHighlightRects ArrayList<Rect> rects = nativeGetTouchHighlightRects
(d.mX, d.mY, d.mSlop); (d.mX, d.mY, d.mSlop);
mWebView.mPrivateHandler.obtainMessage( mWebView.mPrivateHandler.obtainMessage(
@@ -1584,12 +1589,6 @@ public final class WebViewCore {
.sendToTarget(); .sendToTarget();
break; break;
case REMOVE_TOUCH_HIGHLIGHT_RECTS:
mWebView.mPrivateHandler.obtainMessage(
WebView.SET_TOUCH_HIGHLIGHT_RECTS, null)
.sendToTarget();
break;
case USE_MOCK_DEVICE_ORIENTATION: case USE_MOCK_DEVICE_ORIENTATION:
useMockDeviceOrientation(); useMockDeviceOrientation();
break; break;
@@ -2225,9 +2224,9 @@ public final class WebViewCore {
} }
// remove the touch highlight when moving to a new page // remove the touch highlight when moving to a new page
if (getSettings().supportTouchOnly()) { if (WebView.USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
mEventHub.sendMessage(Message.obtain(null, mWebView.mPrivateHandler.sendEmptyMessage(
EventHub.REMOVE_TOUCH_HIGHLIGHT_RECTS)); WebView.SET_TOUCH_HIGHLIGHT_RECTS);
} }
// reset the scroll position, the restored offset and scales // reset the scroll position, the restored offset and scales