Bug 603008 - Android widget multitouch implementation. r=blassey,kats

This commit is contained in:
Wes Johnston 2012-01-25 01:31:33 +01:00
parent 3627f3a4b8
commit a02904d162
16 changed files with 509 additions and 104 deletions

View File

@ -148,6 +148,7 @@ MOZ_SPELLCHECK = @MOZ_SPELLCHECK@
MOZ_ANDROID_HISTORY = @MOZ_ANDROID_HISTORY@ MOZ_ANDROID_HISTORY = @MOZ_ANDROID_HISTORY@
MOZ_WEBSMS_BACKEND = @MOZ_WEBSMS_BACKEND@ MOZ_WEBSMS_BACKEND = @MOZ_WEBSMS_BACKEND@
MOZ_JAVA_COMPOSITOR = @MOZ_JAVA_COMPOSITOR@ MOZ_JAVA_COMPOSITOR = @MOZ_JAVA_COMPOSITOR@
MOZ_ONLY_TOUCH_EVENTS = @MOZ_ONLY_TOUCH_EVENTS@
MOZ_TOUCH = @MOZ_TOUCH@ MOZ_TOUCH = @MOZ_TOUCH@
MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@ MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
MOZ_FEEDS = @MOZ_FEEDS@ MOZ_FEEDS = @MOZ_FEEDS@

View File

@ -1790,4 +1790,7 @@ public class GeckoAppShell
public static void disableNetworkNotifications() { public static void disableNetworkNotifications() {
GeckoNetworkManager.getInstance().disableNotifications(); GeckoNetworkManager.getInstance().disableNotifications();
} }
// This is only used in Native Fennec.
public static void preventPanning() { }
} }

View File

@ -46,6 +46,7 @@ import android.widget.*;
import android.hardware.*; import android.hardware.*;
import android.location.*; import android.location.*;
import android.util.FloatMath; import android.util.FloatMath;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@ -101,7 +102,12 @@ public class GeckoEvent {
public int mType; public int mType;
public int mAction; public int mAction;
public long mTime; public long mTime;
public Point mP0, mP1, mP2; public Point[] mPoints;
public int[] mPointIndicies;
public int mPointerIndex;
public float[] mOrientations;
public float[] mPressures;
public Point[] mPointRadii;
public Rect mRect; public Rect mRect;
public double mX, mY, mZ; public double mX, mY, mZ;
public double mAlpha, mBeta, mGamma; public double mAlpha, mBeta, mGamma;
@ -144,10 +150,76 @@ public class GeckoEvent {
mAction = m.getAction(); mAction = m.getAction();
mTime = m.getEventTime(); mTime = m.getEventTime();
mMetaState = m.getMetaState(); mMetaState = m.getMetaState();
mP0 = new Point((int)m.getX(0), (int)m.getY(0));
switch (mAction & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: {
mCount = m.getPointerCount(); mCount = m.getPointerCount();
if (mCount > 1) mPoints = new Point[mCount];
mP1 = new Point((int)m.getX(1), (int)m.getY(1)); mPointIndicies = new int[mCount];
mOrientations = new float[mCount];
mPressures = new float[mCount];
mPointRadii = new Point[mCount];
mPointerIndex = (mAction & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
for (int i = 0; i < mCount; i++) {
addMotionPoint(i, i, m);
}
break;
}
default: {
mCount = 0;
mPointerIndex = -1;
mPoints = new Point[mCount];
mPointIndicies = new int[mCount];
mOrientations = new float[mCount];
mPressures = new float[mCount];
mPointRadii = new Point[mCount];
}
}
}
public void addMotionPoint(int index, int eventIndex, MotionEvent event) {
PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
mPoints[index] = new Point((int)Math.round(geckoPoint.x), (int)Math.round(geckoPoint.y));
mPointIndicies[index] = event.getPointerId(eventIndex);
// getToolMajor, getToolMinor and getOrientation are API Level 9 features
if (Build.VERSION.SDK_INT >= 9) {
double radians = event.getOrientation(eventIndex);
mOrientations[index] = (float) Math.toDegrees(radians);
// w3c touchevents spec does not allow orientations == 90
// this shifts it to -90, which will be shifted to zero below
if (mOrientations[index] == 90)
mOrientations[index] = -90;
// w3c touchevent radius are given by an orientation between 0 and 90
// the radius is found by removing the orientation and measuring the x and y
// radius of the resulting ellipse
// for android orientations >= 0 and < 90, the major axis should correspond to
// just reporting the y radius as the major one, and x as minor
// however, for a radius < 0, we have to shift the orientation by adding 90, and
// reverse which radius is major and minor
if (mOrientations[index] < 0) {
mOrientations[index] += 90;
mPointRadii[index] = new Point((int)event.getToolMajor(eventIndex)/2,
(int)event.getToolMinor(eventIndex)/2);
} else {
mPointRadii[index] = new Point((int)event.getToolMinor(eventIndex)/2,
(int)event.getToolMajor(eventIndex)/2);
}
} else {
float size = event.getSize(eventIndex);
DisplayMetrics displaymetrics = new DisplayMetrics();
GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
size = size*Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels);
mPointRadii[index] = new Point((int)size,(int)size);
mOrientations[index] = 0;
}
mPressures[index] = event.getPressure(eventIndex);
} }
public GeckoEvent(SensorEvent s) { public GeckoEvent(SensorEvent s) {
@ -227,9 +299,10 @@ public class GeckoEvent {
mType = etype; mType = etype;
mP0 = new Point(w, h); mPoints = new Point[3];
mP1 = new Point(screenw, screenh); mPoints[0] = new Point(w, h);
mP2 = new Point(0, 0); mPoints[1] = new Point(screenw, screenh);
mPoints[2] = new Point(0, 0);
} }
public GeckoEvent(String subject, String data) { public GeckoEvent(String subject, String data) {

View File

@ -503,6 +503,9 @@ public class GeckoAppShell
layerController.setOnTouchListener(new View.OnTouchListener() { layerController.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) { public boolean onTouch(View view, MotionEvent event) {
if (event == null)
return true;
GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
return true; return true;
} }
}); });
@ -1117,6 +1120,15 @@ public class GeckoAppShell
}); });
} }
public static void preventPanning() {
getMainHandler().post(new Runnable() {
public void run() {
LayerController layerController = GeckoApp.mAppContext.getLayerController();
layerController.preventPanning(true);
}
});
}
public static boolean isNetworkLinkUp() { public static boolean isNetworkLinkUp() {
ConnectivityManager cm = (ConnectivityManager) ConnectivityManager cm = (ConnectivityManager)
GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE); GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);

