Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / events / EventDispatcher.h
bloba7305f177f7d89a8de544a3d053ef6d466bba4bc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifdef MOZILLA_INTERNAL_API
8 # ifndef mozilla_EventDispatcher_h_
9 # define mozilla_EventDispatcher_h_
11 # include "mozilla/dom/BindingDeclarations.h"
12 # include "mozilla/dom/Touch.h"
13 # include "mozilla/EventForwards.h"
14 # include "mozilla/Maybe.h"
15 # include "nsCOMPtr.h"
16 # include "nsTArray.h"
18 // Microsoft's API Name hackery sucks
19 # undef CreateEvent
21 class nsIContent;
22 class nsPresContext;
24 template <class E>
25 class nsCOMArray;
27 namespace mozilla {
28 namespace dom {
29 class Event;
30 class EventTarget;
31 } // namespace dom
33 /**
34 * About event dispatching:
35 * When either EventDispatcher::Dispatch or
36 * EventDispatcher::DispatchDOMEvent is called an event target chain is
37 * created. EventDispatcher creates the chain by calling GetEventTargetParent
38 * on each event target and the creation continues until either the mCanHandle
39 * member of the EventChainPreVisitor object is false or the mParentTarget
40 * does not point to a new target. The event target chain is created in the
41 * heap.
43 * If the event needs retargeting, mEventTargetAtParent must be set in
44 * GetEventTargetParent.
46 * The capture, target and bubble phases of the event dispatch are handled
47 * by iterating through the event target chain. Iteration happens twice,
48 * first for the default event group and then for the system event group.
49 * While dispatching the event for the system event group PostHandleEvent
50 * is called right after calling event listener for the current event target.
53 class MOZ_STACK_CLASS EventChainVisitor {
54 public:
55 // For making creators of this class instances guarantee the lifetime of
56 // aPresContext, this needs to be marked as MOZ_CAN_RUN_SCRIPT.
57 MOZ_CAN_RUN_SCRIPT
58 EventChainVisitor(nsPresContext* aPresContext, WidgetEvent* aEvent,
59 dom::Event* aDOMEvent,
60 nsEventStatus aEventStatus = nsEventStatus_eIgnore)
61 : mPresContext(aPresContext),
62 mEvent(aEvent),
63 mDOMEvent(aDOMEvent),
64 mEventStatus(aEventStatus),
65 mItemFlags(0) {}
67 /**
68 * The prescontext, possibly nullptr.
69 * Note that the lifetime of mPresContext is guaranteed by the creators.
71 MOZ_KNOWN_LIVE nsPresContext* const mPresContext;
73 /**
74 * The WidgetEvent which is being dispatched. Never nullptr.
76 WidgetEvent* const mEvent;
78 /**
79 * The DOM Event assiciated with the mEvent. Possibly nullptr if a DOM Event
80 * is not (yet) created.
82 dom::Event* mDOMEvent;
84 /**
85 * The status of the event.
86 * @see nsEventStatus.h
88 nsEventStatus mEventStatus;
90 /**
91 * Bits for items in the event target chain.
92 * Set in GetEventTargetParent() and used in PostHandleEvent().
94 * @note These bits are different for each item in the event target chain.
95 * It is up to the Pre/PostHandleEvent implementation to decide how to
96 * use these bits.
98 * @note Using uint16_t because that is used also in EventTargetChainItem.
100 uint16_t mItemFlags;
103 * Data for items in the event target chain.
104 * Set in GetEventTargetParent() and used in PostHandleEvent().
106 * @note This data is different for each item in the event target chain.
107 * It is up to the Pre/PostHandleEvent implementation to decide how to
108 * use this.
110 nsCOMPtr<nsISupports> mItemData;
113 class MOZ_STACK_CLASS EventChainPreVisitor final : public EventChainVisitor {
114 public:
115 MOZ_CAN_RUN_SCRIPT
116 EventChainPreVisitor(nsPresContext* aPresContext, WidgetEvent* aEvent,
117 dom::Event* aDOMEvent, nsEventStatus aEventStatus,
118 bool aIsInAnon,
119 dom::EventTarget* aTargetInKnownToBeHandledScope)
120 : EventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
121 mCanHandle(true),
122 mAutomaticChromeDispatch(true),
123 mForceContentDispatch(false),
124 mRelatedTargetIsInAnon(false),
125 mOriginalTargetIsInAnon(aIsInAnon),
126 mWantsWillHandleEvent(false),
127 mMayHaveListenerManager(true),
128 mWantsPreHandleEvent(false),
129 mRootOfClosedTree(false),
130 mItemInShadowTree(false),
131 mParentIsSlotInClosedTree(false),
132 mParentIsChromeHandler(false),
133 mRelatedTargetRetargetedInCurrentScope(false),
134 mIgnoreBecauseOfShadowDOM(false),
135 mWantsActivationBehavior(false),
136 mParentTarget(nullptr),
137 mEventTargetAtParent(nullptr),
138 mRetargetedRelatedTarget(nullptr),
139 mTargetInKnownToBeHandledScope(aTargetInKnownToBeHandledScope) {}
141 void Reset() {
142 mItemFlags = 0;
143 mItemData = nullptr;
144 mCanHandle = true;
145 mAutomaticChromeDispatch = true;
146 mForceContentDispatch = false;
147 mWantsWillHandleEvent = false;
148 mMayHaveListenerManager = true;
149 mWantsPreHandleEvent = false;
150 mRootOfClosedTree = false;
151 mItemInShadowTree = false;
152 mParentIsSlotInClosedTree = false;
153 mParentIsChromeHandler = false;
154 // Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
155 // since it is used during event path creation to indicate whether
156 // relatedTarget may need to be retargeted.
157 mIgnoreBecauseOfShadowDOM = false;
158 mWantsActivationBehavior = false;
159 mParentTarget = nullptr;
160 mEventTargetAtParent = nullptr;
161 mRetargetedRelatedTarget = nullptr;
162 mRetargetedTouchTargets.reset();
165 dom::EventTarget* GetParentTarget() { return mParentTarget; }
167 void SetParentTarget(dom::EventTarget* aParentTarget, bool aIsChromeHandler) {
168 mParentTarget = aParentTarget;
169 if (mParentTarget) {
170 mParentIsChromeHandler = aIsChromeHandler;
174 void IgnoreCurrentTargetBecauseOfShadowDOMRetargeting();
177 * Member that must be set in GetEventTargetParent by event targets. If set to
178 * false, indicates that this event target will not be handling the event and
179 * construction of the event target chain is complete. The target that sets
180 * mCanHandle to false is NOT included in the event target chain.
182 bool mCanHandle;
185 * If mCanHandle is false and mAutomaticChromeDispatch is also false
186 * event will not be dispatched to the chrome event handler.
188 bool mAutomaticChromeDispatch;
191 * If mForceContentDispatch is set to true,
192 * content dispatching is not disabled for this event target.
193 * FIXME! This is here for backward compatibility. Bug 329119
195 bool mForceContentDispatch;
198 * true if it is known that related target is or is a descendant of an
199 * element which is anonymous for events.
201 bool mRelatedTargetIsInAnon;
204 * true if the original target of the event is inside anonymous content.
205 * This is set before calling GetEventTargetParent on event targets.
207 bool mOriginalTargetIsInAnon;
210 * Whether or not EventTarget::WillHandleEvent will be
211 * called. Default is false;
213 bool mWantsWillHandleEvent;
216 * If it is known that the current target doesn't have a listener manager
217 * when GetEventTargetParent is called, set this to false.
219 bool mMayHaveListenerManager;
222 * Whether or not EventTarget::PreHandleEvent will be called. Default is
223 * false;
225 bool mWantsPreHandleEvent;
228 * True if the current target is either closed ShadowRoot or root of
229 * chrome only access tree (for example native anonymous content).
231 bool mRootOfClosedTree;
234 * If target is node and its root is a shadow root.
235 * https://dom.spec.whatwg.org/#event-path-item-in-shadow-tree
237 bool mItemInShadowTree;
240 * True if mParentTarget is HTMLSlotElement in a closed shadow tree and the
241 * current target is assigned to that slot.
243 bool mParentIsSlotInClosedTree;
246 * True if mParentTarget is a chrome handler in the event path.
248 bool mParentIsChromeHandler;
251 * True if event's related target has been already retargeted in the
252 * current 'scope'. This should be set to false initially and whenever
253 * event path creation crosses shadow boundary.
255 bool mRelatedTargetRetargetedInCurrentScope;
258 * True if Shadow DOM relatedTarget retargeting causes the current item
259 * to not show up in the event path.
261 bool mIgnoreBecauseOfShadowDOM;
264 * True if the activation behavior of the current item should run
265 * See activationTarget in https://dom.spec.whatwg.org/#concept-event-dispatch
267 bool mWantsActivationBehavior;
269 private:
271 * Parent item in the event target chain.
273 dom::EventTarget* mParentTarget;
275 public:
277 * If the event needs to be retargeted, this is the event target,
278 * which should be used when the event is handled at mParentTarget.
280 dom::EventTarget* mEventTargetAtParent;
283 * If the related target of the event needs to be retargeted, set this
284 * to a new EventTarget.
286 dom::EventTarget* mRetargetedRelatedTarget;
289 * If mEvent is a WidgetTouchEvent and its mTouches needs retargeting,
290 * set the targets to this array. The array should contain one entry per
291 * each object in WidgetTouchEvent::mTouches.
293 mozilla::Maybe<nsTArray<RefPtr<dom::EventTarget>>> mRetargetedTouchTargets;
296 * Set to the value of mEvent->mTarget of the previous scope in case of
297 * Shadow DOM or such, and if there is no anonymous content this just points
298 * to the initial target.
300 dom::EventTarget* mTargetInKnownToBeHandledScope;
303 class MOZ_STACK_CLASS EventChainPostVisitor final
304 : public mozilla::EventChainVisitor {
305 public:
306 // Note that for making guarantee the lifetime of mPresContext and mDOMEvent,
307 // creators should guarantee that aOther won't be deleted while the instance
308 // of this class is alive.
309 MOZ_CAN_RUN_SCRIPT
310 explicit EventChainPostVisitor(EventChainVisitor& aOther)
311 : EventChainVisitor(aOther.mPresContext, aOther.mEvent,
312 MOZ_KnownLive(aOther.mDOMEvent),
313 aOther.mEventStatus) {}
317 * If an EventDispatchingCallback object is passed to Dispatch,
318 * its HandleEvent method is called after handling the default event group,
319 * before handling the system event group.
320 * This is used in PresShell.
322 class MOZ_STACK_CLASS EventDispatchingCallback {
323 public:
324 MOZ_CAN_RUN_SCRIPT
325 virtual void HandleEvent(EventChainPostVisitor& aVisitor) = 0;
329 * The generic class for event dispatching.
330 * Must not be used outside Gecko!
332 class EventDispatcher {
333 public:
335 * If the target of aEvent is set before calling this method, the target of
336 * aEvent is used as the target (unless there is event
337 * retargeting) and the originalTarget of the DOM Event.
338 * aTarget is always used as the starting point for constructing the event
339 * target chain, no matter what the value of aEvent->mTarget is.
340 * In other words, aEvent->mTarget is only a property of the event and it has
341 * nothing to do with the construction of the event target chain.
342 * Neither aTarget nor aEvent is allowed to be nullptr.
344 * If aTargets is non-null, event target chain will be created, but
345 * event won't be handled. In this case aEvent->mMessage should be
346 * eVoidEvent.
347 * @note Use this method when dispatching a WidgetEvent.
349 MOZ_CAN_RUN_SCRIPT static nsresult Dispatch(
350 dom::EventTarget* aTarget, nsPresContext* aPresContext,
351 WidgetEvent* aEvent, dom::Event* aDOMEvent = nullptr,
352 nsEventStatus* aEventStatus = nullptr,
353 EventDispatchingCallback* aCallback = nullptr,
354 nsTArray<dom::EventTarget*>* aTargets = nullptr);
357 * Dispatches an event.
358 * If aDOMEvent is not nullptr, it is used for dispatching
359 * (aEvent can then be nullptr) and (if aDOMEvent is not |trusted| already),
360 * the |trusted| flag is set if the caller uses the system principal.
361 * Otherwise this works like EventDispatcher::Dispatch.
362 * @note Use this method when dispatching a dom::Event.
364 MOZ_CAN_RUN_SCRIPT static nsresult DispatchDOMEvent(
365 dom::EventTarget* aTarget, WidgetEvent* aEvent, dom::Event* aDOMEvent,
366 nsPresContext* aPresContext, nsEventStatus* aEventStatus);
369 * Creates a DOM Event. Returns null if the event type is unsupported.
371 static already_AddRefed<dom::Event> CreateEvent(
372 dom::EventTarget* aOwner, nsPresContext* aPresContext,
373 WidgetEvent* aEvent, const nsAString& aEventType,
374 dom::CallerType aCallerType = dom::CallerType::System);
376 static void GetComposedPathFor(WidgetEvent* aEvent,
377 nsTArray<RefPtr<dom::EventTarget>>& aPath);
380 * Called at shutting down.
382 static void Shutdown();
385 } // namespace mozilla
387 # endif // mozilla_EventDispatcher_h_
388 #endif