tor-browser

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

EventStateManager.h (62748B)


      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_EventStateManager_h_
      8 #define mozilla_EventStateManager_h_
      9 
     10 #include "Units.h"
     11 #include "WheelHandlingHelper.h"  // for WheelDeltaAdjustmentStrategy
     12 #include "mozilla/Attributes.h"
     13 #include "mozilla/EventForwards.h"
     14 #include "mozilla/TimeStamp.h"
     15 #include "mozilla/dom/Record.h"
     16 #include "mozilla/layers/APZPublicUtils.h"
     17 #include "nsCOMArray.h"
     18 #include "nsCOMPtr.h"
     19 #include "nsCycleCollectionParticipant.h"
     20 #include "nsIObserver.h"
     21 #include "nsIWeakReferenceUtils.h"
     22 #include "nsRefPtrHashtable.h"
     23 #include "nsWeakReference.h"
     24 
     25 class nsFrameLoader;
     26 class nsIContent;
     27 class nsICookieJarSettings;
     28 class nsIDocShell;
     29 class nsIDocShellTreeItem;
     30 class nsIFrame;
     31 class imgIContainer;
     32 class nsIDocumentViewer;
     33 class nsITimer;
     34 class nsIWidget;
     35 class nsPresContext;
     36 
     37 enum class FormControlType : uint8_t;
     38 
     39 namespace mozilla {
     40 
     41 class EditorBase;
     42 class EnterLeaveDispatcher;
     43 class IMEContentObserver;
     44 class LazyLogModule;
     45 class ScrollbarsForWheel;
     46 class ScrollContainerFrame;
     47 class TextControlElement;
     48 class WheelTransaction;
     49 
     50 namespace dom {
     51 class DataTransfer;
     52 class Document;
     53 class Element;
     54 class Selection;
     55 class BrowserParent;
     56 class RemoteDragStartData;
     57 
     58 }  // namespace dom
     59 
     60 class OverOutElementsWrapper final : public nsISupports {
     61  ~OverOutElementsWrapper() = default;
     62 
     63 public:
     64  enum class BoundaryEventType : bool { Mouse, Pointer };
     65  explicit OverOutElementsWrapper(BoundaryEventType aType) : mType(aType) {}
     66 
     67  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     68  NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper)
     69 
     70  already_AddRefed<nsIWidget> GetLastOverWidget() const;
     71 
     72  void ContentRemoved(nsIContent& aContent);
     73  void WillDispatchOverAndEnterEvent(nsIContent* aOverEventTarget);
     74  void DidDispatchOverAndEnterEvent(
     75      nsIContent* aOriginalOverTargetInComposedDoc,
     76      nsIWidget* aOverEventTargetWidget);
     77  [[nodiscard]] bool IsDispatchingOverEventOn(
     78      nsIContent* aOverEventTarget) const {
     79    MOZ_ASSERT(aOverEventTarget);
     80    return LastOverEventTargetIsOutEventTarget() &&
     81           mDeepestEnterEventTarget == aOverEventTarget;
     82  }
     83  void WillDispatchOutAndOrLeaveEvent() {
     84    // Store the first "out" event target or the deepest "leave" event target
     85    // which we fire and don't refire "out" event to that element while the
     86    // first "out" event is still ongoing.
     87    mDispatchingOutOrDeepestLeaveEventTarget = mDeepestEnterEventTarget;
     88  }
     89  void DidDispatchOutAndOrLeaveEvent() {
     90    StoreOverEventTargetAndDeepestEnterEventTarget(nullptr);
     91    mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
     92  }
     93  [[nodiscard]] bool IsDispatchingOutEventOnLastOverEventTarget() const {
     94    return mDispatchingOutOrDeepestLeaveEventTarget &&
     95           mDispatchingOutOrDeepestLeaveEventTarget == mDeepestEnterEventTarget;
     96  }
     97  void OverrideOverEventTarget(nsIContent* aOverEventTarget) {
     98    StoreOverEventTargetAndDeepestEnterEventTarget(aOverEventTarget);
     99    // We don't need the widget for aOverEventTarget because this method is used
    100    // for adjusting the "over" event target for the following "out" event
    101    // dispatch.
    102    mLastOverWidget = nullptr;
    103  }
    104 
    105  [[nodiscard]] nsIContent* GetDeepestLeaveEventTarget() const {
    106    // The last deepest "enter" event targe (it may be same as the last "over"
    107    // target) is the deepest "leave" event target.
    108    return mDeepestEnterEventTarget;
    109  }
    110  [[nodiscard]] nsIContent* GetOutEventTarget() const {
    111    // The last deepest "enter" event target is same as the "over" event target
    112    // unless it's never been removed from the DOM tree.  If and only if the
    113    // last "over" event target has not been removed from the DOM tree, it's
    114    // the next "out" event target.  Once the last "over" target is removed,
    115    // "out" event should not be fired on the target nor its ancestor.
    116    return LastOverEventTargetIsOutEventTarget()
    117               ? mDeepestEnterEventTarget.get()
    118               : nullptr;
    119  }
    120 
    121  /**
    122   * Called when EventStateManager::PreHandleEvent() receives an event which
    123   * should be treated as the deadline to restore the last "over" event target
    124   * as the next "out" event target and for avoiding to dispatch redundant
    125   * "over" event on the same target again when it was removed but reconnected.
    126   * If the last "over" event target was reconnected under the last deepest
    127   * "enter" event target, this restores the last "over" event target.
    128   * Otherwise, makes the instance forget the last "over" target because the
    129   * user maybe has seen that the last "over" target is completely removed from
    130   * the tree.
    131   *
    132   * @param aEvent      The event which the caller received.  If this is set to
    133   *                    nullptr or not a mouse event, this forgets the pending
    134   *                    last "over" event target.
    135   */
    136  void TryToRestorePendingRemovedOverTarget(const WidgetEvent* aEvent);
    137 
    138  /**
    139   * Return true if we have a pending removing last "over" event target at least
    140   * for the weak reference to it.  In other words, when this returns true, we
    141   * need to handle the pending removing "over" event target.
    142   */
    143  [[nodiscard]] bool MaybeHasPendingRemovingOverEventTarget() const {
    144    return mPendingRemovingOverEventTarget;
    145  }
    146 
    147 private:
    148  /**
    149   * Whether the last "over" event target is the target of "out" event if you
    150   * dispatch "out" event.
    151   */
    152  [[nodiscard]] bool LastOverEventTargetIsOutEventTarget() const {
    153    MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget,
    154                  mDeepestEnterEventTarget);
    155    MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget,
    156                  !MaybeHasPendingRemovingOverEventTarget());
    157    return mDeepestEnterEventTargetIsOverEventTarget;
    158  }
    159 
    160  void StoreOverEventTargetAndDeepestEnterEventTarget(
    161      nsIContent* aOverEventTargetAndDeepestEnterEventTarget);
    162  void UpdateDeepestEnterEventTarget(nsIContent* aDeepestEnterEventTarget);
    163 
    164  nsCOMPtr<nsIContent> GetPendingRemovingOverEventTarget() const {
    165    nsCOMPtr<nsIContent> pendingRemovingOverEventTarget =
    166        do_QueryReferent(mPendingRemovingOverEventTarget);
    167    return pendingRemovingOverEventTarget.forget();
    168  }
    169 
    170  // The deepest event target of the last "enter" event.  If
    171  // mDeepestEnterEventTargetIsOverEventTarget is true, this is the last "over"
    172  // event target too.  If it's set to false, this is an ancestor of the last
    173  // "over" event target which is not removed from the DOM tree.
    174  nsCOMPtr<nsIContent> mDeepestEnterEventTarget;
    175 
    176  // The last "over" event target which will be considered as disconnected or
    177  // connected later because web apps may remove the "over" event target
    178  // temporarily and reconnect it to the deepest "enter" target immediately.
    179  // In such case, we should keep treating it as the last "over" event target
    180  // as the next "out" event target.
    181  // FYI: This needs to be a weak pointer.  Otherwise, the leak window checker
    182  // of mochitests will detect windows in the closed tabs which ran tests
    183  // synthesizing mouse moves because while a <browser> is stored with a strong
    184  // pointer, the child window is also grabbed by the element.
    185  nsWeakPtr mPendingRemovingOverEventTarget;
    186 
    187  // While we're dispatching "over" and "enter" events, this is set to the
    188  // "over" event target.  If it's removed from the DOM tree, this is set to
    189  // nullptr.
    190  nsCOMPtr<nsIContent> mDispatchingOverEventTarget;
    191 
    192  // While we're dispatching "out" and/or "leave" events, this is set to the
    193  // "out" event target or the deepest leave event target.  If it's removed from
    194  // the DOM tree, this is set to nullptr.
    195  nsCOMPtr<nsIContent> mDispatchingOutOrDeepestLeaveEventTarget;
    196 
    197  // The widget on which we dispatched the last "over" event.  Note that
    198  // nsIWidget is not cycle collectable.  Therefore, for avoiding unexpected
    199  // memory leaks, we use nsWeakPtr to store the widget here.
    200  nsWeakPtr mLastOverWidget;
    201 
    202  const BoundaryEventType mType;
    203 
    204  // Once the last "over" element is removed from the tree, this is set
    205  // to false.  Then, mDeepestEnterEventTarget may be an ancestor of the
    206  // "over" element which should be the deepest target of next "leave"
    207  // element but shouldn't be target of "out" event.
    208  bool mDeepestEnterEventTargetIsOverEventTarget = false;
    209 };
    210 
    211 class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
    212  friend class mozilla::EnterLeaveDispatcher;
    213  friend class mozilla::ScrollbarsForWheel;
    214  friend class mozilla::WheelTransaction;
    215 
    216  using ElementState = dom::ElementState;
    217 
    218  virtual ~EventStateManager();
    219 
    220 public:
    221  EventStateManager();
    222 
    223  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    224  NS_DECL_NSIOBSERVER
    225 
    226  nsresult Init();
    227  nsresult Shutdown();
    228 
    229  static LazyLogModule& MouseCursorUpdateLogRef();
    230 
    231  /* The PreHandleEvent method is called before event dispatch to either
    232   * the DOM or frames.  Any processing which must not be prevented or
    233   * cancelled should occur here.  Any processing which is intended to
    234   * be conditional based on either DOM or frame processing should occur in
    235   * PostHandleEvent.  Any centralized event processing which must occur before
    236   * DOM or frame event handling should occur here as well.
    237   *
    238   * aOverrideClickTarget can be used to indicate which element should be
    239   * used as the *up target when deciding whether to send click event.
    240   * This is used when releasing pointer capture. Otherwise null.
    241   */
    242  MOZ_CAN_RUN_SCRIPT
    243  nsresult PreHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
    244                          nsIFrame* aTargetFrame, nsIContent* aTargetContent,
    245                          nsEventStatus* aStatus,
    246                          nsIContent* aOverrideClickTarget);
    247 
    248  /* The PostHandleEvent method should contain all system processing which
    249   * should occur conditionally based on DOM or frame processing.  It should
    250   * also contain any centralized event processing which must occur after
    251   * DOM and frame processing.
    252   */
    253  MOZ_CAN_RUN_SCRIPT
    254  nsresult PostHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
    255                           nsIFrame* aTargetFrame, nsEventStatus* aStatus,
    256                           nsIContent* aOverrideClickTarget);
    257 
    258  MOZ_CAN_RUN_SCRIPT void PostHandleKeyboardEvent(
    259      WidgetKeyboardEvent* aKeyboardEvent, nsIFrame* aTargetFrame,
    260      nsEventStatus& aStatus);
    261 
    262  /**
    263   * DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll
    264   * event and eLegacyMousePixelScroll event for compatibility with old Gecko.
    265   */
    266  MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchLegacyMouseScrollEvents(
    267      nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, nsEventStatus* aStatus);
    268 
    269  MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyDestroyPresContext(
    270      nsPresContext* aPresContext);
    271 
    272  void ResetHoverState();
    273 
    274  void SetPresContext(nsPresContext* aPresContext);
    275  void ClearFrameRefs(nsIFrame* aFrame);
    276 
    277  nsIFrame* GetEventTarget();
    278  already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent);
    279 
    280  // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET
    281  static bool ManagesState(ElementState aState) {
    282    return aState == ElementState::ACTIVE || aState == ElementState::HOVER ||
    283           aState == ElementState::DRAGOVER ||
    284           aState == ElementState::URLTARGET;
    285  }
    286 
    287  /**
    288   * Notify that the given ElementState::* bit has changed for this content.
    289   * @param aContent Content which has changed states
    290   * @param aState   Corresponding state flags such as ElementState::FOCUS
    291   * @return  Whether the content was able to change all states. Returns false
    292   *                  if a resulting DOM event causes the content node passed in
    293   *                  to not change states. Note, the frame for the content may
    294   *                  change as a result of the content state change, because of
    295   *                  frame reconstructions that may occur, but this does not
    296   *                  affect the return value.
    297   */
    298  bool SetContentState(nsIContent* aContent, ElementState aState);
    299 
    300  nsIContent* GetActiveContent() const { return mActiveContent; }
    301 
    302  void NativeAnonymousContentRemoved(nsIContent* aAnonContent);
    303  void ContentInserted(nsIContent* aChild, const ContentInsertInfo& aInfo);
    304  void ContentAppended(nsIContent* aFirstNewContent,
    305                       const ContentAppendInfo& aInfo);
    306  MOZ_CAN_RUN_SCRIPT_BOUNDARY void ContentRemoved(
    307      dom::Document* aDocument, nsIContent* aContent,
    308      const ContentRemoveInfo& aInfo);
    309 
    310  /**
    311   * Called when a native anonymous <div> element which is root element of
    312   * text editor will be removed.
    313   */
    314  void TextControlRootWillBeRemoved(TextControlElement& aTextControlElement);
    315 
    316  /**
    317   * Called when a native anonymous <div> element which is root element of
    318   * text editor is created.
    319   */
    320  void TextControlRootAdded(dom::Element& aAnonymousDivElement,
    321                            TextControlElement& aTextControlElement);
    322 
    323  bool EventStatusOK(WidgetGUIEvent* aEvent);
    324 
    325  /**
    326   * EventStateManager stores IMEContentObserver while it's observing contents.
    327   * Following mehtods are called by IMEContentObserver when it starts to
    328   * observe or stops observing the content.
    329   */
    330  void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver);
    331  void OnStopObservingContent(IMEContentObserver* aIMEContentObserver);
    332 
    333  /**
    334   * TryToFlushPendingNotificationsToIME() suggests flushing pending
    335   * notifications to IME to IMEContentObserver.
    336   * Doesn't do anything in child processes where flushing happens
    337   * asynchronously.
    338   */
    339  void TryToFlushPendingNotificationsToIME();
    340 
    341  static bool IsKeyboardEventUserActivity(WidgetEvent* aEvent);
    342 
    343  /**
    344   * Register accesskey on the given element. When accesskey is activated then
    345   * the element will be notified via Element::PerformAccesskey() method.
    346   *
    347   * @param  aElement  the given element
    348   * @param  aKey      accesskey
    349   */
    350  void RegisterAccessKey(dom::Element* aElement, uint32_t aKey);
    351 
    352  /**
    353   * Unregister accesskey for the given element.
    354   *
    355   * @param  aElement  the given element
    356   * @param  aKey      accesskey
    357   */
    358  void UnregisterAccessKey(dom::Element* aElement, uint32_t aKey);
    359 
    360  /**
    361   * Get accesskey registered on the given element or 0 if there is none.
    362   *
    363   * @param  aElement  the given element (must not be null)
    364   * @return           registered accesskey
    365   */
    366  uint32_t GetRegisteredAccessKey(dom::Element* aContent);
    367 
    368  static void GetAccessKeyLabelPrefix(dom::Element* aElement,
    369                                      nsAString& aPrefix);
    370 
    371  /**
    372   * HandleAccessKey() looks for access keys which matches with aEvent and
    373   * execute when it matches with a chrome access key or some content access
    374   * keys.
    375   * If the event may match chrome access keys, this handles the access key
    376   * synchronously (if there are nested ESMs, their HandleAccessKey() are
    377   * also called recursively).
    378   * If the event may match content access keys and focused target is a remote
    379   * process, this does nothing for the content because when this is called,
    380   * it should already have been handled in the remote process.
    381   * If the event may match content access keys and focused target is not in
    382   * remote process but there are some remote children, this will post
    383   * HandleAccessKey messages to all remote children.
    384   *
    385   * @return            true if there is accesskey which aEvent and
    386   *                    aAccessCharCodes match with.  Otherwise, false.
    387   *                    I.e., when this returns true, a target is executed
    388   *                    or focused.
    389   *                    Note that even if this returns false, a target in
    390   *                    remote process may be executed or focused
    391   *                    asynchronously.
    392   */
    393  bool HandleAccessKey(WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext,
    394                       nsTArray<uint32_t>& aAccessCharCodes) {
    395    return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
    396                                        nullptr, eAccessKeyProcessingNormal,
    397                                        true);
    398  }
    399 
    400  /**
    401   * CheckIfEventMatchesAccessKey() looks for access key which matches with
    402   * aEvent in the process but won't execute it.
    403   *
    404   * @return            true if there is accesskey which aEvent matches with
    405   *                    in this process.  Otherwise, false.
    406   */
    407  bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent,
    408                                    nsPresContext* aPresContext);
    409 
    410  nsresult SetCursor(StyleCursorKind, imgIContainer*, const ImageResolution&,
    411                     const Maybe<gfx::IntPoint>& aHotspot, nsIWidget* aWidget,
    412                     bool aLockCursor);
    413 
    414  void StartHidingCursorWhileTyping(nsIWidget*);
    415 
    416  /**
    417   * Checks if the current mouse over element matches the given
    418   * Element (which has a remote frame), and if so, notifies
    419   * the BrowserParent of the mouse enter.
    420   * Called when we reconstruct the BrowserParent and need to
    421   * recompute state on the new object.
    422   */
    423  void RecomputeMouseEnterStateForRemoteFrame(dom::Element& aElement);
    424 
    425  nsPresContext* GetPresContext() const { return mPresContext; }
    426 
    427  PresShell* GetPresShell() const {
    428    return mPresContext ? mPresContext->GetPresShell() : nullptr;
    429  }
    430 
    431  /**
    432   * Return the in-process root PresShell which is associated with the root
    433   * nsPresContext of mPresContext.
    434   */
    435  PresShell* GetRootPresShell() const;
    436 
    437  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, nsIObserver)
    438 
    439  // The manager in this process that is setting the cursor. In the parent
    440  // process it might be null if a remote process is setting the cursor.
    441  static EventStateManager* sCursorSettingManager;
    442  static void ClearCursorSettingManager() { sCursorSettingManager = nullptr; }
    443 
    444  // Checks if the manager in this process has a locked cursor
    445  static bool CursorSettingManagerHasLockedCursor();
    446 
    447  static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
    448 
    449  // Sets aNewESM to be the active event state manager, and
    450  // if aContent is non-null, marks the object as active.
    451  static void SetActiveManager(EventStateManager* aNewESM,
    452                               nsIContent* aContent);
    453 
    454  static bool IsRemoteTarget(nsIContent* target);
    455 
    456  static bool IsTopLevelRemoteTarget(nsIContent* aTarget);
    457 
    458  // Returns the kind of APZ action the given WidgetWheelEvent will perform.
    459  static Maybe<layers::APZWheelAction> APZWheelActionFor(
    460      const WidgetWheelEvent* aEvent);
    461 
    462  // For some kinds of scrollings, the delta values of WidgetWheelEvent are
    463  // possbile to be adjusted. This function is used to detect such scrollings
    464  // and returns a wheel delta adjustment strategy to use, which is corresponded
    465  // to the kind of the scrolling.
    466  // It returns WheelDeltaAdjustmentStrategy::eAutoDir if the current default
    467  // action is auto-dir scrolling which honours the scrolling target(The
    468  // comments in WheelDeltaAdjustmentStrategy describes the concept in detail).
    469  // It returns WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour if the
    470  // current action is auto-dir scrolling which honours the root element in the
    471  // document where the scrolling target is(The comments in
    472  // WheelDeltaAdjustmentStrategy describes the concept in detail).
    473  // It returns WheelDeltaAdjustmentStrategy::eHorizontalize if the current
    474  // default action is horizontalized scrolling.
    475  // It returns WheelDeltaAdjustmentStrategy::eNone to mean no delta adjustment
    476  // strategy should be used if the scrolling is just a tranditional scrolling
    477  // whose delta values are never possible to be adjusted.
    478  static WheelDeltaAdjustmentStrategy GetWheelDeltaAdjustmentStrategy(
    479      const WidgetWheelEvent& aEvent);
    480 
    481  // Returns user-set multipliers for a wheel event.
    482  static void GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent,
    483                                        double* aOutMultiplierX,
    484                                        double* aOutMultiplierY);
    485 
    486  // Holds the point in screen coords that a mouse event was dispatched to,
    487  // before we went into pointer lock mode. This is constantly updated while
    488  // the pointer is not locked, but we don't update it while the pointer is
    489  // locked. This is used by dom::Event::GetScreenCoords() to make mouse
    490  // events' screen coord appear frozen at the last mouse position while
    491  // the pointer is locked.
    492  static CSSIntPoint sLastScreenPoint;
    493 
    494  // Holds the point in client coords of the last mouse event. Used by
    495  // dom::Event::GetClientCoords() to make mouse events' client coords appear
    496  // frozen at the last mouse position while the pointer is locked.
    497  static CSSIntPoint sLastClientPoint;
    498 
    499  /**
    500   * If the absolute values of mMultiplierX and/or mMultiplierY are equal or
    501   * larger than this value, the computed scroll amount isn't rounded down to
    502   * the page width or height.
    503   */
    504  static constexpr double MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL =
    505      1000.0;
    506 
    507  /**
    508   * HandleMiddleClickPaste() handles middle mouse button event as pasting
    509   * clipboard text.  Note that if aEditorBase is nullptr, this only
    510   * dispatches ePaste event because it's necessary for some web apps which
    511   * want to implement their own editor and supports middle click paste.
    512   *
    513   * @param aPresShell              The PresShell for the ESM.  This lifetime
    514   *                                should be guaranteed by the caller.
    515   * @param aMouseEvent             The ePointerClick event which caused the
    516   *                                paste.
    517   * @param aStatus                 The event status of aMouseEvent.
    518   * @param aEditorBase             EditorBase which may be pasted the
    519   *                                clipboard text by the middle click.
    520   *                                If there is no editor for aMouseEvent,
    521   *                                set nullptr.
    522   */
    523  MOZ_CAN_RUN_SCRIPT
    524  nsresult HandleMiddleClickPaste(PresShell* aPresShell,
    525                                  WidgetMouseEvent* aMouseEvent,
    526                                  nsEventStatus* aStatus,
    527                                  EditorBase* aEditorBase);
    528 
    529  static void ConsumeInteractionData(
    530      dom::Record<nsString, dom::InteractionData>& aInteractions);
    531 
    532  // Stop tracking a possible drag. If aClearInChildProcesses is true, send
    533  // a notification to any child processes that are in the drag service that
    534  // tried to start a drag.
    535  void StopTrackingDragGesture(bool aClearInChildProcesses);
    536 
    537  /**
    538   * Return the last "mouseover" (or next "mouseout"), the last deepest
    539   * "mouseenter" (or next deepest "mouseleave") targets.
    540   */
    541  const OverOutElementsWrapper* GetExtantMouseBoundaryEventTarget() const {
    542    return mMouseEnterLeaveHelper;
    543  }
    544 
    545  nsIContent* GetTrackingDragGestureContent() const {
    546    return mGestureDownContent;
    547  }
    548 
    549  // Update the tracked gesture content to the parent of its frame when it's
    550  // removed, so that the gesture can be continued.
    551  void NotifyContentWillBeRemovedForGesture(nsIContent& aContent);
    552 
    553  bool IsTrackingDragGesture() const { return mGestureDownContent != nullptr; }
    554 
    555 protected:
    556  /*
    557   * If aTargetFrame's widget has a cached cursor value, resets the cursor
    558   * such that the next call to SetCursor on the widget will force an update
    559   * of the native cursor. For use in getting puppet widget to update its
    560   * cursor between mouse exit / enter transitions. This call basically wraps
    561   * nsIWidget ClearCachedCursor.
    562   */
    563  void ClearCachedWidgetCursor(nsIFrame* aTargetFrame);
    564 
    565  void UpdateCursor(nsPresContext*, WidgetMouseEvent*, nsIFrame* aTargetFrame,
    566                    nsEventStatus* aStatus);
    567  /**
    568   * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the
    569   * specified content.
    570   *
    571   * @return widget which is the nearest widget from the event target frame.
    572   */
    573  [[nodiscard]] MOZ_CAN_RUN_SCRIPT already_AddRefed<nsIWidget>
    574  DispatchMouseOrPointerBoundaryEvent(WidgetMouseEvent* aMouseEvent,
    575                                      EventMessage aMessage,
    576                                      nsIContent* aTargetContent,
    577                                      nsIContent* aRelatedContent);
    578  /**
    579   * Synthesize DOM pointerover and pointerout events
    580   */
    581  void GeneratePointerEnterExit(EventMessage aMessage,
    582                                WidgetMouseEvent* aEvent);
    583  /**
    584   * Synthesize DOM and frame mouseover and mouseout events from this
    585   * MOUSE_MOVE or MOUSE_EXIT event.
    586   */
    587  void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent);
    588  /**
    589   * Tell this ESM and ESMs in parent documents that the mouse is
    590   * over some content in this document.
    591   */
    592  MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOver(
    593      WidgetMouseEvent* aMouseEvent, nsIContent* aContent);
    594  /**
    595   * Tell this ESM and ESMs in affected child documents that the mouse
    596   * has exited this document's currently hovered content.
    597   * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
    598   *
    599   * @param aMouseEvent the event that triggered the mouseout
    600   * @param aMovingInto the content node we've moved into.  This is used to set
    601   *        the relatedTarget for mouseout events.  Also, if it's non-null
    602   *        NotifyMouseOut will NOT change the current hover content to null;
    603   *        in that case the caller is responsible for updating hover state.
    604   */
    605  MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
    606                                                  nsIContent* aMovingInto);
    607  MOZ_CAN_RUN_SCRIPT void GenerateDragDropEnterExit(
    608      nsPresContext* aPresContext, WidgetDragEvent* aDragEvent);
    609 
    610  /**
    611   * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper
    612   * elements wrapper. If mPointersEnterLeaveHelper does not contain wrapper for
    613   * pointerId it create new one
    614   */
    615  OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent);
    616 
    617  /**
    618   * Fire the dragenter and dragexit/dragleave events when the mouse moves to a
    619   * new target.
    620   *
    621   * @param aRelatedTarget relatedTarget to set for the event
    622   * @param aTargetContent target to set for the event
    623   * @param aTargetFrame target frame for the event
    624   */
    625  MOZ_CAN_RUN_SCRIPT void FireDragEnterOrExit(nsPresContext* aPresContext,
    626                                              WidgetDragEvent* aDragEvent,
    627                                              EventMessage aMessage,
    628                                              nsIContent* aRelatedTarget,
    629                                              nsIContent* aTargetContent,
    630                                              AutoWeakFrame& aTargetFrame);
    631  /**
    632   * Update the initial drag session data transfer with any changes that occur
    633   * on cloned data transfer objects used for events.
    634   */
    635  void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
    636 
    637  /**
    638   * InitAndDispatchClickEvent() dispatches a click event.
    639   *
    640   * @param aMouseUpEvent           eMouseUp event which causes the click event.
    641   *                                EventCausesClickEvents() must return true
    642   *                                if this event is set to it.
    643   * @param aStatus                 Returns the result of click event.
    644   *                                If the status indicates consumed, the
    645   *                                value won't be overwritten with
    646   *                                nsEventStatus_eIgnore.
    647   * @param aMessage                Should be ePointerClick, eMouseDoubleClick
    648   *                                or ePointerAuxClick.
    649   * @param aPresShell              The PresShell.
    650   * @param aMouseUpContent         The event target of aMouseUpEvent.
    651   * @param aCurrentTarget          Current target of the caller.
    652   * @param aNoContentDispatch      true if the event shouldn't be exposed to
    653   *                                web contents (although will be fired on
    654   *                                document and window).
    655   * @param aOverrideClickTarget    Preferred click event target.  If this is
    656   *                                not nullptr, aMouseUpContent and
    657   *                                aCurrentTarget are ignored.
    658   */
    659  MOZ_CAN_RUN_SCRIPT
    660  static nsresult InitAndDispatchClickEvent(
    661      WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
    662      EventMessage aMessage, PresShell* aPresShell, nsIContent* aMouseUpContent,
    663      AutoWeakFrame aCurrentTarget, bool aNoContentDispatch,
    664      nsIContent* aOverrideClickTarget);
    665 
    666  /**
    667   * Prepare aEvent and corresponding LastMouseDownInfo for dispatching
    668   * ePointerClick, ePointerAuxClick or eContextMenu later.
    669   */
    670  void PrepareForFollowingClickEvent(
    671      WidgetMouseEvent& aEvent, nsIContent* aOverrideClickTarget = nullptr);
    672 
    673  /**
    674   * EventCausesClickEvents() returns true when aMouseEvent is an eMouseUp
    675   * event and it should cause ePointerClick, eMouseDoubleClick and/or
    676   * ePointerAuxClick events.  Note that this method assumes that
    677   * aMouseEvent.mClickCount has already been initialized with SetClickCount().
    678   */
    679  static bool EventCausesClickEvents(const WidgetMouseEvent& aMouseEvent);
    680 
    681  /**
    682   * PostHandleMouseUp() handles default actions of eMouseUp event.
    683   *
    684   * @param aMouseUpEvent           eMouseUp event which causes the click event.
    685   *                                EventCausesClickEvents() must return true
    686   *                                if this event is set to it.
    687   * @param aStatus                 Returns the result of event status.
    688   *                                If one of dispatching event is consumed or
    689   *                                this does something as default action,
    690   *                                returns nsEventStatus_eConsumeNoDefault.
    691   * @param aOverrideClickTarget    Preferred click event target.  If nullptr,
    692   *                                aMouseUpEvent target and current target
    693   *                                are used.
    694   */
    695  MOZ_CAN_RUN_SCRIPT
    696  nsresult PostHandleMouseUp(WidgetMouseEvent* aMouseUpEvent,
    697                             nsEventStatus* aStatus,
    698                             nsIContent* aOverrideClickTarget);
    699 
    700  /**
    701   * DispatchClickEvents() dispatches ePointerClick, eMouseDoubleClick and
    702   * ePointerAuxClick events for aMouseUpEvent.  aMouseUpEvent should cause
    703   * click event.
    704   *
    705   * @param aPresShell              The PresShell.
    706   * @param aMouseUpEvent           eMouseUp event which causes the click event.
    707   *                                EventCausesClickEvents() must return true
    708   *                                if this event is set to it.
    709   * @param aStatus                 Returns the result of event status.
    710   *                                If one of dispatching click event is
    711   *                                consumed, returns
    712   *                                nsEventStatus_eConsumeNoDefault.
    713   * @param aMouseUpContent         The event target of aMouseUpEvent.
    714   * @param aOverrideClickTarget    Preferred click event target.  If this is
    715   *                                not nullptr, aMouseUpContent and
    716   *                                current target frame of the ESM are ignored.
    717   */
    718  MOZ_CAN_RUN_SCRIPT
    719  nsresult DispatchClickEvents(PresShell* aPresShell,
    720                               WidgetMouseEvent* aMouseUpEvent,
    721                               nsEventStatus* aStatus,
    722                               nsIContent* aMouseUpContent,
    723                               nsIContent* aOverrideClickTarget);
    724 
    725  void EnsureDocument(nsPresContext* aPresContext);
    726  MOZ_CAN_RUN_SCRIPT_BOUNDARY
    727  void FlushLayout(nsPresContext* aPresContext);
    728 
    729  /**
    730   * The phases of WalkESMTreeToHandleAccessKey processing. See below.
    731   */
    732  enum ProcessingAccessKeyState {
    733    eAccessKeyProcessingNormal = 0,
    734    eAccessKeyProcessingUp,
    735    eAccessKeyProcessingDown
    736  };
    737 
    738  /**
    739   * Walk EMS to look for access key and execute found access key when aExecute
    740   * is true.
    741   * If there is registered element for the accesskey given by the key event
    742   * and modifier mask then call element.PerformAccesskey(), otherwise call
    743   * WalkESMTreeToHandleAccessKey() recursively, on descendant docshells first,
    744   * then on the ancestor (with |aBubbledFrom| set to the docshell associated
    745   * with |this|), until something matches.
    746   *
    747   * @param aEvent the keyboard event triggering the acccess key
    748   * @param aPresContext the presentation context
    749   * @param aAccessCharCodes list of charcode candidates
    750   * @param aBubbledFrom is used by an ancestor to avoid calling
    751   *        WalkESMTreeToHandleAccessKey() on the child the call originally
    752   *        came from, i.e. this is the child that recursively called us in
    753   *        its Up phase. The initial caller passes |nullptr| here. This is to
    754   *        avoid an infinite loop.
    755   * @param aAccessKeyState Normal, Down or Up processing phase (see enums
    756   *        above). The initial event receiver uses 'normal', then 'down' when
    757   *        processing children and Up when recursively calling its ancestor.
    758   * @param aExecute is true, execute an accesskey if it's found.  Otherwise,
    759   *        found accesskey won't be executed.
    760   *
    761   * @return            true if there is a target which aEvent and
    762   *                    aAccessCharCodes match with in this process.
    763   *                    Otherwise, false.  I.e., when this returns true and
    764   *                    aExecute is true, a target is executed or focused.
    765   *                    Note that even if this returns false, a target in
    766   *                    remote process may be executed or focused
    767   *                    asynchronously.
    768   */
    769  bool WalkESMTreeToHandleAccessKey(WidgetKeyboardEvent* aEvent,
    770                                    nsPresContext* aPresContext,
    771                                    nsTArray<uint32_t>& aAccessCharCodes,
    772                                    nsIDocShellTreeItem* aBubbledFrom,
    773                                    ProcessingAccessKeyState aAccessKeyState,
    774                                    bool aExecute);
    775 
    776  /**
    777   * Look for access key and execute found access key if aExecute is true in
    778   * the instance.
    779   *
    780   * @return            true if there is a target which matches with
    781   *                    aAccessCharCodes and aIsTrustedEvent.  Otherwise,
    782   *                    false.  I.e., when this returns true and aExecute
    783   *                    is true, a target is executed or focused.
    784   */
    785  MOZ_CAN_RUN_SCRIPT_BOUNDARY bool LookForAccessKeyAndExecute(
    786      nsTArray<uint32_t>& aAccessCharCodes, bool aIsTrustedEvent,
    787      bool aIsRepeat, bool aExecute);
    788 
    789  //---------------------------------------------
    790  // DocShell Focus Traversal Methods
    791  //---------------------------------------------
    792 
    793  dom::Element* GetFocusedElement();
    794  bool IsShellVisible(nsIDocShell* aShell);
    795 
    796  // These functions are for mousewheel and pixel scrolling
    797 
    798  class WheelPrefs {
    799   public:
    800    static WheelPrefs* GetInstance();
    801    static void Shutdown();
    802 
    803    /**
    804     * ApplyUserPrefsToDelta() overrides the wheel event's delta values with
    805     * user prefs.
    806     */
    807    void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent);
    808 
    809    /**
    810     * Returns whether or not ApplyUserPrefsToDelta() would change the delta
    811     * values of an event.
    812     */
    813    void GetUserPrefsForEvent(const WidgetWheelEvent* aEvent,
    814                              double* aOutMultiplierX, double* aOutMultiplierY);
    815 
    816    /**
    817     * If ApplyUserPrefsToDelta() changed the delta values with customized
    818     * prefs, the overflowDelta values would be inflated.
    819     * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
    820     */
    821    void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent);
    822 
    823    /**
    824     * Computes the default action for the aEvent with the prefs.
    825     */
    826    enum Action : uint8_t {
    827      ACTION_NONE = 0,
    828      ACTION_SCROLL,
    829      ACTION_HISTORY,
    830      ACTION_ZOOM,
    831      // Horizontalized scrolling means treating vertical wheel scrolling as
    832      // horizontal scrolling during the process of its default action and
    833      // plugins handling scrolling. Note that delta values as the event object
    834      // in a DOM event listener won't be affected, and will be still the
    835      // original values. For more details, refer to
    836      // mozilla::WheelDeltaAdjustmentStrategy::eHorizontalize
    837      ACTION_HORIZONTALIZED_SCROLL,
    838      ACTION_PINCH_ZOOM,
    839      ACTION_LAST = ACTION_PINCH_ZOOM,
    840      // Following actions are used only by internal processing.  So, cannot
    841      // specified by prefs.
    842      ACTION_SEND_TO_PLUGIN,
    843    };
    844    Action ComputeActionFor(const WidgetWheelEvent* aEvent);
    845 
    846    /**
    847     * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
    848     * computed the lineOrPageDelta values.
    849     */
    850    bool NeedToComputeLineOrPageDelta(const WidgetWheelEvent* aEvent);
    851 
    852    /**
    853     * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
    854     * be rounded down to the page width/height (false) or not (true).
    855     */
    856    bool IsOverOnePageScrollAllowedX(const WidgetWheelEvent* aEvent);
    857    bool IsOverOnePageScrollAllowedY(const WidgetWheelEvent* aEvent);
    858 
    859   private:
    860    WheelPrefs();
    861    ~WheelPrefs();
    862 
    863    static void OnPrefChanged(const char* aPrefName, void* aClosure);
    864 
    865    enum Index {
    866      INDEX_DEFAULT = 0,
    867      INDEX_ALT,
    868      INDEX_CONTROL,
    869      INDEX_META,
    870      INDEX_SHIFT,
    871      COUNT_OF_MULTIPLIERS
    872    };
    873 
    874    /**
    875     * GetIndexFor() returns the index of the members which should be used for
    876     * the aEvent.  When only one modifier key of MODIFIER_ALT,
    877     * MODIFIER_CONTROL, MODIFIER_META or MODIFIER_SHIFT is pressed, returns the
    878     * index for the modifier.  Otherwise, this return the default index which
    879     * is used at either no modifier key is pressed or two or modifier keys are
    880     * pressed.
    881     */
    882    Index GetIndexFor(const WidgetWheelEvent* aEvent);
    883 
    884    /**
    885     * GetPrefNameBase() returns the base pref name for aEvent.
    886     * It's decided by GetModifierForPref() which modifier should be used for
    887     * the aEvent.
    888     *
    889     * @param aBasePrefName The result, must be "mousewheel.with_*." or
    890     *                      "mousewheel.default.".
    891     */
    892    void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
    893 
    894    void Init(Index aIndex);
    895 
    896    void Reset();
    897 
    898    /**
    899     * Retrieve multiplier for aEvent->mDeltaX and aEvent->mDeltaY.
    900     *
    901     * Note that if the default action is ACTION_HORIZONTALIZED_SCROLL and the
    902     * delta values have been adjusted by WheelDeltaHorizontalizer() before this
    903     * function is called, this function will swap the X and Y multipliers. By
    904     * doing this, multipliers will still apply to the delta values they
    905     * originally corresponded to.
    906     *
    907     * @param aEvent    The event which is being handled.
    908     * @param aIndex    The index of mMultiplierX and mMultiplierY.
    909     *                  Should be result of GetIndexFor(aEvent).
    910     * @param aMultiplierForDeltaX      Will be set to multiplier for
    911     *                                  aEvent->mDeltaX.
    912     * @param aMultiplierForDeltaY      Will be set to multiplier for
    913     *                                  aEvent->mDeltaY.
    914     */
    915    void GetMultiplierForDeltaXAndY(const WidgetWheelEvent* aEvent,
    916                                    Index aIndex, double* aMultiplierForDeltaX,
    917                                    double* aMultiplierForDeltaY);
    918 
    919    bool mInit[COUNT_OF_MULTIPLIERS];
    920    double mMultiplierX[COUNT_OF_MULTIPLIERS];
    921    double mMultiplierY[COUNT_OF_MULTIPLIERS];
    922    double mMultiplierZ[COUNT_OF_MULTIPLIERS];
    923    Action mActions[COUNT_OF_MULTIPLIERS];
    924    /**
    925     * action values overridden by .override_x pref.
    926     * If an .override_x value is -1, same as the
    927     * corresponding mActions value.
    928     */
    929    Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS];
    930 
    931    static WheelPrefs* sInstance;
    932  };
    933 
    934  /**
    935   * DeltaDirection is used for specifying whether the called method should
    936   * handle vertical delta or horizontal delta.
    937   * This is clearer than using bool.
    938   */
    939  enum DeltaDirection { DELTA_DIRECTION_X = 0, DELTA_DIRECTION_Y };
    940 
    941  struct MOZ_STACK_CLASS EventState {
    942    bool mDefaultPrevented;
    943    bool mDefaultPreventedByContent;
    944 
    945    EventState()
    946        : mDefaultPrevented(false), mDefaultPreventedByContent(false) {}
    947  };
    948 
    949  /**
    950   * SendLineScrollEvent() dispatches a DOMMouseScroll event for the
    951   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
    952   * wheel event because it's not necessary for compatiblity.
    953   *
    954   * @param aTargetFrame        The event target of wheel event.
    955   * @param aEvent              The original Wheel event.
    956   * @param aState              The event which should be set to the dispatching
    957   *                            event.  This also returns the dispatched event
    958   *                            state.
    959   * @param aDelta              The delta value of the event.
    960   * @param aDeltaDirection     The X/Y direction of dispatching event.
    961   */
    962  MOZ_CAN_RUN_SCRIPT void SendLineScrollEvent(nsIFrame* aTargetFrame,
    963                                              WidgetWheelEvent* aEvent,
    964                                              EventState& aState,
    965                                              int32_t aDelta,
    966                                              DeltaDirection aDeltaDirection);
    967 
    968  /**
    969   * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
    970   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
    971   * wheel event because it's not necessary for compatiblity.
    972   *
    973   * @param aTargetFrame        The event target of wheel event.
    974   * @param aEvent              The original Wheel event.
    975   * @param aState              The event which should be set to the dispatching
    976   *                            event.  This also returns the dispatched event
    977   *                            state.
    978   * @param aPixelDelta         The delta value of the event.
    979   * @param aDeltaDirection     The X/Y direction of dispatching event.
    980   */
    981  MOZ_CAN_RUN_SCRIPT void SendPixelScrollEvent(nsIFrame* aTargetFrame,
    982                                               WidgetWheelEvent* aEvent,
    983                                               EventState& aState,
    984                                               int32_t aPixelDelta,
    985                                               DeltaDirection aDeltaDirection);
    986 
    987  /**
    988   * ComputeScrollTargetAndMayAdjustWheelEvent() returns the scrollable frame
    989   * which should be scrolled.
    990   *
    991   * @param aTargetFrame        The event target of the wheel event.
    992   * @param aEvent              The handling mouse wheel event.
    993   * @param aOptions            The options for finding the scroll target.
    994   *                            Callers should use COMPUTE_*.
    995   * @return                    The scrollable frame which should be scrolled.
    996   */
    997  // These flags are used in ComputeScrollTargetAndMayAdjustWheelEvent().
    998  // Callers should use COMPUTE_*.
    999  enum {
   1000    PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001,
   1001    PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002,
   1002    PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004,
   1003    START_FROM_PARENT = 0x00000008,
   1004    INCLUDE_PLUGIN_AS_TARGET = 0x00000010,
   1005    // Indicates the wheel scroll event being computed is an auto-dir scroll, so
   1006    // its delta may be adjusted after being computed.
   1007    MAY_BE_ADJUSTED_BY_AUTO_DIR = 0x00000020,
   1008  };
   1009  enum ComputeScrollTargetOptions {
   1010    // At computing scroll target for legacy mouse events, we should return
   1011    // first scrollable element even when it's not scrollable to the direction.
   1012    COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0,
   1013    // Default action prefers the scrolled element immediately before if it's
   1014    // still under the mouse cursor.  Otherwise, it prefers the nearest
   1015    // scrollable ancestor which will be scrolled actually.
   1016    COMPUTE_DEFAULT_ACTION_TARGET =
   1017        (PREFER_MOUSE_WHEEL_TRANSACTION |
   1018         PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
   1019         PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
   1020    // Compute the default action target without considering the current wheel
   1021    // transaction.
   1022    COMPUTE_DEFAULT_ACTION_TARGET_WITHOUT_WHEEL_TRANSACTION =
   1023        (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
   1024         PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
   1025    COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR =
   1026        (COMPUTE_DEFAULT_ACTION_TARGET | MAY_BE_ADJUSTED_BY_AUTO_DIR),
   1027    // Look for the nearest scrollable ancestor which can be scrollable with
   1028    // aEvent.
   1029    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS =
   1030        (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
   1031    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS =
   1032        (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT),
   1033    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR =
   1034        (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS |
   1035         MAY_BE_ADJUSTED_BY_AUTO_DIR),
   1036    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR =
   1037        (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS |
   1038         MAY_BE_ADJUSTED_BY_AUTO_DIR),
   1039  };
   1040 
   1041  // Compute the scroll target.
   1042  // The delta values in the wheel event may be changed if the event is for
   1043  // auto-dir scrolling. For information on auto-dir,
   1044  // @see mozilla::WheelDeltaAdjustmentStrategy
   1045  ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
   1046      nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
   1047      ComputeScrollTargetOptions aOptions);
   1048 
   1049  ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
   1050      nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
   1051      WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions);
   1052 
   1053  ScrollContainerFrame* ComputeScrollTarget(
   1054      nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
   1055      ComputeScrollTargetOptions aOptions) {
   1056    MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
   1057               "aEvent may be modified by auto-dir");
   1058    return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, aEvent,
   1059                                                     aOptions);
   1060  }
   1061 
   1062  ScrollContainerFrame* ComputeScrollTarget(
   1063      nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
   1064      WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions) {
   1065    MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
   1066               "aEvent may be modified by auto-dir");
   1067    return ComputeScrollTargetAndMayAdjustWheelEvent(
   1068        aTargetFrame, aDirectionX, aDirectionY, aEvent, aOptions);
   1069  }
   1070 
   1071  /**
   1072   * GetScrollAmount() returns the scroll amount in app uints of one line or
   1073   * one page.  If the wheel event scrolls a page, returns the page width and
   1074   * height.  Otherwise, returns line height for both its width and height.
   1075   *
   1076   * @param aScrollContainerFrame A frame which will be scrolled by the event.
   1077   *                              The result of
   1078   *                              ComputeScrollTargetAndMayAdjustWheelEvent() is
   1079   *                              expected for this value.
   1080   *                              This can be nullptr if there is no scrollable
   1081   *                              frame.  Then, this method uses root frame's
   1082   *                              line height or visible area's width and
   1083   *                              height.
   1084   */
   1085  nsSize GetScrollAmount(nsPresContext* aPresContext, WidgetWheelEvent* aEvent,
   1086                         ScrollContainerFrame* aScrollContainerFrame);
   1087 
   1088  /**
   1089   * DoScrollText() scrolls the scroll container frame for aEvent.
   1090   */
   1091  void DoScrollText(ScrollContainerFrame* aScrollContainerFrame,
   1092                    WidgetWheelEvent* aEvent);
   1093 
   1094  MOZ_CAN_RUN_SCRIPT
   1095  void DoScrollHistory(int32_t direction);
   1096  void DoScrollZoom(nsIFrame* aTargetFrame, int32_t adjustment);
   1097  void ChangeZoom(bool aIncrease);
   1098 
   1099  /**
   1100   * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
   1101   * event.  If wheel events are caused by pixel scroll only devices or
   1102   * the delta values are customized by prefs, this class stores the delta
   1103   * values and set lineOrPageDelta values.
   1104   */
   1105  class DeltaAccumulator {
   1106   public:
   1107    static DeltaAccumulator* GetInstance() {
   1108      if (!sInstance) {
   1109        sInstance = new DeltaAccumulator;
   1110      }
   1111      return sInstance;
   1112    }
   1113 
   1114    static void Shutdown() {
   1115      delete sInstance;
   1116      sInstance = nullptr;
   1117    }
   1118 
   1119    bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; }
   1120 
   1121    /**
   1122     * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents
   1123     * which are caused if it's needed.  And if the accumulated delta becomes a
   1124     * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
   1125     */
   1126    void InitLineOrPageDelta(nsIFrame* aTargetFrame, EventStateManager* aESM,
   1127                             WidgetWheelEvent* aEvent);
   1128 
   1129    /**
   1130     * Reset() resets all members.
   1131     */
   1132    void Reset();
   1133 
   1134    /**
   1135     * ComputeScrollAmountForDefaultAction() computes the default action's
   1136     * scroll amount in device pixels with mPendingScrollAmount*.
   1137     */
   1138    nsIntPoint ComputeScrollAmountForDefaultAction(
   1139        WidgetWheelEvent* aEvent, const nsIntSize& aScrollAmountInDevPixels);
   1140 
   1141   private:
   1142    DeltaAccumulator()
   1143        : mX(0.0),
   1144          mY(0.0),
   1145          mPendingScrollAmountX(0.0),
   1146          mPendingScrollAmountY(0.0),
   1147          mHandlingDeltaMode(UINT32_MAX),
   1148          mIsNoLineOrPageDeltaDevice(false) {}
   1149 
   1150    double mX;
   1151    double mY;
   1152 
   1153    // When default action of a wheel event is scroll but some delta values
   1154    // are ignored because the computed amount values are not integer, the
   1155    // fractional values are saved by these members.
   1156    double mPendingScrollAmountX;
   1157    double mPendingScrollAmountY;
   1158 
   1159    TimeStamp mLastTime;
   1160 
   1161    uint32_t mHandlingDeltaMode;
   1162    bool mIsNoLineOrPageDeltaDevice;
   1163 
   1164    static DeltaAccumulator* sInstance;
   1165  };
   1166 
   1167  // end mousewheel functions
   1168 
   1169  /*
   1170   * When a touch gesture is about to start, this function determines what
   1171   * kind of gesture interaction we will want to use, based on what is
   1172   * underneath the initial touch point.
   1173   * Currently it decides between panning (finger scrolling) or dragging
   1174   * the target element, as well as the orientation to trigger panning and
   1175   * display visual boundary feedback. The decision is stored back in aEvent.
   1176   */
   1177  void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
   1178                          nsIFrame* targetFrame);
   1179 
   1180  // routines for the d&d gesture tracking state machine
   1181  void BeginTrackingDragGesture(nsPresContext* aPresContext,
   1182                                WidgetMouseEvent* aDownEvent,
   1183                                nsIFrame* aDownFrame);
   1184 
   1185  void SetGestureDownPoint(WidgetGUIEvent* aEvent);
   1186 
   1187  LayoutDeviceIntPoint GetEventRefPoint(WidgetEvent* aEvent) const;
   1188 
   1189  friend class mozilla::dom::BrowserParent;
   1190  void BeginTrackingRemoteDragGesture(nsIContent* aContent,
   1191                                      dom::RemoteDragStartData* aDragStartData);
   1192 
   1193  MOZ_CAN_RUN_SCRIPT
   1194  void GenerateDragGesture(nsPresContext* aPresContext,
   1195                           WidgetInputEvent* aEvent);
   1196 
   1197  /**
   1198   * Try to dispatch ePointerCancel for aSourceEvent to aTargetContent.
   1199   */
   1200  MOZ_CAN_RUN_SCRIPT void MaybeDispatchPointerCancel(
   1201      const WidgetInputEvent& aSourceEvent, nsIContent& aTargetContent);
   1202 
   1203  /**
   1204   * Determine which node the drag should be targeted at.
   1205   * This is either the node clicked when there is a selection, or, for HTML,
   1206   * the element with a draggable property set to true.
   1207   *
   1208   * aSelectionTarget - target to check for selection
   1209   * aDataTransfer - data transfer object that will contain the data to drag
   1210   * aAllowEmptyDataTransfer - [out] set to true, if dnd operation can be
   1211   *                           started even if DataTransfer is empty
   1212   * aSelection - [out] set to the selection to be dragged
   1213   * aTargetNode - [out] the draggable node, or null if there isn't one
   1214   * aPrincipal - [out] set to the triggering principal of the drag, or null
   1215   *                    if it's from browser chrome or OS
   1216   * aCookieJarSettings - [out] set to the cookieJarSettings of the drag, or
   1217   *                            null if it's from browser chrome or OS.
   1218   */
   1219  void DetermineDragTargetAndDefaultData(
   1220      nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
   1221      dom::DataTransfer* aDataTransfer, bool* aAllowEmptyDataTransfer,
   1222      dom::Selection** aSelection,
   1223      dom::RemoteDragStartData** aRemoteDragStartData, nsIContent** aTargetNode,
   1224      nsIPrincipal** aPrincipal, nsIPolicyContainer** aPolicyContainer,
   1225      nsICookieJarSettings** aCookieJarSettings);
   1226 
   1227  /*
   1228   * Perform the default handling for the dragstart event and set up a
   1229   * drag for aDataTransfer if it contains any data. Returns true if a drag has
   1230   * started.
   1231   *
   1232   * aDragEvent - the dragstart event
   1233   * aDataTransfer - the data transfer that holds the data to be dragged
   1234   * aAllowEmptyDataTransfer - if true, dnd can be started even if there is no
   1235   *                           data to drag
   1236   * aDragTarget - the target of the drag
   1237   * aSelection - the selection to be dragged
   1238   * aData - information pertaining to a drag started in a child process
   1239   * aPrincipal - the triggering principal of the drag, or null if it's from
   1240   *              browser chrome or OS
   1241   * aCookieJarSettings - the cookieJarSettings of the drag. or null if it's
   1242   *                      from browser chrome or OS.
   1243   */
   1244  MOZ_CAN_RUN_SCRIPT
   1245  bool DoDefaultDragStart(nsPresContext* aPresContext,
   1246                          WidgetDragEvent* aDragEvent,
   1247                          dom::DataTransfer* aDataTransfer,
   1248                          bool aAllowEmptyDataTransfer, nsIContent* aDragTarget,
   1249                          dom::Selection* aSelection,
   1250                          dom::RemoteDragStartData* aDragStartData,
   1251                          nsIPrincipal* aPrincipal,
   1252                          nsIPolicyContainer* aPolicyContainer,
   1253                          nsICookieJarSettings* aCookieJarSettings);
   1254 
   1255  /**
   1256   * Set the fields of aEvent to reflect the mouse position and modifier keys
   1257   * that were set when the user first pressed the mouse button (stored by
   1258   * BeginTrackingDragGesture). aEvent->mWidget must be
   1259   * mCurrentTarget->GetNearestWidget().
   1260   */
   1261  void FillInEventFromGestureDown(WidgetMouseEvent* aEvent);
   1262 
   1263  MOZ_CAN_RUN_SCRIPT
   1264  nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent);
   1265  MOZ_CAN_RUN_SCRIPT
   1266  nsresult DoContentCommandInsertTextEvent(WidgetContentCommandEvent* aEvent);
   1267  MOZ_CAN_RUN_SCRIPT
   1268  nsresult DoContentCommandReplaceTextEvent(WidgetContentCommandEvent* aEvent);
   1269  nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent);
   1270 
   1271  dom::BrowserParent* GetCrossProcessTarget();
   1272  bool IsTargetCrossProcess(WidgetGUIEvent* aEvent);
   1273 
   1274  /**
   1275   * DispatchCrossProcessEvent() try to post aEvent to target remote process.
   1276   * If you need to check if the event is posted to a remote process, you
   1277   * can use aEvent->HasBeenPostedToRemoteProcess().
   1278   */
   1279  void DispatchCrossProcessEvent(WidgetEvent* aEvent,
   1280                                 dom::BrowserParent* aRemoteTarget,
   1281                                 nsEventStatus* aStatus);
   1282  /**
   1283   * HandleCrossProcessEvent() may post aEvent to target remote processes.
   1284   * When it succeeded to post the event to at least one remote process,
   1285   * returns true.  Otherwise, including the case not tried to dispatch to
   1286   * post the event, returns false.
   1287   * If you need to check if the event is posted to at least one remote
   1288   * process, you can use aEvent->HasBeenPostedToRemoteProcess().
   1289   */
   1290  bool HandleCrossProcessEvent(WidgetEvent* aEvent, nsEventStatus* aStatus);
   1291 
   1292  void ReleaseCurrentIMEContentObserver();
   1293 
   1294  MOZ_CAN_RUN_SCRIPT void HandleQueryContentEvent(
   1295      WidgetQueryContentEvent* aEvent);
   1296 
   1297 private:
   1298  // Removes a node from the :hover / :active chain if needed, notifying if the
   1299  // node is not a NAC subtree.
   1300  //
   1301  // Only meant to be called from ContentRemoved and
   1302  // NativeAnonymousContentRemoved.
   1303  void RemoveNodeFromChainIfNeeded(ElementState aState,
   1304                                   nsIContent* aContentRemoved, bool aNotify);
   1305 
   1306  bool IsEventOutsideDragThreshold(WidgetInputEvent* aEvent) const;
   1307 
   1308  static inline void DoStateChange(dom::Element* aElement, ElementState aState,
   1309                                   bool aAddState);
   1310  static inline void DoStateChange(nsIContent* aContent, ElementState aState,
   1311                                   bool aAddState);
   1312  static void UpdateAncestorState(nsIContent* aStartNode,
   1313                                  nsIContent* aStopBefore, ElementState aState,
   1314                                  bool aAddState);
   1315 
   1316  /**
   1317   * Update the attribute mLastRefPoint of the mouse event. It should be
   1318   *     the center of the window while the pointer is locked.
   1319   *     the same value as mRefPoint while there is no known last ref point.
   1320   *     the same value as the last known mRefPoint.
   1321   */
   1322  static void UpdateLastRefPointOfMouseEvent(WidgetMouseEvent* aMouseEvent);
   1323 
   1324  static void ResetPointerToWindowCenterWhilePointerLocked(
   1325      WidgetMouseEvent* aMouseEvent);
   1326 
   1327  // Update the last known ref point to the current event's mRefPoint.
   1328  static void UpdateLastPointerPosition(WidgetMouseEvent* aMouseEvent);
   1329 
   1330  void UpdateGestureContent(nsIContent* aContent);
   1331 
   1332  /**
   1333   * Notify target when user has been interaction with some speicific user
   1334   * gestures which are eKeyUp, eMouseUp, eTouchEnd.
   1335   */
   1336  void NotifyTargetUserActivation(WidgetEvent* aEvent,
   1337                                  nsIContent* aTargetContent);
   1338 
   1339  /**
   1340   * https://html.spec.whatwg.org/multipage/popover.html#light-dismiss-open-popovers.
   1341   */
   1342  MOZ_CAN_RUN_SCRIPT void LightDismissOpenPopovers(WidgetEvent* aEvent,
   1343                                                   nsIContent* aTargetContent);
   1344 
   1345  /**
   1346   * https://html.spec.whatwg.org/multipage/interactive-elements.html#light-dismiss-open-dialogs
   1347   */
   1348  MOZ_CAN_RUN_SCRIPT void LightDismissOpenDialogs(WidgetEvent* aEvent,
   1349                                                  nsIContent* aTargetContent);
   1350 
   1351  already_AddRefed<EventStateManager> ESMFromContentOrThis(
   1352      nsIContent* aContent);
   1353 
   1354  struct LastMouseDownInfo {
   1355    nsCOMPtr<nsIContent> mLastMouseDownContent;
   1356    Maybe<FormControlType> mLastMouseDownInputControlType;
   1357    uint32_t mClickCount = 0;
   1358  };
   1359 
   1360  LastMouseDownInfo& GetLastMouseDownInfo(int16_t aButton);
   1361 
   1362  // These variables are only relevant if we're the cursor-setting manager.
   1363  StyleCursorKind mLockCursor;
   1364  bool mHidingCursorWhileTyping = false;
   1365 
   1366  // Last mouse event screen point (in device pixel) when mouse was locked, used
   1367  // to restore mouse position after unlocking.
   1368  static LayoutDeviceIntPoint sPreLockScreenPoint;
   1369 
   1370  // Stores the mRefPoint of the last synthetic mouse move we dispatched
   1371  // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
   1372  // means we've not recently dispatched a centering event. We use this to
   1373  // detect when we receive the synth event, so we can cancel and not send it
   1374  // to content.
   1375  static LayoutDeviceIntPoint sSynthCenteringPoint;
   1376 
   1377  WeakFrame mCurrentTarget;
   1378  nsCOMPtr<nsIContent> mCurrentTargetContent;
   1379  static AutoWeakFrame sLastDragOverFrame;
   1380 
   1381  // Stores the mRefPoint (the offset from the widget's origin in device
   1382  // pixels) of the last mouse event.
   1383  static LayoutDeviceIntPoint sLastRefPoint;
   1384  static LayoutDeviceIntPoint sLastRefPointOfRawUpdate;
   1385 
   1386  // member variables for the d&d gesture state machine
   1387  LayoutDeviceIntPoint mGestureDownPoint;  // screen coordinates
   1388  // The content to use as target if we start a d&d (what we drag).
   1389  RefPtr<nsIContent> mGestureDownContent;
   1390  // The content of the frame where the mouse-down event occurred. It's the same
   1391  // as the target in most cases but not always - for example when dragging
   1392  // an <area> of an image map this is the image. (bug 289667)
   1393  nsCOMPtr<nsIContent> mGestureDownFrameOwner;
   1394  // Data associated with a drag started in a content process.
   1395  RefPtr<dom::RemoteDragStartData> mGestureDownDragStartData;
   1396  // State of keys when the original gesture-down happened
   1397  Modifiers mGestureModifiers;
   1398  uint16_t mGestureDownButtons;
   1399  int16_t mGestureDownButton;
   1400 
   1401  LastMouseDownInfo mLastLeftMouseDownInfo;
   1402  LastMouseDownInfo mLastMiddleMouseDownInfo;
   1403  LastMouseDownInfo mLastRightMouseDownInfo;
   1404 
   1405  nsCOMPtr<nsIContent> mActiveContent;
   1406  nsCOMPtr<nsIContent> mHoverContent;
   1407  static nsCOMPtr<nsIContent> sDragOverContent;
   1408  nsCOMPtr<nsIContent> mURLTargetContent;
   1409  nsCOMPtr<nsINode> mPopoverPointerDownTarget;
   1410 
   1411  nsPresContext* mPresContext;      // Not refcnted
   1412  RefPtr<dom::Document> mDocument;  // Doesn't necessarily need to be owner
   1413 
   1414  RefPtr<IMEContentObserver> mIMEContentObserver;
   1415 
   1416  bool mShouldAlwaysUseLineDeltas : 1;
   1417  bool mShouldAlwaysUseLineDeltasInitialized : 1;
   1418 
   1419  bool mGestureDownInTextControl : 1;
   1420 
   1421  bool mInTouchDrag;
   1422 
   1423  bool m_haveShutdown;
   1424 
   1425  RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
   1426  nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper>
   1427      mPointersEnterLeaveHelper;
   1428 
   1429  // Array for accesskey support
   1430  nsCOMArray<dom::Element> mAccessKeys;
   1431 
   1432  bool ShouldAlwaysUseLineDeltas();
   1433 
   1434 public:
   1435  static nsresult UpdateUserActivityTimer(void);
   1436 
   1437  static bool sNormalLMouseEventInProcess;
   1438  static int16_t sCurrentMouseBtn;
   1439 
   1440  static EventStateManager* sActiveESM;
   1441 
   1442  static void ClearGlobalActiveContent(EventStateManager* aClearer);
   1443 
   1444  // Functions used for click hold context menus
   1445  nsCOMPtr<nsITimer> mClickHoldTimer;
   1446  void CreateClickHoldTimer(nsPresContext* aPresContext, nsIFrame* aDownFrame,
   1447                            WidgetGUIEvent* aMouseDownEvent);
   1448  void KillClickHoldTimer();
   1449  MOZ_CAN_RUN_SCRIPT_BOUNDARY void FireContextClick();
   1450 
   1451  MOZ_CAN_RUN_SCRIPT static void SetPointerLock(nsIWidget* aWidget,
   1452                                                nsPresContext* aPresContext);
   1453  static void sClickHoldCallback(nsITimer* aTimer, void* aESM);
   1454 };
   1455 
   1456 }  // namespace mozilla
   1457 
   1458 // Click and double-click events need to be handled even for content that
   1459 // has no frame. This is required for Web compatibility.
   1460 #define NS_EVENT_NEEDS_FRAME(event)          \
   1461  ((event)->mMessage != ePointerClick &&     \
   1462   (event)->mMessage != eMouseDoubleClick && \
   1463   (event)->mMessage != ePointerAuxClick)
   1464 
   1465 #endif  // mozilla_EventStateManager_h_