View File

@ -48,6 +48,11 @@ import android.widget.*;
import android.hardware.*; import android.hardware.*;
import android.location.*; import android.location.*;
import android.util.FloatMath; import android.util.FloatMath;
import android.util.DisplayMetrics;
import android.graphics.PointF;
import android.text.format.Time;
import android.os.SystemClock;
import java.lang.System;
import android.util.Log; import android.util.Log;
@ -104,7 +109,12 @@ public class GeckoEvent {
public int mType; public int mType;
public int mAction; public int mAction;
public long mTime; public long mTime;
public Point mP0, mP1, mP2; public Point[] mPoints;
public int[] mPointIndicies;
public int mPointerIndex; // index of the point that has changed
public float[] mOrientations;
public float[] mPressures;
public Point[] mPointRadii;
public Rect mRect; public Rect mRect;
public double mX, mY, mZ; public double mX, mY, mZ;
public double mAlpha, mBeta, mGamma; public double mAlpha, mBeta, mGamma;
@ -145,12 +155,79 @@ public class GeckoEvent {
public GeckoEvent(MotionEvent m) { public GeckoEvent(MotionEvent m) {
mType = MOTION_EVENT; mType = MOTION_EVENT;
mAction = m.getAction(); mAction = m.getAction();
mTime = m.getEventTime(); mTime = (System.currentTimeMillis() - SystemClock.elapsedRealtime()) + m.getEventTime();
mMetaState = m.getMetaState(); mMetaState = m.getMetaState();
mP0 = new Point((int)m.getX(0), (int)m.getY(0));
switch (mAction & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: {
mCount = m.getPointerCount(); mCount = m.getPointerCount();
if (mCount > 1) mPoints = new Point[mCount];
mP1 = new Point((int)m.getX(1), (int)m.getY(1)); mPointIndicies = new int[mCount];
mOrientations = new float[mCount];
mPressures = new float[mCount];
mPointRadii = new Point[mCount];
mPointerIndex = (mAction & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
for (int i = 0; i < mCount; i++) {
addMotionPoint(i, i, m);
}
break;
}
default: {
mCount = 0;
mPointerIndex = -1;
mPoints = new Point[mCount];
mPointIndicies = new int[mCount];
mOrientations = new float[mCount];
mPressures = new float[mCount];
mPointRadii = new Point[mCount];
}
}
}
public void addMotionPoint(int index, int eventIndex, MotionEvent event) {
PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
geckoPoint = GeckoApp.mAppContext.getLayerController().convertViewPointToLayerPoint(geckoPoint);
mPoints[index] = new Point((int)Math.round(geckoPoint.x), (int)Math.round(geckoPoint.y));
mPointIndicies[index] = event.getPointerId(eventIndex);
// getToolMajor, getToolMinor and getOrientation are API Level 9 features
if (Build.VERSION.SDK_INT >= 9) {
double radians = event.getOrientation(eventIndex);
mOrientations[index] = (float) Math.toDegrees(radians);
// w3c touchevents spec does not allow orientations == 90
// this shifts it to -90, which will be shifted to zero below
if (mOrientations[index] == 90)
mOrientations[index] = -90;
// w3c touchevent radius are given by an orientation between 0 and 90
// the radius is found by removing the orientation and measuring the x and y
// radius of the resulting ellipse
// for android orientations >= 0 and < 90, the major axis should correspond to
// just reporting the y radius as the major one, and x as minor
// however, for a radius < 0, we have to shift the orientation by adding 90, and
// reverse which radius is major and minor
if (mOrientations[index] < 0) {
mOrientations[index] += 90;
mPointRadii[index] = new Point((int)event.getToolMajor(eventIndex)/2,
(int)event.getToolMinor(eventIndex)/2);
} else {
mPointRadii[index] = new Point((int)event.getToolMinor(eventIndex)/2,
(int)event.getToolMajor(eventIndex)/2);
}
} else {
float size = event.getSize(eventIndex);
DisplayMetrics displaymetrics = new DisplayMetrics();
GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
size = size*Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels);
mPointRadii[index] = new Point((int)size,(int)size);
mOrientations[index] = 0;
}
mPressures[index] = event.getPressure(eventIndex);
} }
public GeckoEvent(SensorEvent s) { public GeckoEvent(SensorEvent s) {
@ -230,9 +307,10 @@ public class GeckoEvent {
mType = etype; mType = etype;
mP0 = new Point(w, h); mPoints = new Point[3];
mP1 = new Point(screenw, screenh); mPoints[0] = new Point(w, h);
mP2 = new Point(tilew, tileh); mPoints[1] = new Point(screenw, screenh);
mPoints[2] = new Point(tilew, tileh);
} }
public GeckoEvent(String subject, String data) { public GeckoEvent(String subject, String data) {

View File

@ -45,10 +45,12 @@ import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.ui.PanZoomController;
import org.mozilla.gecko.ui.SimpleScaleGestureDetector; import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoEvent;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
@ -59,6 +61,8 @@ import android.view.GestureDetector;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import java.lang.Math; import java.lang.Math;
import java.util.Timer;
import java.util.TimerTask;
/** /**
* The layer controller manages a tile that represents the visible page. It does panning and * The layer controller manages a tile that represents the visible page. It does panning and
@ -100,6 +104,14 @@ public class LayerController {
private static final int DANGER_ZONE_X = 75; private static final int DANGER_ZONE_X = 75;
private static final int DANGER_ZONE_Y = 150; private static final int DANGER_ZONE_Y = 150;
/* The time limit for pages to respond with preventDefault on touchevents
* before we begin panning the page */
private static final int PREVENT_DEFAULT_TIMEOUT = 200;
private boolean allowDefaultActions = true;
private Timer allowDefaultTimer = null;
private boolean inTouchSession = false;
public LayerController(Context context) { public LayerController(Context context) {
mContext = context; mContext = context;
@ -149,6 +161,7 @@ public class LayerController {
public Bitmap getBackgroundPattern() { return getDrawable("background"); } public Bitmap getBackgroundPattern() { return getDrawable("background"); }
public Bitmap getShadowPattern() { return getDrawable("shadow"); } public Bitmap getShadowPattern() { return getDrawable("shadow"); }
public PanZoomController getPanZoomController() { return mPanZoomController; }
public GestureDetector.OnGestureListener getGestureListener() { return mPanZoomController; } public GestureDetector.OnGestureListener getGestureListener() { return mPanZoomController; }
public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() { public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() {
return mPanZoomController; return mPanZoomController;
@ -347,11 +360,58 @@ public class LayerController {
* pan/zoom controller to do the dirty work. * pan/zoom controller to do the dirty work.
*/ */
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (mPanZoomController.onTouchEvent(event)) int action = event.getAction();
return true; if ((action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
post(new Runnable() {
public void run() {
mView.clearEventQueue();
preventPanning(true);
}
});
}
if (mOnTouchListener != null) if (mOnTouchListener != null)
return mOnTouchListener.onTouch(mView, event); mOnTouchListener.onTouch(mView, event);
return false;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
if (!inTouchSession && allowDefaultTimer == null) {
inTouchSession = true;
allowDefaultTimer = new Timer();
allowDefaultTimer.schedule(new TimerTask() {
public void run() {
post(new Runnable() {
public void run() {
preventPanning(false);
}
});
}
}, PREVENT_DEFAULT_TIMEOUT);
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
inTouchSession = false;
}
}
return !allowDefaultActions;
}
public void preventPanning(boolean aValue) {
if (allowDefaultTimer != null) {
allowDefaultTimer.cancel();
allowDefaultTimer.purge();
allowDefaultTimer = null;
}
allowDefaultActions = !aValue;
if (aValue) {
mView.clearEventQueue();
mPanZoomController.cancelTouch();
} else {
mView.processEventQueue();
}
} }
/** Retrieves the color that the checkerboard should be. */ /** Retrieves the color that the checkerboard should be. */

View File

@ -48,6 +48,8 @@ import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.util.Log;
import java.util.LinkedList;
/** /**
* A view rendered by the layer compositor. * A view rendered by the layer compositor.
@ -64,6 +66,10 @@ public class LayerView extends GLSurfaceView {
private SimpleScaleGestureDetector mScaleGestureDetector; private SimpleScaleGestureDetector mScaleGestureDetector;
private long mRenderTime; private long mRenderTime;
private boolean mRenderTimeReset; private boolean mRenderTimeReset;
private static String LOGTAG = "GeckoLayerView";
/* List of events to be processed if the page does not prevent them. Should only be touched on the main thread */
private LinkedList<MotionEvent> mEventQueue = new LinkedList<MotionEvent>();
public LayerView(Context context, LayerController controller) { public LayerView(Context context, LayerController controller) {
super(context); super(context);
@ -83,14 +89,40 @@ public class LayerView extends GLSurfaceView {
setFocusableInTouchMode(true); setFocusableInTouchMode(true);
} }
private void addToEventQueue(MotionEvent event) {
MotionEvent copy = MotionEvent.obtain(event);
mEventQueue.add(copy);
}
public void processEventQueue() {
MotionEvent event = mEventQueue.poll();
while(event != null) {
processEvent(event);
event = mEventQueue.poll();
}
}
public void clearEventQueue() {
mEventQueue.clear();
}
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (mController.onTouchEvent(event)) {
addToEventQueue(event);
return true;
}
return processEvent(event);
}
private boolean processEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) if (mGestureDetector.onTouchEvent(event))
return true; return true;
mScaleGestureDetector.onTouchEvent(event); mScaleGestureDetector.onTouchEvent(event);
if (mScaleGestureDetector.isInProgress()) if (mScaleGestureDetector.isInProgress())
return true; return true;
return mController.onTouchEvent(event); mController.getPanZoomController().onTouchEvent(event);
return true;
} }
public LayerController getController() { return mController; } public LayerController getController() { return mController; }

View File

@ -843,7 +843,7 @@ public class PanZoomController
return true; return true;
} }
private void cancelTouch() { public void cancelTouch() {
GeckoEvent e = new GeckoEvent("Gesture:CancelTouch", ""); GeckoEvent e = new GeckoEvent("Gesture:CancelTouch", "");
GeckoAppShell.sendEventToGecko(e); GeckoAppShell.sendEventToGecko(e);
} }

View File

@ -67,6 +67,9 @@ MOZ_APP_COMPONENT_INCLUDE=nsBrowserComponents.h
# use custom widget for html:select # use custom widget for html:select
MOZ_USE_NATIVE_POPUP_WINDOWS=1 MOZ_USE_NATIVE_POPUP_WINDOWS=1
# dispatch only touch events (no mouse events)
MOZ_ONLY_TOUCH_EVENTS=1
MOZ_APP_ID={aa3c5121-dab2-40e2-81ca-7ea25febc110} MOZ_APP_ID={aa3c5121-dab2-40e2-81ca-7ea25febc110}
MOZ_JAVA_COMPOSITOR=1 MOZ_JAVA_COMPOSITOR=1

View File

@ -139,6 +139,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I"); jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V"); jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V");
jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V"); jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
jPreventPanning = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "preventPanning", "()V");
jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V"); jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V");
jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V"); jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V");
jVibrate1 = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "(J)V"); jVibrate1 = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "(J)V");
@ -1612,3 +1613,9 @@ NS_IMETHODIMP nsAndroidBridge::SetDrawMetadataProvider(nsIAndroidDrawMetadataPro
return NS_OK; return NS_OK;
} }
void
AndroidBridge::PreventPanning() {
ALOG_BRIDGE("AndroidBridge::PreventPanning");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jPreventPanning);
}

