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