dom/events/EventStateManager.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/events/EventStateManager.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,924 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef mozilla_EventStateManager_h_
    1.10 +#define mozilla_EventStateManager_h_
    1.11 +
    1.12 +#include "mozilla/EventForwards.h"
    1.13 +#include "mozilla/TypedEnum.h"
    1.14 +
    1.15 +#include "nsIObserver.h"
    1.16 +#include "nsWeakReference.h"
    1.17 +#include "nsCOMPtr.h"
    1.18 +#include "nsCOMArray.h"
    1.19 +#include "nsCycleCollectionParticipant.h"
    1.20 +#include "mozilla/TimeStamp.h"
    1.21 +#include "nsIFrame.h"
    1.22 +#include "Units.h"
    1.23 +
    1.24 +class nsFrameLoader;
    1.25 +class nsIContent;
    1.26 +class nsIDocument;
    1.27 +class nsIDocShell;
    1.28 +class nsIDocShellTreeItem;
    1.29 +class imgIContainer;
    1.30 +class EnterLeaveDispatcher;
    1.31 +class nsIMarkupDocumentViewer;
    1.32 +class nsIScrollableFrame;
    1.33 +class nsITimer;
    1.34 +class nsPresContext;
    1.35 +
    1.36 +namespace mozilla {
    1.37 +
    1.38 +class EnterLeaveDispatcher;
    1.39 +class EventStates;
    1.40 +class IMEContentObserver;
    1.41 +class ScrollbarsForWheel;
    1.42 +class WheelTransaction;
    1.43 +
    1.44 +namespace dom {
    1.45 +class DataTransfer;
    1.46 +class TabParent;
    1.47 +} // namespace dom
    1.48 +
    1.49 +class OverOutElementsWrapper MOZ_FINAL : public nsISupports
    1.50 +{
    1.51 +public:
    1.52 +  OverOutElementsWrapper();
    1.53 +  ~OverOutElementsWrapper();
    1.54 +
    1.55 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1.56 +  NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper)
    1.57 +
    1.58 +  nsWeakFrame mLastOverFrame;
    1.59 +
    1.60 +  nsCOMPtr<nsIContent> mLastOverElement;
    1.61 +
    1.62 +  // The last element on which we fired a over event, or null if
    1.63 +  // the last over event we fired has finished processing.
    1.64 +  nsCOMPtr<nsIContent> mFirstOverEventElement;
    1.65 +
    1.66 +  // The last element on which we fired a out event, or null if
    1.67 +  // the last out event we fired has finished processing.
    1.68 +  nsCOMPtr<nsIContent> mFirstOutEventElement;
    1.69 +};
    1.70 +
    1.71 +class EventStateManager : public nsSupportsWeakReference,
    1.72 +                          public nsIObserver
    1.73 +{
    1.74 +  friend class mozilla::EnterLeaveDispatcher;
    1.75 +  friend class mozilla::ScrollbarsForWheel;
    1.76 +  friend class mozilla::WheelTransaction;
    1.77 +
    1.78 +public:
    1.79 +  EventStateManager();
    1.80 +  virtual ~EventStateManager();
    1.81 +
    1.82 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1.83 +  NS_DECL_NSIOBSERVER
    1.84 +
    1.85 +  nsresult Init();
    1.86 +  nsresult Shutdown();
    1.87 +
    1.88 +  /* The PreHandleEvent method is called before event dispatch to either
    1.89 +   * the DOM or frames.  Any processing which must not be prevented or
    1.90 +   * cancelled should occur here.  Any processing which is intended to
    1.91 +   * be conditional based on either DOM or frame processing should occur in
    1.92 +   * PostHandleEvent.  Any centralized event processing which must occur before
    1.93 +   * DOM or frame event handling should occur here as well.
    1.94 +   */
    1.95 +  nsresult PreHandleEvent(nsPresContext* aPresContext,
    1.96 +                          WidgetEvent* aEvent,
    1.97 +                          nsIFrame* aTargetFrame,
    1.98 +                          nsEventStatus* aStatus);
    1.99 +
   1.100 +  /* The PostHandleEvent method should contain all system processing which
   1.101 +   * should occur conditionally based on DOM or frame processing.  It should
   1.102 +   * also contain any centralized event processing which must occur after
   1.103 +   * DOM and frame processing.
   1.104 +   */
   1.105 +  nsresult PostHandleEvent(nsPresContext* aPresContext,
   1.106 +                           WidgetEvent* aEvent,
   1.107 +                           nsIFrame* aTargetFrame,
   1.108 +                           nsEventStatus* aStatus);
   1.109 +
   1.110 +  /**
   1.111 +   * DispatchLegacyMouseScrollEvents() dispatches NS_MOUSE_SCROLL event and
   1.112 +   * NS_MOUSE_PIXEL_SCROLL event for compatiblity with old Gecko.
   1.113 +   */
   1.114 +  void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
   1.115 +                                       WidgetWheelEvent* aEvent,
   1.116 +                                       nsEventStatus* aStatus);
   1.117 +
   1.118 +  void NotifyDestroyPresContext(nsPresContext* aPresContext);
   1.119 +  void SetPresContext(nsPresContext* aPresContext);
   1.120 +  void ClearFrameRefs(nsIFrame* aFrame);
   1.121 +
   1.122 +  nsIFrame* GetEventTarget();
   1.123 +  already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent);
   1.124 +
   1.125 +  /**
   1.126 +   * Notify that the given NS_EVENT_STATE_* bit has changed for this content.
   1.127 +   * @param aContent Content which has changed states
   1.128 +   * @param aState   Corresponding state flags such as NS_EVENT_STATE_FOCUS
   1.129 +   * @return  Whether the content was able to change all states. Returns false
   1.130 +   *                  if a resulting DOM event causes the content node passed in
   1.131 +   *                  to not change states. Note, the frame for the content may
   1.132 +   *                  change as a result of the content state change, because of
   1.133 +   *                  frame reconstructions that may occur, but this does not
   1.134 +   *                  affect the return value.
   1.135 +   */
   1.136 +  bool SetContentState(nsIContent* aContent, EventStates aState);
   1.137 +  void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent);
   1.138 +  bool EventStatusOK(WidgetGUIEvent* aEvent);
   1.139 +
   1.140 +  /**
   1.141 +   * EventStateManager stores IMEContentObserver while it's observing contents.
   1.142 +   * Following mehtods are called by IMEContentObserver when it starts to
   1.143 +   * observe or stops observing the content.
   1.144 +   */
   1.145 +  void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver);
   1.146 +  void OnStopObservingContent(IMEContentObserver* aIMEContentObserver);
   1.147 +
   1.148 +  /**
   1.149 +   * Register accesskey on the given element. When accesskey is activated then
   1.150 +   * the element will be notified via nsIContent::PerformAccesskey() method.
   1.151 +   *
   1.152 +   * @param  aContent  the given element
   1.153 +   * @param  aKey      accesskey
   1.154 +   */
   1.155 +  void RegisterAccessKey(nsIContent* aContent, uint32_t aKey);
   1.156 +
   1.157 +  /**
   1.158 +   * Unregister accesskey for the given element.
   1.159 +   *
   1.160 +   * @param  aContent  the given element
   1.161 +   * @param  aKey      accesskey
   1.162 +   */
   1.163 +  void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey);
   1.164 +
   1.165 +  /**
   1.166 +   * Get accesskey registered on the given element or 0 if there is none.
   1.167 +   *
   1.168 +   * @param  aContent  the given element (must not be null)
   1.169 +   * @return           registered accesskey
   1.170 +   */
   1.171 +  uint32_t GetRegisteredAccessKey(nsIContent* aContent);
   1.172 +
   1.173 +  bool GetAccessKeyLabelPrefix(nsAString& aPrefix);
   1.174 +
   1.175 +  nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
   1.176 +                     bool aHaveHotspot, float aHotspotX, float aHotspotY,
   1.177 +                     nsIWidget* aWidget, bool aLockCursor); 
   1.178 +
   1.179 +  static void StartHandlingUserInput()
   1.180 +  {
   1.181 +    ++sUserInputEventDepth;
   1.182 +    if (sUserInputEventDepth == 1) {
   1.183 +      sHandlingInputStart = TimeStamp::Now();
   1.184 +    }
   1.185 +  }
   1.186 +
   1.187 +  static void StopHandlingUserInput()
   1.188 +  {
   1.189 +    --sUserInputEventDepth;
   1.190 +    if (sUserInputEventDepth == 0) {
   1.191 +      sHandlingInputStart = TimeStamp();
   1.192 +    }
   1.193 +  }
   1.194 +
   1.195 +  /**
   1.196 +   * Returns true if the current code is being executed as a result of user input.
   1.197 +   * This includes timers or anything else that is initiated from user input.
   1.198 +   * However, mouse over events are not counted as user input, nor are
   1.199 +   * page load events. If this method is called from asynchronously executed code,
   1.200 +   * such as during layout reflows, it will return false. If more time has elapsed
   1.201 +   * since the user input than is specified by the
   1.202 +   * dom.event.handling-user-input-time-limit pref (default 1 second), this
   1.203 +   * function also returns false.
   1.204 +   */
   1.205 +  static bool IsHandlingUserInput();
   1.206 +
   1.207 +  nsPresContext* GetPresContext() { return mPresContext; }
   1.208 +
   1.209 +  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager,
   1.210 +                                           nsIObserver)
   1.211 +
   1.212 +  static nsIDocument* sMouseOverDocument;
   1.213 +
   1.214 +  static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
   1.215 +
   1.216 +  // Sets aNewESM to be the active event state manager, and
   1.217 +  // if aContent is non-null, marks the object as active.
   1.218 +  static void SetActiveManager(EventStateManager* aNewESM,
   1.219 +                               nsIContent* aContent);
   1.220 +
   1.221 +  // Sets the full-screen event state on aElement to aIsFullScreen.
   1.222 +  static void SetFullScreenState(dom::Element* aElement, bool aIsFullScreen);
   1.223 +
   1.224 +  static bool IsRemoteTarget(nsIContent* aTarget);
   1.225 +  static LayoutDeviceIntPoint GetChildProcessOffset(nsFrameLoader* aFrameLoader,
   1.226 +                                                    const WidgetEvent& aEvent);
   1.227 +
   1.228 +  // Holds the point in screen coords that a mouse event was dispatched to,
   1.229 +  // before we went into pointer lock mode. This is constantly updated while
   1.230 +  // the pointer is not locked, but we don't update it while the pointer is
   1.231 +  // locked. This is used by dom::Event::GetScreenCoords() to make mouse
   1.232 +  // events' screen coord appear frozen at the last mouse position while
   1.233 +  // the pointer is locked.
   1.234 +  static nsIntPoint sLastScreenPoint;
   1.235 +
   1.236 +  // Holds the point in client coords of the last mouse event. Used by
   1.237 +  // dom::Event::GetClientCoords() to make mouse events' client coords appear
   1.238 +  // frozen at the last mouse position while the pointer is locked.
   1.239 +  static CSSIntPoint sLastClientPoint;
   1.240 +
   1.241 +  static bool sIsPointerLocked;
   1.242 +  static nsWeakPtr sPointerLockedElement;
   1.243 +  static nsWeakPtr sPointerLockedDoc;
   1.244 +
   1.245 +protected:
   1.246 +  /**
   1.247 +   * Prefs class capsules preference management.
   1.248 +   */
   1.249 +  class Prefs
   1.250 +  {
   1.251 +  public:
   1.252 +    static bool KeyCausesActivation() { return sKeyCausesActivation; }
   1.253 +    static bool ClickHoldContextMenu() { return sClickHoldContextMenu; }
   1.254 +    static int32_t ChromeAccessModifierMask();
   1.255 +    static int32_t ContentAccessModifierMask();
   1.256 +
   1.257 +    static void Init();
   1.258 +    static void OnChange(const char* aPrefName, void*);
   1.259 +    static void Shutdown();
   1.260 +
   1.261 +  private:
   1.262 +    static bool sKeyCausesActivation;
   1.263 +    static bool sClickHoldContextMenu;
   1.264 +    static int32_t sGenericAccessModifierKey;
   1.265 +    static int32_t sChromeAccessModifierMask;
   1.266 +    static int32_t sContentAccessModifierMask;
   1.267 +
   1.268 +    static int32_t GetAccessModifierMask(int32_t aItemType);
   1.269 +  };
   1.270 +
   1.271 +  /**
   1.272 +   * Get appropriate access modifier mask for the aDocShell.  Returns -1 if
   1.273 +   * access key isn't available.
   1.274 +   */
   1.275 +  static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell);
   1.276 +
   1.277 +  void UpdateCursor(nsPresContext* aPresContext,
   1.278 +                    WidgetEvent* aEvent,
   1.279 +                    nsIFrame* aTargetFrame,
   1.280 +                    nsEventStatus* aStatus);
   1.281 +  /**
   1.282 +   * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified
   1.283 +   * content.  This returns the primary frame for the content (or null
   1.284 +   * if it goes away during the event).
   1.285 +   */
   1.286 +  nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
   1.287 +                                        uint32_t aMessage,
   1.288 +                                        nsIContent* aTargetContent,
   1.289 +                                        nsIContent* aRelatedContent);
   1.290 +  /**
   1.291 +   * Synthesize DOM and frame mouseover and mouseout events from this
   1.292 +   * MOUSE_MOVE or MOUSE_EXIT event.
   1.293 +   */
   1.294 +  void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent);
   1.295 +  /**
   1.296 +   * Tell this ESM and ESMs in parent documents that the mouse is
   1.297 +   * over some content in this document.
   1.298 +   */
   1.299 +  void NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
   1.300 +                       nsIContent* aContent);
   1.301 +  /**
   1.302 +   * Tell this ESM and ESMs in affected child documents that the mouse
   1.303 +   * has exited this document's currently hovered content.
   1.304 +   * @param aMouseEvent the event that triggered the mouseout
   1.305 +   * @param aMovingInto the content node we've moved into.  This is used to set
   1.306 +   *        the relatedTarget for mouseout events.  Also, if it's non-null
   1.307 +   *        NotifyMouseOut will NOT change the current hover content to null;
   1.308 +   *        in that case the caller is responsible for updating hover state.
   1.309 +   */
   1.310 +  void NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
   1.311 +                      nsIContent* aMovingInto);
   1.312 +  void GenerateDragDropEnterExit(nsPresContext* aPresContext,
   1.313 +                                 WidgetDragEvent* aDragEvent);
   1.314 +
   1.315 +  /**
   1.316 +   * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper elements wrapper.
   1.317 +   * If mPointersEnterLeaveHelper does not contain wrapper for pointerId it create new one
   1.318 +   */
   1.319 +  OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent);
   1.320 +
   1.321 +  /**
   1.322 +   * Fire the dragenter and dragexit/dragleave events when the mouse moves to a
   1.323 +   * new target.
   1.324 +   *
   1.325 +   * @param aRelatedTarget relatedTarget to set for the event
   1.326 +   * @param aTargetContent target to set for the event
   1.327 +   * @param aTargetFrame target frame for the event
   1.328 +   */
   1.329 +  void FireDragEnterOrExit(nsPresContext* aPresContext,
   1.330 +                           WidgetDragEvent* aDragEvent,
   1.331 +                           uint32_t aMsg,
   1.332 +                           nsIContent* aRelatedTarget,
   1.333 +                           nsIContent* aTargetContent,
   1.334 +                           nsWeakFrame& aTargetFrame);
   1.335 +  /**
   1.336 +   * Update the initial drag session data transfer with any changes that occur
   1.337 +   * on cloned data transfer objects used for events.
   1.338 +   */
   1.339 +  void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
   1.340 +
   1.341 +  nsresult SetClickCount(nsPresContext* aPresContext,
   1.342 +                         WidgetMouseEvent* aEvent,
   1.343 +                         nsEventStatus* aStatus);
   1.344 +  nsresult CheckForAndDispatchClick(nsPresContext* aPresContext,
   1.345 +                                    WidgetMouseEvent* aEvent,
   1.346 +                                    nsEventStatus* aStatus);
   1.347 +  void EnsureDocument(nsPresContext* aPresContext);
   1.348 +  void FlushPendingEvents(nsPresContext* aPresContext);
   1.349 +
   1.350 +  /**
   1.351 +   * The phases of HandleAccessKey processing. See below.
   1.352 +   */
   1.353 +  typedef enum {
   1.354 +    eAccessKeyProcessingNormal = 0,
   1.355 +    eAccessKeyProcessingUp,
   1.356 +    eAccessKeyProcessingDown
   1.357 +  } ProcessingAccessKeyState;
   1.358 +
   1.359 +  /**
   1.360 +   * Access key handling.  If there is registered content for the accesskey
   1.361 +   * given by the key event and modifier mask then call
   1.362 +   * content.PerformAccesskey(), otherwise call HandleAccessKey() recursively,
   1.363 +   * on descendant docshells first, then on the ancestor (with |aBubbledFrom|
   1.364 +   * set to the docshell associated with |this|), until something matches.
   1.365 +   *
   1.366 +   * @param aPresContext the presentation context
   1.367 +   * @param aEvent the key event
   1.368 +   * @param aStatus the event status
   1.369 +   * @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey()
   1.370 +   *        on the child the call originally came from, i.e. this is the child
   1.371 +   *        that recursively called us in its Up phase. The initial caller
   1.372 +   *        passes |nullptr| here. This is to avoid an infinite loop.
   1.373 +   * @param aAccessKeyState Normal, Down or Up processing phase (see enums
   1.374 +   *        above). The initial event receiver uses 'normal', then 'down' when
   1.375 +   *        processing children and Up when recursively calling its ancestor.
   1.376 +   * @param aModifierMask modifier mask for the key event
   1.377 +   */
   1.378 +  void HandleAccessKey(nsPresContext* aPresContext,
   1.379 +                       WidgetKeyboardEvent* aEvent,
   1.380 +                       nsEventStatus* aStatus,
   1.381 +                       nsIDocShellTreeItem* aBubbledFrom,
   1.382 +                       ProcessingAccessKeyState aAccessKeyState,
   1.383 +                       int32_t aModifierMask);
   1.384 +
   1.385 +  bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
   1.386 +                          bool aIsTrustedEvent);
   1.387 +
   1.388 +  //---------------------------------------------
   1.389 +  // DocShell Focus Traversal Methods
   1.390 +  //---------------------------------------------
   1.391 +
   1.392 +  nsIContent* GetFocusedContent();
   1.393 +  bool IsShellVisible(nsIDocShell* aShell);
   1.394 +
   1.395 +  // These functions are for mousewheel and pixel scrolling
   1.396 +
   1.397 +  class WheelPrefs
   1.398 +  {
   1.399 +  public:
   1.400 +    static WheelPrefs* GetInstance();
   1.401 +    static void Shutdown();
   1.402 +
   1.403 +    /**
   1.404 +     * ApplyUserPrefsToDelta() overrides the wheel event's delta values with
   1.405 +     * user prefs.
   1.406 +     */
   1.407 +    void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent);
   1.408 +
   1.409 +    /**
   1.410 +     * If ApplyUserPrefsToDelta() changed the delta values with customized
   1.411 +     * prefs, the overflowDelta values would be inflated.
   1.412 +     * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
   1.413 +     */
   1.414 +    void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent);
   1.415 +
   1.416 +    /**
   1.417 +     * Computes the default action for the aEvent with the prefs.
   1.418 +     */
   1.419 +    enum Action MOZ_ENUM_TYPE(uint8_t)
   1.420 +    {
   1.421 +      ACTION_NONE = 0,
   1.422 +      ACTION_SCROLL,
   1.423 +      ACTION_HISTORY,
   1.424 +      ACTION_ZOOM,
   1.425 +      ACTION_LAST = ACTION_ZOOM
   1.426 +    };
   1.427 +    Action ComputeActionFor(WidgetWheelEvent* aEvent);
   1.428 +
   1.429 +    /**
   1.430 +     * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
   1.431 +     * computed the lineOrPageDelta values.
   1.432 +     */
   1.433 +    bool NeedToComputeLineOrPageDelta(WidgetWheelEvent* aEvent);
   1.434 +
   1.435 +    /**
   1.436 +     * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
   1.437 +     * be rounded down to the page width/height (false) or not (true).
   1.438 +     */
   1.439 +    bool IsOverOnePageScrollAllowedX(WidgetWheelEvent* aEvent);
   1.440 +    bool IsOverOnePageScrollAllowedY(WidgetWheelEvent* aEvent);
   1.441 +
   1.442 +  private:
   1.443 +    WheelPrefs();
   1.444 +    ~WheelPrefs();
   1.445 +
   1.446 +    static void OnPrefChanged(const char* aPrefName, void* aClosure);
   1.447 +
   1.448 +    enum Index
   1.449 +    {
   1.450 +      INDEX_DEFAULT = 0,
   1.451 +      INDEX_ALT,
   1.452 +      INDEX_CONTROL,
   1.453 +      INDEX_META,
   1.454 +      INDEX_SHIFT,
   1.455 +      INDEX_OS,
   1.456 +      COUNT_OF_MULTIPLIERS
   1.457 +    };
   1.458 +
   1.459 +    /**
   1.460 +     * GetIndexFor() returns the index of the members which should be used for
   1.461 +     * the aEvent.  When only one modifier key of MODIFIER_ALT,
   1.462 +     * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is
   1.463 +     * pressed, returns the index for the modifier.  Otherwise, this return the
   1.464 +     * default index which is used at either no modifier key is pressed or
   1.465 +     * two or modifier keys are pressed.
   1.466 +     */
   1.467 +    Index GetIndexFor(WidgetWheelEvent* aEvent);
   1.468 +
   1.469 +    /**
   1.470 +     * GetPrefNameBase() returns the base pref name for aEvent.
   1.471 +     * It's decided by GetModifierForPref() which modifier should be used for
   1.472 +     * the aEvent.
   1.473 +     *
   1.474 +     * @param aBasePrefName The result, must be "mousewheel.with_*." or
   1.475 +     *                      "mousewheel.default.".
   1.476 +     */
   1.477 +    void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
   1.478 +
   1.479 +    void Init(Index aIndex);
   1.480 +
   1.481 +    void Reset();
   1.482 +
   1.483 +    /**
   1.484 +     * If the abosolute values of mMultiplierX and/or mMultiplierY are equals or
   1.485 +     * larger than this value, the computed scroll amount isn't rounded down to
   1.486 +     * the page width or height.
   1.487 +     */
   1.488 +    enum {
   1.489 +      MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
   1.490 +    };
   1.491 +
   1.492 +    bool mInit[COUNT_OF_MULTIPLIERS];
   1.493 +    double mMultiplierX[COUNT_OF_MULTIPLIERS];
   1.494 +    double mMultiplierY[COUNT_OF_MULTIPLIERS];
   1.495 +    double mMultiplierZ[COUNT_OF_MULTIPLIERS];
   1.496 +    Action mActions[COUNT_OF_MULTIPLIERS];
   1.497 +    /**
   1.498 +     * action values overridden by .override_x pref.
   1.499 +     * If an .override_x value is -1, same as the
   1.500 +     * corresponding mActions value.
   1.501 +     */
   1.502 +    Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS];
   1.503 +
   1.504 +    static WheelPrefs* sInstance;
   1.505 +  };
   1.506 +
   1.507 +  /**
   1.508 +   * DeltaDirection is used for specifying whether the called method should
   1.509 +   * handle vertical delta or horizontal delta.
   1.510 +   * This is clearer than using bool.
   1.511 +   */
   1.512 +  enum DeltaDirection
   1.513 +  {
   1.514 +    DELTA_DIRECTION_X = 0,
   1.515 +    DELTA_DIRECTION_Y
   1.516 +  };
   1.517 +
   1.518 +  struct MOZ_STACK_CLASS EventState
   1.519 +  {
   1.520 +    bool mDefaultPrevented;
   1.521 +    bool mDefaultPreventedByContent;
   1.522 +
   1.523 +    EventState() :
   1.524 +      mDefaultPrevented(false), mDefaultPreventedByContent(false)
   1.525 +    {
   1.526 +    }
   1.527 +  };
   1.528 +
   1.529 +  /**
   1.530 +   * SendLineScrollEvent() dispatches a DOMMouseScroll event for the
   1.531 +   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
   1.532 +   * wheel event because it's not necessary for compatiblity.
   1.533 +   *
   1.534 +   * @param aTargetFrame        The event target of wheel event.
   1.535 +   * @param aEvent              The original Wheel event.
   1.536 +   * @param aState              The event which should be set to the dispatching
   1.537 +   *                            event.  This also returns the dispatched event
   1.538 +   *                            state.
   1.539 +   * @param aDelta              The delta value of the event.
   1.540 +   * @param aDeltaDirection     The X/Y direction of dispatching event.
   1.541 +   */
   1.542 +  void SendLineScrollEvent(nsIFrame* aTargetFrame,
   1.543 +                           WidgetWheelEvent* aEvent,
   1.544 +                           EventState& aState,
   1.545 +                           int32_t aDelta,
   1.546 +                           DeltaDirection aDeltaDirection);
   1.547 +
   1.548 +  /**
   1.549 +   * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
   1.550 +   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
   1.551 +   * wheel event because it's not necessary for compatiblity.
   1.552 +   *
   1.553 +   * @param aTargetFrame        The event target of wheel event.
   1.554 +   * @param aEvent              The original Wheel event.
   1.555 +   * @param aState              The event which should be set to the dispatching
   1.556 +   *                            event.  This also returns the dispatched event
   1.557 +   *                            state.
   1.558 +   * @param aPixelDelta         The delta value of the event.
   1.559 +   * @param aDeltaDirection     The X/Y direction of dispatching event.
   1.560 +   */
   1.561 +  void SendPixelScrollEvent(nsIFrame* aTargetFrame,
   1.562 +                            WidgetWheelEvent* aEvent,
   1.563 +                            EventState& aState,
   1.564 +                            int32_t aPixelDelta,
   1.565 +                            DeltaDirection aDeltaDirection);
   1.566 +
   1.567 +  /**
   1.568 +   * ComputeScrollTarget() returns the scrollable frame which should be
   1.569 +   * scrolled.
   1.570 +   *
   1.571 +   * @param aTargetFrame        The event target of the wheel event.
   1.572 +   * @param aEvent              The handling mouse wheel event.
   1.573 +   * @param aOptions            The options for finding the scroll target.
   1.574 +   *                            Callers should use COMPUTE_*.
   1.575 +   * @return                    The scrollable frame which should be scrolled.
   1.576 +   */
   1.577 +  // These flags are used in ComputeScrollTarget(). Callers should use
   1.578 +  // COMPUTE_*.
   1.579 +  enum
   1.580 +  {
   1.581 +    PREFER_MOUSE_WHEEL_TRANSACTION               = 1,
   1.582 +    PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 2,
   1.583 +    PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 4,
   1.584 +    START_FROM_PARENT                            = 8
   1.585 +  };
   1.586 +  enum ComputeScrollTargetOptions
   1.587 +  {
   1.588 +    // At computing scroll target for legacy mouse events, we should return
   1.589 +    // first scrollable element even when it's not scrollable to the direction.
   1.590 +    COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET     = 0,
   1.591 +    // Default action prefers the scrolled element immediately before if it's
   1.592 +    // still under the mouse cursor.  Otherwise, it prefers the nearest
   1.593 +    // scrollable ancestor which will be scrolled actually.
   1.594 +    COMPUTE_DEFAULT_ACTION_TARGET                =
   1.595 +      (PREFER_MOUSE_WHEEL_TRANSACTION |
   1.596 +       PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
   1.597 +       PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
   1.598 +    // Look for the nearest scrollable ancestor which can be scrollable with
   1.599 +    // aEvent.
   1.600 +    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS     =
   1.601 +      (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
   1.602 +    COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS     =
   1.603 +      (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT)
   1.604 +  };
   1.605 +  nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
   1.606 +                                          WidgetWheelEvent* aEvent,
   1.607 +                                          ComputeScrollTargetOptions aOptions);
   1.608 +
   1.609 +  nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
   1.610 +                                          double aDirectionX,
   1.611 +                                          double aDirectionY,
   1.612 +                                          WidgetWheelEvent* aEvent,
   1.613 +                                          ComputeScrollTargetOptions aOptions);
   1.614 +
   1.615 +  /**
   1.616 +   * GetScrollAmount() returns the scroll amount in app uints of one line or
   1.617 +   * one page.  If the wheel event scrolls a page, returns the page width and
   1.618 +   * height.  Otherwise, returns line height for both its width and height.
   1.619 +   *
   1.620 +   * @param aScrollableFrame    A frame which will be scrolled by the event.
   1.621 +   *                            The result of ComputeScrollTarget() is
   1.622 +   *                            expected for this value.
   1.623 +   *                            This can be nullptr if there is no scrollable
   1.624 +   *                            frame.  Then, this method uses root frame's
   1.625 +   *                            line height or visible area's width and height.
   1.626 +   */
   1.627 +  nsSize GetScrollAmount(nsPresContext* aPresContext,
   1.628 +                         WidgetWheelEvent* aEvent,
   1.629 +                         nsIScrollableFrame* aScrollableFrame);
   1.630 +
   1.631 +  /**
   1.632 +   * DoScrollText() scrolls the scrollable frame for aEvent.
   1.633 +   */
   1.634 +  void DoScrollText(nsIScrollableFrame* aScrollableFrame,
   1.635 +                    WidgetWheelEvent* aEvent);
   1.636 +
   1.637 +  void DoScrollHistory(int32_t direction);
   1.638 +  void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment);
   1.639 +  nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
   1.640 +  nsresult ChangeTextSize(int32_t change);
   1.641 +  nsresult ChangeFullZoom(int32_t change);
   1.642 +
   1.643 +  /**
   1.644 +   * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
   1.645 +   * event.  If wheel events are caused by pixel scroll only devices or
   1.646 +   * the delta values are customized by prefs, this class stores the delta
   1.647 +   * values and set lineOrPageDelta values.
   1.648 +   */
   1.649 +  class DeltaAccumulator
   1.650 +  {
   1.651 +  public:
   1.652 +    static DeltaAccumulator* GetInstance()
   1.653 +    {
   1.654 +      if (!sInstance) {
   1.655 +        sInstance = new DeltaAccumulator;
   1.656 +      }
   1.657 +      return sInstance;
   1.658 +    }
   1.659 +
   1.660 +    static void Shutdown()
   1.661 +    {
   1.662 +      delete sInstance;
   1.663 +      sInstance = nullptr;
   1.664 +    }
   1.665 +
   1.666 +    bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; }
   1.667 +
   1.668 +    /**
   1.669 +     * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents
   1.670 +     * which are caused if it's needed.  And if the accumulated delta becomes a
   1.671 +     * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
   1.672 +     */
   1.673 +    void InitLineOrPageDelta(nsIFrame* aTargetFrame,
   1.674 +                             EventStateManager* aESM,
   1.675 +                             WidgetWheelEvent* aEvent);
   1.676 +
   1.677 +    /**
   1.678 +     * Reset() resets all members.
   1.679 +     */
   1.680 +    void Reset();
   1.681 +
   1.682 +    /**
   1.683 +     * ComputeScrollAmountForDefaultAction() computes the default action's
   1.684 +     * scroll amount in device pixels with mPendingScrollAmount*.
   1.685 +     */
   1.686 +    nsIntPoint ComputeScrollAmountForDefaultAction(
   1.687 +                 WidgetWheelEvent* aEvent,
   1.688 +                 const nsIntSize& aScrollAmountInDevPixels);
   1.689 +
   1.690 +  private:
   1.691 +    DeltaAccumulator() :
   1.692 +      mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0),
   1.693 +      mHandlingDeltaMode(UINT32_MAX), mHandlingPixelOnlyDevice(false)
   1.694 +    {
   1.695 +    }
   1.696 +
   1.697 +    double mX;
   1.698 +    double mY;
   1.699 +
   1.700 +    // When default action of a wheel event is scroll but some delta values
   1.701 +    // are ignored because the computed amount values are not integer, the
   1.702 +    // fractional values are saved by these members.
   1.703 +    double mPendingScrollAmountX;
   1.704 +    double mPendingScrollAmountY;
   1.705 +
   1.706 +    TimeStamp mLastTime;
   1.707 +
   1.708 +    uint32_t mHandlingDeltaMode;
   1.709 +    bool mHandlingPixelOnlyDevice;
   1.710 +
   1.711 +    static DeltaAccumulator* sInstance;
   1.712 +  };
   1.713 +
   1.714 +  // end mousewheel functions
   1.715 +
   1.716 +  /*
   1.717 +   * When a touch gesture is about to start, this function determines what
   1.718 +   * kind of gesture interaction we will want to use, based on what is
   1.719 +   * underneath the initial touch point.
   1.720 +   * Currently it decides between panning (finger scrolling) or dragging
   1.721 +   * the target element, as well as the orientation to trigger panning and
   1.722 +   * display visual boundary feedback. The decision is stored back in aEvent.
   1.723 +   */
   1.724 +  void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
   1.725 +                          nsIFrame* targetFrame);
   1.726 +
   1.727 +  // routines for the d&d gesture tracking state machine
   1.728 +  void BeginTrackingDragGesture(nsPresContext* aPresContext,
   1.729 +                                WidgetMouseEvent* aDownEvent,
   1.730 +                                nsIFrame* aDownFrame);
   1.731 +  void StopTrackingDragGesture();
   1.732 +  void GenerateDragGesture(nsPresContext* aPresContext,
   1.733 +                           WidgetMouseEvent* aEvent);
   1.734 +
   1.735 +  /**
   1.736 +   * Determine which node the drag should be targeted at.
   1.737 +   * This is either the node clicked when there is a selection, or, for HTML,
   1.738 +   * the element with a draggable property set to true.
   1.739 +   *
   1.740 +   * aSelectionTarget - target to check for selection
   1.741 +   * aDataTransfer - data transfer object that will contain the data to drag
   1.742 +   * aSelection - [out] set to the selection to be dragged
   1.743 +   * aTargetNode - [out] the draggable node, or null if there isn't one
   1.744 +   */
   1.745 +  void DetermineDragTarget(nsPIDOMWindow* aWindow,
   1.746 +                           nsIContent* aSelectionTarget,
   1.747 +                           dom::DataTransfer* aDataTransfer,
   1.748 +                           nsISelection** aSelection,
   1.749 +                           nsIContent** aTargetNode);
   1.750 +
   1.751 +  /*
   1.752 +   * Perform the default handling for the dragstart/draggesture event and set up a
   1.753 +   * drag for aDataTransfer if it contains any data. Returns true if a drag has
   1.754 +   * started.
   1.755 +   *
   1.756 +   * aDragEvent - the dragstart/draggesture event
   1.757 +   * aDataTransfer - the data transfer that holds the data to be dragged
   1.758 +   * aDragTarget - the target of the drag
   1.759 +   * aSelection - the selection to be dragged
   1.760 +   */
   1.761 +  bool DoDefaultDragStart(nsPresContext* aPresContext,
   1.762 +                          WidgetDragEvent* aDragEvent,
   1.763 +                          dom::DataTransfer* aDataTransfer,
   1.764 +                          nsIContent* aDragTarget,
   1.765 +                          nsISelection* aSelection);
   1.766 +
   1.767 +  bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; }
   1.768 +  /**
   1.769 +   * Set the fields of aEvent to reflect the mouse position and modifier keys
   1.770 +   * that were set when the user first pressed the mouse button (stored by
   1.771 +   * BeginTrackingDragGesture). aEvent->widget must be
   1.772 +   * mCurrentTarget->GetNearestWidget().
   1.773 +   */
   1.774 +  void FillInEventFromGestureDown(WidgetMouseEvent* aEvent);
   1.775 +
   1.776 +  nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent);
   1.777 +  nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent);
   1.778 +
   1.779 +  void DoQuerySelectedText(WidgetQueryContentEvent* aEvent);
   1.780 +
   1.781 +  bool RemoteQueryContentEvent(WidgetEvent* aEvent);
   1.782 +  dom::TabParent *GetCrossProcessTarget();
   1.783 +  bool IsTargetCrossProcess(WidgetGUIEvent* aEvent);
   1.784 +
   1.785 +  bool DispatchCrossProcessEvent(WidgetEvent* aEvent,
   1.786 +                                 nsFrameLoader* aRemote,
   1.787 +                                 nsEventStatus *aStatus);
   1.788 +  bool HandleCrossProcessEvent(WidgetEvent* aEvent,
   1.789 +                               nsIFrame* aTargetFrame,
   1.790 +                               nsEventStatus* aStatus);
   1.791 +
   1.792 +  void ReleaseCurrentIMEContentObserver();
   1.793 +
   1.794 +private:
   1.795 +  static inline void DoStateChange(dom::Element* aElement,
   1.796 +                                   EventStates aState, bool aAddState);
   1.797 +  static inline void DoStateChange(nsIContent* aContent, EventStates aState,
   1.798 +                                   bool aAddState);
   1.799 +  static void UpdateAncestorState(nsIContent* aStartNode,
   1.800 +                                  nsIContent* aStopBefore,
   1.801 +                                  EventStates aState,
   1.802 +                                  bool aAddState);
   1.803 +  static PLDHashOperator ResetLastOverForContent(const uint32_t& aIdx,
   1.804 +                                                 nsRefPtr<OverOutElementsWrapper>& aChunk,
   1.805 +                                                 void* aClosure);
   1.806 +
   1.807 +  int32_t     mLockCursor;
   1.808 +
   1.809 +  // Last mouse event refPoint (the offset from the widget's origin in
   1.810 +  // device pixels) when mouse was locked, used to restore mouse position
   1.811 +  // after unlocking.
   1.812 +  LayoutDeviceIntPoint mPreLockPoint;
   1.813 +
   1.814 +  // Stores the refPoint of the last synthetic mouse move we dispatched
   1.815 +  // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
   1.816 +  // means we've not recently dispatched a centering event. We use this to
   1.817 +  // detect when we receive the synth event, so we can cancel and not send it
   1.818 +  // to content.
   1.819 +  static LayoutDeviceIntPoint sSynthCenteringPoint;
   1.820 +
   1.821 +  nsWeakFrame mCurrentTarget;
   1.822 +  nsCOMPtr<nsIContent> mCurrentTargetContent;
   1.823 +  static nsWeakFrame sLastDragOverFrame;
   1.824 +
   1.825 +  // Stores the refPoint (the offset from the widget's origin in device
   1.826 +  // pixels) of the last mouse event.
   1.827 +  static LayoutDeviceIntPoint sLastRefPoint;
   1.828 +
   1.829 +  // member variables for the d&d gesture state machine
   1.830 +  LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates
   1.831 +  // The content to use as target if we start a d&d (what we drag).
   1.832 +  nsCOMPtr<nsIContent> mGestureDownContent;
   1.833 +  // The content of the frame where the mouse-down event occurred. It's the same
   1.834 +  // as the target in most cases but not always - for example when dragging
   1.835 +  // an <area> of an image map this is the image. (bug 289667)
   1.836 +  nsCOMPtr<nsIContent> mGestureDownFrameOwner;
   1.837 +  // State of keys when the original gesture-down happened
   1.838 +  Modifiers mGestureModifiers;
   1.839 +  uint16_t mGestureDownButtons;
   1.840 +
   1.841 +  nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
   1.842 +  nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent;
   1.843 +  nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
   1.844 +  nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent;
   1.845 +  nsCOMPtr<nsIContent> mLastRightMouseDownContent;
   1.846 +  nsCOMPtr<nsIContent> mLastRightMouseDownContentParent;
   1.847 +
   1.848 +  nsCOMPtr<nsIContent> mActiveContent;
   1.849 +  nsCOMPtr<nsIContent> mHoverContent;
   1.850 +  static nsCOMPtr<nsIContent> sDragOverContent;
   1.851 +  nsCOMPtr<nsIContent> mURLTargetContent;
   1.852 +
   1.853 +  nsPresContext* mPresContext;      // Not refcnted
   1.854 +  nsCOMPtr<nsIDocument> mDocument;   // Doesn't necessarily need to be owner
   1.855 +
   1.856 +  nsRefPtr<IMEContentObserver> mIMEContentObserver;
   1.857 +
   1.858 +  uint32_t mLClickCount;
   1.859 +  uint32_t mMClickCount;
   1.860 +  uint32_t mRClickCount;
   1.861 +
   1.862 +  bool m_haveShutdown;
   1.863 +
   1.864 +  // Time at which we began handling user input.
   1.865 +  static TimeStamp sHandlingInputStart;
   1.866 +
   1.867 +  nsRefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
   1.868 +  nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper;
   1.869 +
   1.870 +public:
   1.871 +  static nsresult UpdateUserActivityTimer(void);
   1.872 +  // Array for accesskey support
   1.873 +  nsCOMArray<nsIContent> mAccessKeys;
   1.874 +
   1.875 +  static int32_t sUserInputEventDepth;
   1.876 +  
   1.877 +  static bool sNormalLMouseEventInProcess;
   1.878 +
   1.879 +  static EventStateManager* sActiveESM;
   1.880 +  
   1.881 +  static void ClearGlobalActiveContent(EventStateManager* aClearer);
   1.882 +
   1.883 +  // Functions used for click hold context menus
   1.884 +  nsCOMPtr<nsITimer> mClickHoldTimer;
   1.885 +  void CreateClickHoldTimer(nsPresContext* aPresContext,
   1.886 +                            nsIFrame* aDownFrame,
   1.887 +                            WidgetGUIEvent* aMouseDownEvent);
   1.888 +  void KillClickHoldTimer();
   1.889 +  void FireContextClick();
   1.890 +
   1.891 +  void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ;
   1.892 +  static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ;
   1.893 +};
   1.894 +
   1.895 +/**
   1.896 + * This class is used while processing real user input. During this time, popups
   1.897 + * are allowed. For mousedown events, mouse capturing is also permitted.
   1.898 + */
   1.899 +class AutoHandlingUserInputStatePusher
   1.900 +{
   1.901 +public:
   1.902 +  AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
   1.903 +                                   WidgetEvent* aEvent,
   1.904 +                                   nsIDocument* aDocument);
   1.905 +  ~AutoHandlingUserInputStatePusher();
   1.906 +
   1.907 +protected:
   1.908 +  bool mIsHandlingUserInput;
   1.909 +  bool mIsMouseDown;
   1.910 +  bool mResetFMMouseDownState;
   1.911 +
   1.912 +private:
   1.913 +  // Hide so that this class can only be stack-allocated
   1.914 +  static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; }
   1.915 +  static void operator delete(void* /*memory*/) {}
   1.916 +};
   1.917 +
   1.918 +} // namespace mozilla
   1.919 +
   1.920 +// Click and double-click events need to be handled even for content that
   1.921 +// has no frame. This is required for Web compatibility.
   1.922 +#define NS_EVENT_NEEDS_FRAME(event) \
   1.923 +    (!(event)->HasPluginActivationEventMessage() && \
   1.924 +     (event)->message != NS_MOUSE_CLICK && \
   1.925 +     (event)->message != NS_MOUSE_DOUBLECLICK)
   1.926 +
   1.927 +#endif // mozilla_EventStateManager_h_

mercurial