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_RESUME = 29;
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.
@ -98,6 +99,10 @@ public class GeckoEvent {
public static final int IME_RANGE_FORECOLOR = 2;
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;
public int mAction;
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) {
GeckoEvent event = new GeckoEvent(MOTION_EVENT);
event.initMotionEvent(m);

View File

@ -870,6 +870,8 @@ public class PanZoomController
mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
cancelTouch();
GeckoAppShell.sendEventToGecko(GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY_START, mLastZoomFocus, getMetrics().zoomFactor));
return true;
}
@ -938,6 +940,9 @@ public class PanZoomController
mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY, mLastZoomFocus, getMetrics().zoomFactor);
GeckoAppShell.sendEventToGecko(event);
return true;
}
@ -951,6 +956,10 @@ public class PanZoomController
// Force a viewport synchronisation
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);
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:
mTime = jenv->GetLongField(jobj, jTimeField);
mMetaState = jenv->GetIntField(jobj, jMetaStateField);

View File

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

View File

@ -230,10 +230,6 @@ nsWindow::Create(nsIWidget *aParent,
mParent = parent;
}
float dpi = GetDPI();
mSwipeMaxPinchDelta = SWIPE_MAX_PINCH_DELTA_INCHES * dpi;
mSwipeMinDistance = SWIPE_MIN_DISTANCE_INCHES * dpi;
return NS_OK;
}
@ -845,10 +841,6 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
#endif
if (target) {
bool preventDefaultActions = target->OnMultitouchEvent(ae);
if (!preventDefaultActions && ae->Count() == 2) {
target->OnGestureEvent(ae);
}
if (!preventDefaultActions && ae->Count() < 2)
target->OnMouseEvent(ae);
}
@ -856,6 +848,20 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
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:
win->UserActivity();
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)
{
nsRefPtr<nsWindow> kungFuDeathGrip(this);
@ -1450,80 +1448,34 @@ nsWindow::DispatchMultitouchEvent(nsTouchEvent &event, AndroidGeckoEvent *ae)
}
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;
midPoint.x = ((ae->Points()[0].x + ae->Points()[1].x) / 2);
midPoint.y = ((ae->Points()[0].y + ae->Points()[1].y) / 2);
nsIntPoint refPoint = midPoint - WidgetToScreenOffset();
switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) {
case AndroidMotionEvent::ACTION_MAGNIFY_START:
msg = NS_SIMPLE_GESTURE_MAGNIFY_START;
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]);
double pinchDelta = 0;
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;
}
}
}
nsRefPtr<nsWindow> kungFuDeathGrip(this);
DispatchGestureEvent(msg, 0, delta, pt, ae->Time());
}
void

View File

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