View File

@ -218,6 +218,8 @@ public:
void ShowInputMethodPicker(); void ShowInputMethodPicker();
void PreventPanning();
void HideProgressDialogOnce(); void HideProgressDialogOnce();
bool IsNetworkLinkUp(); bool IsNetworkLinkUp();
@ -413,6 +415,7 @@ protected:
jmethodID jGetDpi; jmethodID jGetDpi;
jmethodID jSetFullScreen; jmethodID jSetFullScreen;
jmethodID jShowInputMethodPicker; jmethodID jShowInputMethodPicker;
jmethodID jPreventPanning;
jmethodID jHideProgressDialog; jmethodID jHideProgressDialog;
jmethodID jPerformHapticFeedback; jmethodID jPerformHapticFeedback;
jmethodID jVibrate1; jmethodID jVibrate1;

View File

@ -44,9 +44,11 @@ jclass AndroidGeckoEvent::jGeckoEventClass = 0;
jfieldID AndroidGeckoEvent::jActionField = 0; jfieldID AndroidGeckoEvent::jActionField = 0;
jfieldID AndroidGeckoEvent::jTypeField = 0; jfieldID AndroidGeckoEvent::jTypeField = 0;
jfieldID AndroidGeckoEvent::jTimeField = 0; jfieldID AndroidGeckoEvent::jTimeField = 0;
jfieldID AndroidGeckoEvent::jP0Field = 0; jfieldID AndroidGeckoEvent::jPoints = 0;
jfieldID AndroidGeckoEvent::jP1Field = 0; jfieldID AndroidGeckoEvent::jPointIndicies = 0;
jfieldID AndroidGeckoEvent::jP2Field = 0; jfieldID AndroidGeckoEvent::jPressures = 0;
jfieldID AndroidGeckoEvent::jPointRadii = 0;
jfieldID AndroidGeckoEvent::jOrientations = 0;
jfieldID AndroidGeckoEvent::jAlphaField = 0; jfieldID AndroidGeckoEvent::jAlphaField = 0;
jfieldID AndroidGeckoEvent::jBetaField = 0; jfieldID AndroidGeckoEvent::jBetaField = 0;
jfieldID AndroidGeckoEvent::jGammaField = 0; jfieldID AndroidGeckoEvent::jGammaField = 0;
@ -64,6 +66,7 @@ jfieldID AndroidGeckoEvent::jFlagsField = 0;
jfieldID AndroidGeckoEvent::jUnicodeCharField = 0; jfieldID AndroidGeckoEvent::jUnicodeCharField = 0;
jfieldID AndroidGeckoEvent::jOffsetField = 0; jfieldID AndroidGeckoEvent::jOffsetField = 0;
jfieldID AndroidGeckoEvent::jCountField = 0; jfieldID AndroidGeckoEvent::jCountField = 0;
jfieldID AndroidGeckoEvent::jPointerIndexField = 0;
jfieldID AndroidGeckoEvent::jRangeTypeField = 0; jfieldID AndroidGeckoEvent::jRangeTypeField = 0;
jfieldID AndroidGeckoEvent::jRangeStylesField = 0; jfieldID AndroidGeckoEvent::jRangeStylesField = 0;
jfieldID AndroidGeckoEvent::jRangeForeColorField = 0; jfieldID AndroidGeckoEvent::jRangeForeColorField = 0;
@ -157,9 +160,11 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
jActionField = getField("mAction", "I"); jActionField = getField("mAction", "I");
jTypeField = getField("mType", "I"); jTypeField = getField("mType", "I");
jTimeField = getField("mTime", "J"); jTimeField = getField("mTime", "J");
jP0Field = getField("mP0", "Landroid/graphics/Point;"); jPoints = getField("mPoints", "[Landroid/graphics/Point;");
jP1Field = getField("mP1", "Landroid/graphics/Point;"); jPointIndicies = getField("mPointIndicies", "[I");
jP2Field = getField("mP2", "Landroid/graphics/Point;"); jOrientations = getField("mOrientations", "[F");
jPressures = getField("mPressures", "[F");
jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;");
jAlphaField = getField("mAlpha", "D"); jAlphaField = getField("mAlpha", "D");
jBetaField = getField("mBeta", "D"); jBetaField = getField("mBeta", "D");
jGammaField = getField("mGamma", "D"); jGammaField = getField("mGamma", "D");
@ -176,6 +181,7 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
jUnicodeCharField = getField("mUnicodeChar", "I"); jUnicodeCharField = getField("mUnicodeChar", "I");
jOffsetField = getField("mOffset", "I"); jOffsetField = getField("mOffset", "I");
jCountField = getField("mCount", "I"); jCountField = getField("mCount", "I");
jPointerIndexField = getField("mPointerIndex", "I");
jRangeTypeField = getField("mRangeType", "I"); jRangeTypeField = getField("mRangeType", "I");
jRangeStylesField = getField("mRangeStyles", "I"); jRangeStylesField = getField("mRangeStyles", "I");
jRangeForeColorField = getField("mRangeForeColor", "I"); jRangeForeColorField = getField("mRangeForeColor", "I");
@ -338,27 +344,47 @@ AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv)
#undef getMethod #undef getMethod
void void
AndroidGeckoEvent::ReadP0Field(JNIEnv *jenv) AndroidGeckoEvent::ReadPointArray(nsTArray<nsIntPoint> &points,
JNIEnv *jenv,
jfieldID field,
PRUint32 count)
{ {
AndroidPoint p0(jenv, jenv->GetObjectField(wrappedObject(), jP0Field)); jobjectArray jObjArray = (jobjectArray)jenv->GetObjectField(wrapped_obj, field);
mP0.x = p0.X(); for (PRInt32 i = 0; i < count; i++) {
mP0.y = p0.Y(); jobject jObj = jenv->GetObjectArrayElement(jObjArray, i);
AndroidPoint jpoint(jenv, jObj);
nsIntPoint p(jpoint.X(), jpoint.Y());
points.AppendElement(p);
}
} }
void void
AndroidGeckoEvent::ReadP1Field(JNIEnv *jenv) AndroidGeckoEvent::ReadIntArray(nsTArray<int> &aVals,
JNIEnv *jenv,
jfieldID field,
PRUint32 count)
{ {
AndroidPoint p1(jenv, jenv->GetObjectField(wrappedObject(), jP1Field)); jintArray jIntArray = (jintArray)jenv->GetObjectField(wrapped_obj, field);
mP1.x = p1.X(); jint *vals = jenv->GetIntArrayElements(jIntArray, false);
mP1.y = p1.Y(); for (PRInt32 i = 0; i < count; i++) {
aVals.AppendElement(vals[i]);
}
jenv->ReleaseIntArrayElements(jIntArray, vals, JNI_ABORT);
} }
void void
AndroidGeckoEvent::ReadP2Field(JNIEnv *jenv) AndroidGeckoEvent::ReadFloatArray(nsTArray<float> &aVals,
JNIEnv *jenv,
jfieldID field,
PRUint32 count)
{ {
AndroidPoint p2(jenv, jenv->GetObjectField(wrappedObject(), jP2Field)); jfloatArray jFloatArray = (jfloatArray)jenv->GetObjectField(wrapped_obj, field);
mP2.x = p2.X(); jfloat *vals = jenv->GetFloatArrayElements(jFloatArray, false);
mP2.y = p2.Y(); for (PRInt32 i = 0; i < count; i++) {
aVals.AppendElement(vals[i]);
}
jenv->ReleaseFloatArrayElements(jFloatArray, vals, JNI_ABORT);
} }
void void
@ -425,9 +451,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
switch (mType) { switch (mType) {
case SIZE_CHANGED: case SIZE_CHANGED:
ReadP0Field(jenv); ReadPointArray(mPoints, jenv, jPoints, 3);
ReadP1Field(jenv);
ReadP2Field(jenv);
break; break;
case KEY_EVENT: case KEY_EVENT:
@ -443,9 +467,14 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
mTime = jenv->GetLongField(jobj, jTimeField); mTime = jenv->GetLongField(jobj, jTimeField);
mMetaState = jenv->GetIntField(jobj, jMetaStateField); mMetaState = jenv->GetIntField(jobj, jMetaStateField);
mCount = jenv->GetIntField(jobj, jCountField); mCount = jenv->GetIntField(jobj, jCountField);
ReadP0Field(jenv); mPointerIndex = jenv->GetIntField(jobj, jPointerIndexField);
if (mCount > 1)
ReadP1Field(jenv); ReadPointArray(mPointRadii, jenv, jPointRadii, mCount);
ReadFloatArray(mOrientations, jenv, jOrientations, mCount);
ReadFloatArray(mPressures, jenv, jPressures, mCount);
ReadPointArray(mPoints, jenv, jPoints, mCount);
ReadIntArray(mPointIndicies, jenv, jPointIndicies, mCount);
break; break;
case IME_EVENT: case IME_EVENT:
@ -544,10 +573,7 @@ AndroidGeckoEvent::Init(AndroidGeckoEvent *aResizeEvent)
mType = FORCED_RESIZE; mType = FORCED_RESIZE;
mTime = aResizeEvent->mTime; mTime = aResizeEvent->mTime;
mP0.x = aResizeEvent->mP0.x; mPoints = aResizeEvent->mPoints; // x,y coordinates
mP0.y = aResizeEvent->mP0.y;
mP1.x = aResizeEvent->mP1.x;
mP1.y = aResizeEvent->mP1.y;
} }
void void

