am 0904c0dc: b/3302354 Always pass multi-touch events into WebKit, then handle them in WebView if preventDefault is not set. WebViewCore.java: add a MotionEvent field into TouchEventData for multi-touch so the extra data such as pressure, size can be preserved. WebVie
* commit '0904c0dcfb11da9bb756b8d4f8a817b5efc9edc0': b/3302354 Always pass multi-touch events into WebKit, then handle them in WebView if preventDefault is not set. WebViewCore.java: add a MotionEvent field into TouchEventData for multi-touch so the extra data such as pressure, size can be preserved. WebView.java: 1. Extracted the common code for multi-touch and single touch to a new private function: handleTouchEventCommon() 2. Extracted the multi-touch code, including zooming and panning, to a new private function: handleMultiTouchInWebView() 3. In onTouchEvent(), single touch events keep the code path, but multi-touch events are always passed to Webkit first. 4. In Privatehandler.handleMessage(), if WebKit didn't consume the multi-touch event, the private handler calls the handleMultiTouchInWebView() to zoom and pan.
This commit is contained in:
@@ -56,6 +56,7 @@ import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.text.Selection;
|
||||
@@ -5329,17 +5330,10 @@ public class WebView extends AbsoluteLayout
|
||||
+ " numPointers=" + ev.getPointerCount());
|
||||
}
|
||||
|
||||
int action = ev.getAction();
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
long eventTime = ev.getEventTime();
|
||||
|
||||
// mDeferMultitouch is a hack for layout tests, where it is used to
|
||||
// force passing multi-touch events to webkit.
|
||||
// FIXME: always pass multi-touch events to webkit and remove everything
|
||||
// related to mDeferMultitouch.
|
||||
if (ev.getPointerCount() > 1 &&
|
||||
(mDeferMultitouch || mZoomManager.isZoomScaleFixed())) {
|
||||
// Always pass multi-touch event to WebKit first.
|
||||
// If WebKit doesn't consume it and set preventDefault to true,
|
||||
// WebView's private handler will handle it.
|
||||
if (ev.getPointerCount() > 1) {
|
||||
if (DebugFlags.WEB_VIEW) {
|
||||
Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit");
|
||||
}
|
||||
@@ -5347,59 +5341,15 @@ public class WebView extends AbsoluteLayout
|
||||
return true;
|
||||
}
|
||||
|
||||
final ScaleGestureDetector detector =
|
||||
mZoomManager.getMultiTouchGestureDetector();
|
||||
return handleTouchEventCommon(ev);
|
||||
}
|
||||
|
||||
if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
|
||||
if (!detector.isInProgress() &&
|
||||
ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
|
||||
// Insert a fake pointer down event in order to start
|
||||
// the zoom scale detector.
|
||||
MotionEvent temp = MotionEvent.obtain(ev);
|
||||
// Clear the original event and set it to
|
||||
// ACTION_POINTER_DOWN.
|
||||
try {
|
||||
temp.setAction(temp.getAction() &
|
||||
~MotionEvent.ACTION_MASK |
|
||||
MotionEvent.ACTION_POINTER_DOWN);
|
||||
detector.onTouchEvent(temp);
|
||||
} finally {
|
||||
temp.recycle();
|
||||
}
|
||||
}
|
||||
private boolean handleTouchEventCommon(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
long eventTime = ev.getEventTime();
|
||||
|
||||
detector.onTouchEvent(ev);
|
||||
|
||||
if (detector.isInProgress()) {
|
||||
mLastTouchTime = eventTime;
|
||||
cancelLongPress();
|
||||
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||
if (!mZoomManager.supportsPanDuringZoom()) {
|
||||
return true;
|
||||
}
|
||||
mTouchMode = TOUCH_DRAG_MODE;
|
||||
if (mVelocityTracker == null) {
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
}
|
||||
}
|
||||
|
||||
x = detector.getFocusX();
|
||||
y = detector.getFocusY();
|
||||
action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
cancelTouch();
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||
// set mLastTouchX/Y to the remaining point
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
// negative x or y indicate it is on the edge, skip it.
|
||||
if (x < 0 || y < 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Due to the touch screen edge effect, a touch closer to the edge
|
||||
// always snapped to the edge. As getViewWidth() can be different from
|
||||
@@ -5612,22 +5562,6 @@ public class WebView extends AbsoluteLayout
|
||||
break;
|
||||
}
|
||||
|
||||
// Only lock dragging to one axis if we don't have a scale in progress.
|
||||
// Scaling implies free-roaming movement. Note this is only ever a question
|
||||
// if mZoomManager.supportsPanDuringZoom() is true.
|
||||
if (detector != null && !detector.isInProgress()) {
|
||||
// if it starts nearly horizontal or vertical, enforce it
|
||||
int ax = Math.abs(deltaX);
|
||||
int ay = Math.abs(deltaY);
|
||||
if (ax > MAX_SLOPE_FOR_DIAG * ay) {
|
||||
mSnapScrollMode = SNAP_X;
|
||||
mSnapPositive = deltaX > 0;
|
||||
} else if (ay > MAX_SLOPE_FOR_DIAG * ax) {
|
||||
mSnapScrollMode = SNAP_Y;
|
||||
mSnapPositive = deltaY > 0;
|
||||
}
|
||||
}
|
||||
|
||||
mTouchMode = TOUCH_DRAG_MODE;
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
@@ -5884,13 +5818,82 @@ public class WebView extends AbsoluteLayout
|
||||
ted.mPoints[c] = new Point(x, y);
|
||||
}
|
||||
ted.mMetaState = ev.getMetaState();
|
||||
ted.mReprocess = mDeferTouchProcess;
|
||||
ted.mReprocess = true;
|
||||
ted.mMotionEvent = MotionEvent.obtain(ev);
|
||||
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
|
||||
cancelLongPress();
|
||||
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||
mPreventDefault = PREVENT_DEFAULT_IGNORE;
|
||||
}
|
||||
|
||||
private boolean handleMultiTouchInWebView(MotionEvent ev) {
|
||||
if (DebugFlags.WEB_VIEW) {
|
||||
Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
|
||||
+ " mTouchMode=" + mTouchMode
|
||||
+ " numPointers=" + ev.getPointerCount()
|
||||
+ " scrolloffset=(" + mScrollX + "," + mScrollY + ")");
|
||||
}
|
||||
|
||||
final ScaleGestureDetector detector =
|
||||
mZoomManager.getMultiTouchGestureDetector();
|
||||
int action = ev.getAction();
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
long eventTime = ev.getEventTime();
|
||||
|
||||
if (!detector.isInProgress() &&
|
||||
ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
|
||||
// Insert a fake pointer down event in order to start
|
||||
// the zoom scale detector.
|
||||
MotionEvent temp = MotionEvent.obtain(ev);
|
||||
// Clear the original event and set it to
|
||||
// ACTION_POINTER_DOWN.
|
||||
try {
|
||||
temp.setAction(temp.getAction() &
|
||||
~MotionEvent.ACTION_MASK |
|
||||
MotionEvent.ACTION_POINTER_DOWN);
|
||||
detector.onTouchEvent(temp);
|
||||
} finally {
|
||||
temp.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
detector.onTouchEvent(ev);
|
||||
|
||||
if (detector.isInProgress()) {
|
||||
if (DebugFlags.WEB_VIEW) {
|
||||
Log.v(LOGTAG, "detector is in progress");
|
||||
}
|
||||
mLastTouchTime = eventTime;
|
||||
cancelLongPress();
|
||||
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||
if (!mZoomManager.supportsPanDuringZoom()) {
|
||||
return false;
|
||||
}
|
||||
mTouchMode = TOUCH_DRAG_MODE;
|
||||
if (mVelocityTracker == null) {
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
}
|
||||
}
|
||||
|
||||
action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
cancelTouch();
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||
// set mLastTouchX/Y to the remaining point
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
// negative x or y indicate it is on the edge, skip it.
|
||||
if (x < 0 || y < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return handleTouchEventCommon(ev);
|
||||
}
|
||||
|
||||
private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
|
||||
if (shouldForwardTouchEvent()) {
|
||||
if (removeEvents) {
|
||||
@@ -7263,6 +7266,13 @@ public class WebView extends AbsoluteLayout
|
||||
// prevent default is not called in WebCore, so the
|
||||
// message needs to be reprocessed in UI
|
||||
TouchEventData ted = (TouchEventData) msg.obj;
|
||||
|
||||
if (ted.mPoints.length > 1) { // for multi-touch.
|
||||
handleMultiTouchInWebView(ted.mMotionEvent);
|
||||
break;
|
||||
}
|
||||
|
||||
// Following is for single touch.
|
||||
switch (ted.mAction) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.webkit.DeviceMotionService;
|
||||
@@ -830,6 +831,7 @@ final class WebViewCore {
|
||||
Point[] mPoints;
|
||||
int mMetaState;
|
||||
boolean mReprocess;
|
||||
MotionEvent mMotionEvent;
|
||||
}
|
||||
|
||||
static class GeolocationPermissionsData {
|
||||
|
||||
Reference in New Issue
Block a user