Bug 784887 - Use Native Gesture detector for MozGesture events. r=blassey

This commit is contained in:
Wes Johnston 2012-10-02 13:18:21 -07:00
parent cbfb8056df
commit e15c46b32f
6 changed files with 82 additions and 94 deletions

View File

@ -67,6 +67,7 @@ public class GeckoEvent {
private static final int COMPOSITOR_PAUSE = 28; private static final int COMPOSITOR_PAUSE = 28;
private static final int COMPOSITOR_RESUME = 29; private static final int COMPOSITOR_RESUME = 29;
private static final int PAINT_LISTEN_START_EVENT = 30; private static final int PAINT_LISTEN_START_EVENT = 30;
private static final int NATIVE_GESTURE_EVENT = 31;
/** /**
* These DOM_KEY_LOCATION constants mirror the DOM KeyboardEvent's constants. * These DOM_KEY_LOCATION constants mirror the DOM KeyboardEvent's constants.
@ -98,6 +99,10 @@ public class GeckoEvent {
public static final int IME_RANGE_FORECOLOR = 2; public static final int IME_RANGE_FORECOLOR = 2;
public static final int IME_RANGE_BACKCOLOR = 4; public static final int IME_RANGE_BACKCOLOR = 4;
public static final int ACTION_MAGNIFY_START = 11;
public static final int ACTION_MAGNIFY = 12;
public static final int ACTION_MAGNIFY_END = 13;
final public int mType; final public int mType;
public int mAction; public int mAction;
public long mTime; public long mTime;
@ -260,6 +265,21 @@ public class GeckoEvent {
} }
} }
public static GeckoEvent createNativeGestureEvent(int action, PointF pt, double size) {
GeckoEvent event = new GeckoEvent(NATIVE_GESTURE_EVENT);
event.mAction = action;
event.mCount = 1;
event.mPoints = new Point[1];
PointF geckoPoint = new PointF(pt.x, pt.y);
geckoPoint = GeckoApp.mAppContext.getLayerView().convertViewPointToLayerPoint(geckoPoint);
event.mPoints[0] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
event.mX = size;
event.mTime = System.currentTimeMillis();
return event;
}
public static GeckoEvent createMotionEvent(MotionEvent m) { public static GeckoEvent createMotionEvent(MotionEvent m) {
GeckoEvent event = new GeckoEvent(MOTION_EVENT); GeckoEvent event = new GeckoEvent(MOTION_EVENT);
event.initMotionEvent(m); event.initMotionEvent(m);

View File

@ -870,6 +870,8 @@ public class PanZoomController
mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY()); mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
cancelTouch(); cancelTouch();
GeckoAppShell.sendEventToGecko(GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY_START, mLastZoomFocus, getMetrics().zoomFactor));
return true; return true;
} }
@ -938,6 +940,9 @@ public class PanZoomController
mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY()); mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY, mLastZoomFocus, getMetrics().zoomFactor);
GeckoAppShell.sendEventToGecko(event);
return true; return true;
} }
@ -951,6 +956,10 @@ public class PanZoomController
// Force a viewport synchronisation // Force a viewport synchronisation
mTarget.setForceRedraw(); mTarget.setForceRedraw();
PointF point = new PointF(detector.getFocusX(), detector.getFocusY());
GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY_END, point, getMetrics().zoomFactor);
GeckoAppShell.sendEventToGecko(event);
} }
/** /**

View File

@ -511,6 +511,15 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
ReadCharactersField(jenv); ReadCharactersField(jenv);
break; break;
case NATIVE_GESTURE_EVENT:
mTime = jenv->GetLongField(jobj, jTimeField);
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
mCount = jenv->GetIntField(jobj, jCountField);
ReadPointArray(mPoints, jenv, jPoints, mCount);
mX = jenv->GetDoubleField(jobj, jXField);
break;
case MOTION_EVENT: case MOTION_EVENT:
mTime = jenv->GetLongField(jobj, jTimeField); mTime = jenv->GetLongField(jobj, jTimeField);
mMetaState = jenv->GetIntField(jobj, jMetaStateField); mMetaState = jenv->GetIntField(jobj, jMetaStateField);

View File

@ -555,6 +555,9 @@ public:
ACTION_HOVER_MOVE = 7, ACTION_HOVER_MOVE = 7,
ACTION_HOVER_ENTER = 9, ACTION_HOVER_ENTER = 9,
ACTION_HOVER_EXIT = 10, ACTION_HOVER_EXIT = 10,
ACTION_MAGNIFY_START = 11,
ACTION_MAGNIFY = 12,
ACTION_MAGNIFY_END = 13,
ACTION_POINTER_ID_MASK = 0xff00, ACTION_POINTER_ID_MASK = 0xff00,
ACTION_POINTER_ID_SHIFT = 8, ACTION_POINTER_ID_SHIFT = 8,
EDGE_TOP = 0x00000001, EDGE_TOP = 0x00000001,
@ -761,6 +764,7 @@ public:
COMPOSITOR_PAUSE = 28, COMPOSITOR_PAUSE = 28,
COMPOSITOR_RESUME = 29, COMPOSITOR_RESUME = 29,
PAINT_LISTEN_START_EVENT = 30, PAINT_LISTEN_START_EVENT = 30,
NATIVE_GESTURE_EVENT = 31,
dummy_java_enum_list_end dummy_java_enum_list_end
}; };

View File

@ -230,10 +230,6 @@ nsWindow::Create(nsIWidget *aParent,
mParent = parent; mParent = parent;
} }
float dpi = GetDPI();
mSwipeMaxPinchDelta = SWIPE_MAX_PINCH_DELTA_INCHES * dpi;
mSwipeMinDistance = SWIPE_MIN_DISTANCE_INCHES * dpi;
return NS_OK; return NS_OK;
} }
@ -845,10 +841,6 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
#endif #endif
if (target) { if (target) {
bool preventDefaultActions = target->OnMultitouchEvent(ae); bool preventDefaultActions = target->OnMultitouchEvent(ae);
if (!preventDefaultActions && ae->Count() == 2) {
target->OnGestureEvent(ae);
}
if (!preventDefaultActions && ae->Count() < 2) if (!preventDefaultActions && ae->Count() < 2)
target->OnMouseEvent(ae); target->OnMouseEvent(ae);
} }
@ -856,6 +848,20 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
break; break;
} }
case AndroidGeckoEvent::NATIVE_GESTURE_EVENT: {
nsIntPoint pt(0,0);
nsTArray<nsIntPoint> points = ae->Points();
if (points.Length() > 0) {
pt = points[0];
}
pt.x = clamped(pt.x, 0, NS_MAX(gAndroidBounds.width - 1, 0));
pt.y = clamped(pt.y, 0, NS_MAX(gAndroidBounds.height - 1, 0));
nsWindow *target = win->FindWindowForPoint(pt);
target->OnNativeGestureEvent(ae);
break;
}
case AndroidGeckoEvent::KEY_EVENT: case AndroidGeckoEvent::KEY_EVENT:
win->UserActivity(); win->UserActivity();
if (win->mFocus) if (win->mFocus)
@ -1338,14 +1344,6 @@ send_again:
} }
} }
static double
getDistance(const nsIntPoint &p1, const nsIntPoint &p2)
{
double deltaX = p2.x - p1.x;
double deltaY = p2.y - p1.y;
return sqrt(deltaX*deltaX + deltaY*deltaY);
}
bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae) bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
{ {
nsRefPtr<nsWindow> kungFuDeathGrip(this); nsRefPtr<nsWindow> kungFuDeathGrip(this);
@ -1450,80 +1448,34 @@ nsWindow::DispatchMultitouchEvent(nsTouchEvent &event, AndroidGeckoEvent *ae)
} }
void void
nsWindow::OnGestureEvent(AndroidGeckoEvent *ae) nsWindow::OnNativeGestureEvent(AndroidGeckoEvent *ae)
{ {
uint32_t msg = 0; nsIntPoint pt(ae->Points()[0].x,
ae->Points()[0].y);
double delta = ae->X();
int msg = 0;
nsIntPoint midPoint; switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) {
midPoint.x = ((ae->Points()[0].x + ae->Points()[1].x) / 2); case AndroidMotionEvent::ACTION_MAGNIFY_START:
midPoint.y = ((ae->Points()[0].y + ae->Points()[1].y) / 2); msg = NS_SIMPLE_GESTURE_MAGNIFY_START;
nsIntPoint refPoint = midPoint - WidgetToScreenOffset(); mStartDist = delta;
mLastDist = delta;
break;
case AndroidMotionEvent::ACTION_MAGNIFY:
msg = NS_SIMPLE_GESTURE_MAGNIFY_UPDATE;
delta -= mLastDist;
mLastDist += delta;
break;
case AndroidMotionEvent::ACTION_MAGNIFY_END:
msg = NS_SIMPLE_GESTURE_MAGNIFY;
delta -= mStartDist;
break;
default:
return;
}
double pinchDist = getDistance(ae->Points()[0], ae->Points()[1]); nsRefPtr<nsWindow> kungFuDeathGrip(this);
double pinchDelta = 0; DispatchGestureEvent(msg, 0, delta, pt, ae->Time());
switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) {
case AndroidMotionEvent::ACTION_POINTER_DOWN:
msg = NS_SIMPLE_GESTURE_MAGNIFY_START;
mStartPoint = new nsIntPoint(midPoint);
mStartDist = mLastDist = pinchDist;
mGestureFinished = false;
break;
case AndroidMotionEvent::ACTION_MOVE:
msg = NS_SIMPLE_GESTURE_MAGNIFY_UPDATE;
pinchDelta = pinchDist - mLastDist;
mLastDist = pinchDist;
break;
case AndroidMotionEvent::ACTION_POINTER_UP:
msg = NS_SIMPLE_GESTURE_MAGNIFY;
pinchDelta = pinchDist - mStartDist;
mStartPoint = nullptr;
break;
default:
return;
}
if (!mGestureFinished) {
nsRefPtr<nsWindow> kungFuDeathGrip(this);
DispatchGestureEvent(msg, 0, pinchDelta, refPoint, ae->Time());
if (Destroyed())
return;
// If the cumulative pinch delta goes past the threshold, treat this
// as a pinch only, and not a swipe.
if (fabs(pinchDist - mStartDist) > mSwipeMaxPinchDelta)
mStartPoint = nullptr;
// If we have traveled more than SWIPE_MIN_DISTANCE from the start
// point, stop the pinch gesture and fire a swipe event.
if (mStartPoint) {
double swipeDistance = getDistance(midPoint, *mStartPoint);
if (swipeDistance > mSwipeMinDistance) {
uint32_t direction = 0;
nsIntPoint motion = midPoint - *mStartPoint;
if (motion.x < -swipeDistance/2)
direction |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT;
if (motion.x > swipeDistance/2)
direction |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT;
if (motion.y < -swipeDistance/2)
direction |= nsIDOMSimpleGestureEvent::DIRECTION_UP;
if (motion.y > swipeDistance/2)
direction |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN;
// Finish the pinch gesture, then fire the swipe event:
msg = NS_SIMPLE_GESTURE_MAGNIFY;
DispatchGestureEvent(msg, 0, pinchDist - mStartDist, refPoint, ae->Time());
if (Destroyed())
return;
msg = NS_SIMPLE_GESTURE_SWIPE;
DispatchGestureEvent(msg, direction, 0, refPoint, ae->Time());
// Don't generate any more gesture events for this touch.
mGestureFinished = true;
}
}
}
} }
void void

View File

@ -50,7 +50,7 @@ public:
void OnAndroidEvent(mozilla::AndroidGeckoEvent *ae); void OnAndroidEvent(mozilla::AndroidGeckoEvent *ae);
void OnDraw(mozilla::AndroidGeckoEvent *ae); void OnDraw(mozilla::AndroidGeckoEvent *ae);
bool OnMultitouchEvent(mozilla::AndroidGeckoEvent *ae); bool OnMultitouchEvent(mozilla::AndroidGeckoEvent *ae);
void OnGestureEvent(mozilla::AndroidGeckoEvent *ae); void OnNativeGestureEvent(mozilla::AndroidGeckoEvent *ae);
void OnMouseEvent(mozilla::AndroidGeckoEvent *ae); void OnMouseEvent(mozilla::AndroidGeckoEvent *ae);
void OnKeyEvent(mozilla::AndroidGeckoEvent *ae); void OnKeyEvent(mozilla::AndroidGeckoEvent *ae);
void OnIMEEvent(mozilla::AndroidGeckoEvent *ae); void OnIMEEvent(mozilla::AndroidGeckoEvent *ae);
@ -177,14 +177,8 @@ protected:
nsWindow* mParent; nsWindow* mParent;
nsWindow* mFocus; nsWindow* mFocus;
bool mGestureFinished;
double mStartDist; double mStartDist;
double mLastDist; double mLastDist;
nsAutoPtr<nsIntPoint> mStartPoint;
// Multitouch swipe thresholds in screen pixels
double mSwipeMaxPinchDelta;
double mSwipeMinDistance;
nsCOMPtr<nsIIdleServiceInternal> mIdleService; nsCOMPtr<nsIIdleServiceInternal> mIdleService;