View File

@ -434,9 +434,11 @@ public:
int Action() { return mAction; } int Action() { return mAction; }
int Type() { return mType; } int Type() { return mType; }
int64_t Time() { return mTime; } int64_t Time() { return mTime; }
const nsIntPoint& P0() { return mP0; } nsTArray<nsIntPoint> Points() { return mPoints; }
const nsIntPoint& P1() { return mP1; } nsTArray<int> PointIndicies() { return mPointIndicies; }
const nsIntPoint& P2() { return mP2; } nsTArray<float> Pressures() { return mPressures; }
nsTArray<float> Orientations() { return mOrientations; }
nsTArray<nsIntPoint> PointRadii() { return mPointRadii; }
double Alpha() { return mAlpha; } double Alpha() { return mAlpha; }
double Beta() { return mBeta; } double Beta() { return mBeta; }
double Gamma() { return mGamma; } double Gamma() { return mGamma; }
@ -452,6 +454,7 @@ public:
int UnicodeChar() { return mUnicodeChar; } int UnicodeChar() { return mUnicodeChar; }
int Offset() { return mOffset; } int Offset() { return mOffset; }
int Count() { return mCount; } int Count() { return mCount; }
int PointerIndex() { return mPointerIndex; }
int RangeType() { return mRangeType; } int RangeType() { return mRangeType; }
int RangeStyles() { return mRangeStyles; } int RangeStyles() { return mRangeStyles; }
int RangeForeColor() { return mRangeForeColor; } int RangeForeColor() { return mRangeForeColor; }
@ -465,9 +468,11 @@ protected:
int mAction; int mAction;
int mType; int mType;
int64_t mTime; int64_t mTime;
nsIntPoint mP0; nsTArray<nsIntPoint> mPoints;
nsIntPoint mP1; nsTArray<nsIntPoint> mPointRadii;
nsIntPoint mP2; nsTArray<int> mPointIndicies;
nsTArray<float> mOrientations;
nsTArray<float> mPressures;
nsIntRect mRect; nsIntRect mRect;
int mFlags, mMetaState; int mFlags, mMetaState;
int mKeyCode, mUnicodeChar; int mKeyCode, mUnicodeChar;
@ -476,15 +481,25 @@ protected:
int mRangeForeColor, mRangeBackColor; int mRangeForeColor, mRangeBackColor;
double mAlpha, mBeta, mGamma; double mAlpha, mBeta, mGamma;
double mX, mY, mZ; double mX, mY, mZ;
int mPointerIndex;
nsString mCharacters, mCharactersExtra; nsString mCharacters, mCharactersExtra;
nsRefPtr<nsGeoPosition> mGeoPosition; nsRefPtr<nsGeoPosition> mGeoPosition;
nsRefPtr<nsGeoPositionAddress> mGeoAddress; nsRefPtr<nsGeoPositionAddress> mGeoAddress;
double mBandwidth; double mBandwidth;
bool mCanBeMetered; bool mCanBeMetered;
void ReadP0Field(JNIEnv *jenv); void ReadIntArray(nsTArray<int> &aVals,
void ReadP1Field(JNIEnv *jenv); JNIEnv *jenv,
void ReadP2Field(JNIEnv *jenv); jfieldID field,
PRUint32 count);
void ReadFloatArray(nsTArray<float> &aVals,
JNIEnv *jenv,
jfieldID field,
PRUint32 count);
void ReadPointArray(nsTArray<nsIntPoint> &mPoints,
JNIEnv *jenv,
jfieldID field,
PRUint32 count);
void ReadRectField(JNIEnv *jenv); void ReadRectField(JNIEnv *jenv);
void ReadCharactersField(JNIEnv *jenv); void ReadCharactersField(JNIEnv *jenv);
void ReadCharactersExtraField(JNIEnv *jenv); void ReadCharactersExtraField(JNIEnv *jenv);
@ -493,9 +508,11 @@ protected:
static jfieldID jActionField; static jfieldID jActionField;
static jfieldID jTypeField; static jfieldID jTypeField;
static jfieldID jTimeField; static jfieldID jTimeField;
static jfieldID jP0Field; static jfieldID jPoints;
static jfieldID jP1Field; static jfieldID jPointIndicies;
static jfieldID jP2Field; static jfieldID jOrientations;
static jfieldID jPressures;
static jfieldID jPointRadii;
static jfieldID jAlphaField; static jfieldID jAlphaField;
static jfieldID jBetaField; static jfieldID jBetaField;
static jfieldID jGammaField; static jfieldID jGammaField;
@ -512,6 +529,7 @@ protected:
static jfieldID jFlagsField; static jfieldID jFlagsField;
static jfieldID jOffsetField; static jfieldID jOffsetField;
static jfieldID jCountField; static jfieldID jCountField;
static jfieldID jPointerIndexField;
static jfieldID jUnicodeCharField; static jfieldID jUnicodeCharField;
static jfieldID jRangeTypeField; static jfieldID jRangeTypeField;
static jfieldID jRangeStylesField; static jfieldID jRangeStylesField;

