tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

APZInputBridge.h (13235B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_layers_APZInputBridge_h
      8 #define mozilla_layers_APZInputBridge_h
      9 
     10 #include "Units.h"                  // for LayoutDeviceIntPoint
     11 #include "mozilla/EventForwards.h"  // for WidgetInputEvent, nsEventStatus
     12 #include "mozilla/layers/APZPublicUtils.h"  // for APZWheelAction, DispatchToContent
     13 #include "mozilla/layers/LayersTypes.h"          // for ScrollDirections
     14 #include "mozilla/layers/ScrollableLayerGuid.h"  // for ScrollableLayerGuid
     15 
     16 namespace mozilla {
     17 
     18 class InputData;
     19 
     20 namespace layers {
     21 
     22 class APZInputBridgeParent;
     23 class AsyncPanZoomController;
     24 class InputBlockState;
     25 class TouchBlockState;
     26 struct ScrollableLayerGuid;
     27 struct TargetConfirmationFlags;
     28 struct PointerEventsConsumableFlags;
     29 
     30 enum class APZHandledPlace : uint8_t {
     31  Unhandled = 0,         // we know for sure that the event will not be handled
     32                         // by either the root APZC or others
     33  HandledByRoot = 1,     // we know for sure that the event will be handled
     34                         // by the root content APZC
     35  HandledByContent = 2,  // we know for sure it will be handled by a non-root
     36                         // APZC or by an event listener using preventDefault()
     37                         // in a document
     38  Invalid = 3,
     39  Last = Invalid
     40 };
     41 
     42 struct APZHandledResult {
     43  APZHandledPlace mPlace = APZHandledPlace::Invalid;
     44  SideBits mScrollableDirections = SideBits::eNone;
     45  ScrollDirections mOverscrollDirections = ScrollDirections();
     46 
     47  APZHandledResult() = default;
     48  // A constructor for cases where we have the target of the input block this
     49  // event is part of, the target might be adjusted to be the root in the
     50  // ScrollingDownWillMoveDynamicToolbar case.
     51  //
     52  // NOTE: There's a case where |aTarget| is the APZC for the root content but
     53  // |aPlace| has to be `HandledByContent`, for example, the root content has
     54  // an event handler using preventDefault() in the callback, so call sites of
     55  // this function should be responsible to set a proper |aPlace|.
     56  APZHandledResult(APZHandledPlace aPlace,
     57                   const AsyncPanZoomController* aTarget,
     58                   bool aPopulateDirectionsForUnhandled = false);
     59  APZHandledResult(APZHandledPlace aPlace, SideBits aScrollableDirections,
     60                   ScrollDirections aOverscrollDirections)
     61      : mPlace(aPlace),
     62        mScrollableDirections(aScrollableDirections),
     63        mOverscrollDirections(aOverscrollDirections) {}
     64 
     65  bool IsHandledByContent() const {
     66    return mPlace == APZHandledPlace::HandledByContent;
     67  }
     68  bool IsHandledByRoot() const {
     69    return mPlace == APZHandledPlace::HandledByRoot;
     70  }
     71  bool operator==(const APZHandledResult& aOther) const {
     72    return mPlace == aOther.mPlace &&
     73           mScrollableDirections == aOther.mScrollableDirections &&
     74           mOverscrollDirections == aOther.mOverscrollDirections;
     75  }
     76 
     77  // Compute an initial (optional) APZHandledResult for an event.
     78  // If aDispatchToContent==false, the result is guaranteed to not be empty.
     79  static Maybe<APZHandledResult> Initialize(
     80      const AsyncPanZoomController* aInitialTarget,
     81      DispatchToContent aDispatchToContent);
     82 
     83  // Update |aHandledResult| with information specific to touch events.
     84  // If aDispatchToContent==false, the resulting value of |aHandledResult|
     85  // is guarateed to not be empty.
     86  static void UpdateForTouchEvent(Maybe<APZHandledResult>& aHandledResult,
     87                                  const InputBlockState& aBlock,
     88                                  PointerEventsConsumableFlags aConsumableFlags,
     89                                  const AsyncPanZoomController* aTarget,
     90                                  DispatchToContent aDispatchToContent);
     91 };
     92 
     93 /**
     94 * Represents the outcome of APZ receiving and processing an input event.
     95 * This is returned from APZInputBridge::ReceiveInputEvent() and related APIs.
     96 */
     97 struct APZEventResult {
     98  /**
     99   * Creates a default result with a status of eIgnore, no block ID, and empty
    100   * target guid.
    101   */
    102  APZEventResult();
    103 
    104  /**
    105   * Creates a result with a status of eIgnore, no block ID, the guid of the
    106   * given initial target, and an APZHandledResult if we are sure the event
    107   * is not going to be dispatched to contents.
    108   */
    109  APZEventResult(const RefPtr<AsyncPanZoomController>& aInitialTarget,
    110                 TargetConfirmationFlags aFlags);
    111 
    112  void SetStatusAsConsumeNoDefault() {
    113    mStatus = nsEventStatus_eConsumeNoDefault;
    114  }
    115 
    116  void SetStatusAsIgnore() { mStatus = nsEventStatus_eIgnore; }
    117 
    118  // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult
    119  // depending on |aTarget|.
    120  void SetStatusAsConsumeDoDefault(
    121      const RefPtr<AsyncPanZoomController>& aTarget);
    122 
    123  // Set mStatus to nsEventStatus_eConsumeDoDefault, unlike above
    124  // SetStatusAsConsumeDoDefault(const RefPtr<AsyncPanZoomController>&) this
    125  // function doesn't mutate mHandledResult.
    126  void SetStatusAsConsumeDoDefault() {
    127    mStatus = nsEventStatus_eConsumeDoDefault;
    128  }
    129 
    130  // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult
    131  // depending on |aBlock|'s target APZC.
    132  void SetStatusAsConsumeDoDefault(const InputBlockState& aBlock);
    133  // Set mStatus and mHandledResult for a touch event which is not dropped
    134  // altogether (i.e. the status is not eConsumeNoDefault).
    135  void SetStatusForTouchEvent(const InputBlockState& aBlock,
    136                              TargetConfirmationFlags aFlags,
    137                              PointerEventsConsumableFlags aConsumableFlags,
    138                              const AsyncPanZoomController* aTarget);
    139 
    140  // Set mStatus and mHandledResult during in a stat of fast fling.
    141  void SetStatusForFastFling(const TouchBlockState& aBlock,
    142                             TargetConfirmationFlags aFlags,
    143                             PointerEventsConsumableFlags aConsumableFlags,
    144                             const AsyncPanZoomController* aTarget);
    145 
    146  // DO NOT USE THIS UpdateStatus DIRECTLY. THIS FUNCTION IS ONLY FOR
    147  // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC.
    148  void UpdateStatus(nsEventStatus aStatus) { mStatus = aStatus; }
    149  nsEventStatus GetStatus() const { return mStatus; };
    150 
    151  // DO NOT USE THIS UpdateHandledResult DIRECTLY. THIS FUNCTION IS ONLY FOR
    152  // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC.
    153  void UpdateHandledResult(const Maybe<APZHandledResult>& aHandledResult) {
    154    mHandledResult = aHandledResult;
    155  }
    156  const Maybe<APZHandledResult>& GetHandledResult() const {
    157    return mHandledResult;
    158  }
    159 
    160  bool WillHaveDelayedResult() const {
    161    return GetStatus() != nsEventStatus_eConsumeNoDefault &&
    162           !GetHandledResult();
    163  }
    164 
    165 private:
    166  /**
    167   * A status flag indicated how APZ handled the event.
    168   * The interpretation of each value is as follows:
    169   *
    170   * nsEventStatus_eConsumeNoDefault is returned to indicate the
    171   *   APZ is consuming this event and the caller should discard the event with
    172   *   extreme prejudice. The exact scenarios under which this is returned is
    173   *   implementation-dependent and may vary.
    174   * nsEventStatus_eIgnore is returned to indicate that the APZ code didn't
    175   *   use this event. This might be because it was directed at a point on
    176   *   the screen where there was no APZ, or because the thing the user was
    177   *   trying to do was not allowed. (For example, attempting to pan a
    178   *   non-pannable document).
    179   * nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ
    180   *   code may have used this event to do some user-visible thing. Note that
    181   *   in some cases CONSUMED is returned even if the event was NOT used. This
    182   *   is because we cannot always know at the time of event delivery whether
    183   *   the event will be used or not. So we err on the side of sending
    184   *   CONSUMED when we are uncertain.
    185   */
    186  nsEventStatus mStatus;
    187 
    188  /**
    189   * This is:
    190   *  - set to HandledByRoot if we know for sure that the event will be handled
    191   *    by the root content APZC;
    192   *  - set to HandledByContent if we know for sure it will not be;
    193   *  - left empty if we are unsure.
    194   */
    195  Maybe<APZHandledResult> mHandledResult;
    196 
    197 public:
    198  /**
    199   * The guid of the APZC initially targeted by this event.
    200   * This will usually be the APZC that handles the event, but in cases
    201   * where the event is dispatched to content, it may end up being
    202   * handled by a different APZC.
    203   */
    204  ScrollableLayerGuid mTargetGuid;
    205  /**
    206   * If this event started or was added to an input block, the id of that
    207   * input block, otherwise InputBlockState::NO_BLOCK_ID.
    208   */
    209  uint64_t mInputBlockId;
    210 };
    211 
    212 /**
    213 * This class lives in the main process, and is accessed via the controller
    214 * thread (which is the process main thread for desktop, and the Java UI
    215 * thread for Android). This class exposes a synchronous API to deliver
    216 * incoming input events to APZ and modify them in-place to unapply the APZ
    217 * async transform. If there is a GPU process, then this class does sync IPC
    218 * calls over to the GPU process in order to accomplish this. Otherwise,
    219 * APZCTreeManager overrides and implements these methods directly.
    220 */
    221 class APZInputBridge {
    222 public:
    223  using InputBlockCallback = std::function<void(
    224      uint64_t aInputBlockId, const APZHandledResult& aHandledResult)>;
    225 
    226  /**
    227   * General handler for incoming input events. Manipulates the frame metrics
    228   * based on what type of input it is. For example, a PinchGestureEvent will
    229   * cause scaling. This should only be called externally to this class, and
    230   * must be called on the controller thread.
    231   *
    232   * This function transforms |aEvent| to have its coordinates in DOM space.
    233   * This is so that the event can be passed through the DOM and content can
    234   * handle them. The event may need to be converted to a WidgetInputEvent
    235   * by the caller if it wants to do this.
    236   *
    237   * @param aEvent input event object; is modified in-place
    238   * @param aCallback an optional callback to be invoked when the input block is
    239   * ready for handling,
    240   * @return The result of processing the event. Refer to the documentation of
    241   * APZEventResult and its field.
    242   */
    243  virtual APZEventResult ReceiveInputEvent(
    244      InputData& aEvent,
    245      InputBlockCallback&& aCallback = InputBlockCallback()) = 0;
    246 
    247  /**
    248   * WidgetInputEvent handler. Transforms |aEvent| (which is assumed to be an
    249   * already-existing instance of an WidgetInputEvent which may be an
    250   * WidgetTouchEvent) to have its coordinates in DOM space. This is so that the
    251   * event can be passed through the DOM and content can handle them.
    252   *
    253   * NOTE: Be careful of invoking the WidgetInputEvent variant. This can only be
    254   * called on the main thread. See widget/InputData.h for more information on
    255   * why we have InputData and WidgetInputEvent separated. If this function is
    256   * used, the controller thread must be the main thread, or undefined behaviour
    257   * may occur.
    258   * NOTE: On unix, mouse events are treated as touch and are forwarded
    259   * to the appropriate apz as such.
    260   *
    261   * See documentation for other ReceiveInputEvent above.
    262   */
    263  APZEventResult ReceiveInputEvent(
    264      WidgetInputEvent& aEvent,
    265      InputBlockCallback&& aCallback = InputBlockCallback());
    266 
    267  // Returns the kind of wheel event action, if any, that will be (or was)
    268  // performed by APZ. If this returns true, the event must not perform a
    269  // synchronous scroll.
    270  //
    271  // Even if this returns Nothing(), all wheel events in APZ-aware widgets must
    272  // be sent through APZ so they are transformed correctly for BrowserParent.
    273  static Maybe<APZWheelAction> ActionForWheelEvent(WidgetWheelEvent* aEvent);
    274 
    275 protected:
    276  friend class APZInputBridgeParent;
    277 
    278  // Methods to help process WidgetInputEvents (or manage conversion to/from
    279  // InputData)
    280 
    281  virtual void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
    282                                     ScrollableLayerGuid* aOutTargetGuid,
    283                                     uint64_t* aOutFocusSequenceNumber,
    284                                     LayersId* aOutLayersId) = 0;
    285 
    286  virtual void UpdateWheelTransaction(
    287      LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage,
    288      const Maybe<ScrollableLayerGuid>& aTargetGuid) = 0;
    289 
    290  virtual ~APZInputBridge() = default;
    291 };
    292 
    293 std::ostream& operator<<(std::ostream& aOut,
    294                         const APZHandledResult& aHandledResult);
    295 
    296 // This enum class is used for communicating between APZ and the browser gesture
    297 // support code. APZ needs to wait for the browser to send this response just
    298 // like APZ waits for the content's response if there's an APZ ware event
    299 // listener in the content process.
    300 enum class BrowserGestureResponse : bool {
    301  NotConsumed = 0,  // Representing the browser doesn't consume the gesture
    302  Consumed = 1,  // Representing the browser has started consuming the gesture.
    303 };
    304 
    305 }  // namespace layers
    306 }  // namespace mozilla
    307 
    308 #endif  // mozilla_layers_APZInputBridge_h