mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1557411 - Add GeckoView API to expose how touch events are handled. r=geckoview-reviewers,botond,agi
Differential Revision: https://phabricator.services.mozilla.com/D46601 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
d8ca8b5902
commit
ec2812da2f
@ -1054,6 +1054,8 @@ package org.mozilla.geckoview {
|
||||
method @NonNull public DynamicToolbarAnimator getDynamicToolbarAnimator();
|
||||
method @NonNull public PanZoomController getPanZoomController();
|
||||
method @AnyThread @Nullable public GeckoSession getSession();
|
||||
method public int onGenericMotionEventForResult(@NonNull MotionEvent);
|
||||
method public int onTouchEventForResult(@NonNull MotionEvent);
|
||||
method @UiThread @Nullable public GeckoSession releaseSession();
|
||||
method @UiThread public void setSession(@NonNull GeckoSession);
|
||||
method public void setVerticalClipping(int);
|
||||
@ -1155,9 +1157,9 @@ package org.mozilla.geckoview {
|
||||
@UiThread public class PanZoomController {
|
||||
ctor protected PanZoomController(GeckoSession);
|
||||
method public float getScrollFactor();
|
||||
method public boolean onMotionEvent(@NonNull MotionEvent);
|
||||
method public boolean onMouseEvent(@NonNull MotionEvent);
|
||||
method public boolean onTouchEvent(@NonNull MotionEvent);
|
||||
method public int onMotionEvent(@NonNull MotionEvent);
|
||||
method public int onMouseEvent(@NonNull MotionEvent);
|
||||
method public int onTouchEvent(@NonNull MotionEvent);
|
||||
method @UiThread public void scrollBy(@NonNull ScreenLength, @NonNull ScreenLength);
|
||||
method @UiThread public void scrollBy(@NonNull ScreenLength, @NonNull ScreenLength, int);
|
||||
method @UiThread public void scrollTo(@NonNull ScreenLength, @NonNull ScreenLength);
|
||||
@ -1166,6 +1168,9 @@ package org.mozilla.geckoview {
|
||||
method @UiThread public void scrollToTop();
|
||||
method public void setIsLongpressEnabled(boolean);
|
||||
method public void setScrollFactor(float);
|
||||
field public static final int INPUT_RESULT_HANDLED = 1;
|
||||
field public static final int INPUT_RESULT_HANDLED_CONTENT = 2;
|
||||
field public static final int INPUT_RESULT_UNHANDLED = 0;
|
||||
field public static final int SCROLL_BEHAVIOR_AUTO = 1;
|
||||
field public static final int SCROLL_BEHAVIOR_SMOOTH = 0;
|
||||
}
|
||||
|
@ -654,28 +654,58 @@ public class GeckoView extends FrameLayout {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
return onTouchEventForResult(event) != PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a {@link MotionEvent} to the {@link PanZoomController}. This is the same as
|
||||
* {@link #onTouchEvent(MotionEvent)}, but instead returns a {@link PanZoomController.InputResult}
|
||||
* indicating how the event was handled.
|
||||
*
|
||||
* @param event A {@link MotionEvent}
|
||||
* @return One of the {@link PanZoomController#INPUT_RESULT_UNHANDLED INPUT_RESULT_*}) indicating how the event was handled.
|
||||
*/
|
||||
public @PanZoomController.InputResult int onTouchEventForResult(final @NonNull MotionEvent event) {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
if (mSession == null) {
|
||||
return PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
// NOTE: Treat mouse events as "touch" rather than as "mouse", so mouse can be
|
||||
// used to pan/zoom. Call onMouseEvent() instead for behavior similar to desktop.
|
||||
return mSession != null &&
|
||||
mSession.getPanZoomController().onTouchEvent(event);
|
||||
return mSession.getPanZoomController().onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(final MotionEvent event) {
|
||||
return onGenericMotionEventForResult(event) != PanZoomController.INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a {@link MotionEvent} to the {@link PanZoomController}. This is the same as
|
||||
* {@link #onGenericMotionEvent(MotionEvent)} (MotionEvent)}, but instead returns
|
||||
* a {@link PanZoomController.InputResult} indicating how the event was handled.
|
||||
*
|
||||
* @param event A {@link MotionEvent}
|
||||
* @return One of the {@link PanZoomController#INPUT_RESULT_UNHANDLED INPUT_RESULT_*}) indicating how the event was handled.
|
||||
*/
|
||||
public @PanZoomController.InputResult int onGenericMotionEventForResult(final @NonNull MotionEvent event) {
|
||||
if (AndroidGamepadManager.handleMotionEvent(event)) {
|
||||
return true;
|
||||
return PanZoomController.INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (mSession == null) {
|
||||
return false;
|
||||
return PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
return mSession.getAccessibility().onMotionEvent(event) ||
|
||||
mSession.getPanZoomController().onMotionEvent(event);
|
||||
if (mSession.getAccessibility().onMotionEvent(event)) {
|
||||
return PanZoomController.INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return mSession.getPanZoomController().onMotionEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,6 +58,30 @@ public class PanZoomController {
|
||||
*/
|
||||
public static final int SCROLL_BEHAVIOR_AUTO = 1;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({INPUT_RESULT_UNHANDLED, INPUT_RESULT_HANDLED, INPUT_RESULT_HANDLED_CONTENT})
|
||||
/* package */ @interface InputResult {}
|
||||
|
||||
/**
|
||||
* Specifies that an input event was not handled by the PanZoomController.
|
||||
*/
|
||||
@WrapForJNI
|
||||
public static final int INPUT_RESULT_UNHANDLED = 0;
|
||||
|
||||
/**
|
||||
* Specifies that an input event was handled by the PanZoomController, but likely
|
||||
* not by any touch event listeners in Web content.
|
||||
*/
|
||||
@WrapForJNI
|
||||
public static final int INPUT_RESULT_HANDLED = 1;
|
||||
|
||||
/**
|
||||
* Specifies that an input event was handled by the PanZoomController and passed on
|
||||
* to touch event listeners in Web content.
|
||||
*/
|
||||
@WrapForJNI
|
||||
public static final int INPUT_RESULT_HANDLED_CONTENT = 2;
|
||||
|
||||
private SynthesizedEventState mPointerState;
|
||||
|
||||
private ArrayList<Pair<Integer, MotionEvent>> mQueuedEvents;
|
||||
@ -72,19 +96,19 @@ public class PanZoomController {
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "ui")
|
||||
public native boolean handleMotionEvent(
|
||||
private native @InputResult int handleMotionEvent(
|
||||
int action, int actionIndex, long time, int metaState, float screenX, float screenY,
|
||||
int pointerId[], float x[], float y[], float orientation[], float pressure[],
|
||||
float toolMajor[], float toolMinor[]);
|
||||
|
||||
@WrapForJNI(calledFrom = "ui")
|
||||
private native boolean handleScrollEvent(
|
||||
private native @InputResult int handleScrollEvent(
|
||||
long time, int metaState,
|
||||
float x, float y,
|
||||
float hScroll, float vScroll);
|
||||
|
||||
@WrapForJNI(calledFrom = "ui")
|
||||
private native boolean handleMouseEvent(
|
||||
private native @InputResult int handleMouseEvent(
|
||||
int action, long time, int metaState,
|
||||
float x, float y, int buttons);
|
||||
|
||||
@ -124,10 +148,10 @@ public class PanZoomController {
|
||||
|
||||
/* package */ final NativeProvider mNative = new NativeProvider();
|
||||
|
||||
private boolean handleMotionEvent(final MotionEvent event) {
|
||||
private @InputResult int handleMotionEvent(final MotionEvent event) {
|
||||
if (!mAttached) {
|
||||
mQueuedEvents.add(new Pair<>(EVENT_SOURCE_MOTION, event));
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final int action = event.getActionMasked();
|
||||
@ -136,7 +160,7 @@ public class PanZoomController {
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mLastDownTime = event.getDownTime();
|
||||
} else if (mLastDownTime != event.getDownTime()) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final int[] pointerId = new int[count];
|
||||
@ -179,16 +203,16 @@ public class PanZoomController {
|
||||
orientation, pressure, toolMajor, toolMinor);
|
||||
}
|
||||
|
||||
private boolean handleScrollEvent(final MotionEvent event) {
|
||||
private @InputResult int handleScrollEvent(final MotionEvent event) {
|
||||
if (!mAttached) {
|
||||
mQueuedEvents.add(new Pair<>(EVENT_SOURCE_SCROLL, event));
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final int count = event.getPointerCount();
|
||||
|
||||
if (count <= 0) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
|
||||
@ -208,16 +232,16 @@ public class PanZoomController {
|
||||
hScroll, vScroll);
|
||||
}
|
||||
|
||||
private boolean handleMouseEvent(final MotionEvent event) {
|
||||
private @InputResult int handleMouseEvent(final MotionEvent event) {
|
||||
if (!mAttached) {
|
||||
mQueuedEvents.add(new Pair<>(EVENT_SOURCE_MOUSE, event));
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final int count = event.getPointerCount();
|
||||
|
||||
if (count <= 0) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
|
||||
@ -288,9 +312,9 @@ public class PanZoomController {
|
||||
* display surface.
|
||||
*
|
||||
* @param event MotionEvent to process.
|
||||
* @return True if the event was handled.
|
||||
* @return One of the {@link PanZoomController#INPUT_RESULT_UNHANDLED INPUT_RESULT_*}) constants indicating how the event was handled.
|
||||
*/
|
||||
public boolean onTouchEvent(final @NonNull MotionEvent event) {
|
||||
public @InputResult int onTouchEvent(final @NonNull MotionEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (!sTreatMouseAsTouch && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
|
||||
@ -305,9 +329,9 @@ public class PanZoomController {
|
||||
* display surface.
|
||||
*
|
||||
* @param event MotionEvent to process.
|
||||
* @return True if the event was handled.
|
||||
* @return One of the {@link PanZoomController#INPUT_RESULT_UNHANDLED INPUT_RESULT_*}) constants indicating how the event was handled.
|
||||
*/
|
||||
public boolean onMouseEvent(final @NonNull MotionEvent event) {
|
||||
public @InputResult int onMouseEvent(final @NonNull MotionEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
|
||||
@ -327,9 +351,9 @@ public class PanZoomController {
|
||||
* display surface.
|
||||
*
|
||||
* @param event MotionEvent to process.
|
||||
* @return True if the event was handled.
|
||||
* @return One of the {@link PanZoomController#INPUT_RESULT_UNHANDLED INPUT_RESULT_*}) indicating how the event was handled.
|
||||
*/
|
||||
public boolean onMotionEvent(final @NonNull MotionEvent event) {
|
||||
public @InputResult int onMotionEvent(final @NonNull MotionEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
final int action = event.getActionMasked();
|
||||
@ -339,7 +363,7 @@ public class PanZoomController {
|
||||
} else if ((InputDevice.getDevice(event.getDeviceId()) != null) &&
|
||||
(InputDevice.getDevice(event.getDeviceId()).getSources() &
|
||||
InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
return handleScrollEvent(event);
|
||||
} else if ((action == MotionEvent.ACTION_HOVER_MOVE) ||
|
||||
@ -347,7 +371,7 @@ public class PanZoomController {
|
||||
(action == MotionEvent.ACTION_HOVER_EXIT)) {
|
||||
return handleMouseEvent(event);
|
||||
} else {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,9 @@ exclude: true
|
||||
([bug 1578947]({{bugzilla}}1578947))
|
||||
- Added `setEnhancedTrackingProtectionLevel` to [`ContentBlocking.Settings`][71.14].
|
||||
([bug 1580854]({{bugzilla}}1580854))
|
||||
- ⚠️ Added [`GeckoView.onTouchEventForResult`][71.15] and modified
|
||||
[`PanZoomController.onTouchEvent`][71.16] to return how the touch event was handled. This
|
||||
allows apps to know if an event is handled by touch event listeners in web content. The methods in `PanZoomController` now return `int` instead of `boolean`.
|
||||
|
||||
[71.1]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onBooleanScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
[71.2]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onLongScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
@ -52,6 +55,8 @@ exclude: true
|
||||
[71.11]: https://developer.mozilla.org/en-US/docs/Web/API/Clients/openWindow
|
||||
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled-boolean-
|
||||
[71.13]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onFirstContentfulPaint-org.mozilla.geckoview.GeckoSession-
|
||||
[71.15]: {{javadoc_uri}}/GeckoView.html#onTouchEventForResult-android.view.MotionEvent-
|
||||
[71.16]: {{javadoc_uri}}/PanZoomController.html#onTouchEvent-android.view.MotionEvent-
|
||||
|
||||
## v70
|
||||
- Added API for session context assignment
|
||||
@ -374,4 +379,4 @@ exclude: true
|
||||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: bc4c4b661a4dd390c2a10c1057a2ce2aa09e3483
|
||||
[api-version]: 68710f52723909eea09a02b94b618a527cc9dfc8
|
||||
|
@ -125,6 +125,13 @@ static bool sFailedToCreateGLContext = false;
|
||||
static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4;
|
||||
static const double SWIPE_MIN_DISTANCE_INCHES = 0.6;
|
||||
|
||||
static const int32_t INPUT_RESULT_UNHANDLED =
|
||||
java::PanZoomController::INPUT_RESULT_UNHANDLED;
|
||||
static const int32_t INPUT_RESULT_HANDLED =
|
||||
java::PanZoomController::INPUT_RESULT_HANDLED;
|
||||
static const int32_t INPUT_RESULT_HANDLED_CONTENT =
|
||||
java::PanZoomController::INPUT_RESULT_HANDLED_CONTENT;
|
||||
|
||||
template <typename Lambda, bool IsStatic, typename InstanceType, class Impl>
|
||||
class nsWindow::WindowEvent : public Runnable {
|
||||
bool IsStaleCall() {
|
||||
@ -485,8 +492,8 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
}
|
||||
|
||||
bool HandleScrollEvent(int64_t aTime, int32_t aMetaState, float aX, float aY,
|
||||
float aHScroll, float aVScroll) {
|
||||
int32_t HandleScrollEvent(int64_t aTime, int32_t aMetaState, float aX,
|
||||
float aY, float aHScroll, float aVScroll) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
|
||||
RefPtr<IAPZCTreeManager> controller;
|
||||
@ -496,7 +503,7 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
|
||||
if (!controller) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
ScreenPoint origin = ScreenPoint(aX, aY);
|
||||
@ -520,7 +527,7 @@ class nsWindow::NPZCSupport final
|
||||
APZEventResult result = controller->InputBridge()->ReceiveInputEvent(input);
|
||||
|
||||
if (result.mStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return true;
|
||||
return INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
PostInputEvent([input, result](nsWindow* window) {
|
||||
@ -528,7 +535,8 @@ class nsWindow::NPZCSupport final
|
||||
window->ProcessUntransformedAPZEvent(&wheelEvent, result);
|
||||
});
|
||||
|
||||
return true;
|
||||
return result.mHitRegionWithApzAwareListeners ? INPUT_RESULT_HANDLED_CONTENT
|
||||
: INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -575,8 +583,8 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
|
||||
public:
|
||||
bool HandleMouseEvent(int32_t aAction, int64_t aTime, int32_t aMetaState,
|
||||
float aX, float aY, int buttons) {
|
||||
int32_t HandleMouseEvent(int32_t aAction, int64_t aTime, int32_t aMetaState,
|
||||
float aX, float aY, int buttons) {
|
||||
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
|
||||
|
||||
RefPtr<IAPZCTreeManager> controller;
|
||||
@ -586,7 +594,7 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
|
||||
if (!controller) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
MouseInput::MouseType mouseType = MouseInput::MOUSE_NONE;
|
||||
@ -619,7 +627,7 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
|
||||
if (mouseType == MouseInput::MOUSE_NONE) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
ScreenPoint origin = ScreenPoint(aX, aY);
|
||||
@ -632,7 +640,7 @@ class nsWindow::NPZCSupport final
|
||||
APZEventResult result = controller->InputBridge()->ReceiveInputEvent(input);
|
||||
|
||||
if (result.mStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return true;
|
||||
return INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
PostInputEvent([input, result](nsWindow* window) {
|
||||
@ -640,10 +648,11 @@ class nsWindow::NPZCSupport final
|
||||
window->ProcessUntransformedAPZEvent(&mouseEvent, result);
|
||||
});
|
||||
|
||||
return true;
|
||||
return result.mHitRegionWithApzAwareListeners ? INPUT_RESULT_HANDLED_CONTENT
|
||||
: INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
bool HandleMotionEvent(
|
||||
int32_t HandleMotionEvent(
|
||||
const PanZoomController::NativeProvider::LocalRef& aInstance,
|
||||
int32_t aAction, int32_t aActionIndex, int64_t aTime, int32_t aMetaState,
|
||||
float aScreenX, float aScreenY, jni::IntArray::Param aPointerId,
|
||||
@ -659,7 +668,7 @@ class nsWindow::NPZCSupport final
|
||||
}
|
||||
|
||||
if (!controller) {
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
nsTArray<int32_t> pointerId(aPointerId->GetElements());
|
||||
@ -688,7 +697,7 @@ class nsWindow::NPZCSupport final
|
||||
type = MultiTouchInput::MULTITOUCH_CANCEL;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
|
||||
MultiTouchInput input(type, aTime, GetEventTimeStamp(aTime), 0);
|
||||
@ -747,7 +756,7 @@ class nsWindow::NPZCSupport final
|
||||
APZEventResult result = controller->InputBridge()->ReceiveInputEvent(input);
|
||||
|
||||
if (result.mStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
return true;
|
||||
return INPUT_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
// Dispatch APZ input event on Gecko thread.
|
||||
@ -756,7 +765,9 @@ class nsWindow::NPZCSupport final
|
||||
window->ProcessUntransformedAPZEvent(&touchEvent, result);
|
||||
window->DispatchHitTest(touchEvent);
|
||||
});
|
||||
return true;
|
||||
|
||||
return result.mHitRegionWithApzAwareListeners ? INPUT_RESULT_HANDLED_CONTENT
|
||||
: INPUT_RESULT_HANDLED;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user