View File

@ -103,6 +103,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/system/android \ -I$(topsrcdir)/dom/system/android \
-I$(topsrcdir)/toolkit/components/places \ -I$(topsrcdir)/toolkit/components/places \
-I$(topsrcdir)/docshell/base \ -I$(topsrcdir)/docshell/base \
-I$(topsrcdir)/content/events/src \
-I$(srcdir) \ -I$(srcdir) \
$(NULL) $(NULL)

View File

@ -58,6 +58,7 @@ using mozilla::unused;
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsIDOMSimpleGestureEvent.h" #include "nsIDOMSimpleGestureEvent.h"
#include "nsDOMTouchEvent.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsWidgetsCID.h" #include "nsWidgetsCID.h"
@ -895,8 +896,11 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
win->mChildren[i]->mBounds.height = 0; win->mChildren[i]->mBounds.height = 0;
} }
case AndroidGeckoEvent::SIZE_CHANGED: { case AndroidGeckoEvent::SIZE_CHANGED: {
int nw = ae->P0().x; nsTArray<nsIntPoint> points = ae->Points();
int nh = ae->P0().y; NS_ASSERTION(points.Length() != 3, "Size changed does not have enough coordinates");
int nw = points[0].x;
int nh = points[0].y;
if (ae->Type() == AndroidGeckoEvent::FORCED_RESIZE || nw != gAndroidBounds.width || if (ae->Type() == AndroidGeckoEvent::FORCED_RESIZE || nw != gAndroidBounds.width ||
nh != gAndroidBounds.height) { nh != gAndroidBounds.height) {
@ -913,11 +917,11 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
} }
} }
gAndroidTileSize.width = ae->P2().x; gAndroidTileSize.width = points[2].x;
gAndroidTileSize.height = ae->P2().y; gAndroidTileSize.height = points[2].y;
int newScreenWidth = ae->P1().x; int newScreenWidth = points[1].x;
int newScreenHeight = ae->P1().y; int newScreenHeight = points[1].y;
if (newScreenWidth == gAndroidScreenBounds.width && if (newScreenWidth == gAndroidScreenBounds.width &&
newScreenHeight == gAndroidScreenBounds.height) newScreenHeight == gAndroidScreenBounds.height)
@ -951,29 +955,36 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
else else
obs->RemoveObserver(notifier, "ipc:content-created"); obs->RemoveObserver(notifier, "ipc:content-created");
} }
break;
} }
case AndroidGeckoEvent::MOTION_EVENT: { case AndroidGeckoEvent::MOTION_EVENT: {
win->UserActivity(); win->UserActivity();
if (!gTopLevelWindows.IsEmpty()) { if (!gTopLevelWindows.IsEmpty()) {
nsIntPoint pt(ae->P0()); nsIntPoint pt(0,0);
nsTArray<nsIntPoint> points = ae->Points();
if (points.Length() > 0) {
pt = points[0];
}
pt.x = clamped(pt.x, 0, gAndroidBounds.width - 1); pt.x = clamped(pt.x, 0, gAndroidBounds.width - 1);
pt.y = clamped(pt.y, 0, gAndroidBounds.height - 1); pt.y = clamped(pt.y, 0, gAndroidBounds.height - 1);
nsWindow *target = win->FindWindowForPoint(pt); nsWindow *target = win->FindWindowForPoint(pt);
#if 0 #if 0
ALOG("MOTION_EVENT %f,%f -> %p (visible: %d children: %d)", ae->P0().x, ae->P0().y, (void*)target, ALOG("MOTION_EVENT %f,%f -> %p (visible: %d children: %d)", pt.x, pt.y, (void*)target,
target ? target->mIsVisible : 0, target ? target->mIsVisible : 0,
target ? target->mChildren.Length() : 0); target ? target->mChildren.Length() : 0);
DumpWindows(); DumpWindows();
#endif #endif
if (target) { if (target) {
if (ae->Count() > 1) bool preventDefaultActions = target->OnMultitouchEvent(ae);
target->OnMultitouchEvent(ae); if (!preventDefaultActions && ae->Count() == 2) {
else target->OnGestureEvent(ae);
}
#ifndef MOZ_ONLY_TOUCH_EVENTS
if (!preventDefaultActions && ae->Count() < 2)
target->OnMotionEvent(ae); target->OnMotionEvent(ae);
#endif
} }
} }
break; break;
@ -1470,30 +1481,11 @@ nsWindow::OnMotionEvent(AndroidGeckoEvent *ae)
return; return;
} }
nsRefPtr<nsWindow> kungFuDeathGrip(this);
nsIntPoint pt(ae->P0());
nsIntPoint offset = WidgetToScreenOffset();
//ALOG("#### motion pt: %d %d offset: %d %d", pt.x, pt.y, offset.x, offset.y);
pt.x -= offset.x;
pt.y -= offset.y;
// XXX possibly bound the range of pt here. some code may get confused.
send_again: send_again:
nsMouseEvent event(true, nsMouseEvent event(true,
msg, this, msg, this,
nsMouseEvent::eReal, nsMouseEvent::eNormal); nsMouseEvent::eReal, nsMouseEvent::eNormal);
InitEvent(event, &pt);
event.time = ae->Time();
event.isShift = !!(ae->MetaState() & AndroidKeyEvent::META_SHIFT_ON);
event.isControl = false;
event.isMeta = false;
event.isAlt = !!(ae->MetaState() & AndroidKeyEvent::META_ALT_ON);
// XXX can we synthesize different buttons? // XXX can we synthesize different buttons?
event.button = nsMouseEvent::eLeftButton; event.button = nsMouseEvent::eLeftButton;
@ -1501,8 +1493,8 @@ send_again:
event.clickCount = 1; event.clickCount = 1;
// XXX add the double-click handling logic here // XXX add the double-click handling logic here
if (ae->Points().Length() > 0)
DispatchEvent(&event); DispatchMotionEvent(event, ae, ae->Points()[0]);
if (Destroyed()) if (Destroyed())
return; return;
@ -1520,16 +1512,87 @@ getDistance(const nsIntPoint &p1, const nsIntPoint &p2)
return sqrt(deltaX*deltaX + deltaY*deltaY); return sqrt(deltaX*deltaX + deltaY*deltaY);
} }
void nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae) bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae)
{
switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) {
case AndroidMotionEvent::ACTION_DOWN:
case AndroidMotionEvent::ACTION_POINTER_DOWN: {
nsTouchEvent event(PR_TRUE, NS_TOUCH_START, this);
return DispatchMultitouchEvent(event, ae);
}
case AndroidMotionEvent::ACTION_MOVE: {
nsTouchEvent event(PR_TRUE, NS_TOUCH_MOVE, this);
return DispatchMultitouchEvent(event, ae);
}
case AndroidMotionEvent::ACTION_UP:
case AndroidMotionEvent::ACTION_POINTER_UP: {
nsTouchEvent event(PR_TRUE, NS_TOUCH_END, this);
return DispatchMultitouchEvent(event, ae);
}
case AndroidMotionEvent::ACTION_OUTSIDE:
case AndroidMotionEvent::ACTION_CANCEL: {
nsTouchEvent event(PR_TRUE, NS_TOUCH_CANCEL, this);
return DispatchMultitouchEvent(event, ae);
}
}
return false;
}
bool
nsWindow::DispatchMultitouchEvent(nsTouchEvent &event, AndroidGeckoEvent *ae)
{
nsIntPoint offset = WidgetToScreenOffset();
event.isShift = false;
event.isControl = false;
event.isMeta = false;
event.isAlt = false;
event.time = ae->Time();
int action = ae->Action() & AndroidMotionEvent::ACTION_MASK;
if (action == AndroidMotionEvent::ACTION_UP ||
action == AndroidMotionEvent::ACTION_POINTER_UP) {
event.touches.SetCapacity(1);
int pointerIndex = ae->PointerIndex();
nsCOMPtr<nsIDOMTouch> t(new nsDOMTouch(ae->PointIndicies()[pointerIndex],
ae->Points()[pointerIndex] - offset,
ae->PointRadii()[pointerIndex],
ae->Orientations()[pointerIndex],
ae->Pressures()[pointerIndex]));
event.touches.AppendElement(t);
} else {
int count = ae->Count();
event.touches.SetCapacity(count);
for (int i = 0; i < count; i++) {
nsCOMPtr<nsIDOMTouch> t(new nsDOMTouch(ae->PointIndicies()[i],
ae->Points()[i] - offset,
ae->PointRadii()[i],
ae->Orientations()[i],
ae->Pressures()[i]));
event.touches.AppendElement(t);
}
}
nsEventStatus status;
DispatchEvent(&event, status);
if (status == nsEventStatus_eConsumeNoDefault) {
AndroidBridge::Bridge()->PreventPanning();
return true;
}
return false;
}
void
nsWindow::OnGestureEvent(AndroidGeckoEvent *ae)
{ {
PRUint32 msg = 0; PRUint32 msg = 0;
nsIntPoint midPoint; nsIntPoint midPoint;
midPoint.x = ((ae->P0().x + ae->P1().x) / 2); midPoint.x = ((ae->Points()[0].x + ae->Points()[1].x) / 2);
midPoint.y = ((ae->P0().y + ae->P1().y) / 2); midPoint.y = ((ae->Points()[0].y + ae->Points()[1].y) / 2);
nsIntPoint refPoint = midPoint - WidgetToScreenOffset(); nsIntPoint refPoint = midPoint - WidgetToScreenOffset();
double pinchDist = getDistance(ae->P0(), ae->P1()); double pinchDist = getDistance(ae->Points()[0], ae->Points()[1]);
double pinchDelta = 0; double pinchDelta = 0;
switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) { switch (ae->Action() & AndroidMotionEvent::ACTION_MASK) {
@ -1612,6 +1675,26 @@ nsWindow::DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
DispatchEvent(&event); DispatchEvent(&event);
} }
void
nsWindow::DispatchMotionEvent(nsInputEvent &event, AndroidGeckoEvent *ae,
const nsIntPoint &refPoint)
{
nsIntPoint offset = WidgetToScreenOffset();
event.isShift = PR_FALSE;
event.isControl = PR_FALSE;
event.isMeta = PR_FALSE;
event.isAlt = PR_FALSE;
event.time = ae->Time();
// XXX possibly bound the range of event.refPoint here.
// some code may get confused.
event.refPoint = refPoint - offset;
DispatchEvent(&event);
}
void void
nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key) nsWindow::InitKeyEvent(nsKeyEvent& event, AndroidGeckoEvent& key)
{ {

View File

@ -73,8 +73,9 @@ 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);
void OnGestureEvent(mozilla::AndroidGeckoEvent *ae);
void OnMotionEvent(mozilla::AndroidGeckoEvent *ae); void OnMotionEvent(mozilla::AndroidGeckoEvent *ae);
void OnMultitouchEvent(mozilla::AndroidGeckoEvent *ae);
void OnKeyEvent(mozilla::AndroidGeckoEvent *ae); void OnKeyEvent(mozilla::AndroidGeckoEvent *ae);
void OnIMEEvent(mozilla::AndroidGeckoEvent *ae); void OnIMEEvent(mozilla::AndroidGeckoEvent *ae);
@ -221,7 +222,11 @@ protected:
private: private:
void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key); void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key);
void DispatchGestureEvent(mozilla::AndroidGeckoEvent *ae); bool DispatchMultitouchEvent(nsTouchEvent &event,
mozilla::AndroidGeckoEvent *ae);
void DispatchMotionEvent(nsInputEvent &event,
mozilla::AndroidGeckoEvent *ae,
const nsIntPoint &refPoint);
void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta, void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
const nsIntPoint &refPoint, PRUint64 time); const nsIntPoint &refPoint, PRUint64 time);
void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae); void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae);