/work/obj-fuzz/dist/include/mozilla/EventStateManager.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef mozilla_EventStateManager_h_ |
8 | | #define mozilla_EventStateManager_h_ |
9 | | |
10 | | #include "mozilla/EventForwards.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 "mozilla/layers/APZUtils.h" |
19 | | #include "nsIFrame.h" |
20 | | #include "Units.h" |
21 | | #include "WheelHandlingHelper.h" // for WheelDeltaAdjustmentStrategy |
22 | | |
23 | 0 | #define NS_USER_INTERACTION_INTERVAL 5000 // ms |
24 | | |
25 | | class nsFrameLoader; |
26 | | class nsIContent; |
27 | | class nsIDocument; |
28 | | class nsIDocShell; |
29 | | class nsIDocShellTreeItem; |
30 | | class imgIContainer; |
31 | | class nsIContentViewer; |
32 | | class nsIScrollableFrame; |
33 | | class nsITimer; |
34 | | class nsPresContext; |
35 | | |
36 | | namespace mozilla { |
37 | | |
38 | | class EnterLeaveDispatcher; |
39 | | class EventStates; |
40 | | class IMEContentObserver; |
41 | | class ScrollbarsForWheel; |
42 | | class WheelTransaction; |
43 | | |
44 | | namespace dom { |
45 | | class DataTransfer; |
46 | | class Element; |
47 | | class Selection; |
48 | | class TabParent; |
49 | | } // namespace dom |
50 | | |
51 | | class OverOutElementsWrapper final : public nsISupports |
52 | | { |
53 | | ~OverOutElementsWrapper(); |
54 | | |
55 | | public: |
56 | | OverOutElementsWrapper(); |
57 | | |
58 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
59 | | NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper) |
60 | | |
61 | | WeakFrame mLastOverFrame; |
62 | | |
63 | | nsCOMPtr<nsIContent> mLastOverElement; |
64 | | |
65 | | // The last element on which we fired a over event, or null if |
66 | | // the last over event we fired has finished processing. |
67 | | nsCOMPtr<nsIContent> mFirstOverEventElement; |
68 | | |
69 | | // The last element on which we fired a out event, or null if |
70 | | // the last out event we fired has finished processing. |
71 | | nsCOMPtr<nsIContent> mFirstOutEventElement; |
72 | | }; |
73 | | |
74 | | class EventStateManager : public nsSupportsWeakReference, |
75 | | public nsIObserver |
76 | | { |
77 | | friend class mozilla::EnterLeaveDispatcher; |
78 | | friend class mozilla::ScrollbarsForWheel; |
79 | | friend class mozilla::WheelTransaction; |
80 | | |
81 | | virtual ~EventStateManager(); |
82 | | |
83 | | public: |
84 | | EventStateManager(); |
85 | | |
86 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
87 | | NS_DECL_NSIOBSERVER |
88 | | |
89 | | nsresult Init(); |
90 | | nsresult Shutdown(); |
91 | | |
92 | | /* The PreHandleEvent method is called before event dispatch to either |
93 | | * the DOM or frames. Any processing which must not be prevented or |
94 | | * cancelled should occur here. Any processing which is intended to |
95 | | * be conditional based on either DOM or frame processing should occur in |
96 | | * PostHandleEvent. Any centralized event processing which must occur before |
97 | | * DOM or frame event handling should occur here as well. |
98 | | * |
99 | | * aOverrideClickTarget can be used to indicate which element should be |
100 | | * used as the *up target when deciding whether to send click event. |
101 | | * This is used when releasing pointer capture. Otherwise null. |
102 | | */ |
103 | | nsresult PreHandleEvent(nsPresContext* aPresContext, |
104 | | WidgetEvent* aEvent, |
105 | | nsIFrame* aTargetFrame, |
106 | | nsIContent* aTargetContent, |
107 | | nsEventStatus* aStatus, |
108 | | nsIContent* aOverrideClickTarget); |
109 | | |
110 | | /* The PostHandleEvent method should contain all system processing which |
111 | | * should occur conditionally based on DOM or frame processing. It should |
112 | | * also contain any centralized event processing which must occur after |
113 | | * DOM and frame processing. |
114 | | */ |
115 | | nsresult PostHandleEvent(nsPresContext* aPresContext, |
116 | | WidgetEvent* aEvent, |
117 | | nsIFrame* aTargetFrame, |
118 | | nsEventStatus* aStatus, |
119 | | nsIContent* aOverrideClickTarget); |
120 | | |
121 | | void PostHandleKeyboardEvent(WidgetKeyboardEvent* aKeyboardEvent, |
122 | | nsIFrame* aTargetFrame, nsEventStatus& aStatus); |
123 | | |
124 | | /** |
125 | | * DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll |
126 | | * event and eLegacyMousePixelScroll event for compatibility with old Gecko. |
127 | | */ |
128 | | void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame, |
129 | | WidgetWheelEvent* aEvent, |
130 | | nsEventStatus* aStatus); |
131 | | |
132 | | void NotifyDestroyPresContext(nsPresContext* aPresContext); |
133 | | void SetPresContext(nsPresContext* aPresContext); |
134 | | void ClearFrameRefs(nsIFrame* aFrame); |
135 | | |
136 | | nsIFrame* GetEventTarget(); |
137 | | already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent); |
138 | | |
139 | | /** |
140 | | * Notify that the given NS_EVENT_STATE_* bit has changed for this content. |
141 | | * @param aContent Content which has changed states |
142 | | * @param aState Corresponding state flags such as NS_EVENT_STATE_FOCUS |
143 | | * @return Whether the content was able to change all states. Returns false |
144 | | * if a resulting DOM event causes the content node passed in |
145 | | * to not change states. Note, the frame for the content may |
146 | | * change as a result of the content state change, because of |
147 | | * frame reconstructions that may occur, but this does not |
148 | | * affect the return value. |
149 | | */ |
150 | | bool SetContentState(nsIContent* aContent, EventStates aState); |
151 | | |
152 | | void NativeAnonymousContentRemoved(nsIContent* aAnonContent); |
153 | | void ContentRemoved(nsIDocument* aDocument, nsIContent* aContent); |
154 | | |
155 | | bool EventStatusOK(WidgetGUIEvent* aEvent); |
156 | | |
157 | | /** |
158 | | * EventStateManager stores IMEContentObserver while it's observing contents. |
159 | | * Following mehtods are called by IMEContentObserver when it starts to |
160 | | * observe or stops observing the content. |
161 | | */ |
162 | | void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver); |
163 | | void OnStopObservingContent(IMEContentObserver* aIMEContentObserver); |
164 | | |
165 | | /** |
166 | | * TryToFlushPendingNotificationsToIME() suggests flushing pending |
167 | | * notifications to IME to IMEContentObserver. |
168 | | * Doesn't do anything in child processes where flushing happens |
169 | | * asynchronously. |
170 | | */ |
171 | | void TryToFlushPendingNotificationsToIME(); |
172 | | |
173 | | /** |
174 | | * Register accesskey on the given element. When accesskey is activated then |
175 | | * the element will be notified via nsIContent::PerformAccesskey() method. |
176 | | * |
177 | | * @param aElement the given element |
178 | | * @param aKey accesskey |
179 | | */ |
180 | | void RegisterAccessKey(dom::Element* aElement, uint32_t aKey); |
181 | | |
182 | | /** |
183 | | * Unregister accesskey for the given element. |
184 | | * |
185 | | * @param aElement the given element |
186 | | * @param aKey accesskey |
187 | | */ |
188 | | void UnregisterAccessKey(dom::Element* aElement, uint32_t aKey); |
189 | | |
190 | | /** |
191 | | * Get accesskey registered on the given element or 0 if there is none. |
192 | | * |
193 | | * @param aElement the given element (must not be null) |
194 | | * @return registered accesskey |
195 | | */ |
196 | | uint32_t GetRegisteredAccessKey(dom::Element* aContent); |
197 | | |
198 | | static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix); |
199 | | |
200 | | /** |
201 | | * HandleAccessKey() looks for access keys which matches with aEvent and |
202 | | * execute when it matches with a chrome access key or some content access |
203 | | * keys. |
204 | | * If the event may match chrome access keys, this handles the access key |
205 | | * synchronously (if there are nested ESMs, their HandleAccessKey() are |
206 | | * also called recursively). |
207 | | * If the event may match content access keys and focused target is a remote |
208 | | * process, this does nothing for the content because when this is called, |
209 | | * it should already have been handled in the remote process. |
210 | | * If the event may match content access keys and focused target is not in |
211 | | * remote process but there are some remote children, this will post |
212 | | * HandleAccessKey messages to all remote children. |
213 | | * |
214 | | * @return true if there is accesskey which aEvent and |
215 | | * aAccessCharCodes match with. Otherwise, false. |
216 | | * I.e., when this returns true, a target is executed |
217 | | * or focused. |
218 | | * Note that even if this returns false, a target in |
219 | | * remote process may be executed or focused |
220 | | * asynchronously. |
221 | | */ |
222 | | bool HandleAccessKey(WidgetKeyboardEvent* aEvent, |
223 | | nsPresContext* aPresContext, |
224 | | nsTArray<uint32_t>& aAccessCharCodes) |
225 | 0 | { |
226 | 0 | return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, aAccessCharCodes, |
227 | 0 | nullptr, eAccessKeyProcessingNormal, |
228 | 0 | true); |
229 | 0 | } |
230 | | |
231 | | /** |
232 | | * CheckIfEventMatchesAccessKey() looks for access key which matches with |
233 | | * aEvent in the process but won't execute it. |
234 | | * |
235 | | * @return true if there is accesskey which aEvent matches with |
236 | | * in this process. Otherwise, false. |
237 | | */ |
238 | | bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent, |
239 | | nsPresContext* aPresContext); |
240 | | |
241 | | nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer, |
242 | | bool aHaveHotspot, float aHotspotX, float aHotspotY, |
243 | | nsIWidget* aWidget, bool aLockCursor); |
244 | | |
245 | | /** |
246 | | * StartHandlingUserInput() is called when we start to handle a user input. |
247 | | * StopHandlingUserInput() is called when we finish handling a user input. |
248 | | * If the caller knows which input event caused that, it should set |
249 | | * aMessage to the event message. Otherwise, set eVoidEvent. |
250 | | * Note that StopHandlingUserInput() caller should call it with exactly same |
251 | | * event message as its corresponding StartHandlingUserInput() call because |
252 | | * these methods may count the number of specific event message. |
253 | | */ |
254 | | static void StartHandlingUserInput(EventMessage aMessage); |
255 | | static void StopHandlingUserInput(EventMessage aMessage); |
256 | | |
257 | 0 | static TimeStamp GetHandlingInputStart() { |
258 | 0 | return sHandlingInputStart; |
259 | 0 | } |
260 | | |
261 | | /** |
262 | | * Returns true if the current code is being executed as a result of |
263 | | * user input or keyboard input. The former includes anything that is |
264 | | * initiated by user, with the exception of page load events or mouse |
265 | | * over events. And the latter returns true when one of the user inputs |
266 | | * is an input from keyboard. If these methods are called from asynchronously |
267 | | * executed code, such as during layout reflows, it will return false. |
268 | | */ |
269 | | static bool IsHandlingUserInput(); |
270 | | static bool IsHandlingKeyboardInput(); |
271 | | |
272 | | /** |
273 | | * Get the number of user inputs handled since process start. This |
274 | | * includes anything that is initiated by user, with the exception |
275 | | * of page load events or mouse over events. |
276 | | */ |
277 | | static uint64_t UserInputCount() |
278 | 0 | { |
279 | 0 | return sUserInputCounter; |
280 | 0 | } |
281 | | |
282 | | /** |
283 | | * Get the timestamp at which the latest user input was handled. |
284 | | * |
285 | | * Guaranteed to be monotonic. Until the first user input, return |
286 | | * the epoch. |
287 | | */ |
288 | | static TimeStamp LatestUserInputStart() |
289 | 0 | { |
290 | 0 | return sLatestUserInputStart; |
291 | 0 | } |
292 | | |
293 | 0 | nsPresContext* GetPresContext() { return mPresContext; } |
294 | | |
295 | | NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, |
296 | | nsIObserver) |
297 | | |
298 | | static nsIDocument* sMouseOverDocument; |
299 | | |
300 | 0 | static EventStateManager* GetActiveEventStateManager() { return sActiveESM; } |
301 | | |
302 | | // Sets aNewESM to be the active event state manager, and |
303 | | // if aContent is non-null, marks the object as active. |
304 | | static void SetActiveManager(EventStateManager* aNewESM, |
305 | | nsIContent* aContent); |
306 | | |
307 | | // Sets the fullscreen event state on aElement to aIsFullscreen. |
308 | | static void SetFullscreenState(dom::Element* aElement, bool aIsFullscreen); |
309 | | |
310 | | static bool IsRemoteTarget(nsIContent* aTarget); |
311 | | |
312 | | // Returns the kind of APZ action the given WidgetWheelEvent will perform. |
313 | | static Maybe<layers::APZWheelAction> APZWheelActionFor(const WidgetWheelEvent* aEvent); |
314 | | |
315 | | // For some kinds of scrollings, the delta values of WidgetWheelEvent are |
316 | | // possbile to be adjusted. This function is used to detect such scrollings |
317 | | // and returns a wheel delta adjustment strategy to use, which is corresponded |
318 | | // to the kind of the scrolling. |
319 | | // It returns WheelDeltaAdjustmentStrategy::eAutoDir if the current default |
320 | | // action is auto-dir scrolling which honours the scrolling target(The |
321 | | // comments in WheelDeltaAdjustmentStrategy describes the concept in detail). |
322 | | // It returns WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour if the |
323 | | // current action is auto-dir scrolling which honours the root element in the |
324 | | // document where the scrolling target is(The comments in |
325 | | // WheelDeltaAdjustmentStrategy describes the concept in detail). |
326 | | // It returns WheelDeltaAdjustmentStrategy::eHorizontalize if the current |
327 | | // default action is horizontalized scrolling. |
328 | | // It returns WheelDeltaAdjustmentStrategy::eNone to mean no delta adjustment |
329 | | // strategy should be used if the scrolling is just a tranditional scrolling |
330 | | // whose delta values are never possible to be adjusted. |
331 | | static WheelDeltaAdjustmentStrategy |
332 | | GetWheelDeltaAdjustmentStrategy(const WidgetWheelEvent& aEvent); |
333 | | |
334 | | // Returns user-set multipliers for a wheel event. |
335 | | static void GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent, |
336 | | double* aOutMultiplierX, |
337 | | double* aOutMultiplierY); |
338 | | |
339 | | // Holds the point in screen coords that a mouse event was dispatched to, |
340 | | // before we went into pointer lock mode. This is constantly updated while |
341 | | // the pointer is not locked, but we don't update it while the pointer is |
342 | | // locked. This is used by dom::Event::GetScreenCoords() to make mouse |
343 | | // events' screen coord appear frozen at the last mouse position while |
344 | | // the pointer is locked. |
345 | | static CSSIntPoint sLastScreenPoint; |
346 | | |
347 | | // Holds the point in client coords of the last mouse event. Used by |
348 | | // dom::Event::GetClientCoords() to make mouse events' client coords appear |
349 | | // frozen at the last mouse position while the pointer is locked. |
350 | | static CSSIntPoint sLastClientPoint; |
351 | | |
352 | | static bool sIsPointerLocked; |
353 | | static nsWeakPtr sPointerLockedElement; |
354 | | static nsWeakPtr sPointerLockedDoc; |
355 | | |
356 | | /** |
357 | | * If the absolute values of mMultiplierX and/or mMultiplierY are equal or |
358 | | * larger than this value, the computed scroll amount isn't rounded down to |
359 | | * the page width or height. |
360 | | */ |
361 | | enum { |
362 | | MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000 |
363 | | }; |
364 | | |
365 | | protected: |
366 | | /** |
367 | | * Prefs class capsules preference management. |
368 | | */ |
369 | | class Prefs |
370 | | { |
371 | | public: |
372 | 0 | static bool KeyCausesActivation() { return sKeyCausesActivation; } |
373 | 0 | static bool ClickHoldContextMenu() { return sClickHoldContextMenu; } |
374 | | |
375 | | static void Init(); |
376 | | static void OnChange(const char* aPrefName, void*); |
377 | | static void Shutdown(); |
378 | | |
379 | | private: |
380 | | static bool sKeyCausesActivation; |
381 | | static bool sClickHoldContextMenu; |
382 | | |
383 | | static int32_t GetAccessModifierMask(int32_t aItemType); |
384 | | }; |
385 | | |
386 | | /* |
387 | | * If aTargetFrame's widget has a cached cursor value, resets the cursor |
388 | | * such that the next call to SetCursor on the widget will force an update |
389 | | * of the native cursor. For use in getting puppet widget to update its |
390 | | * cursor between mouse exit / enter transitions. This call basically wraps |
391 | | * nsIWidget ClearCachedCursor. |
392 | | */ |
393 | | void ClearCachedWidgetCursor(nsIFrame* aTargetFrame); |
394 | | |
395 | | void UpdateCursor(nsPresContext* aPresContext, |
396 | | WidgetEvent* aEvent, |
397 | | nsIFrame* aTargetFrame, |
398 | | nsEventStatus* aStatus); |
399 | | /** |
400 | | * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the specified |
401 | | * content. This returns the primary frame for the content (or null |
402 | | * if it goes away during the event). |
403 | | */ |
404 | | nsIFrame* DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent, |
405 | | EventMessage aMessage, |
406 | | nsIContent* aTargetContent, |
407 | | nsIContent* aRelatedContent); |
408 | | /** |
409 | | * Synthesize DOM pointerover and pointerout events |
410 | | */ |
411 | | void GeneratePointerEnterExit(EventMessage aMessage, |
412 | | WidgetMouseEvent* aEvent); |
413 | | /** |
414 | | * Synthesize DOM and frame mouseover and mouseout events from this |
415 | | * MOUSE_MOVE or MOUSE_EXIT event. |
416 | | */ |
417 | | void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent); |
418 | | /** |
419 | | * Tell this ESM and ESMs in parent documents that the mouse is |
420 | | * over some content in this document. |
421 | | */ |
422 | | void NotifyMouseOver(WidgetMouseEvent* aMouseEvent, |
423 | | nsIContent* aContent); |
424 | | /** |
425 | | * Tell this ESM and ESMs in affected child documents that the mouse |
426 | | * has exited this document's currently hovered content. |
427 | | * @param aMouseEvent the event that triggered the mouseout |
428 | | * @param aMovingInto the content node we've moved into. This is used to set |
429 | | * the relatedTarget for mouseout events. Also, if it's non-null |
430 | | * NotifyMouseOut will NOT change the current hover content to null; |
431 | | * in that case the caller is responsible for updating hover state. |
432 | | */ |
433 | | void NotifyMouseOut(WidgetMouseEvent* aMouseEvent, |
434 | | nsIContent* aMovingInto); |
435 | | void GenerateDragDropEnterExit(nsPresContext* aPresContext, |
436 | | WidgetDragEvent* aDragEvent); |
437 | | |
438 | | /** |
439 | | * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper elements wrapper. |
440 | | * If mPointersEnterLeaveHelper does not contain wrapper for pointerId it create new one |
441 | | */ |
442 | | OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent); |
443 | | |
444 | | /** |
445 | | * Fire the dragenter and dragexit/dragleave events when the mouse moves to a |
446 | | * new target. |
447 | | * |
448 | | * @param aRelatedTarget relatedTarget to set for the event |
449 | | * @param aTargetContent target to set for the event |
450 | | * @param aTargetFrame target frame for the event |
451 | | */ |
452 | | void FireDragEnterOrExit(nsPresContext* aPresContext, |
453 | | WidgetDragEvent* aDragEvent, |
454 | | EventMessage aMessage, |
455 | | nsIContent* aRelatedTarget, |
456 | | nsIContent* aTargetContent, |
457 | | AutoWeakFrame& aTargetFrame); |
458 | | /** |
459 | | * Update the initial drag session data transfer with any changes that occur |
460 | | * on cloned data transfer objects used for events. |
461 | | */ |
462 | | void UpdateDragDataTransfer(WidgetDragEvent* dragEvent); |
463 | | |
464 | | static nsresult InitAndDispatchClickEvent(WidgetMouseEvent* aEvent, |
465 | | nsEventStatus* aStatus, |
466 | | EventMessage aMessage, |
467 | | nsIPresShell* aPresShell, |
468 | | nsIContent* aMouseTarget, |
469 | | AutoWeakFrame aCurrentTarget, |
470 | | bool aNoContentDispatch, |
471 | | nsIContent* aOverrideClickTarget); |
472 | | nsresult SetClickCount(WidgetMouseEvent* aEvent, nsEventStatus* aStatus, |
473 | | nsIContent* aOverrideClickTarget = nullptr); |
474 | | nsresult CheckForAndDispatchClick(WidgetMouseEvent* aEvent, |
475 | | nsEventStatus* aStatus, |
476 | | nsIContent* aOverrideClickTarget); |
477 | | void EnsureDocument(nsPresContext* aPresContext); |
478 | | void FlushPendingEvents(nsPresContext* aPresContext); |
479 | | |
480 | | /** |
481 | | * The phases of WalkESMTreeToHandleAccessKey processing. See below. |
482 | | */ |
483 | | typedef enum { |
484 | | eAccessKeyProcessingNormal = 0, |
485 | | eAccessKeyProcessingUp, |
486 | | eAccessKeyProcessingDown |
487 | | } ProcessingAccessKeyState; |
488 | | |
489 | | /** |
490 | | * Walk EMS to look for access key and execute found access key when aExecute |
491 | | * is true. |
492 | | * If there is registered content for the accesskey given by the key event |
493 | | * and modifier mask then call content.PerformAccesskey(), otherwise call |
494 | | * WalkESMTreeToHandleAccessKey() recursively, on descendant docshells first, |
495 | | * then on the ancestor (with |aBubbledFrom| set to the docshell associated |
496 | | * with |this|), until something matches. |
497 | | * |
498 | | * @param aEvent the keyboard event triggering the acccess key |
499 | | * @param aPresContext the presentation context |
500 | | * @param aAccessCharCodes list of charcode candidates |
501 | | * @param aBubbledFrom is used by an ancestor to avoid calling |
502 | | * WalkESMTreeToHandleAccessKey() on the child the call originally |
503 | | * came from, i.e. this is the child that recursively called us in |
504 | | * its Up phase. The initial caller passes |nullptr| here. This is to |
505 | | * avoid an infinite loop. |
506 | | * @param aAccessKeyState Normal, Down or Up processing phase (see enums |
507 | | * above). The initial event receiver uses 'normal', then 'down' when |
508 | | * processing children and Up when recursively calling its ancestor. |
509 | | * @param aExecute is true, execute an accesskey if it's found. Otherwise, |
510 | | * found accesskey won't be executed. |
511 | | * |
512 | | * @return true if there is a target which aEvent and |
513 | | * aAccessCharCodes match with in this process. |
514 | | * Otherwise, false. I.e., when this returns true and |
515 | | * aExecute is true, a target is executed or focused. |
516 | | * Note that even if this returns false, a target in |
517 | | * remote process may be executed or focused |
518 | | * asynchronously. |
519 | | */ |
520 | | bool WalkESMTreeToHandleAccessKey(WidgetKeyboardEvent* aEvent, |
521 | | nsPresContext* aPresContext, |
522 | | nsTArray<uint32_t>& aAccessCharCodes, |
523 | | nsIDocShellTreeItem* aBubbledFrom, |
524 | | ProcessingAccessKeyState aAccessKeyState, |
525 | | bool aExecute); |
526 | | |
527 | | /** |
528 | | * Look for access key and execute found access key if aExecute is true in |
529 | | * the instance. |
530 | | * |
531 | | * @return true if there is a target which matches with |
532 | | * aAccessCharCodes and aIsTrustedEvent. Otherwise, |
533 | | * false. I.e., when this returns true and aExecute |
534 | | * is true, a target is executed or focused. |
535 | | */ |
536 | | bool LookForAccessKeyAndExecute(nsTArray<uint32_t>& aAccessCharCodes, |
537 | | bool aIsTrustedEvent, |
538 | | bool aExecute); |
539 | | |
540 | | //--------------------------------------------- |
541 | | // DocShell Focus Traversal Methods |
542 | | //--------------------------------------------- |
543 | | |
544 | | nsIContent* GetFocusedContent(); |
545 | | bool IsShellVisible(nsIDocShell* aShell); |
546 | | |
547 | | // These functions are for mousewheel and pixel scrolling |
548 | | |
549 | | class WheelPrefs |
550 | | { |
551 | | public: |
552 | | static WheelPrefs* GetInstance(); |
553 | | static void Shutdown(); |
554 | | |
555 | | /** |
556 | | * ApplyUserPrefsToDelta() overrides the wheel event's delta values with |
557 | | * user prefs. |
558 | | */ |
559 | | void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent); |
560 | | |
561 | | /** |
562 | | * Returns whether or not ApplyUserPrefsToDelta() would change the delta |
563 | | * values of an event. |
564 | | */ |
565 | | void GetUserPrefsForEvent(const WidgetWheelEvent* aEvent, |
566 | | double* aOutMultiplierX, |
567 | | double* aOutMultiplierY); |
568 | | |
569 | | /** |
570 | | * If ApplyUserPrefsToDelta() changed the delta values with customized |
571 | | * prefs, the overflowDelta values would be inflated. |
572 | | * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation. |
573 | | */ |
574 | | void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent); |
575 | | |
576 | | /** |
577 | | * Computes the default action for the aEvent with the prefs. |
578 | | */ |
579 | | enum Action : uint8_t |
580 | | { |
581 | | ACTION_NONE = 0, |
582 | | ACTION_SCROLL, |
583 | | ACTION_HISTORY, |
584 | | ACTION_ZOOM, |
585 | | // Horizontalized scrolling means treating vertical wheel scrolling as |
586 | | // horizontal scrolling during the process of its default action and |
587 | | // plugins handling scrolling. Note that delta values as the event object |
588 | | // in a DOM event listener won't be affected, and will be still the |
589 | | // original values. For more details, refer to |
590 | | // mozilla::WheelDeltaAdjustmentStrategy::eHorizontalize |
591 | | ACTION_HORIZONTALIZED_SCROLL, |
592 | | ACTION_PINCH_ZOOM, |
593 | | ACTION_LAST = ACTION_PINCH_ZOOM, |
594 | | // Following actions are used only by internal processing. So, cannot |
595 | | // specified by prefs. |
596 | | ACTION_SEND_TO_PLUGIN, |
597 | | }; |
598 | | Action ComputeActionFor(const WidgetWheelEvent* aEvent); |
599 | | |
600 | | /** |
601 | | * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be |
602 | | * computed the lineOrPageDelta values. |
603 | | */ |
604 | | bool NeedToComputeLineOrPageDelta(const WidgetWheelEvent* aEvent); |
605 | | |
606 | | /** |
607 | | * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should |
608 | | * be rounded down to the page width/height (false) or not (true). |
609 | | */ |
610 | | bool IsOverOnePageScrollAllowedX(const WidgetWheelEvent* aEvent); |
611 | | bool IsOverOnePageScrollAllowedY(const WidgetWheelEvent* aEvent); |
612 | | |
613 | | /** |
614 | | * WheelEventsEnabledOnPlugins() returns true if user wants to use mouse |
615 | | * wheel on plugins. |
616 | | */ |
617 | | static bool WheelEventsEnabledOnPlugins(); |
618 | | |
619 | | /** |
620 | | * Returns whether the auto-dir feature is enabled for wheel scrolling. For |
621 | | * detailed information on auto-dir, |
622 | | * @see mozilla::WheelDeltaAdjustmentStrategy. |
623 | | */ |
624 | | static bool IsAutoDirEnabled(); |
625 | | |
626 | | /** |
627 | | * Returns whether auto-dir scrolling honours root elements instead of the |
628 | | * scrolling targets. For detailed information on auto-dir, |
629 | | * @see mozilla::WheelDeltaAdjustmentStrategy. |
630 | | */ |
631 | | static bool HonoursRootForAutoDir(); |
632 | | |
633 | | private: |
634 | | WheelPrefs(); |
635 | | ~WheelPrefs(); |
636 | | |
637 | | static void OnPrefChanged(const char* aPrefName, void* aClosure); |
638 | | |
639 | | enum Index |
640 | | { |
641 | | INDEX_DEFAULT = 0, |
642 | | INDEX_ALT, |
643 | | INDEX_CONTROL, |
644 | | INDEX_META, |
645 | | INDEX_SHIFT, |
646 | | INDEX_OS, |
647 | | COUNT_OF_MULTIPLIERS |
648 | | }; |
649 | | |
650 | | /** |
651 | | * GetIndexFor() returns the index of the members which should be used for |
652 | | * the aEvent. When only one modifier key of MODIFIER_ALT, |
653 | | * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is |
654 | | * pressed, returns the index for the modifier. Otherwise, this return the |
655 | | * default index which is used at either no modifier key is pressed or |
656 | | * two or modifier keys are pressed. |
657 | | */ |
658 | | Index GetIndexFor(const WidgetWheelEvent* aEvent); |
659 | | |
660 | | /** |
661 | | * GetPrefNameBase() returns the base pref name for aEvent. |
662 | | * It's decided by GetModifierForPref() which modifier should be used for |
663 | | * the aEvent. |
664 | | * |
665 | | * @param aBasePrefName The result, must be "mousewheel.with_*." or |
666 | | * "mousewheel.default.". |
667 | | */ |
668 | | void GetBasePrefName(Index aIndex, nsACString& aBasePrefName); |
669 | | |
670 | | void Init(Index aIndex); |
671 | | |
672 | | void Reset(); |
673 | | |
674 | | /** |
675 | | * Retrieve multiplier for aEvent->mDeltaX and aEvent->mDeltaY. |
676 | | * |
677 | | * Note that if the default action is ACTION_HORIZONTALIZED_SCROLL and the |
678 | | * delta values have been adjusted by WheelDeltaHorizontalizer() before this |
679 | | * function is called, this function will swap the X and Y multipliers. By |
680 | | * doing this, multipliers will still apply to the delta values they |
681 | | * originally corresponded to. |
682 | | * |
683 | | * @param aEvent The event which is being handled. |
684 | | * @param aIndex The index of mMultiplierX and mMultiplierY. |
685 | | * Should be result of GetIndexFor(aEvent). |
686 | | * @param aMultiplierForDeltaX Will be set to multiplier for |
687 | | * aEvent->mDeltaX. |
688 | | * @param aMultiplierForDeltaY Will be set to multiplier for |
689 | | * aEvent->mDeltaY. |
690 | | */ |
691 | | void GetMultiplierForDeltaXAndY(const WidgetWheelEvent* aEvent, |
692 | | Index aIndex, |
693 | | double* aMultiplierForDeltaX, |
694 | | double* aMultiplierForDeltaY); |
695 | | |
696 | | bool mInit[COUNT_OF_MULTIPLIERS]; |
697 | | double mMultiplierX[COUNT_OF_MULTIPLIERS]; |
698 | | double mMultiplierY[COUNT_OF_MULTIPLIERS]; |
699 | | double mMultiplierZ[COUNT_OF_MULTIPLIERS]; |
700 | | Action mActions[COUNT_OF_MULTIPLIERS]; |
701 | | /** |
702 | | * action values overridden by .override_x pref. |
703 | | * If an .override_x value is -1, same as the |
704 | | * corresponding mActions value. |
705 | | */ |
706 | | Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS]; |
707 | | |
708 | | static WheelPrefs* sInstance; |
709 | | static bool sWheelEventsEnabledOnPlugins; |
710 | | static bool sIsAutoDirEnabled; |
711 | | static bool sHonoursRootForAutoDir; |
712 | | }; |
713 | | |
714 | | /** |
715 | | * DeltaDirection is used for specifying whether the called method should |
716 | | * handle vertical delta or horizontal delta. |
717 | | * This is clearer than using bool. |
718 | | */ |
719 | | enum DeltaDirection |
720 | | { |
721 | | DELTA_DIRECTION_X = 0, |
722 | | DELTA_DIRECTION_Y |
723 | | }; |
724 | | |
725 | | struct MOZ_STACK_CLASS EventState |
726 | | { |
727 | | bool mDefaultPrevented; |
728 | | bool mDefaultPreventedByContent; |
729 | | |
730 | | EventState() : |
731 | | mDefaultPrevented(false), mDefaultPreventedByContent(false) |
732 | 0 | { |
733 | 0 | } |
734 | | }; |
735 | | |
736 | | /** |
737 | | * SendLineScrollEvent() dispatches a DOMMouseScroll event for the |
738 | | * WidgetWheelEvent. This method shouldn't be called for non-trusted |
739 | | * wheel event because it's not necessary for compatiblity. |
740 | | * |
741 | | * @param aTargetFrame The event target of wheel event. |
742 | | * @param aEvent The original Wheel event. |
743 | | * @param aState The event which should be set to the dispatching |
744 | | * event. This also returns the dispatched event |
745 | | * state. |
746 | | * @param aDelta The delta value of the event. |
747 | | * @param aDeltaDirection The X/Y direction of dispatching event. |
748 | | */ |
749 | | void SendLineScrollEvent(nsIFrame* aTargetFrame, |
750 | | WidgetWheelEvent* aEvent, |
751 | | EventState& aState, |
752 | | int32_t aDelta, |
753 | | DeltaDirection aDeltaDirection); |
754 | | |
755 | | /** |
756 | | * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the |
757 | | * WidgetWheelEvent. This method shouldn't be called for non-trusted |
758 | | * wheel event because it's not necessary for compatiblity. |
759 | | * |
760 | | * @param aTargetFrame The event target of wheel event. |
761 | | * @param aEvent The original Wheel event. |
762 | | * @param aState The event which should be set to the dispatching |
763 | | * event. This also returns the dispatched event |
764 | | * state. |
765 | | * @param aPixelDelta The delta value of the event. |
766 | | * @param aDeltaDirection The X/Y direction of dispatching event. |
767 | | */ |
768 | | void SendPixelScrollEvent(nsIFrame* aTargetFrame, |
769 | | WidgetWheelEvent* aEvent, |
770 | | EventState& aState, |
771 | | int32_t aPixelDelta, |
772 | | DeltaDirection aDeltaDirection); |
773 | | |
774 | | /** |
775 | | * ComputeScrollTargetAndMayAdjustWheelEvent() returns the scrollable frame |
776 | | * which should be scrolled. |
777 | | * |
778 | | * @param aTargetFrame The event target of the wheel event. |
779 | | * @param aEvent The handling mouse wheel event. |
780 | | * @param aOptions The options for finding the scroll target. |
781 | | * Callers should use COMPUTE_*. |
782 | | * @return The scrollable frame which should be scrolled. |
783 | | */ |
784 | | // These flags are used in ComputeScrollTargetAndMayAdjustWheelEvent(). |
785 | | // Callers should use COMPUTE_*. |
786 | | enum |
787 | | { |
788 | | PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001, |
789 | | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002, |
790 | | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004, |
791 | | START_FROM_PARENT = 0x00000008, |
792 | | INCLUDE_PLUGIN_AS_TARGET = 0x00000010, |
793 | | // Indicates the wheel scroll event being computed is an auto-dir scroll, so |
794 | | // its delta may be adjusted after being computed. |
795 | | MAY_BE_ADJUSTED_BY_AUTO_DIR = 0x00000020, |
796 | | }; |
797 | | enum ComputeScrollTargetOptions |
798 | | { |
799 | | // At computing scroll target for legacy mouse events, we should return |
800 | | // first scrollable element even when it's not scrollable to the direction. |
801 | | COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0, |
802 | | // Default action prefers the scrolled element immediately before if it's |
803 | | // still under the mouse cursor. Otherwise, it prefers the nearest |
804 | | // scrollable ancestor which will be scrolled actually. |
805 | | COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN = |
806 | | (PREFER_MOUSE_WHEEL_TRANSACTION | |
807 | | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | |
808 | | PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS), |
809 | | // When this is specified, the result may be nsPluginFrame. In such case, |
810 | | // the frame doesn't have nsIScrollableFrame interface. |
811 | | COMPUTE_DEFAULT_ACTION_TARGET = |
812 | | (COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN | |
813 | | INCLUDE_PLUGIN_AS_TARGET), |
814 | | COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR_EXCEPT_PLUGIN = |
815 | | (COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN | |
816 | | MAY_BE_ADJUSTED_BY_AUTO_DIR), |
817 | | COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR = |
818 | | (COMPUTE_DEFAULT_ACTION_TARGET | |
819 | | MAY_BE_ADJUSTED_BY_AUTO_DIR), |
820 | | // Look for the nearest scrollable ancestor which can be scrollable with |
821 | | // aEvent. |
822 | | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS = |
823 | | (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT), |
824 | | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS = |
825 | | (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT), |
826 | | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR = |
827 | | (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS | MAY_BE_ADJUSTED_BY_AUTO_DIR), |
828 | | COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR = |
829 | | (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS | MAY_BE_ADJUSTED_BY_AUTO_DIR), |
830 | | }; |
831 | | static ComputeScrollTargetOptions RemovePluginFromTarget( |
832 | | ComputeScrollTargetOptions aOptions) |
833 | 0 | { |
834 | 0 | switch (aOptions) { |
835 | 0 | case COMPUTE_DEFAULT_ACTION_TARGET: |
836 | 0 | return COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN; |
837 | 0 | case COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR: |
838 | 0 | return COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR_EXCEPT_PLUGIN; |
839 | 0 | default: |
840 | 0 | MOZ_ASSERT(!(aOptions & INCLUDE_PLUGIN_AS_TARGET)); |
841 | 0 | return aOptions; |
842 | 0 | } |
843 | 0 | } |
844 | | |
845 | | // Compute the scroll target. |
846 | | // The delta values in the wheel event may be changed if the event is for |
847 | | // auto-dir scrolling. For information on auto-dir, |
848 | | // @see mozilla::WheelDeltaAdjustmentStrategy |
849 | | nsIFrame* ComputeScrollTargetAndMayAdjustWheelEvent( |
850 | | nsIFrame* aTargetFrame, |
851 | | WidgetWheelEvent* aEvent, |
852 | | ComputeScrollTargetOptions aOptions); |
853 | | |
854 | | nsIFrame* ComputeScrollTargetAndMayAdjustWheelEvent( |
855 | | nsIFrame* aTargetFrame, |
856 | | double aDirectionX, |
857 | | double aDirectionY, |
858 | | WidgetWheelEvent* aEvent, |
859 | | ComputeScrollTargetOptions aOptions); |
860 | | |
861 | | nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, |
862 | | WidgetWheelEvent* aEvent, |
863 | | ComputeScrollTargetOptions aOptions) |
864 | 0 | { |
865 | 0 | MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR), |
866 | 0 | "aEvent may be modified by auto-dir"); |
867 | 0 | return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, aEvent, |
868 | 0 | aOptions); |
869 | 0 | } |
870 | | |
871 | | nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame, |
872 | | double aDirectionX, |
873 | | double aDirectionY, |
874 | | WidgetWheelEvent* aEvent, |
875 | | ComputeScrollTargetOptions aOptions) |
876 | 0 | { |
877 | 0 | MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR), |
878 | 0 | "aEvent may be modified by auto-dir"); |
879 | 0 | return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, |
880 | 0 | aDirectionX, aDirectionY, |
881 | 0 | aEvent, aOptions); |
882 | 0 | } |
883 | | |
884 | | /** |
885 | | * GetScrollAmount() returns the scroll amount in app uints of one line or |
886 | | * one page. If the wheel event scrolls a page, returns the page width and |
887 | | * height. Otherwise, returns line height for both its width and height. |
888 | | * |
889 | | * @param aScrollableFrame A frame which will be scrolled by the event. |
890 | | * The result of |
891 | | * ComputeScrollTargetAndMayAdjustWheelEvent() is |
892 | | * expected for this value. |
893 | | * This can be nullptr if there is no scrollable |
894 | | * frame. Then, this method uses root frame's |
895 | | * line height or visible area's width and height. |
896 | | */ |
897 | | nsSize GetScrollAmount(nsPresContext* aPresContext, |
898 | | WidgetWheelEvent* aEvent, |
899 | | nsIScrollableFrame* aScrollableFrame); |
900 | | |
901 | | /** |
902 | | * DoScrollText() scrolls the scrollable frame for aEvent. |
903 | | */ |
904 | | void DoScrollText(nsIScrollableFrame* aScrollableFrame, |
905 | | WidgetWheelEvent* aEvent); |
906 | | |
907 | | void DoScrollHistory(int32_t direction); |
908 | | void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment); |
909 | | nsresult GetContentViewer(nsIContentViewer** aCv); |
910 | | nsresult ChangeTextSize(int32_t change); |
911 | | nsresult ChangeFullZoom(int32_t change); |
912 | | |
913 | | /** |
914 | | * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll |
915 | | * event. If wheel events are caused by pixel scroll only devices or |
916 | | * the delta values are customized by prefs, this class stores the delta |
917 | | * values and set lineOrPageDelta values. |
918 | | */ |
919 | | class DeltaAccumulator |
920 | | { |
921 | | public: |
922 | | static DeltaAccumulator* GetInstance() |
923 | 0 | { |
924 | 0 | if (!sInstance) { |
925 | 0 | sInstance = new DeltaAccumulator; |
926 | 0 | } |
927 | 0 | return sInstance; |
928 | 0 | } |
929 | | |
930 | | static void Shutdown() |
931 | 0 | { |
932 | 0 | delete sInstance; |
933 | 0 | sInstance = nullptr; |
934 | 0 | } |
935 | | |
936 | 0 | bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; } |
937 | | |
938 | | /** |
939 | | * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents |
940 | | * which are caused if it's needed. And if the accumulated delta becomes a |
941 | | * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically. |
942 | | */ |
943 | | void InitLineOrPageDelta(nsIFrame* aTargetFrame, |
944 | | EventStateManager* aESM, |
945 | | WidgetWheelEvent* aEvent); |
946 | | |
947 | | /** |
948 | | * Reset() resets all members. |
949 | | */ |
950 | | void Reset(); |
951 | | |
952 | | /** |
953 | | * ComputeScrollAmountForDefaultAction() computes the default action's |
954 | | * scroll amount in device pixels with mPendingScrollAmount*. |
955 | | */ |
956 | | nsIntPoint ComputeScrollAmountForDefaultAction( |
957 | | WidgetWheelEvent* aEvent, |
958 | | const nsIntSize& aScrollAmountInDevPixels); |
959 | | |
960 | | private: |
961 | | DeltaAccumulator() : |
962 | | mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0), |
963 | | mHandlingDeltaMode(UINT32_MAX), mIsNoLineOrPageDeltaDevice(false) |
964 | 0 | { |
965 | 0 | } |
966 | | |
967 | | double mX; |
968 | | double mY; |
969 | | |
970 | | // When default action of a wheel event is scroll but some delta values |
971 | | // are ignored because the computed amount values are not integer, the |
972 | | // fractional values are saved by these members. |
973 | | double mPendingScrollAmountX; |
974 | | double mPendingScrollAmountY; |
975 | | |
976 | | TimeStamp mLastTime; |
977 | | |
978 | | uint32_t mHandlingDeltaMode; |
979 | | bool mIsNoLineOrPageDeltaDevice; |
980 | | |
981 | | static DeltaAccumulator* sInstance; |
982 | | }; |
983 | | |
984 | | // end mousewheel functions |
985 | | |
986 | | /* |
987 | | * When a touch gesture is about to start, this function determines what |
988 | | * kind of gesture interaction we will want to use, based on what is |
989 | | * underneath the initial touch point. |
990 | | * Currently it decides between panning (finger scrolling) or dragging |
991 | | * the target element, as well as the orientation to trigger panning and |
992 | | * display visual boundary feedback. The decision is stored back in aEvent. |
993 | | */ |
994 | | void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent, |
995 | | nsIFrame* targetFrame); |
996 | | |
997 | | // routines for the d&d gesture tracking state machine |
998 | | void BeginTrackingDragGesture(nsPresContext* aPresContext, |
999 | | WidgetMouseEvent* aDownEvent, |
1000 | | nsIFrame* aDownFrame); |
1001 | | |
1002 | | friend class mozilla::dom::TabParent; |
1003 | | void BeginTrackingRemoteDragGesture(nsIContent* aContent); |
1004 | | void StopTrackingDragGesture(); |
1005 | | void GenerateDragGesture(nsPresContext* aPresContext, |
1006 | | WidgetInputEvent* aEvent); |
1007 | | |
1008 | | /** |
1009 | | * When starting a dnd session, UA must fire a pointercancel event and stop |
1010 | | * firing the subsequent pointer events. |
1011 | | */ |
1012 | | void MaybeFirePointerCancel(WidgetInputEvent* aEvent); |
1013 | | |
1014 | | /** |
1015 | | * Determine which node the drag should be targeted at. |
1016 | | * This is either the node clicked when there is a selection, or, for HTML, |
1017 | | * the element with a draggable property set to true. |
1018 | | * |
1019 | | * aSelectionTarget - target to check for selection |
1020 | | * aDataTransfer - data transfer object that will contain the data to drag |
1021 | | * aSelection - [out] set to the selection to be dragged |
1022 | | * aTargetNode - [out] the draggable node, or null if there isn't one |
1023 | | * aPrincipalURISpec - [out] set to the URI of the triggering principal of |
1024 | | * the drag, or an empty string if it's from |
1025 | | * browser chrome or OS |
1026 | | */ |
1027 | | void DetermineDragTargetAndDefaultData(nsPIDOMWindowOuter* aWindow, |
1028 | | nsIContent* aSelectionTarget, |
1029 | | dom::DataTransfer* aDataTransfer, |
1030 | | dom::Selection** aSelection, |
1031 | | nsIContent** aTargetNode, |
1032 | | nsACString& aPrincipalURISpec); |
1033 | | |
1034 | | /* |
1035 | | * Perform the default handling for the dragstart event and set up a |
1036 | | * drag for aDataTransfer if it contains any data. Returns true if a drag has |
1037 | | * started. |
1038 | | * |
1039 | | * aDragEvent - the dragstart event |
1040 | | * aDataTransfer - the data transfer that holds the data to be dragged |
1041 | | * aDragTarget - the target of the drag |
1042 | | * aSelection - the selection to be dragged |
1043 | | * aPrincipalURISpec - the URI of the triggering principal of the drag, |
1044 | | * or an empty string if it's from browser chrome or OS |
1045 | | */ |
1046 | | bool DoDefaultDragStart(nsPresContext* aPresContext, |
1047 | | WidgetDragEvent* aDragEvent, |
1048 | | dom::DataTransfer* aDataTransfer, |
1049 | | nsIContent* aDragTarget, |
1050 | | dom::Selection* aSelection, |
1051 | | const nsACString& aPrincipalURISpec); |
1052 | | |
1053 | 0 | bool IsTrackingDragGesture ( ) const { return mGestureDownContent != nullptr; } |
1054 | | /** |
1055 | | * Set the fields of aEvent to reflect the mouse position and modifier keys |
1056 | | * that were set when the user first pressed the mouse button (stored by |
1057 | | * BeginTrackingDragGesture). aEvent->mWidget must be |
1058 | | * mCurrentTarget->GetNearestWidget(). |
1059 | | */ |
1060 | | void FillInEventFromGestureDown(WidgetMouseEvent* aEvent); |
1061 | | |
1062 | | nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent); |
1063 | | nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent); |
1064 | | |
1065 | | dom::TabParent *GetCrossProcessTarget(); |
1066 | | bool IsTargetCrossProcess(WidgetGUIEvent* aEvent); |
1067 | | |
1068 | | /** |
1069 | | * DispatchCrossProcessEvent() try to post aEvent to target remote process. |
1070 | | * If you need to check if the event is posted to a remote process, you |
1071 | | * can use aEvent->HasBeenPostedToRemoteProcess(). |
1072 | | */ |
1073 | | void DispatchCrossProcessEvent(WidgetEvent* aEvent, |
1074 | | nsFrameLoader* aRemote, |
1075 | | nsEventStatus *aStatus); |
1076 | | /** |
1077 | | * HandleCrossProcessEvent() may post aEvent to target remote processes. |
1078 | | * When it succeeded to post the event to at least one remote process, |
1079 | | * returns true. Otherwise, including the case not tried to dispatch to |
1080 | | * post the event, returns false. |
1081 | | * If you need to check if the event is posted to at least one remote |
1082 | | * process, you can use aEvent->HasBeenPostedToRemoteProcess(). |
1083 | | */ |
1084 | | bool HandleCrossProcessEvent(WidgetEvent* aEvent, |
1085 | | nsEventStatus* aStatus); |
1086 | | |
1087 | | void ReleaseCurrentIMEContentObserver(); |
1088 | | |
1089 | | void HandleQueryContentEvent(WidgetQueryContentEvent* aEvent); |
1090 | | |
1091 | | private: |
1092 | | // Removes a node from the :hover / :active chain if needed, notifying if the |
1093 | | // node is not a NAC subtree. |
1094 | | // |
1095 | | // Only meant to be called from ContentRemoved and |
1096 | | // NativeAnonymousContentRemoved. |
1097 | | void RemoveNodeFromChainIfNeeded(EventStates aState, |
1098 | | nsIContent* aContentRemoved, |
1099 | | bool aNotify); |
1100 | | |
1101 | | bool IsEventOutsideDragThreshold(WidgetInputEvent* aEvent) const; |
1102 | | |
1103 | | static inline void DoStateChange(dom::Element* aElement, |
1104 | | EventStates aState, bool aAddState); |
1105 | | static inline void DoStateChange(nsIContent* aContent, EventStates aState, |
1106 | | bool aAddState); |
1107 | | static void UpdateAncestorState(nsIContent* aStartNode, |
1108 | | nsIContent* aStopBefore, |
1109 | | EventStates aState, |
1110 | | bool aAddState); |
1111 | | static void ResetLastOverForContent(const uint32_t& aIdx, |
1112 | | RefPtr<OverOutElementsWrapper>& aChunk, |
1113 | | nsIContent* aClosure); |
1114 | | |
1115 | | /** |
1116 | | * Update the attribute mLastRefPoint of the mouse event. It should be |
1117 | | * the center of the window while the pointer is locked. |
1118 | | * the same value as mRefPoint while there is no known last ref point. |
1119 | | * the same value as the last known mRefPoint. |
1120 | | */ |
1121 | | static void UpdateLastRefPointOfMouseEvent(WidgetMouseEvent* aMouseEvent); |
1122 | | |
1123 | | static void ResetPointerToWindowCenterWhilePointerLocked( |
1124 | | WidgetMouseEvent* aMouseEvent); |
1125 | | |
1126 | | // Update the last known ref point to the current event's mRefPoint. |
1127 | | static void UpdateLastPointerPosition(WidgetMouseEvent* aMouseEvent); |
1128 | | |
1129 | | /** |
1130 | | * Notify target when user has been interaction with some speicific user |
1131 | | * gestures which are eKeyUp, eMouseUp, eTouchEnd. |
1132 | | */ |
1133 | | void NotifyTargetUserActivation(WidgetEvent* aEvent, |
1134 | | nsIContent* aTargetContent); |
1135 | | |
1136 | | already_AddRefed<EventStateManager> ESMFromContentOrThis(nsIContent* aContent); |
1137 | | |
1138 | | int32_t mLockCursor; |
1139 | | bool mLastFrameConsumedSetCursor; |
1140 | | |
1141 | | // Last mouse event mRefPoint (the offset from the widget's origin in |
1142 | | // device pixels) when mouse was locked, used to restore mouse position |
1143 | | // after unlocking. |
1144 | | static LayoutDeviceIntPoint sPreLockPoint; |
1145 | | |
1146 | | // Stores the mRefPoint of the last synthetic mouse move we dispatched |
1147 | | // to re-center the mouse when we were pointer locked. If this is (-1,-1) it |
1148 | | // means we've not recently dispatched a centering event. We use this to |
1149 | | // detect when we receive the synth event, so we can cancel and not send it |
1150 | | // to content. |
1151 | | static LayoutDeviceIntPoint sSynthCenteringPoint; |
1152 | | |
1153 | | WeakFrame mCurrentTarget; |
1154 | | nsCOMPtr<nsIContent> mCurrentTargetContent; |
1155 | | static AutoWeakFrame sLastDragOverFrame; |
1156 | | |
1157 | | // Stores the mRefPoint (the offset from the widget's origin in device |
1158 | | // pixels) of the last mouse event. |
1159 | | static LayoutDeviceIntPoint sLastRefPoint; |
1160 | | |
1161 | | // member variables for the d&d gesture state machine |
1162 | | LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates |
1163 | | // The content to use as target if we start a d&d (what we drag). |
1164 | | nsCOMPtr<nsIContent> mGestureDownContent; |
1165 | | // The content of the frame where the mouse-down event occurred. It's the same |
1166 | | // as the target in most cases but not always - for example when dragging |
1167 | | // an <area> of an image map this is the image. (bug 289667) |
1168 | | nsCOMPtr<nsIContent> mGestureDownFrameOwner; |
1169 | | // State of keys when the original gesture-down happened |
1170 | | Modifiers mGestureModifiers; |
1171 | | uint16_t mGestureDownButtons; |
1172 | | |
1173 | | nsCOMPtr<nsIContent> mLastLeftMouseDownContent; |
1174 | | nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent; |
1175 | | nsCOMPtr<nsIContent> mLastMiddleMouseDownContent; |
1176 | | nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent; |
1177 | | nsCOMPtr<nsIContent> mLastRightMouseDownContent; |
1178 | | nsCOMPtr<nsIContent> mLastRightMouseDownContentParent; |
1179 | | |
1180 | | nsCOMPtr<nsIContent> mActiveContent; |
1181 | | nsCOMPtr<nsIContent> mHoverContent; |
1182 | | static nsCOMPtr<nsIContent> sDragOverContent; |
1183 | | nsCOMPtr<nsIContent> mURLTargetContent; |
1184 | | |
1185 | | nsPresContext* mPresContext; // Not refcnted |
1186 | | nsCOMPtr<nsIDocument> mDocument; // Doesn't necessarily need to be owner |
1187 | | |
1188 | | RefPtr<IMEContentObserver> mIMEContentObserver; |
1189 | | |
1190 | | uint32_t mLClickCount; |
1191 | | uint32_t mMClickCount; |
1192 | | uint32_t mRClickCount; |
1193 | | |
1194 | | bool mInTouchDrag; |
1195 | | |
1196 | | bool m_haveShutdown; |
1197 | | |
1198 | | // Time at which we began handling user input. Reset to the epoch |
1199 | | // once we have finished handling user input. |
1200 | | static TimeStamp sHandlingInputStart; |
1201 | | |
1202 | | // Time at which we began handling the latest user input. Not reset |
1203 | | // at the end of the input. |
1204 | | static TimeStamp sLatestUserInputStart; |
1205 | | |
1206 | | RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper; |
1207 | | nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper; |
1208 | | |
1209 | | public: |
1210 | | static nsresult UpdateUserActivityTimer(void); |
1211 | | // Array for accesskey support |
1212 | | nsCOMArray<nsIContent> mAccessKeys; |
1213 | | |
1214 | | // The number of user inputs handled since process start. This |
1215 | | // includes anything that is initiated by user, with the exception |
1216 | | // of page load events or mouse over events. |
1217 | | static uint64_t sUserInputCounter; |
1218 | | |
1219 | | // The current depth of user and keyboard inputs. sUserInputEventDepth |
1220 | | // is the number of any user input events, page load events and mouse over |
1221 | | // events. sUserKeyboardEventDepth is the number of keyboard input events. |
1222 | | // Incremented whenever we start handling a user input, decremented when we |
1223 | | // have finished handling a user input. This depth is *not* reset in case |
1224 | | // of nested event loops. |
1225 | | static int32_t sUserInputEventDepth; |
1226 | | static int32_t sUserKeyboardEventDepth; |
1227 | | |
1228 | | static bool sNormalLMouseEventInProcess; |
1229 | | |
1230 | | static EventStateManager* sActiveESM; |
1231 | | |
1232 | | static void ClearGlobalActiveContent(EventStateManager* aClearer); |
1233 | | |
1234 | | // Functions used for click hold context menus |
1235 | | nsCOMPtr<nsITimer> mClickHoldTimer; |
1236 | | void CreateClickHoldTimer(nsPresContext* aPresContext, |
1237 | | nsIFrame* aDownFrame, |
1238 | | WidgetGUIEvent* aMouseDownEvent); |
1239 | | void KillClickHoldTimer(); |
1240 | | void FireContextClick(); |
1241 | | |
1242 | | static void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ; |
1243 | | static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ; |
1244 | | }; |
1245 | | |
1246 | | /** |
1247 | | * This class is used while processing real user input. During this time, popups |
1248 | | * are allowed. For mousedown events, mouse capturing is also permitted. |
1249 | | */ |
1250 | | class AutoHandlingUserInputStatePusher |
1251 | | { |
1252 | | public: |
1253 | | AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput, |
1254 | | WidgetEvent* aEvent, |
1255 | | nsIDocument* aDocument); |
1256 | | ~AutoHandlingUserInputStatePusher(); |
1257 | | |
1258 | | protected: |
1259 | | nsCOMPtr<nsIDocument> mMouseButtonEventHandlingDocument; |
1260 | | EventMessage mMessage; |
1261 | | bool mIsHandlingUserInput; |
1262 | | |
1263 | | bool NeedsToResetFocusManagerMouseButtonHandlingState() const |
1264 | 0 | { |
1265 | 0 | return mMessage == eMouseDown || mMessage == eMouseUp; |
1266 | 0 | } |
1267 | | |
1268 | | private: |
1269 | | // Hide so that this class can only be stack-allocated |
1270 | 0 | static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; } |
1271 | 0 | static void operator delete(void* /*memory*/) {} |
1272 | | }; |
1273 | | |
1274 | | } // namespace mozilla |
1275 | | |
1276 | | // Click and double-click events need to be handled even for content that |
1277 | | // has no frame. This is required for Web compatibility. |
1278 | | #define NS_EVENT_NEEDS_FRAME(event) \ |
1279 | 0 | (!(event)->HasPluginActivationEventMessage() && \ |
1280 | 0 | (event)->mMessage != eMouseClick && \ |
1281 | 0 | (event)->mMessage != eMouseDoubleClick && \ |
1282 | 0 | (event)->mMessage != eMouseAuxClick) |
1283 | | |
1284 | | #endif // mozilla_EventStateManager_h_ |