EventStateManager.h 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_EventStateManager_h_
  6. #define mozilla_EventStateManager_h_
  7. #include "mozilla/EventForwards.h"
  8. #include "nsIObserver.h"
  9. #include "nsWeakReference.h"
  10. #include "nsCOMPtr.h"
  11. #include "nsCOMArray.h"
  12. #include "nsCycleCollectionParticipant.h"
  13. #include "mozilla/TimeStamp.h"
  14. #include "nsIFrame.h"
  15. #include "Units.h"
  16. class nsFrameLoader;
  17. class nsIContent;
  18. class nsIDocument;
  19. class nsIDocShell;
  20. class nsIDocShellTreeItem;
  21. class imgIContainer;
  22. class EnterLeaveDispatcher;
  23. class nsIContentViewer;
  24. class nsIScrollableFrame;
  25. class nsITimer;
  26. class nsPresContext;
  27. namespace mozilla {
  28. class EnterLeaveDispatcher;
  29. class EventStates;
  30. class IMEContentObserver;
  31. class ScrollbarsForWheel;
  32. class WheelTransaction;
  33. namespace dom {
  34. class DataTransfer;
  35. class Element;
  36. class TabParent;
  37. } // namespace dom
  38. class OverOutElementsWrapper final : public nsISupports
  39. {
  40. ~OverOutElementsWrapper();
  41. public:
  42. OverOutElementsWrapper();
  43. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  44. NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper)
  45. nsWeakFrame mLastOverFrame;
  46. nsCOMPtr<nsIContent> mLastOverElement;
  47. // The last element on which we fired a over event, or null if
  48. // the last over event we fired has finished processing.
  49. nsCOMPtr<nsIContent> mFirstOverEventElement;
  50. // The last element on which we fired a out event, or null if
  51. // the last out event we fired has finished processing.
  52. nsCOMPtr<nsIContent> mFirstOutEventElement;
  53. };
  54. class EventStateManager : public nsSupportsWeakReference,
  55. public nsIObserver
  56. {
  57. friend class mozilla::EnterLeaveDispatcher;
  58. friend class mozilla::ScrollbarsForWheel;
  59. friend class mozilla::WheelTransaction;
  60. virtual ~EventStateManager();
  61. public:
  62. EventStateManager();
  63. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  64. NS_DECL_NSIOBSERVER
  65. nsresult Init();
  66. nsresult Shutdown();
  67. /* The PreHandleEvent method is called before event dispatch to either
  68. * the DOM or frames. Any processing which must not be prevented or
  69. * cancelled should occur here. Any processing which is intended to
  70. * be conditional based on either DOM or frame processing should occur in
  71. * PostHandleEvent. Any centralized event processing which must occur before
  72. * DOM or frame event handling should occur here as well.
  73. */
  74. nsresult PreHandleEvent(nsPresContext* aPresContext,
  75. WidgetEvent* aEvent,
  76. nsIFrame* aTargetFrame,
  77. nsIContent* aTargetContent,
  78. nsEventStatus* aStatus);
  79. /* The PostHandleEvent method should contain all system processing which
  80. * should occur conditionally based on DOM or frame processing. It should
  81. * also contain any centralized event processing which must occur after
  82. * DOM and frame processing.
  83. */
  84. nsresult PostHandleEvent(nsPresContext* aPresContext,
  85. WidgetEvent* aEvent,
  86. nsIFrame* aTargetFrame,
  87. nsEventStatus* aStatus);
  88. void PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent,
  89. nsEventStatus& aStatus,
  90. bool dispatchedToContentProcess);
  91. /**
  92. * DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll
  93. * event and eLegacyMousePixelScroll event for compatibility with old Gecko.
  94. */
  95. void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
  96. WidgetWheelEvent* aEvent,
  97. nsEventStatus* aStatus);
  98. void NotifyDestroyPresContext(nsPresContext* aPresContext);
  99. void SetPresContext(nsPresContext* aPresContext);
  100. void ClearFrameRefs(nsIFrame* aFrame);
  101. nsIFrame* GetEventTarget();
  102. already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent);
  103. /**
  104. * Notify that the given NS_EVENT_STATE_* bit has changed for this content.
  105. * @param aContent Content which has changed states
  106. * @param aState Corresponding state flags such as NS_EVENT_STATE_FOCUS
  107. * @return Whether the content was able to change all states. Returns false
  108. * if a resulting DOM event causes the content node passed in
  109. * to not change states. Note, the frame for the content may
  110. * change as a result of the content state change, because of
  111. * frame reconstructions that may occur, but this does not
  112. * affect the return value.
  113. */
  114. bool SetContentState(nsIContent* aContent, EventStates aState);
  115. void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent);
  116. bool EventStatusOK(WidgetGUIEvent* aEvent);
  117. /**
  118. * EventStateManager stores IMEContentObserver while it's observing contents.
  119. * Following mehtods are called by IMEContentObserver when it starts to
  120. * observe or stops observing the content.
  121. */
  122. void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver);
  123. void OnStopObservingContent(IMEContentObserver* aIMEContentObserver);
  124. /**
  125. * TryToFlushPendingNotificationsToIME() suggests flushing pending
  126. * notifications to IME to IMEContentObserver.
  127. */
  128. void TryToFlushPendingNotificationsToIME();
  129. /**
  130. * Register accesskey on the given element. When accesskey is activated then
  131. * the element will be notified via nsIContent::PerformAccesskey() method.
  132. *
  133. * @param aContent the given element
  134. * @param aKey accesskey
  135. */
  136. void RegisterAccessKey(nsIContent* aContent, uint32_t aKey);
  137. /**
  138. * Unregister accesskey for the given element.
  139. *
  140. * @param aContent the given element
  141. * @param aKey accesskey
  142. */
  143. void UnregisterAccessKey(nsIContent* aContent, uint32_t aKey);
  144. /**
  145. * Get accesskey registered on the given element or 0 if there is none.
  146. *
  147. * @param aContent the given element (must not be null)
  148. * @return registered accesskey
  149. */
  150. uint32_t GetRegisteredAccessKey(nsIContent* aContent);
  151. static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix);
  152. bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
  153. nsPresContext* aPresContext,
  154. nsTArray<uint32_t>& aAccessCharCodes,
  155. int32_t aModifierMask,
  156. bool aMatchesContentAccessKey)
  157. {
  158. return HandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
  159. aMatchesContentAccessKey, nullptr,
  160. eAccessKeyProcessingNormal, aModifierMask);
  161. }
  162. nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
  163. bool aHaveHotspot, float aHotspotX, float aHotspotY,
  164. nsIWidget* aWidget, bool aLockCursor);
  165. static void StartHandlingUserInput()
  166. {
  167. ++sUserInputEventDepth;
  168. ++sUserInputCounter;
  169. if (sUserInputEventDepth == 1) {
  170. sLatestUserInputStart = sHandlingInputStart = TimeStamp::Now();
  171. }
  172. }
  173. static void StopHandlingUserInput()
  174. {
  175. --sUserInputEventDepth;
  176. if (sUserInputEventDepth == 0) {
  177. sHandlingInputStart = TimeStamp();
  178. }
  179. }
  180. /**
  181. * Returns true if the current code is being executed as a result of
  182. * user input. This includes anything that is initiated by user,
  183. * with the exception of page load events or mouse over events. If
  184. * this method is called from asynchronously executed code, such as
  185. * during layout reflows, it will return false. If more time has
  186. * elapsed since the user input than is specified by the
  187. * dom.event.handling-user-input-time-limit pref (default 1 second),
  188. * this function also returns false.
  189. */
  190. static bool IsHandlingUserInput();
  191. /**
  192. * Get the number of user inputs handled since process start. This
  193. * includes anything that is initiated by user, with the exception
  194. * of page load events or mouse over events.
  195. */
  196. static uint64_t UserInputCount()
  197. {
  198. return sUserInputCounter;
  199. }
  200. /**
  201. * Get the timestamp at which the latest user input was handled.
  202. *
  203. * Guaranteed to be monotonic. Until the first user input, return
  204. * the epoch.
  205. */
  206. static TimeStamp LatestUserInputStart()
  207. {
  208. return sLatestUserInputStart;
  209. }
  210. nsPresContext* GetPresContext() { return mPresContext; }
  211. NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager,
  212. nsIObserver)
  213. static nsIDocument* sMouseOverDocument;
  214. static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
  215. // Sets aNewESM to be the active event state manager, and
  216. // if aContent is non-null, marks the object as active.
  217. static void SetActiveManager(EventStateManager* aNewESM,
  218. nsIContent* aContent);
  219. // Sets the full-screen event state on aElement to aIsFullScreen.
  220. static void SetFullScreenState(dom::Element* aElement, bool aIsFullScreen);
  221. static bool IsRemoteTarget(nsIContent* aTarget);
  222. // Returns true if the given WidgetWheelEvent will resolve to a scroll action.
  223. static bool WheelEventIsScrollAction(WidgetWheelEvent* aEvent);
  224. // Returns user-set multipliers for a wheel event.
  225. static void GetUserPrefsForWheelEvent(WidgetWheelEvent* aEvent,
  226. double* aOutMultiplierX,
  227. double* aOutMultiplierY);
  228. // Returns whether or not a frame can be vertically scrolled with a mouse
  229. // wheel (as opposed to, say, a selection or touch scroll).
  230. static bool CanVerticallyScrollFrameWithWheel(nsIFrame* aFrame);
  231. // Holds the point in screen coords that a mouse event was dispatched to,
  232. // before we went into pointer lock mode. This is constantly updated while
  233. // the pointer is not locked, but we don't update it while the pointer is
  234. // locked. This is used by dom::Event::GetScreenCoords() to make mouse
  235. // events' screen coord appear frozen at the last mouse position while
  236. // the pointer is locked.
  237. static CSSIntPoint sLastScreenPoint;
  238. // Holds the point in client coords of the last mouse event. Used by
  239. // dom::Event::GetClientCoords() to make mouse events' client coords appear
  240. // frozen at the last mouse position while the pointer is locked.
  241. static CSSIntPoint sLastClientPoint;
  242. static bool sIsPointerLocked;
  243. static nsWeakPtr sPointerLockedElement;
  244. static nsWeakPtr sPointerLockedDoc;
  245. /**
  246. * If the absolute values of mMultiplierX and/or mMultiplierY are equal or
  247. * larger than this value, the computed scroll amount isn't rounded down to
  248. * the page width or height.
  249. */
  250. enum {
  251. MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
  252. };
  253. protected:
  254. /**
  255. * Prefs class capsules preference management.
  256. */
  257. class Prefs
  258. {
  259. public:
  260. static bool KeyCausesActivation() { return sKeyCausesActivation; }
  261. static bool ClickHoldContextMenu() { return sClickHoldContextMenu; }
  262. static int32_t ChromeAccessModifierMask();
  263. static int32_t ContentAccessModifierMask();
  264. static void Init();
  265. static void OnChange(const char* aPrefName, void*);
  266. static void Shutdown();
  267. private:
  268. static bool sKeyCausesActivation;
  269. static bool sClickHoldContextMenu;
  270. static int32_t sGenericAccessModifierKey;
  271. static int32_t sChromeAccessModifierMask;
  272. static int32_t sContentAccessModifierMask;
  273. static int32_t GetAccessModifierMask(int32_t aItemType);
  274. };
  275. /**
  276. * Get appropriate access modifier mask for the aDocShell. Returns -1 if
  277. * access key isn't available.
  278. */
  279. static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell);
  280. /*
  281. * If aTargetFrame's widget has a cached cursor value, resets the cursor
  282. * such that the next call to SetCursor on the widget will force an update
  283. * of the native cursor. For use in getting puppet widget to update its
  284. * cursor between mouse exit / enter transitions. This call basically wraps
  285. * nsIWidget ClearCachedCursor.
  286. */
  287. void ClearCachedWidgetCursor(nsIFrame* aTargetFrame);
  288. void UpdateCursor(nsPresContext* aPresContext,
  289. WidgetEvent* aEvent,
  290. nsIFrame* aTargetFrame,
  291. nsEventStatus* aStatus);
  292. /**
  293. * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified
  294. * content. This returns the primary frame for the content (or null
  295. * if it goes away during the event).
  296. */
  297. nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
  298. EventMessage aMessage,
  299. nsIContent* aTargetContent,
  300. nsIContent* aRelatedContent);
  301. /**
  302. * Synthesize DOM pointerover and pointerout events
  303. */
  304. void GeneratePointerEnterExit(EventMessage aMessage,
  305. WidgetMouseEvent* aEvent);
  306. /**
  307. * Synthesize DOM and frame mouseover and mouseout events from this
  308. * MOUSE_MOVE or MOUSE_EXIT event.
  309. */
  310. void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent);
  311. /**
  312. * Tell this ESM and ESMs in parent documents that the mouse is
  313. * over some content in this document.
  314. */
  315. void NotifyMouseOver(WidgetMouseEvent* aMouseEvent,
  316. nsIContent* aContent);
  317. /**
  318. * Tell this ESM and ESMs in affected child documents that the mouse
  319. * has exited this document's currently hovered content.
  320. * @param aMouseEvent the event that triggered the mouseout
  321. * @param aMovingInto the content node we've moved into. This is used to set
  322. * the relatedTarget for mouseout events. Also, if it's non-null
  323. * NotifyMouseOut will NOT change the current hover content to null;
  324. * in that case the caller is responsible for updating hover state.
  325. */
  326. void NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
  327. nsIContent* aMovingInto);
  328. void GenerateDragDropEnterExit(nsPresContext* aPresContext,
  329. WidgetDragEvent* aDragEvent);
  330. /**
  331. * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper elements wrapper.
  332. * If mPointersEnterLeaveHelper does not contain wrapper for pointerId it create new one
  333. */
  334. OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent);
  335. /**
  336. * Fire the dragenter and dragexit/dragleave events when the mouse moves to a
  337. * new target.
  338. *
  339. * @param aRelatedTarget relatedTarget to set for the event
  340. * @param aTargetContent target to set for the event
  341. * @param aTargetFrame target frame for the event
  342. */
  343. void FireDragEnterOrExit(nsPresContext* aPresContext,
  344. WidgetDragEvent* aDragEvent,
  345. EventMessage aMessage,
  346. nsIContent* aRelatedTarget,
  347. nsIContent* aTargetContent,
  348. nsWeakFrame& aTargetFrame);
  349. /**
  350. * Update the initial drag session data transfer with any changes that occur
  351. * on cloned data transfer objects used for events.
  352. */
  353. void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
  354. static nsresult InitAndDispatchClickEvent(WidgetMouseEvent* aEvent,
  355. nsEventStatus* aStatus,
  356. EventMessage aMessage,
  357. nsIPresShell* aPresShell,
  358. nsIContent* aMouseTarget,
  359. nsWeakFrame aCurrentTarget,
  360. bool aNoContentDispatch);
  361. nsresult SetClickCount(WidgetMouseEvent* aEvent, nsEventStatus* aStatus);
  362. nsresult CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
  363. nsEventStatus* aStatus);
  364. void EnsureDocument(nsPresContext* aPresContext);
  365. void FlushPendingEvents(nsPresContext* aPresContext);
  366. /**
  367. * The phases of HandleAccessKey processing. See below.
  368. */
  369. typedef enum {
  370. eAccessKeyProcessingNormal = 0,
  371. eAccessKeyProcessingUp,
  372. eAccessKeyProcessingDown
  373. } ProcessingAccessKeyState;
  374. /**
  375. * Access key handling. If there is registered content for the accesskey
  376. * given by the key event and modifier mask then call
  377. * content.PerformAccesskey(), otherwise call HandleAccessKey() recursively,
  378. * on descendant docshells first, then on the ancestor (with |aBubbledFrom|
  379. * set to the docshell associated with |this|), until something matches.
  380. *
  381. * @param aEvent the keyboard event triggering the acccess key
  382. * @param aPresContext the presentation context
  383. * @param aAccessCharCodes list of charcode candidates
  384. * @param aMatchesContentAccessKey true if the content accesskey modifier is pressed
  385. * @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey()
  386. * on the child the call originally came from, i.e. this is the child
  387. * that recursively called us in its Up phase. The initial caller
  388. * passes |nullptr| here. This is to avoid an infinite loop.
  389. * @param aAccessKeyState Normal, Down or Up processing phase (see enums
  390. * above). The initial event receiver uses 'normal', then 'down' when
  391. * processing children and Up when recursively calling its ancestor.
  392. * @param aModifierMask modifier mask for the key event
  393. */
  394. bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
  395. nsPresContext* aPresContext,
  396. nsTArray<uint32_t>& aAccessCharCodes,
  397. bool aMatchesContentAccessKey,
  398. nsIDocShellTreeItem* aBubbledFrom,
  399. ProcessingAccessKeyState aAccessKeyState,
  400. int32_t aModifierMask);
  401. bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
  402. bool aIsTrustedEvent);
  403. //---------------------------------------------
  404. // DocShell Focus Traversal Methods
  405. //---------------------------------------------
  406. nsIContent* GetFocusedContent();
  407. bool IsShellVisible(nsIDocShell* aShell);
  408. // These functions are for mousewheel and pixel scrolling
  409. class WheelPrefs
  410. {
  411. public:
  412. static WheelPrefs* GetInstance();
  413. static void Shutdown();
  414. /**
  415. * ApplyUserPrefsToDelta() overrides the wheel event's delta values with
  416. * user prefs.
  417. */
  418. void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent);
  419. /**
  420. * Returns whether or not ApplyUserPrefsToDelta() would change the delta
  421. * values of an event.
  422. */
  423. void GetUserPrefsForEvent(WidgetWheelEvent* aEvent,
  424. double* aOutMultiplierX,
  425. double* aOutMultiplierY);
  426. /**
  427. * If ApplyUserPrefsToDelta() changed the delta values with customized
  428. * prefs, the overflowDelta values would be inflated.
  429. * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
  430. */
  431. void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent);
  432. /**
  433. * Computes the default action for the aEvent with the prefs.
  434. */
  435. enum Action : uint8_t
  436. {
  437. ACTION_NONE = 0,
  438. ACTION_SCROLL,
  439. ACTION_HISTORY,
  440. ACTION_ZOOM,
  441. ACTION_HSCROLL,
  442. ACTION_LAST = ACTION_HSCROLL,
  443. // Following actions are used only by internal processing. So, cannot
  444. // specified by prefs.
  445. ACTION_SEND_TO_PLUGIN
  446. };
  447. Action ComputeActionFor(WidgetWheelEvent* aEvent);
  448. /**
  449. * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
  450. * computed the lineOrPageDelta values.
  451. */
  452. bool NeedToComputeLineOrPageDelta(WidgetWheelEvent* aEvent);
  453. /**
  454. * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
  455. * be rounded down to the page width/height (false) or not (true).
  456. */
  457. bool IsOverOnePageScrollAllowedX(WidgetWheelEvent* aEvent);
  458. bool IsOverOnePageScrollAllowedY(WidgetWheelEvent* aEvent);
  459. /**
  460. * WheelEventsEnabledOnPlugins() returns true if user wants to use mouse
  461. * wheel on plugins.
  462. */
  463. static bool WheelEventsEnabledOnPlugins();
  464. private:
  465. WheelPrefs();
  466. ~WheelPrefs();
  467. static void OnPrefChanged(const char* aPrefName, void* aClosure);
  468. enum Index
  469. {
  470. INDEX_DEFAULT = 0,
  471. INDEX_ALT,
  472. INDEX_CONTROL,
  473. INDEX_META,
  474. INDEX_SHIFT,
  475. INDEX_OS,
  476. COUNT_OF_MULTIPLIERS
  477. };
  478. /**
  479. * GetIndexFor() returns the index of the members which should be used for
  480. * the aEvent. When only one modifier key of MODIFIER_ALT,
  481. * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is
  482. * pressed, returns the index for the modifier. Otherwise, this return the
  483. * default index which is used at either no modifier key is pressed or
  484. * two or modifier keys are pressed.
  485. */
  486. Index GetIndexFor(WidgetWheelEvent* aEvent);
  487. /**
  488. * GetPrefNameBase() returns the base pref name for aEvent.
  489. * It's decided by GetModifierForPref() which modifier should be used for
  490. * the aEvent.
  491. *
  492. * @param aBasePrefName The result, must be "mousewheel.with_*." or
  493. * "mousewheel.default.".
  494. */
  495. void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
  496. void Init(Index aIndex);
  497. void Reset();
  498. bool mInit[COUNT_OF_MULTIPLIERS];
  499. double mMultiplierX[COUNT_OF_MULTIPLIERS];
  500. double mMultiplierY[COUNT_OF_MULTIPLIERS];
  501. double mMultiplierZ[COUNT_OF_MULTIPLIERS];
  502. Action mActions[COUNT_OF_MULTIPLIERS];
  503. /**
  504. * action values overridden by .override_x pref.
  505. * If an .override_x value is -1, same as the
  506. * corresponding mActions value.
  507. */
  508. Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS];
  509. static WheelPrefs* sInstance;
  510. static bool sWheelEventsEnabledOnPlugins;
  511. };
  512. /**
  513. * DeltaDirection is used for specifying whether the called method should
  514. * handle vertical delta or horizontal delta.
  515. * This is clearer than using bool.
  516. */
  517. enum DeltaDirection
  518. {
  519. DELTA_DIRECTION_X = 0,
  520. DELTA_DIRECTION_Y
  521. };
  522. struct MOZ_STACK_CLASS EventState
  523. {
  524. bool mDefaultPrevented;
  525. bool mDefaultPreventedByContent;
  526. EventState() :
  527. mDefaultPrevented(false), mDefaultPreventedByContent(false)
  528. {
  529. }
  530. };
  531. /**
  532. * SendLineScrollEvent() dispatches a DOMMouseScroll event for the
  533. * WidgetWheelEvent. This method shouldn't be called for non-trusted
  534. * wheel event because it's not necessary for compatiblity.
  535. *
  536. * @param aTargetFrame The event target of wheel event.
  537. * @param aEvent The original Wheel event.
  538. * @param aState The event which should be set to the dispatching
  539. * event. This also returns the dispatched event
  540. * state.
  541. * @param aDelta The delta value of the event.
  542. * @param aDeltaDirection The X/Y direction of dispatching event.
  543. */
  544. void SendLineScrollEvent(nsIFrame* aTargetFrame,
  545. WidgetWheelEvent* aEvent,
  546. EventState& aState,
  547. int32_t aDelta,
  548. DeltaDirection aDeltaDirection);
  549. /**
  550. * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
  551. * WidgetWheelEvent. This method shouldn't be called for non-trusted
  552. * wheel event because it's not necessary for compatiblity.
  553. *
  554. * @param aTargetFrame The event target of wheel event.
  555. * @param aEvent The original Wheel event.
  556. * @param aState The event which should be set to the dispatching
  557. * event. This also returns the dispatched event
  558. * state.
  559. * @param aPixelDelta The delta value of the event.
  560. * @param aDeltaDirection The X/Y direction of dispatching event.
  561. */
  562. void SendPixelScrollEvent(nsIFrame* aTargetFrame,
  563. WidgetWheelEvent* aEvent,
  564. EventState& aState,
  565. int32_t aPixelDelta,
  566. DeltaDirection aDeltaDirection);
  567. /**
  568. * ComputeScrollTarget() returns the scrollable frame which should be
  569. * scrolled.
  570. *
  571. * @param aTargetFrame The event target of the wheel event.
  572. * @param aEvent The handling mouse wheel event.
  573. * @param aOptions The options for finding the scroll target.
  574. * Callers should use COMPUTE_*.
  575. * @return The scrollable frame which should be scrolled.
  576. */
  577. // These flags are used in ComputeScrollTarget(). Callers should use
  578. // COMPUTE_*.
  579. enum
  580. {
  581. PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001,
  582. PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002,
  583. PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004,
  584. START_FROM_PARENT = 0x00000008,
  585. INCLUDE_PLUGIN_AS_TARGET = 0x00000010
  586. };
  587. enum ComputeScrollTargetOptions
  588. {
  589. // At computing scroll target for legacy mouse events, we should return
  590. // first scrollable element even when it's not scrollable to the direction.
  591. COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0,
  592. // Default action prefers the scrolled element immediately before if it's
  593. // still under the mouse cursor. Otherwise, it prefers the nearest
  594. // scrollable ancestor which will be scrolled actually.
  595. COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN =
  596. (PREFER_MOUSE_WHEEL_TRANSACTION |
  597. PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
  598. PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
  599. // When this is specified, the result may be nsPluginFrame. In such case,
  600. // the frame doesn't have nsIScrollableFrame interface.
  601. COMPUTE_DEFAULT_ACTION_TARGET =
  602. (COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN |
  603. INCLUDE_PLUGIN_AS_TARGET),
  604. // Look for the nearest scrollable ancestor which can be scrollable with
  605. // aEvent.
  606. COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS =
  607. (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
  608. COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS =
  609. (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT)
  610. };
  611. static ComputeScrollTargetOptions RemovePluginFromTarget(
  612. ComputeScrollTargetOptions aOptions)
  613. {
  614. switch (aOptions) {
  615. case COMPUTE_DEFAULT_ACTION_TARGET:
  616. return COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN;
  617. default:
  618. MOZ_ASSERT(!(aOptions & INCLUDE_PLUGIN_AS_TARGET));
  619. return aOptions;
  620. }
  621. }
  622. nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
  623. WidgetWheelEvent* aEvent,
  624. ComputeScrollTargetOptions aOptions);
  625. nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
  626. double aDirectionX,
  627. double aDirectionY,
  628. WidgetWheelEvent* aEvent,
  629. ComputeScrollTargetOptions aOptions);
  630. /**
  631. * GetScrollAmount() returns the scroll amount in app uints of one line or
  632. * one page. If the wheel event scrolls a page, returns the page width and
  633. * height. Otherwise, returns line height for both its width and height.
  634. *
  635. * @param aScrollableFrame A frame which will be scrolled by the event.
  636. * The result of ComputeScrollTarget() is
  637. * expected for this value.
  638. * This can be nullptr if there is no scrollable
  639. * frame. Then, this method uses root frame's
  640. * line height or visible area's width and height.
  641. */
  642. nsSize GetScrollAmount(nsPresContext* aPresContext,
  643. WidgetWheelEvent* aEvent,
  644. nsIScrollableFrame* aScrollableFrame);
  645. /**
  646. * DoScrollText() scrolls the scrollable frame for aEvent.
  647. */
  648. void DoScrollText(nsIScrollableFrame* aScrollableFrame,
  649. WidgetWheelEvent* aEvent);
  650. void DoScrollHistory(int32_t direction);
  651. void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment);
  652. nsresult GetContentViewer(nsIContentViewer** aCv);
  653. nsresult ChangeTextSize(int32_t change);
  654. nsresult ChangeFullZoom(int32_t change);
  655. /**
  656. * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
  657. * event. If wheel events are caused by pixel scroll only devices or
  658. * the delta values are customized by prefs, this class stores the delta
  659. * values and set lineOrPageDelta values.
  660. */
  661. class DeltaAccumulator
  662. {
  663. public:
  664. static DeltaAccumulator* GetInstance()
  665. {
  666. if (!sInstance) {
  667. sInstance = new DeltaAccumulator;
  668. }
  669. return sInstance;
  670. }
  671. static void Shutdown()
  672. {
  673. delete sInstance;
  674. sInstance = nullptr;
  675. }
  676. bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; }
  677. /**
  678. * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents
  679. * which are caused if it's needed. And if the accumulated delta becomes a
  680. * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
  681. */
  682. void InitLineOrPageDelta(nsIFrame* aTargetFrame,
  683. EventStateManager* aESM,
  684. WidgetWheelEvent* aEvent);
  685. /**
  686. * Reset() resets all members.
  687. */
  688. void Reset();
  689. /**
  690. * ComputeScrollAmountForDefaultAction() computes the default action's
  691. * scroll amount in device pixels with mPendingScrollAmount*.
  692. */
  693. nsIntPoint ComputeScrollAmountForDefaultAction(
  694. WidgetWheelEvent* aEvent,
  695. const nsIntSize& aScrollAmountInDevPixels);
  696. private:
  697. DeltaAccumulator() :
  698. mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0),
  699. mHandlingDeltaMode(UINT32_MAX), mIsNoLineOrPageDeltaDevice(false)
  700. {
  701. }
  702. double mX;
  703. double mY;
  704. // When default action of a wheel event is scroll but some delta values
  705. // are ignored because the computed amount values are not integer, the
  706. // fractional values are saved by these members.
  707. double mPendingScrollAmountX;
  708. double mPendingScrollAmountY;
  709. TimeStamp mLastTime;
  710. uint32_t mHandlingDeltaMode;
  711. bool mIsNoLineOrPageDeltaDevice;
  712. static DeltaAccumulator* sInstance;
  713. };
  714. // end mousewheel functions
  715. /*
  716. * When a touch gesture is about to start, this function determines what
  717. * kind of gesture interaction we will want to use, based on what is
  718. * underneath the initial touch point.
  719. * Currently it decides between panning (finger scrolling) or dragging
  720. * the target element, as well as the orientation to trigger panning and
  721. * display visual boundary feedback. The decision is stored back in aEvent.
  722. */
  723. void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
  724. nsIFrame* targetFrame);
  725. // routines for the d&d gesture tracking state machine
  726. void BeginTrackingDragGesture(nsPresContext* aPresContext,
  727. WidgetMouseEvent* aDownEvent,
  728. nsIFrame* aDownFrame);
  729. friend class mozilla::dom::TabParent;
  730. void BeginTrackingRemoteDragGesture(nsIContent* aContent);
  731. void StopTrackingDragGesture();
  732. void GenerateDragGesture(nsPresContext* aPresContext,
  733. WidgetInputEvent* aEvent);
  734. /**
  735. * Determine which node the drag should be targeted at.
  736. * This is either the node clicked when there is a selection, or, for HTML,
  737. * the element with a draggable property set to true.
  738. *
  739. * aSelectionTarget - target to check for selection
  740. * aDataTransfer - data transfer object that will contain the data to drag
  741. * aSelection - [out] set to the selection to be dragged
  742. * aTargetNode - [out] the draggable node, or null if there isn't one
  743. */
  744. void DetermineDragTargetAndDefaultData(nsPIDOMWindowOuter* aWindow,
  745. nsIContent* aSelectionTarget,
  746. dom::DataTransfer* aDataTransfer,
  747. nsISelection** aSelection,
  748. nsIContent** aTargetNode);
  749. /*
  750. * Perform the default handling for the dragstart event and set up a
  751. * drag for aDataTransfer if it contains any data. Returns true if a drag has
  752. * started.
  753. *
  754. * aDragEvent - the dragstart event
  755. * aDataTransfer - the data transfer that holds the data to be dragged
  756. * aDragTarget - the target of the drag
  757. * aSelection - the selection to be dragged
  758. */
  759. bool DoDefaultDragStart(nsPresContext* aPresContext,
  760. WidgetDragEvent* aDragEvent,
  761. dom::DataTransfer* aDataTransfer,
  762. nsIContent* aDragTarget,
  763. nsISelection* aSelection);
  764. bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; }
  765. /**
  766. * Set the fields of aEvent to reflect the mouse position and modifier keys
  767. * that were set when the user first pressed the mouse button (stored by
  768. * BeginTrackingDragGesture). aEvent->mWidget must be
  769. * mCurrentTarget->GetNearestWidget().
  770. */
  771. void FillInEventFromGestureDown(WidgetMouseEvent* aEvent);
  772. nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent);
  773. nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent);
  774. dom::TabParent *GetCrossProcessTarget();
  775. bool IsTargetCrossProcess(WidgetGUIEvent* aEvent);
  776. bool DispatchCrossProcessEvent(WidgetEvent* aEvent,
  777. nsFrameLoader* aRemote,
  778. nsEventStatus *aStatus);
  779. bool HandleCrossProcessEvent(WidgetEvent* aEvent,
  780. nsEventStatus* aStatus);
  781. void ReleaseCurrentIMEContentObserver();
  782. void HandleQueryContentEvent(WidgetQueryContentEvent* aEvent);
  783. private:
  784. static inline void DoStateChange(dom::Element* aElement,
  785. EventStates aState, bool aAddState);
  786. static inline void DoStateChange(nsIContent* aContent, EventStates aState,
  787. bool aAddState);
  788. static void UpdateAncestorState(nsIContent* aStartNode,
  789. nsIContent* aStopBefore,
  790. EventStates aState,
  791. bool aAddState);
  792. static void ResetLastOverForContent(const uint32_t& aIdx,
  793. RefPtr<OverOutElementsWrapper>& aChunk,
  794. nsIContent* aClosure);
  795. int32_t mLockCursor;
  796. bool mLastFrameConsumedSetCursor;
  797. // Last mouse event mRefPoint (the offset from the widget's origin in
  798. // device pixels) when mouse was locked, used to restore mouse position
  799. // after unlocking.
  800. static LayoutDeviceIntPoint sPreLockPoint;
  801. // Stores the mRefPoint of the last synthetic mouse move we dispatched
  802. // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
  803. // means we've not recently dispatched a centering event. We use this to
  804. // detect when we receive the synth event, so we can cancel and not send it
  805. // to content.
  806. static LayoutDeviceIntPoint sSynthCenteringPoint;
  807. nsWeakFrame mCurrentTarget;
  808. nsCOMPtr<nsIContent> mCurrentTargetContent;
  809. static nsWeakFrame sLastDragOverFrame;
  810. // Stores the mRefPoint (the offset from the widget's origin in device
  811. // pixels) of the last mouse event.
  812. static LayoutDeviceIntPoint sLastRefPoint;
  813. // member variables for the d&d gesture state machine
  814. LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates
  815. // The content to use as target if we start a d&d (what we drag).
  816. nsCOMPtr<nsIContent> mGestureDownContent;
  817. // The content of the frame where the mouse-down event occurred. It's the same
  818. // as the target in most cases but not always - for example when dragging
  819. // an <area> of an image map this is the image. (bug 289667)
  820. nsCOMPtr<nsIContent> mGestureDownFrameOwner;
  821. // State of keys when the original gesture-down happened
  822. Modifiers mGestureModifiers;
  823. uint16_t mGestureDownButtons;
  824. nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
  825. nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent;
  826. nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
  827. nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent;
  828. nsCOMPtr<nsIContent> mLastRightMouseDownContent;
  829. nsCOMPtr<nsIContent> mLastRightMouseDownContentParent;
  830. nsCOMPtr<nsIContent> mActiveContent;
  831. nsCOMPtr<nsIContent> mHoverContent;
  832. static nsCOMPtr<nsIContent> sDragOverContent;
  833. nsCOMPtr<nsIContent> mURLTargetContent;
  834. nsPresContext* mPresContext; // Not refcnted
  835. nsCOMPtr<nsIDocument> mDocument; // Doesn't necessarily need to be owner
  836. RefPtr<IMEContentObserver> mIMEContentObserver;
  837. uint32_t mLClickCount;
  838. uint32_t mMClickCount;
  839. uint32_t mRClickCount;
  840. bool mInTouchDrag;
  841. bool m_haveShutdown;
  842. // Time at which we began handling user input. Reset to the epoch
  843. // once we have finished handling user input.
  844. static TimeStamp sHandlingInputStart;
  845. // Time at which we began handling the latest user input. Not reset
  846. // at the end of the input.
  847. static TimeStamp sLatestUserInputStart;
  848. RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
  849. nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper;
  850. public:
  851. static nsresult UpdateUserActivityTimer(void);
  852. // Array for accesskey support
  853. nsCOMArray<nsIContent> mAccessKeys;
  854. // The number of user inputs handled since process start. This
  855. // includes anything that is initiated by user, with the exception
  856. // of page load events or mouse over events.
  857. static uint64_t sUserInputCounter;
  858. // The current depth of user inputs. This includes anything that is
  859. // initiated by user, with the exception of page load events or
  860. // mouse over events. Incremented whenever we start handling a user
  861. // input, decremented when we have finished handling a user
  862. // input. This depth is *not* reset in case of nested event loops.
  863. static int32_t sUserInputEventDepth;
  864. static bool sNormalLMouseEventInProcess;
  865. static EventStateManager* sActiveESM;
  866. static void ClearGlobalActiveContent(EventStateManager* aClearer);
  867. // Functions used for click hold context menus
  868. nsCOMPtr<nsITimer> mClickHoldTimer;
  869. void CreateClickHoldTimer(nsPresContext* aPresContext,
  870. nsIFrame* aDownFrame,
  871. WidgetGUIEvent* aMouseDownEvent);
  872. void KillClickHoldTimer();
  873. void FireContextClick();
  874. static void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ;
  875. static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ;
  876. };
  877. /**
  878. * This class is used while processing real user input. During this time, popups
  879. * are allowed. For mousedown events, mouse capturing is also permitted.
  880. */
  881. class AutoHandlingUserInputStatePusher
  882. {
  883. public:
  884. AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
  885. WidgetEvent* aEvent,
  886. nsIDocument* aDocument);
  887. ~AutoHandlingUserInputStatePusher();
  888. protected:
  889. bool mIsHandlingUserInput;
  890. bool mIsMouseDown;
  891. bool mResetFMMouseButtonHandlingState;
  892. nsCOMPtr<nsIDocument> mMouseButtonEventHandlingDocument;
  893. private:
  894. // Hide so that this class can only be stack-allocated
  895. static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; }
  896. static void operator delete(void* /*memory*/) {}
  897. };
  898. } // namespace mozilla
  899. // Click and double-click events need to be handled even for content that
  900. // has no frame. This is required for Web compatibility.
  901. #define NS_EVENT_NEEDS_FRAME(event) \
  902. (!(event)->HasPluginActivationEventMessage() && \
  903. (event)->mMessage != eMouseClick && \
  904. (event)->mMessage != eMouseDoubleClick && \
  905. (event)->mMessage != eMouseAuxClick)
  906. #endif // mozilla_EventStateManager_h_