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