EventDispatcher.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. #ifdef MOZILLA_INTERNAL_API
  6. #ifndef mozilla_EventDispatcher_h_
  7. #define mozilla_EventDispatcher_h_
  8. #include "mozilla/EventForwards.h"
  9. #include "nsCOMPtr.h"
  10. #include "nsTArray.h"
  11. // Microsoft's API Name hackery sucks
  12. #undef CreateEvent
  13. class nsIContent;
  14. class nsIDOMEvent;
  15. class nsPresContext;
  16. template<class E> class nsCOMArray;
  17. namespace mozilla {
  18. namespace dom {
  19. class Event;
  20. class EventTarget;
  21. } // namespace dom
  22. /**
  23. * About event dispatching:
  24. * When either EventDispatcher::Dispatch or
  25. * EventDispatcher::DispatchDOMEvent is called an event target chain is
  26. * created. EventDispatcher creates the chain by calling GetEventTargetParent
  27. * on each event target and the creation continues until either the mCanHandle
  28. * member of the EventChainPreVisitor object is false or the mParentTarget
  29. * does not point to a new target. The event target chain is created in the
  30. * heap.
  31. *
  32. * If the event needs retargeting, mEventTargetAtParent must be set in
  33. * GetEventTargetParent.
  34. *
  35. * The capture, target and bubble phases of the event dispatch are handled
  36. * by iterating through the event target chain. Iteration happens twice,
  37. * first for the default event group and then for the system event group.
  38. * While dispatching the event for the system event group PostHandleEvent
  39. * is called right after calling event listener for the current event target.
  40. */
  41. class EventChainVisitor
  42. {
  43. public:
  44. EventChainVisitor(nsPresContext* aPresContext,
  45. WidgetEvent* aEvent,
  46. nsIDOMEvent* aDOMEvent,
  47. nsEventStatus aEventStatus = nsEventStatus_eIgnore)
  48. : mPresContext(aPresContext)
  49. , mEvent(aEvent)
  50. , mDOMEvent(aDOMEvent)
  51. , mEventStatus(aEventStatus)
  52. , mItemFlags(0)
  53. {
  54. }
  55. /**
  56. * The prescontext, possibly nullptr.
  57. */
  58. nsPresContext* const mPresContext;
  59. /**
  60. * The WidgetEvent which is being dispatched. Never nullptr.
  61. */
  62. WidgetEvent* const mEvent;
  63. /**
  64. * The DOM Event assiciated with the mEvent. Possibly nullptr if a DOM Event
  65. * is not (yet) created.
  66. */
  67. nsIDOMEvent* mDOMEvent;
  68. /**
  69. * The status of the event.
  70. * @see nsEventStatus.h
  71. */
  72. nsEventStatus mEventStatus;
  73. /**
  74. * Bits for items in the event target chain.
  75. * Set in GetEventTargetParent() and used in PostHandleEvent().
  76. *
  77. * @note These bits are different for each item in the event target chain.
  78. * It is up to the Pre/PostHandleEvent implementation to decide how to
  79. * use these bits.
  80. *
  81. * @note Using uint16_t because that is used also in EventTargetChainItem.
  82. */
  83. uint16_t mItemFlags;
  84. /**
  85. * Data for items in the event target chain.
  86. * Set in GetEventTargetParent() and used in PostHandleEvent().
  87. *
  88. * @note This data is different for each item in the event target chain.
  89. * It is up to the Pre/PostHandleEvent implementation to decide how to
  90. * use this.
  91. */
  92. nsCOMPtr<nsISupports> mItemData;
  93. };
  94. class EventChainPreVisitor : public EventChainVisitor
  95. {
  96. public:
  97. EventChainPreVisitor(nsPresContext* aPresContext,
  98. WidgetEvent* aEvent,
  99. nsIDOMEvent* aDOMEvent,
  100. nsEventStatus aEventStatus,
  101. bool aIsInAnon)
  102. : EventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus)
  103. , mCanHandle(true)
  104. , mAutomaticChromeDispatch(true)
  105. , mForceContentDispatch(false)
  106. , mRelatedTargetIsInAnon(false)
  107. , mOriginalTargetIsInAnon(aIsInAnon)
  108. , mWantsWillHandleEvent(false)
  109. , mMayHaveListenerManager(true)
  110. , mWantsPreHandleEvent(false)
  111. , mRootOfClosedTree(false)
  112. , mParentIsSlotInClosedTree(false)
  113. , mParentIsChromeHandler(false)
  114. , mParentTarget(nullptr)
  115. , mEventTargetAtParent(nullptr)
  116. {
  117. }
  118. void Reset()
  119. {
  120. mItemFlags = 0;
  121. mItemData = nullptr;
  122. mCanHandle = true;
  123. mAutomaticChromeDispatch = true;
  124. mForceContentDispatch = false;
  125. mWantsWillHandleEvent = false;
  126. mMayHaveListenerManager = true;
  127. mWantsPreHandleEvent = false;
  128. mRootOfClosedTree = false;
  129. mParentIsSlotInClosedTree = false;
  130. mParentIsChromeHandler = false;
  131. mParentTarget = nullptr;
  132. mEventTargetAtParent = nullptr;
  133. }
  134. dom::EventTarget* GetParentTarget()
  135. {
  136. return mParentTarget;
  137. }
  138. void SetParentTarget(dom::EventTarget* aParentTarget, bool aIsChromeHandler)
  139. {
  140. mParentTarget = aParentTarget;
  141. if (mParentTarget) {
  142. mParentIsChromeHandler = aIsChromeHandler;
  143. }
  144. }
  145. /**
  146. * Member that must be set in GetEventTargetParent by event targets. If set to
  147. * false, indicates that this event target will not be handling the event and
  148. * construction of the event target chain is complete. The target that sets
  149. * mCanHandle to false is NOT included in the event target chain.
  150. */
  151. bool mCanHandle;
  152. /**
  153. * If mCanHandle is false and mAutomaticChromeDispatch is also false
  154. * event will not be dispatched to the chrome event handler.
  155. */
  156. bool mAutomaticChromeDispatch;
  157. /**
  158. * If mForceContentDispatch is set to true,
  159. * content dispatching is not disabled for this event target.
  160. * FIXME! This is here for backward compatibility. Bug 329119
  161. */
  162. bool mForceContentDispatch;
  163. /**
  164. * true if it is known that related target is or is a descendant of an
  165. * element which is anonymous for events.
  166. */
  167. bool mRelatedTargetIsInAnon;
  168. /**
  169. * true if the original target of the event is inside anonymous content.
  170. * This is set before calling GetEventTargetParent on event targets.
  171. */
  172. bool mOriginalTargetIsInAnon;
  173. /**
  174. * Whether or not nsIDOMEventTarget::WillHandleEvent will be
  175. * called. Default is false;
  176. */
  177. bool mWantsWillHandleEvent;
  178. /**
  179. * If it is known that the current target doesn't have a listener manager
  180. * when GetEventTargetParent is called, set this to false.
  181. */
  182. bool mMayHaveListenerManager;
  183. /**
  184. * Whether or not nsIDOMEventTarget::PreHandleEvent will be called. Default is
  185. * false;
  186. */
  187. bool mWantsPreHandleEvent;
  188. /**
  189. * True if the current target is either closed ShadowRoot or root of
  190. * chrome only access tree (for example native anonymous content).
  191. */
  192. bool mRootOfClosedTree;
  193. /**
  194. * True if mParentTarget is HTMLSlotElement in a closed shadow tree and the
  195. * current target is assigned to that slot.
  196. */
  197. bool mParentIsSlotInClosedTree;
  198. /**
  199. * True if mParentTarget is a chrome handler in the event path.
  200. */
  201. bool mParentIsChromeHandler;
  202. private:
  203. /**
  204. * Parent item in the event target chain.
  205. */
  206. dom::EventTarget* mParentTarget;
  207. public:
  208. /**
  209. * If the event needs to be retargeted, this is the event target,
  210. * which should be used when the event is handled at mParentTarget.
  211. */
  212. dom::EventTarget* mEventTargetAtParent;
  213. };
  214. class EventChainPostVisitor : public mozilla::EventChainVisitor
  215. {
  216. public:
  217. explicit EventChainPostVisitor(EventChainVisitor& aOther)
  218. : EventChainVisitor(aOther.mPresContext, aOther.mEvent,
  219. aOther.mDOMEvent, aOther.mEventStatus)
  220. {
  221. }
  222. };
  223. /**
  224. * If an EventDispatchingCallback object is passed to Dispatch,
  225. * its HandleEvent method is called after handling the default event group,
  226. * before handling the system event group.
  227. * This is used in nsPresShell.
  228. */
  229. class MOZ_STACK_CLASS EventDispatchingCallback
  230. {
  231. public:
  232. virtual void HandleEvent(EventChainPostVisitor& aVisitor) = 0;
  233. };
  234. /**
  235. * The generic class for event dispatching.
  236. * Must not be used outside Gecko!
  237. */
  238. class EventDispatcher
  239. {
  240. public:
  241. /**
  242. * aTarget should QI to EventTarget.
  243. * If the target of aEvent is set before calling this method, the target of
  244. * aEvent is used as the target (unless there is event
  245. * retargeting) and the originalTarget of the DOM Event.
  246. * aTarget is always used as the starting point for constructing the event
  247. * target chain, no matter what the value of aEvent->mTarget is.
  248. * In other words, aEvent->mTarget is only a property of the event and it has
  249. * nothing to do with the construction of the event target chain.
  250. * Neither aTarget nor aEvent is allowed to be nullptr.
  251. *
  252. * If aTargets is non-null, event target chain will be created, but
  253. * event won't be handled. In this case aEvent->mMessage should be
  254. * eVoidEvent.
  255. * @note Use this method when dispatching a WidgetEvent.
  256. */
  257. static nsresult Dispatch(nsISupports* aTarget,
  258. nsPresContext* aPresContext,
  259. WidgetEvent* aEvent,
  260. nsIDOMEvent* aDOMEvent = nullptr,
  261. nsEventStatus* aEventStatus = nullptr,
  262. EventDispatchingCallback* aCallback = nullptr,
  263. nsTArray<dom::EventTarget*>* aTargets = nullptr);
  264. /**
  265. * Dispatches an event.
  266. * If aDOMEvent is not nullptr, it is used for dispatching
  267. * (aEvent can then be nullptr) and (if aDOMEvent is not |trusted| already),
  268. * the |trusted| flag is set based on the UniversalXPConnect capability.
  269. * Otherwise this works like EventDispatcher::Dispatch.
  270. * @note Use this method when dispatching nsIDOMEvent.
  271. */
  272. static nsresult DispatchDOMEvent(nsISupports* aTarget,
  273. WidgetEvent* aEvent,
  274. nsIDOMEvent* aDOMEvent,
  275. nsPresContext* aPresContext,
  276. nsEventStatus* aEventStatus);
  277. /**
  278. * Creates a DOM Event. Returns null if the event type is unsupported.
  279. */
  280. static already_AddRefed<dom::Event> CreateEvent(dom::EventTarget* aOwner,
  281. nsPresContext* aPresContext,
  282. WidgetEvent* aEvent,
  283. const nsAString& aEventType);
  284. static void GetComposedPathFor(WidgetEvent* aEvent,
  285. nsTArray<RefPtr<dom::EventTarget>>& aPath);
  286. /**
  287. * Called at shutting down.
  288. */
  289. static void Shutdown();
  290. };
  291. } // namespace mozilla
  292. #endif // mozilla_EventDispatcher_h_
  293. #endif