--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/NativePanZoomController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/NativePanZoomController.java
@@ -4,36 +4,41 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.mozglue.JNIObject;
import org.mozilla.gecko.util.ThreadUtils;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.Log;
+import android.util.Pair;
import android.view.MotionEvent;
import android.view.InputDevice;
import java.util.ArrayList;
public final class NativePanZoomController extends JNIObject {
private static final String LOGTAG = "GeckoNPZC";
+ private static final int EVENT_SOURCE_SCROLL = 0;
+ private static final int EVENT_SOURCE_MOTION = 1;
+ private static final int EVENT_SOURCE_MOUSE = 2;
private final LayerSession mSession;
private final Rect mTempRect = new Rect();
private boolean mAttached;
private float mPointerScrollFactor = 64.0f;
private long mLastDownTime;
private SynthesizedEventState mPointerState;
+ private ArrayList<Pair<Integer, MotionEvent>> mQueuedEvents;
+
@WrapForJNI(calledFrom = "ui")
private native boolean handleMotionEvent(
int action, int actionIndex, long time, int metaState,
int pointerId[], float x[], float y[], float orientation[], float pressure[],
float toolMajor[], float toolMinor[]);
@WrapForJNI(calledFrom = "ui")
private native boolean handleScrollEvent(
@@ -43,16 +48,17 @@ public final class NativePanZoomControll
@WrapForJNI(calledFrom = "ui")
private native boolean handleMouseEvent(
int action, long time, int metaState,
float x, float y, int buttons);
private boolean handleMotionEvent(MotionEvent event) {
if (!mAttached) {
+ mQueuedEvents.add(new Pair(EVENT_SOURCE_MOTION, event));
return false;
}
final int action = event.getActionMasked();
final int count = event.getPointerCount();
if (action == MotionEvent.ACTION_DOWN) {
mLastDownTime = event.getDownTime();
@@ -87,16 +93,17 @@ public final class NativePanZoomControll
return handleMotionEvent(action, event.getActionIndex(), event.getEventTime(),
event.getMetaState(), pointerId, x, y, orientation, pressure,
toolMajor, toolMinor);
}
private boolean handleScrollEvent(MotionEvent event) {
if (!mAttached) {
+ mQueuedEvents.add(new Pair(EVENT_SOURCE_SCROLL, event));
return false;
}
final int count = event.getPointerCount();
if (count <= 0) {
return false;
}
@@ -115,16 +122,17 @@ public final class NativePanZoomControll
mPointerScrollFactor;
return handleScrollEvent(event.getEventTime(), event.getMetaState(), x, y,
hScroll, vScroll);
}
private boolean handleMouseEvent(MotionEvent event) {
if (!mAttached) {
+ mQueuedEvents.add(new Pair(EVENT_SOURCE_MOUSE, event));
return false;
}
final int count = event.getPointerCount();
if (count <= 0) {
return false;
}
@@ -138,16 +146,17 @@ public final class NativePanZoomControll
final float y = coords.y - mTempRect.top;
return handleMouseEvent(event.getActionMasked(), event.getEventTime(),
event.getMetaState(), x, y, event.getButtonState());
}
/* package */ NativePanZoomController(final LayerSession session) {
mSession = session;
+ enableEventQueue();
}
/**
* Set the current scroll factor. The scroll factor is the maximum scroll amount that
* one scroll event may generate, in device pixels.
*
* @param factor Scroll factor.
*/
@@ -220,23 +229,54 @@ public final class NativePanZoomControll
(action == MotionEvent.ACTION_HOVER_ENTER) ||
(action == MotionEvent.ACTION_HOVER_EXIT)) {
return handleMouseEvent(event);
} else {
return false;
}
}
+ private void enableEventQueue() {
+ if (mQueuedEvents != null) {
+ throw new IllegalStateException("Already have an event queue");
+ }
+ mQueuedEvents = new ArrayList<>();
+ }
+
+ private void flushEventQueue() {
+ if (mQueuedEvents == null) {
+ return;
+ }
+
+ ArrayList<Pair<Integer, MotionEvent>> events = mQueuedEvents;
+ mQueuedEvents = null;
+ for (Pair<Integer, MotionEvent> pair : events) {
+ switch (pair.first) {
+ case EVENT_SOURCE_MOTION:
+ handleMotionEvent(pair.second);
+ break;
+ case EVENT_SOURCE_SCROLL:
+ handleScrollEvent(pair.second);
+ break;
+ case EVENT_SOURCE_MOUSE:
+ handleMouseEvent(pair.second);
+ break;
+ }
+ }
+ }
+
@WrapForJNI(calledFrom = "ui")
private void setAttached(final boolean attached) {
if (attached) {
mAttached = true;
+ flushEventQueue();
} else if (mAttached) {
mAttached = false;
disposeNative();
+ enableEventQueue();
}
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko") @Override // JNIObject
protected native void disposeNative();
@WrapForJNI(stubName = "SetIsLongpressEnabled") // Called from test thread.
private native void nativeSetIsLongpressEnabled(boolean isLongpressEnabled);
@@ -454,17 +494,17 @@ public final class NativePanZoomControll
eventType == MotionEvent.ACTION_HOVER_MOVE)
{
mPointerState.pointers.remove(pointerIndex);
}
}
@WrapForJNI(calledFrom = "ui")
private void synthesizeNativeTouchPoint(int pointerId, int eventType, int clientX,
- int clientY, double pressure, int orientation) {
+ int clientY, double pressure, int orientation) {
if (pointerId == PointerInfo.RESERVED_MOUSE_POINTER_ID) {
throw new IllegalArgumentException("Pointer ID reserved for mouse");
}
synthesizeNativePointer(InputDevice.SOURCE_TOUCHSCREEN, pointerId,
eventType, clientX, clientY, pressure, orientation);
}
@WrapForJNI(calledFrom = "ui")