summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/public/APZInputBridge.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/apz/public/APZInputBridge.h')
-rw-r--r--gfx/layers/apz/public/APZInputBridge.h297
1 files changed, 297 insertions, 0 deletions
diff --git a/gfx/layers/apz/public/APZInputBridge.h b/gfx/layers/apz/public/APZInputBridge.h
new file mode 100644
index 0000000000..07ed39548d
--- /dev/null
+++ b/gfx/layers/apz/public/APZInputBridge.h
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_APZInputBridge_h
+#define mozilla_layers_APZInputBridge_h
+
+#include "Units.h" // for LayoutDeviceIntPoint
+#include "mozilla/EventForwards.h" // for WidgetInputEvent, nsEventStatus
+#include "mozilla/layers/APZPublicUtils.h" // for APZWheelAction
+#include "mozilla/layers/LayersTypes.h" // for ScrollDirections
+#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
+
+namespace mozilla {
+
+class InputData;
+
+namespace layers {
+
+class APZInputBridgeParent;
+class AsyncPanZoomController;
+class InputBlockState;
+class TouchBlockState;
+struct ScrollableLayerGuid;
+struct TargetConfirmationFlags;
+struct PointerEventsConsumableFlags;
+
+enum class APZHandledPlace : uint8_t {
+ Unhandled = 0, // we know for sure that the event will not be handled
+ // by either the root APZC or others
+ HandledByRoot = 1, // we know for sure that the event will be handled
+ // by the root content APZC
+ HandledByContent = 2, // we know for sure it will be handled by a non-root
+ // APZC or by an event listener using preventDefault()
+ // in a document
+ Invalid = 3,
+ Last = Invalid
+};
+
+struct APZHandledResult {
+ APZHandledPlace mPlace = APZHandledPlace::Invalid;
+ SideBits mScrollableDirections = SideBits::eNone;
+ ScrollDirections mOverscrollDirections = ScrollDirections();
+
+ APZHandledResult() = default;
+ // A constructor for cases where we have the target of the input block this
+ // event is part of, the target might be adjusted to be the root in the
+ // ScrollingDownWillMoveDynamicToolbar case.
+ //
+ // NOTE: There's a case where |aTarget| is the APZC for the root content but
+ // |aPlace| has to be `HandledByContent`, for example, the root content has
+ // an event handler using preventDefault() in the callback, so call sites of
+ // this function should be responsible to set a proper |aPlace|.
+ APZHandledResult(APZHandledPlace aPlace,
+ const AsyncPanZoomController* aTarget);
+ APZHandledResult(APZHandledPlace aPlace, SideBits aScrollableDirections,
+ ScrollDirections aOverscrollDirections)
+ : mPlace(aPlace),
+ mScrollableDirections(aScrollableDirections),
+ mOverscrollDirections(aOverscrollDirections) {}
+
+ bool IsHandledByContent() const {
+ return mPlace == APZHandledPlace::HandledByContent;
+ }
+ bool IsHandledByRoot() const {
+ return mPlace == APZHandledPlace::HandledByRoot;
+ }
+ bool operator==(const APZHandledResult& aOther) const {
+ return mPlace == aOther.mPlace &&
+ mScrollableDirections == aOther.mScrollableDirections &&
+ mOverscrollDirections == aOther.mOverscrollDirections;
+ }
+};
+
+/**
+ * Represents the outcome of APZ receiving and processing an input event.
+ * This is returned from APZInputBridge::ReceiveInputEvent() and related APIs.
+ */
+struct APZEventResult {
+ /**
+ * Creates a default result with a status of eIgnore, no block ID, and empty
+ * target guid.
+ */
+ APZEventResult();
+
+ /**
+ * Creates a result with a status of eIgnore, no block ID, the guid of the
+ * given initial target, and an APZHandledResult if we are sure the event
+ * is not going to be dispatched to contents.
+ */
+ APZEventResult(const RefPtr<AsyncPanZoomController>& aInitialTarget,
+ TargetConfirmationFlags aFlags);
+
+ void SetStatusAsConsumeNoDefault() {
+ mStatus = nsEventStatus_eConsumeNoDefault;
+ }
+
+ void SetStatusAsIgnore() { mStatus = nsEventStatus_eIgnore; }
+
+ // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult
+ // depending on |aTarget|.
+ void SetStatusAsConsumeDoDefault(
+ const RefPtr<AsyncPanZoomController>& aTarget);
+
+ // Set mStatus to nsEventStatus_eConsumeDoDefault, unlike above
+ // SetStatusAsConsumeDoDefault(const RefPtr<AsyncPanZoomController>&) this
+ // function doesn't mutate mHandledResult.
+ void SetStatusAsConsumeDoDefault() {
+ mStatus = nsEventStatus_eConsumeDoDefault;
+ }
+
+ // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult
+ // depending on |aBlock|'s target APZC.
+ void SetStatusAsConsumeDoDefault(const InputBlockState& aBlock);
+ // Set mStatus and mHandledResult for a touch event which is not dropped
+ // altogether (i.e. the status is not eConsumeNoDefault).
+ void SetStatusForTouchEvent(const InputBlockState& aBlock,
+ TargetConfirmationFlags aFlags,
+ PointerEventsConsumableFlags aConsumableFlags,
+ const AsyncPanZoomController* aTarget);
+
+ // Set mStatus and mHandledResult during in a stat of fast fling.
+ void SetStatusForFastFling(const TouchBlockState& aBlock,
+ TargetConfirmationFlags aFlags,
+ PointerEventsConsumableFlags aConsumableFlags,
+ const AsyncPanZoomController* aTarget);
+
+ // DO NOT USE THIS UpdateStatus DIRECTLY. THIS FUNCTION IS ONLY FOR
+ // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC.
+ void UpdateStatus(nsEventStatus aStatus) { mStatus = aStatus; }
+ nsEventStatus GetStatus() const { return mStatus; };
+
+ // DO NOT USE THIS UpdateHandledResult DIRECTLY. THIS FUNCTION IS ONLY FOR
+ // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC.
+ void UpdateHandledResult(const Maybe<APZHandledResult>& aHandledResult) {
+ mHandledResult = aHandledResult;
+ }
+ const Maybe<APZHandledResult>& GetHandledResult() const {
+ return mHandledResult;
+ }
+
+ bool WillHaveDelayedResult() const {
+ return GetStatus() != nsEventStatus_eConsumeNoDefault &&
+ !GetHandledResult();
+ }
+
+ private:
+ void UpdateHandledResult(const InputBlockState& aBlock,
+ PointerEventsConsumableFlags aConsumableFlags,
+ const AsyncPanZoomController* aTarget,
+ bool aDispatchToContent);
+
+ /**
+ * A status flag indicated how APZ handled the event.
+ * The interpretation of each value is as follows:
+ *
+ * nsEventStatus_eConsumeNoDefault is returned to indicate the
+ * APZ is consuming this event and the caller should discard the event with
+ * extreme prejudice. The exact scenarios under which this is returned is
+ * implementation-dependent and may vary.
+ * nsEventStatus_eIgnore is returned to indicate that the APZ code didn't
+ * use this event. This might be because it was directed at a point on
+ * the screen where there was no APZ, or because the thing the user was
+ * trying to do was not allowed. (For example, attempting to pan a
+ * non-pannable document).
+ * nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ
+ * code may have used this event to do some user-visible thing. Note that
+ * in some cases CONSUMED is returned even if the event was NOT used. This
+ * is because we cannot always know at the time of event delivery whether
+ * the event will be used or not. So we err on the side of sending
+ * CONSUMED when we are uncertain.
+ */
+ nsEventStatus mStatus;
+
+ /**
+ * This is:
+ * - set to HandledByRoot if we know for sure that the event will be handled
+ * by the root content APZC;
+ * - set to HandledByContent if we know for sure it will not be;
+ * - left empty if we are unsure.
+ */
+ Maybe<APZHandledResult> mHandledResult;
+
+ public:
+ /**
+ * The guid of the APZC initially targeted by this event.
+ * This will usually be the APZC that handles the event, but in cases
+ * where the event is dispatched to content, it may end up being
+ * handled by a different APZC.
+ */
+ ScrollableLayerGuid mTargetGuid;
+ /**
+ * If this event started or was added to an input block, the id of that
+ * input block, otherwise InputBlockState::NO_BLOCK_ID.
+ */
+ uint64_t mInputBlockId;
+};
+
+/**
+ * This class lives in the main process, and is accessed via the controller
+ * thread (which is the process main thread for desktop, and the Java UI
+ * thread for Android). This class exposes a synchronous API to deliver
+ * incoming input events to APZ and modify them in-place to unapply the APZ
+ * async transform. If there is a GPU process, then this class does sync IPC
+ * calls over to the GPU process in order to accomplish this. Otherwise,
+ * APZCTreeManager overrides and implements these methods directly.
+ */
+class APZInputBridge {
+ public:
+ using InputBlockCallback = std::function<void(
+ uint64_t aInputBlockId, const APZHandledResult& aHandledResult)>;
+
+ /**
+ * General handler for incoming input events. Manipulates the frame metrics
+ * based on what type of input it is. For example, a PinchGestureEvent will
+ * cause scaling. This should only be called externally to this class, and
+ * must be called on the controller thread.
+ *
+ * This function transforms |aEvent| to have its coordinates in DOM space.
+ * This is so that the event can be passed through the DOM and content can
+ * handle them. The event may need to be converted to a WidgetInputEvent
+ * by the caller if it wants to do this.
+ *
+ * @param aEvent input event object; is modified in-place
+ * @param aCallback an optional callback to be invoked when the input block is
+ * ready for handling,
+ * @return The result of processing the event. Refer to the documentation of
+ * APZEventResult and its field.
+ */
+ virtual APZEventResult ReceiveInputEvent(
+ InputData& aEvent,
+ InputBlockCallback&& aCallback = InputBlockCallback()) = 0;
+
+ /**
+ * WidgetInputEvent handler. Transforms |aEvent| (which is assumed to be an
+ * already-existing instance of an WidgetInputEvent which may be an
+ * WidgetTouchEvent) to have its coordinates in DOM space. This is so that the
+ * event can be passed through the DOM and content can handle them.
+ *
+ * NOTE: Be careful of invoking the WidgetInputEvent variant. This can only be
+ * called on the main thread. See widget/InputData.h for more information on
+ * why we have InputData and WidgetInputEvent separated. If this function is
+ * used, the controller thread must be the main thread, or undefined behaviour
+ * may occur.
+ * NOTE: On unix, mouse events are treated as touch and are forwarded
+ * to the appropriate apz as such.
+ *
+ * See documentation for other ReceiveInputEvent above.
+ */
+ APZEventResult ReceiveInputEvent(
+ WidgetInputEvent& aEvent,
+ InputBlockCallback&& aCallback = InputBlockCallback());
+
+ // Returns the kind of wheel event action, if any, that will be (or was)
+ // performed by APZ. If this returns true, the event must not perform a
+ // synchronous scroll.
+ //
+ // Even if this returns Nothing(), all wheel events in APZ-aware widgets must
+ // be sent through APZ so they are transformed correctly for BrowserParent.
+ static Maybe<APZWheelAction> ActionForWheelEvent(WidgetWheelEvent* aEvent);
+
+ protected:
+ friend class APZInputBridgeParent;
+
+ // Methods to help process WidgetInputEvents (or manage conversion to/from
+ // InputData)
+
+ virtual void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
+ ScrollableLayerGuid* aOutTargetGuid,
+ uint64_t* aOutFocusSequenceNumber,
+ LayersId* aOutLayersId) = 0;
+
+ virtual void UpdateWheelTransaction(
+ LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage,
+ const Maybe<ScrollableLayerGuid>& aTargetGuid) = 0;
+
+ virtual ~APZInputBridge() = default;
+};
+
+std::ostream& operator<<(std::ostream& aOut,
+ const APZHandledResult& aHandledResult);
+
+// This enum class is used for communicating between APZ and the browser gesture
+// support code. APZ needs to wait for the browser to send this response just
+// like APZ waits for the content's response if there's an APZ ware event
+// listener in the content process.
+enum class BrowserGestureResponse : bool {
+ NotConsumed = 0, // Representing the browser doesn't consume the gesture
+ Consumed = 1, // Representing the browser has started consuming the gesture.
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_APZInputBridge_h