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