Bug 1895153 - Implement "Find in page..." menu functionality r=android-reviewers...
[gecko.git] / dom / events / EventStateManager.h
blob4f890c1ce863f90d8c0c17d9ccbfbea2b369de5b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_EventStateManager_h_
8 #define mozilla_EventStateManager_h_
10 #include "mozilla/EventForwards.h"
12 #include "nsIObserver.h"
13 #include "nsWeakReference.h"
14 #include "nsCOMPtr.h"
15 #include "nsCOMArray.h"
16 #include "nsCycleCollectionParticipant.h"
17 #include "nsIWeakReferenceUtils.h"
18 #include "nsRefPtrHashtable.h"
19 #include "mozilla/Attributes.h"
20 #include "mozilla/TimeStamp.h"
21 #include "mozilla/layers/APZPublicUtils.h"
22 #include "mozilla/dom/Record.h"
23 #include "Units.h"
24 #include "WheelHandlingHelper.h" // for WheelDeltaAdjustmentStrategy
26 class nsFrameLoader;
27 class nsIContent;
28 class nsICookieJarSettings;
29 class nsIDocShell;
30 class nsIDocShellTreeItem;
31 class nsIFrame;
32 class imgIContainer;
33 class nsIDocumentViewer;
34 class nsITimer;
35 class nsIWidget;
36 class nsPresContext;
38 enum class FormControlType : uint8_t;
40 namespace mozilla {
42 class EditorBase;
43 class EnterLeaveDispatcher;
44 class IMEContentObserver;
45 class ScrollbarsForWheel;
46 class ScrollContainerFrame;
47 class TextControlElement;
48 class WheelTransaction;
50 namespace dom {
51 class DataTransfer;
52 class Document;
53 class Element;
54 class Selection;
55 class BrowserParent;
56 class RemoteDragStartData;
58 } // namespace dom
60 class OverOutElementsWrapper final : public nsISupports {
61 ~OverOutElementsWrapper() = default;
63 public:
64 enum class BoundaryEventType : bool { Mouse, Pointer };
65 explicit OverOutElementsWrapper(BoundaryEventType aType) : mType(aType) {}
67 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
68 NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper)
70 already_AddRefed<nsIWidget> GetLastOverWidget() const;
72 void ContentRemoved(nsIContent& aContent);
73 void WillDispatchOverAndEnterEvent(nsIContent* aOverEventTarget);
74 void DidDispatchOverAndEnterEvent(
75 nsIContent* aOriginalOverTargetInComposedDoc,
76 nsIWidget* aOverEventTargetWidget);
77 [[nodiscard]] bool IsDispatchingOverEventOn(
78 nsIContent* aOverEventTarget) const {
79 MOZ_ASSERT(aOverEventTarget);
80 return LastOverEventTargetIsOutEventTarget() &&
81 mDeepestEnterEventTarget == aOverEventTarget;
83 void WillDispatchOutAndOrLeaveEvent() {
84 // Store the first "out" event target or the deepest "leave" event target
85 // which we fire and don't refire "out" event to that element while the
86 // first "out" event is still ongoing.
87 mDispatchingOutOrDeepestLeaveEventTarget = mDeepestEnterEventTarget;
89 void DidDispatchOutAndOrLeaveEvent() {
90 StoreOverEventTargetAndDeepestEnterEventTarget(nullptr);
91 mDispatchingOutOrDeepestLeaveEventTarget = nullptr;
93 [[nodiscard]] bool IsDispatchingOutEventOnLastOverEventTarget() const {
94 return mDispatchingOutOrDeepestLeaveEventTarget &&
95 mDispatchingOutOrDeepestLeaveEventTarget == mDeepestEnterEventTarget;
97 void OverrideOverEventTarget(nsIContent* aOverEventTarget) {
98 StoreOverEventTargetAndDeepestEnterEventTarget(aOverEventTarget);
99 // We don't need the widget for aOverEventTarget because this method is used
100 // for adjusting the "over" event target for the following "out" event
101 // dispatch.
102 mLastOverWidget = nullptr;
105 [[nodiscard]] nsIContent* GetDeepestLeaveEventTarget() const {
106 // The last deepest "enter" event targe (it may be same as the last "over"
107 // target) is the deepest "leave" event target.
108 return mDeepestEnterEventTarget;
110 [[nodiscard]] nsIContent* GetOutEventTarget() const {
111 // The last deepest "enter" event target is same as the "over" event target
112 // unless it's never been removed from the DOM tree. If and only if the
113 // last "over" event target has not been removed from the DOM tree, it's
114 // the next "out" event target. Once the last "over" target is removed,
115 // "out" event should not be fired on the target nor its ancestor.
116 return LastOverEventTargetIsOutEventTarget()
117 ? mDeepestEnterEventTarget.get()
118 : nullptr;
122 * Called when EventStateManager::PreHandleEvent() receives an event which
123 * should be treated as the deadline to restore the last "over" event target
124 * as the next "out" event target and for avoiding to dispatch redundant
125 * "over" event on the same target again when it was removed but reconnected.
126 * If the last "over" event target was reconnected under the last deepest
127 * "enter" event target, this restores the last "over" event target.
128 * Otherwise, makes the instance forget the last "over" target because the
129 * user maybe has seen that the last "over" target is completely removed from
130 * the tree.
132 * @param aEvent The event which the caller received. If this is set to
133 * nullptr or not a mouse event, this forgets the pending
134 * last "over" event target.
136 void TryToRestorePendingRemovedOverTarget(const WidgetEvent* aEvent);
139 * Return true if we have a pending removing last "over" event target at least
140 * for the weak reference to it. In other words, when this returns true, we
141 * need to handle the pending removing "over" event target.
143 [[nodiscard]] bool MaybeHasPendingRemovingOverEventTarget() const {
144 return mPendingRemovingOverEventTarget;
147 private:
149 * Whether the last "over" event target is the target of "out" event if you
150 * dispatch "out" event.
152 [[nodiscard]] bool LastOverEventTargetIsOutEventTarget() const {
153 MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget,
154 mDeepestEnterEventTarget);
155 MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget,
156 !MaybeHasPendingRemovingOverEventTarget());
157 return mDeepestEnterEventTargetIsOverEventTarget;
160 void StoreOverEventTargetAndDeepestEnterEventTarget(
161 nsIContent* aOverEventTargetAndDeepestEnterEventTarget);
162 void UpdateDeepestEnterEventTarget(nsIContent* aDeepestEnterEventTarget);
164 nsCOMPtr<nsIContent> GetPendingRemovingOverEventTarget() const {
165 nsCOMPtr<nsIContent> pendingRemovingOverEventTarget =
166 do_QueryReferent(mPendingRemovingOverEventTarget);
167 return pendingRemovingOverEventTarget.forget();
170 // The deepest event target of the last "enter" event. If
171 // mDeepestEnterEventTargetIsOverEventTarget is true, this is the last "over"
172 // event target too. If it's set to false, this is an ancestor of the last
173 // "over" event target which is not removed from the DOM tree.
174 nsCOMPtr<nsIContent> mDeepestEnterEventTarget;
176 // The last "over" event target which will be considered as disconnected or
177 // connected later because web apps may remove the "over" event target
178 // temporarily and reconnect it to the deepest "enter" target immediately.
179 // In such case, we should keep treating it as the last "over" event target
180 // as the next "out" event target.
181 // FYI: This needs to be a weak pointer. Otherwise, the leak window checker
182 // of mochitests will detect windows in the closed tabs which ran tests
183 // synthesizing mouse moves because while a <browser> is stored with a strong
184 // pointer, the child window is also grabbed by the element.
185 nsWeakPtr mPendingRemovingOverEventTarget;
187 // While we're dispatching "over" and "enter" events, this is set to the
188 // "over" event target. If it's removed from the DOM tree, this is set to
189 // nullptr.
190 nsCOMPtr<nsIContent> mDispatchingOverEventTarget;
192 // While we're dispatching "out" and/or "leave" events, this is set to the
193 // "out" event target or the deepest leave event target. If it's removed from
194 // the DOM tree, this is set to nullptr.
195 nsCOMPtr<nsIContent> mDispatchingOutOrDeepestLeaveEventTarget;
197 // The widget on which we dispatched the last "over" event. Note that
198 // nsIWidget is not cycle collectable. Therefore, for avoiding unexpected
199 // memory leaks, we use nsWeakPtr to store the widget here.
200 nsWeakPtr mLastOverWidget;
202 const BoundaryEventType mType;
204 // Once the last "over" element is removed from the tree, this is set
205 // to false. Then, mDeepestEnterEventTarget may be an ancestor of the
206 // "over" element which should be the deepest target of next "leave"
207 // element but shouldn't be target of "out" event.
208 bool mDeepestEnterEventTargetIsOverEventTarget = false;
211 class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
212 friend class mozilla::EnterLeaveDispatcher;
213 friend class mozilla::ScrollbarsForWheel;
214 friend class mozilla::WheelTransaction;
216 using ElementState = dom::ElementState;
218 virtual ~EventStateManager();
220 public:
221 EventStateManager();
223 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
224 NS_DECL_NSIOBSERVER
226 nsresult Init();
227 nsresult Shutdown();
229 /* The PreHandleEvent method is called before event dispatch to either
230 * the DOM or frames. Any processing which must not be prevented or
231 * cancelled should occur here. Any processing which is intended to
232 * be conditional based on either DOM or frame processing should occur in
233 * PostHandleEvent. Any centralized event processing which must occur before
234 * DOM or frame event handling should occur here as well.
236 * aOverrideClickTarget can be used to indicate which element should be
237 * used as the *up target when deciding whether to send click event.
238 * This is used when releasing pointer capture. Otherwise null.
240 MOZ_CAN_RUN_SCRIPT
241 nsresult PreHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
242 nsIFrame* aTargetFrame, nsIContent* aTargetContent,
243 nsEventStatus* aStatus,
244 nsIContent* aOverrideClickTarget);
246 /* The PostHandleEvent method should contain all system processing which
247 * should occur conditionally based on DOM or frame processing. It should
248 * also contain any centralized event processing which must occur after
249 * DOM and frame processing.
251 MOZ_CAN_RUN_SCRIPT
252 nsresult PostHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent,
253 nsIFrame* aTargetFrame, nsEventStatus* aStatus,
254 nsIContent* aOverrideClickTarget);
256 MOZ_CAN_RUN_SCRIPT void PostHandleKeyboardEvent(
257 WidgetKeyboardEvent* aKeyboardEvent, nsIFrame* aTargetFrame,
258 nsEventStatus& aStatus);
261 * DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll
262 * event and eLegacyMousePixelScroll event for compatibility with old Gecko.
264 MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchLegacyMouseScrollEvents(
265 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, nsEventStatus* aStatus);
267 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyDestroyPresContext(
268 nsPresContext* aPresContext);
270 void ResetHoverState();
272 void SetPresContext(nsPresContext* aPresContext);
273 void ClearFrameRefs(nsIFrame* aFrame);
275 nsIFrame* GetEventTarget();
276 already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent);
278 // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET
279 static bool ManagesState(ElementState aState) {
280 return aState == ElementState::ACTIVE || aState == ElementState::HOVER ||
281 aState == ElementState::DRAGOVER ||
282 aState == ElementState::URLTARGET;
286 * Notify that the given ElementState::* bit has changed for this content.
287 * @param aContent Content which has changed states
288 * @param aState Corresponding state flags such as ElementState::FOCUS
289 * @return Whether the content was able to change all states. Returns false
290 * if a resulting DOM event causes the content node passed in
291 * to not change states. Note, the frame for the content may
292 * change as a result of the content state change, because of
293 * frame reconstructions that may occur, but this does not
294 * affect the return value.
296 bool SetContentState(nsIContent* aContent, ElementState aState);
298 nsIContent* GetActiveContent() const { return mActiveContent; }
300 void NativeAnonymousContentRemoved(nsIContent* aAnonContent);
301 MOZ_CAN_RUN_SCRIPT_BOUNDARY void ContentRemoved(dom::Document* aDocument,
302 nsIContent* aContent);
305 * Called when a native anonymous <div> element which is root element of
306 * text editor will be removed.
308 void TextControlRootWillBeRemoved(TextControlElement& aTextControlElement);
311 * Called when a native anonymous <div> element which is root element of
312 * text editor is created.
314 void TextControlRootAdded(dom::Element& aAnonymousDivElement,
315 TextControlElement& aTextControlElement);
317 bool EventStatusOK(WidgetGUIEvent* aEvent);
320 * EventStateManager stores IMEContentObserver while it's observing contents.
321 * Following mehtods are called by IMEContentObserver when it starts to
322 * observe or stops observing the content.
324 void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver);
325 void OnStopObservingContent(IMEContentObserver* aIMEContentObserver);
328 * TryToFlushPendingNotificationsToIME() suggests flushing pending
329 * notifications to IME to IMEContentObserver.
330 * Doesn't do anything in child processes where flushing happens
331 * asynchronously.
333 void TryToFlushPendingNotificationsToIME();
335 static bool IsKeyboardEventUserActivity(WidgetEvent* aEvent);
338 * Register accesskey on the given element. When accesskey is activated then
339 * the element will be notified via Element::PerformAccesskey() method.
341 * @param aElement the given element
342 * @param aKey accesskey
344 void RegisterAccessKey(dom::Element* aElement, uint32_t aKey);
347 * Unregister accesskey for the given element.
349 * @param aElement the given element
350 * @param aKey accesskey
352 void UnregisterAccessKey(dom::Element* aElement, uint32_t aKey);
355 * Get accesskey registered on the given element or 0 if there is none.
357 * @param aElement the given element (must not be null)
358 * @return registered accesskey
360 uint32_t GetRegisteredAccessKey(dom::Element* aContent);
362 static void GetAccessKeyLabelPrefix(dom::Element* aElement,
363 nsAString& aPrefix);
366 * HandleAccessKey() looks for access keys which matches with aEvent and
367 * execute when it matches with a chrome access key or some content access
368 * keys.
369 * If the event may match chrome access keys, this handles the access key
370 * synchronously (if there are nested ESMs, their HandleAccessKey() are
371 * also called recursively).
372 * If the event may match content access keys and focused target is a remote
373 * process, this does nothing for the content because when this is called,
374 * it should already have been handled in the remote process.
375 * If the event may match content access keys and focused target is not in
376 * remote process but there are some remote children, this will post
377 * HandleAccessKey messages to all remote children.
379 * @return true if there is accesskey which aEvent and
380 * aAccessCharCodes match with. Otherwise, false.
381 * I.e., when this returns true, a target is executed
382 * or focused.
383 * Note that even if this returns false, a target in
384 * remote process may be executed or focused
385 * asynchronously.
387 bool HandleAccessKey(WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext,
388 nsTArray<uint32_t>& aAccessCharCodes) {
389 return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
390 nullptr, eAccessKeyProcessingNormal,
391 true);
395 * CheckIfEventMatchesAccessKey() looks for access key which matches with
396 * aEvent in the process but won't execute it.
398 * @return true if there is accesskey which aEvent matches with
399 * in this process. Otherwise, false.
401 bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent,
402 nsPresContext* aPresContext);
404 nsresult SetCursor(StyleCursorKind, imgIContainer*, const ImageResolution&,
405 const Maybe<gfx::IntPoint>& aHotspot, nsIWidget* aWidget,
406 bool aLockCursor);
408 void StartHidingCursorWhileTyping(nsIWidget*);
411 * Checks if the current mouse over element matches the given
412 * Element (which has a remote frame), and if so, notifies
413 * the BrowserParent of the mouse enter.
414 * Called when we reconstruct the BrowserParent and need to
415 * recompute state on the new object.
417 void RecomputeMouseEnterStateForRemoteFrame(dom::Element& aElement);
419 nsPresContext* GetPresContext() { return mPresContext; }
421 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, nsIObserver)
423 // The manager in this process that is setting the cursor. In the parent
424 // process it might be null if a remote process is setting the cursor.
425 static EventStateManager* sCursorSettingManager;
426 static void ClearCursorSettingManager() { sCursorSettingManager = nullptr; }
428 // Checks if the manager in this process has a locked cursor
429 static bool CursorSettingManagerHasLockedCursor();
431 static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
433 // Sets aNewESM to be the active event state manager, and
434 // if aContent is non-null, marks the object as active.
435 static void SetActiveManager(EventStateManager* aNewESM,
436 nsIContent* aContent);
438 static bool IsRemoteTarget(nsIContent* target);
440 static bool IsTopLevelRemoteTarget(nsIContent* aTarget);
442 // Returns the kind of APZ action the given WidgetWheelEvent will perform.
443 static Maybe<layers::APZWheelAction> APZWheelActionFor(
444 const WidgetWheelEvent* aEvent);
446 // For some kinds of scrollings, the delta values of WidgetWheelEvent are
447 // possbile to be adjusted. This function is used to detect such scrollings
448 // and returns a wheel delta adjustment strategy to use, which is corresponded
449 // to the kind of the scrolling.
450 // It returns WheelDeltaAdjustmentStrategy::eAutoDir if the current default
451 // action is auto-dir scrolling which honours the scrolling target(The
452 // comments in WheelDeltaAdjustmentStrategy describes the concept in detail).
453 // It returns WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour if the
454 // current action is auto-dir scrolling which honours the root element in the
455 // document where the scrolling target is(The comments in
456 // WheelDeltaAdjustmentStrategy describes the concept in detail).
457 // It returns WheelDeltaAdjustmentStrategy::eHorizontalize if the current
458 // default action is horizontalized scrolling.
459 // It returns WheelDeltaAdjustmentStrategy::eNone to mean no delta adjustment
460 // strategy should be used if the scrolling is just a tranditional scrolling
461 // whose delta values are never possible to be adjusted.
462 static WheelDeltaAdjustmentStrategy GetWheelDeltaAdjustmentStrategy(
463 const WidgetWheelEvent& aEvent);
465 // Returns user-set multipliers for a wheel event.
466 static void GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent,
467 double* aOutMultiplierX,
468 double* aOutMultiplierY);
470 // Holds the point in screen coords that a mouse event was dispatched to,
471 // before we went into pointer lock mode. This is constantly updated while
472 // the pointer is not locked, but we don't update it while the pointer is
473 // locked. This is used by dom::Event::GetScreenCoords() to make mouse
474 // events' screen coord appear frozen at the last mouse position while
475 // the pointer is locked.
476 static CSSIntPoint sLastScreenPoint;
478 // Holds the point in client coords of the last mouse event. Used by
479 // dom::Event::GetClientCoords() to make mouse events' client coords appear
480 // frozen at the last mouse position while the pointer is locked.
481 static CSSIntPoint sLastClientPoint;
484 * If the absolute values of mMultiplierX and/or mMultiplierY are equal or
485 * larger than this value, the computed scroll amount isn't rounded down to
486 * the page width or height.
488 static constexpr double MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL =
489 1000.0;
492 * HandleMiddleClickPaste() handles middle mouse button event as pasting
493 * clipboard text. Note that if aEditorBase is nullptr, this only
494 * dispatches ePaste event because it's necessary for some web apps which
495 * want to implement their own editor and supports middle click paste.
497 * @param aPresShell The PresShell for the ESM. This lifetime
498 * should be guaranteed by the caller.
499 * @param aMouseEvent The ePointerClick event which caused the
500 * paste.
501 * @param aStatus The event status of aMouseEvent.
502 * @param aEditorBase EditorBase which may be pasted the
503 * clipboard text by the middle click.
504 * If there is no editor for aMouseEvent,
505 * set nullptr.
507 MOZ_CAN_RUN_SCRIPT
508 nsresult HandleMiddleClickPaste(PresShell* aPresShell,
509 WidgetMouseEvent* aMouseEvent,
510 nsEventStatus* aStatus,
511 EditorBase* aEditorBase);
513 static void ConsumeInteractionData(
514 dom::Record<nsString, dom::InteractionData>& aInteractions);
516 // Stop tracking a possible drag. If aClearInChildProcesses is true, send
517 // a notification to any child processes that are in the drag service that
518 // tried to start a drag.
519 void StopTrackingDragGesture(bool aClearInChildProcesses);
521 protected:
523 * If aTargetFrame's widget has a cached cursor value, resets the cursor
524 * such that the next call to SetCursor on the widget will force an update
525 * of the native cursor. For use in getting puppet widget to update its
526 * cursor between mouse exit / enter transitions. This call basically wraps
527 * nsIWidget ClearCachedCursor.
529 void ClearCachedWidgetCursor(nsIFrame* aTargetFrame);
531 void UpdateCursor(nsPresContext*, WidgetMouseEvent*, nsIFrame* aTargetFrame,
532 nsEventStatus* aStatus);
534 * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the
535 * specified content.
537 * @return widget which is the nearest widget from the event target frame.
539 [[nodiscard]] MOZ_CAN_RUN_SCRIPT already_AddRefed<nsIWidget>
540 DispatchMouseOrPointerBoundaryEvent(WidgetMouseEvent* aMouseEvent,
541 EventMessage aMessage,
542 nsIContent* aTargetContent,
543 nsIContent* aRelatedContent);
545 * Synthesize DOM pointerover and pointerout events
547 void GeneratePointerEnterExit(EventMessage aMessage,
548 WidgetMouseEvent* aEvent);
550 * Synthesize DOM and frame mouseover and mouseout events from this
551 * MOUSE_MOVE or MOUSE_EXIT event.
553 void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent);
555 * Tell this ESM and ESMs in parent documents that the mouse is
556 * over some content in this document.
558 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOver(
559 WidgetMouseEvent* aMouseEvent, nsIContent* aContent);
561 * Tell this ESM and ESMs in affected child documents that the mouse
562 * has exited this document's currently hovered content.
563 * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
565 * @param aMouseEvent the event that triggered the mouseout
566 * @param aMovingInto the content node we've moved into. This is used to set
567 * the relatedTarget for mouseout events. Also, if it's non-null
568 * NotifyMouseOut will NOT change the current hover content to null;
569 * in that case the caller is responsible for updating hover state.
571 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOut(WidgetMouseEvent* aMouseEvent,
572 nsIContent* aMovingInto);
573 MOZ_CAN_RUN_SCRIPT void GenerateDragDropEnterExit(
574 nsPresContext* aPresContext, WidgetDragEvent* aDragEvent);
577 * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper
578 * elements wrapper. If mPointersEnterLeaveHelper does not contain wrapper for
579 * pointerId it create new one
581 OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent);
584 * Fire the dragenter and dragexit/dragleave events when the mouse moves to a
585 * new target.
587 * @param aRelatedTarget relatedTarget to set for the event
588 * @param aTargetContent target to set for the event
589 * @param aTargetFrame target frame for the event
591 MOZ_CAN_RUN_SCRIPT void FireDragEnterOrExit(nsPresContext* aPresContext,
592 WidgetDragEvent* aDragEvent,
593 EventMessage aMessage,
594 nsIContent* aRelatedTarget,
595 nsIContent* aTargetContent,
596 AutoWeakFrame& aTargetFrame);
598 * Update the initial drag session data transfer with any changes that occur
599 * on cloned data transfer objects used for events.
601 void UpdateDragDataTransfer(WidgetDragEvent* dragEvent);
604 * InitAndDispatchClickEvent() dispatches a click event.
606 * @param aMouseUpEvent eMouseUp event which causes the click event.
607 * EventCausesClickEvents() must return true
608 * if this event is set to it.
609 * @param aStatus Returns the result of click event.
610 * If the status indicates consumed, the
611 * value won't be overwritten with
612 * nsEventStatus_eIgnore.
613 * @param aMessage Should be ePointerClick, eMouseDoubleClick
614 * or ePointerAuxClick.
615 * @param aPresShell The PresShell.
616 * @param aMouseUpContent The event target of aMouseUpEvent.
617 * @param aCurrentTarget Current target of the caller.
618 * @param aNoContentDispatch true if the event shouldn't be exposed to
619 * web contents (although will be fired on
620 * document and window).
621 * @param aOverrideClickTarget Preferred click event target. If this is
622 * not nullptr, aMouseUpContent and
623 * aCurrentTarget are ignored.
625 MOZ_CAN_RUN_SCRIPT
626 static nsresult InitAndDispatchClickEvent(
627 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus,
628 EventMessage aMessage, PresShell* aPresShell, nsIContent* aMouseUpContent,
629 AutoWeakFrame aCurrentTarget, bool aNoContentDispatch,
630 nsIContent* aOverrideClickTarget);
632 nsresult SetClickCount(WidgetMouseEvent* aEvent, nsEventStatus* aStatus,
633 nsIContent* aOverrideClickTarget = nullptr);
636 * EventCausesClickEvents() returns true when aMouseEvent is an eMouseUp
637 * event and it should cause ePointerClick, eMouseDoubleClick and/or
638 * ePointerAuxClick events. Note that this method assumes that
639 * aMouseEvent.mClickCount has already been initialized with SetClickCount().
641 static bool EventCausesClickEvents(const WidgetMouseEvent& aMouseEvent);
644 * PostHandleMouseUp() handles default actions of eMouseUp event.
646 * @param aMouseUpEvent eMouseUp event which causes the click event.
647 * EventCausesClickEvents() must return true
648 * if this event is set to it.
649 * @param aStatus Returns the result of event status.
650 * If one of dispatching event is consumed or
651 * this does something as default action,
652 * returns nsEventStatus_eConsumeNoDefault.
653 * @param aOverrideClickTarget Preferred click event target. If nullptr,
654 * aMouseUpEvent target and current target
655 * are used.
657 MOZ_CAN_RUN_SCRIPT
658 nsresult PostHandleMouseUp(WidgetMouseEvent* aMouseUpEvent,
659 nsEventStatus* aStatus,
660 nsIContent* aOverrideClickTarget);
663 * DispatchClickEvents() dispatches ePointerClick, eMouseDoubleClick and
664 * ePointerAuxClick events for aMouseUpEvent. aMouseUpEvent should cause
665 * click event.
667 * @param aPresShell The PresShell.
668 * @param aMouseUpEvent eMouseUp event which causes the click event.
669 * EventCausesClickEvents() must return true
670 * if this event is set to it.
671 * @param aStatus Returns the result of event status.
672 * If one of dispatching click event is
673 * consumed, returns
674 * nsEventStatus_eConsumeNoDefault.
675 * @param aMouseUpContent The event target of aMouseUpEvent.
676 * @param aOverrideClickTarget Preferred click event target. If this is
677 * not nullptr, aMouseUpContent and
678 * current target frame of the ESM are ignored.
680 MOZ_CAN_RUN_SCRIPT
681 nsresult DispatchClickEvents(PresShell* aPresShell,
682 WidgetMouseEvent* aMouseUpEvent,
683 nsEventStatus* aStatus,
684 nsIContent* aMouseUpContent,
685 nsIContent* aOverrideClickTarget);
687 void EnsureDocument(nsPresContext* aPresContext);
688 MOZ_CAN_RUN_SCRIPT_BOUNDARY
689 void FlushLayout(nsPresContext* aPresContext);
692 * The phases of WalkESMTreeToHandleAccessKey processing. See below.
694 enum ProcessingAccessKeyState {
695 eAccessKeyProcessingNormal = 0,
696 eAccessKeyProcessingUp,
697 eAccessKeyProcessingDown
701 * Walk EMS to look for access key and execute found access key when aExecute
702 * is true.
703 * If there is registered element for the accesskey given by the key event
704 * and modifier mask then call element.PerformAccesskey(), otherwise call
705 * WalkESMTreeToHandleAccessKey() recursively, on descendant docshells first,
706 * then on the ancestor (with |aBubbledFrom| set to the docshell associated
707 * with |this|), until something matches.
709 * @param aEvent the keyboard event triggering the acccess key
710 * @param aPresContext the presentation context
711 * @param aAccessCharCodes list of charcode candidates
712 * @param aBubbledFrom is used by an ancestor to avoid calling
713 * WalkESMTreeToHandleAccessKey() on the child the call originally
714 * came from, i.e. this is the child that recursively called us in
715 * its Up phase. The initial caller passes |nullptr| here. This is to
716 * avoid an infinite loop.
717 * @param aAccessKeyState Normal, Down or Up processing phase (see enums
718 * above). The initial event receiver uses 'normal', then 'down' when
719 * processing children and Up when recursively calling its ancestor.
720 * @param aExecute is true, execute an accesskey if it's found. Otherwise,
721 * found accesskey won't be executed.
723 * @return true if there is a target which aEvent and
724 * aAccessCharCodes match with in this process.
725 * Otherwise, false. I.e., when this returns true and
726 * aExecute is true, a target is executed or focused.
727 * Note that even if this returns false, a target in
728 * remote process may be executed or focused
729 * asynchronously.
731 bool WalkESMTreeToHandleAccessKey(WidgetKeyboardEvent* aEvent,
732 nsPresContext* aPresContext,
733 nsTArray<uint32_t>& aAccessCharCodes,
734 nsIDocShellTreeItem* aBubbledFrom,
735 ProcessingAccessKeyState aAccessKeyState,
736 bool aExecute);
739 * Look for access key and execute found access key if aExecute is true in
740 * the instance.
742 * @return true if there is a target which matches with
743 * aAccessCharCodes and aIsTrustedEvent. Otherwise,
744 * false. I.e., when this returns true and aExecute
745 * is true, a target is executed or focused.
747 MOZ_CAN_RUN_SCRIPT_BOUNDARY bool LookForAccessKeyAndExecute(
748 nsTArray<uint32_t>& aAccessCharCodes, bool aIsTrustedEvent,
749 bool aIsRepeat, bool aExecute);
751 //---------------------------------------------
752 // DocShell Focus Traversal Methods
753 //---------------------------------------------
755 dom::Element* GetFocusedElement();
756 bool IsShellVisible(nsIDocShell* aShell);
758 // These functions are for mousewheel and pixel scrolling
760 class WheelPrefs {
761 public:
762 static WheelPrefs* GetInstance();
763 static void Shutdown();
766 * ApplyUserPrefsToDelta() overrides the wheel event's delta values with
767 * user prefs.
769 void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent);
772 * Returns whether or not ApplyUserPrefsToDelta() would change the delta
773 * values of an event.
775 void GetUserPrefsForEvent(const WidgetWheelEvent* aEvent,
776 double* aOutMultiplierX, double* aOutMultiplierY);
779 * If ApplyUserPrefsToDelta() changed the delta values with customized
780 * prefs, the overflowDelta values would be inflated.
781 * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
783 void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent);
786 * Computes the default action for the aEvent with the prefs.
788 enum Action : uint8_t {
789 ACTION_NONE = 0,
790 ACTION_SCROLL,
791 ACTION_HISTORY,
792 ACTION_ZOOM,
793 // Horizontalized scrolling means treating vertical wheel scrolling as
794 // horizontal scrolling during the process of its default action and
795 // plugins handling scrolling. Note that delta values as the event object
796 // in a DOM event listener won't be affected, and will be still the
797 // original values. For more details, refer to
798 // mozilla::WheelDeltaAdjustmentStrategy::eHorizontalize
799 ACTION_HORIZONTALIZED_SCROLL,
800 ACTION_PINCH_ZOOM,
801 ACTION_LAST = ACTION_PINCH_ZOOM,
802 // Following actions are used only by internal processing. So, cannot
803 // specified by prefs.
804 ACTION_SEND_TO_PLUGIN,
806 Action ComputeActionFor(const WidgetWheelEvent* aEvent);
809 * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
810 * computed the lineOrPageDelta values.
812 bool NeedToComputeLineOrPageDelta(const WidgetWheelEvent* aEvent);
815 * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
816 * be rounded down to the page width/height (false) or not (true).
818 bool IsOverOnePageScrollAllowedX(const WidgetWheelEvent* aEvent);
819 bool IsOverOnePageScrollAllowedY(const WidgetWheelEvent* aEvent);
821 private:
822 WheelPrefs();
823 ~WheelPrefs();
825 static void OnPrefChanged(const char* aPrefName, void* aClosure);
827 enum Index {
828 INDEX_DEFAULT = 0,
829 INDEX_ALT,
830 INDEX_CONTROL,
831 INDEX_META,
832 INDEX_SHIFT,
833 COUNT_OF_MULTIPLIERS
837 * GetIndexFor() returns the index of the members which should be used for
838 * the aEvent. When only one modifier key of MODIFIER_ALT,
839 * MODIFIER_CONTROL, MODIFIER_META or MODIFIER_SHIFT is pressed, returns the
840 * index for the modifier. Otherwise, this return the default index which
841 * is used at either no modifier key is pressed or two or modifier keys are
842 * pressed.
844 Index GetIndexFor(const WidgetWheelEvent* aEvent);
847 * GetPrefNameBase() returns the base pref name for aEvent.
848 * It's decided by GetModifierForPref() which modifier should be used for
849 * the aEvent.
851 * @param aBasePrefName The result, must be "mousewheel.with_*." or
852 * "mousewheel.default.".
854 void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
856 void Init(Index aIndex);
858 void Reset();
861 * Retrieve multiplier for aEvent->mDeltaX and aEvent->mDeltaY.
863 * Note that if the default action is ACTION_HORIZONTALIZED_SCROLL and the
864 * delta values have been adjusted by WheelDeltaHorizontalizer() before this
865 * function is called, this function will swap the X and Y multipliers. By
866 * doing this, multipliers will still apply to the delta values they
867 * originally corresponded to.
869 * @param aEvent The event which is being handled.
870 * @param aIndex The index of mMultiplierX and mMultiplierY.
871 * Should be result of GetIndexFor(aEvent).
872 * @param aMultiplierForDeltaX Will be set to multiplier for
873 * aEvent->mDeltaX.
874 * @param aMultiplierForDeltaY Will be set to multiplier for
875 * aEvent->mDeltaY.
877 void GetMultiplierForDeltaXAndY(const WidgetWheelEvent* aEvent,
878 Index aIndex, double* aMultiplierForDeltaX,
879 double* aMultiplierForDeltaY);
881 bool mInit[COUNT_OF_MULTIPLIERS];
882 double mMultiplierX[COUNT_OF_MULTIPLIERS];
883 double mMultiplierY[COUNT_OF_MULTIPLIERS];
884 double mMultiplierZ[COUNT_OF_MULTIPLIERS];
885 Action mActions[COUNT_OF_MULTIPLIERS];
887 * action values overridden by .override_x pref.
888 * If an .override_x value is -1, same as the
889 * corresponding mActions value.
891 Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS];
893 static WheelPrefs* sInstance;
897 * DeltaDirection is used for specifying whether the called method should
898 * handle vertical delta or horizontal delta.
899 * This is clearer than using bool.
901 enum DeltaDirection { DELTA_DIRECTION_X = 0, DELTA_DIRECTION_Y };
903 struct MOZ_STACK_CLASS EventState {
904 bool mDefaultPrevented;
905 bool mDefaultPreventedByContent;
907 EventState()
908 : mDefaultPrevented(false), mDefaultPreventedByContent(false) {}
912 * SendLineScrollEvent() dispatches a DOMMouseScroll event for the
913 * WidgetWheelEvent. This method shouldn't be called for non-trusted
914 * wheel event because it's not necessary for compatiblity.
916 * @param aTargetFrame The event target of wheel event.
917 * @param aEvent The original Wheel event.
918 * @param aState The event which should be set to the dispatching
919 * event. This also returns the dispatched event
920 * state.
921 * @param aDelta The delta value of the event.
922 * @param aDeltaDirection The X/Y direction of dispatching event.
924 MOZ_CAN_RUN_SCRIPT void SendLineScrollEvent(nsIFrame* aTargetFrame,
925 WidgetWheelEvent* aEvent,
926 EventState& aState,
927 int32_t aDelta,
928 DeltaDirection aDeltaDirection);
931 * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
932 * WidgetWheelEvent. This method shouldn't be called for non-trusted
933 * wheel event because it's not necessary for compatiblity.
935 * @param aTargetFrame The event target of wheel event.
936 * @param aEvent The original Wheel event.
937 * @param aState The event which should be set to the dispatching
938 * event. This also returns the dispatched event
939 * state.
940 * @param aPixelDelta The delta value of the event.
941 * @param aDeltaDirection The X/Y direction of dispatching event.
943 MOZ_CAN_RUN_SCRIPT void SendPixelScrollEvent(nsIFrame* aTargetFrame,
944 WidgetWheelEvent* aEvent,
945 EventState& aState,
946 int32_t aPixelDelta,
947 DeltaDirection aDeltaDirection);
950 * ComputeScrollTargetAndMayAdjustWheelEvent() returns the scrollable frame
951 * which should be scrolled.
953 * @param aTargetFrame The event target of the wheel event.
954 * @param aEvent The handling mouse wheel event.
955 * @param aOptions The options for finding the scroll target.
956 * Callers should use COMPUTE_*.
957 * @return The scrollable frame which should be scrolled.
959 // These flags are used in ComputeScrollTargetAndMayAdjustWheelEvent().
960 // Callers should use COMPUTE_*.
961 enum {
962 PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001,
963 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002,
964 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004,
965 START_FROM_PARENT = 0x00000008,
966 INCLUDE_PLUGIN_AS_TARGET = 0x00000010,
967 // Indicates the wheel scroll event being computed is an auto-dir scroll, so
968 // its delta may be adjusted after being computed.
969 MAY_BE_ADJUSTED_BY_AUTO_DIR = 0x00000020,
971 enum ComputeScrollTargetOptions {
972 // At computing scroll target for legacy mouse events, we should return
973 // first scrollable element even when it's not scrollable to the direction.
974 COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0,
975 // Default action prefers the scrolled element immediately before if it's
976 // still under the mouse cursor. Otherwise, it prefers the nearest
977 // scrollable ancestor which will be scrolled actually.
978 COMPUTE_DEFAULT_ACTION_TARGET =
979 (PREFER_MOUSE_WHEEL_TRANSACTION |
980 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
981 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
982 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR =
983 (COMPUTE_DEFAULT_ACTION_TARGET | MAY_BE_ADJUSTED_BY_AUTO_DIR),
984 // Look for the nearest scrollable ancestor which can be scrollable with
985 // aEvent.
986 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS =
987 (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
988 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS =
989 (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT),
990 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR =
991 (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS |
992 MAY_BE_ADJUSTED_BY_AUTO_DIR),
993 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR =
994 (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS |
995 MAY_BE_ADJUSTED_BY_AUTO_DIR),
998 // Compute the scroll target.
999 // The delta values in the wheel event may be changed if the event is for
1000 // auto-dir scrolling. For information on auto-dir,
1001 // @see mozilla::WheelDeltaAdjustmentStrategy
1002 ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
1003 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
1004 ComputeScrollTargetOptions aOptions);
1006 ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
1007 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
1008 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions);
1010 ScrollContainerFrame* ComputeScrollTarget(
1011 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent,
1012 ComputeScrollTargetOptions aOptions) {
1013 MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
1014 "aEvent may be modified by auto-dir");
1015 return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, aEvent,
1016 aOptions);
1019 ScrollContainerFrame* ComputeScrollTarget(
1020 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY,
1021 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions) {
1022 MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
1023 "aEvent may be modified by auto-dir");
1024 return ComputeScrollTargetAndMayAdjustWheelEvent(
1025 aTargetFrame, aDirectionX, aDirectionY, aEvent, aOptions);
1029 * GetScrollAmount() returns the scroll amount in app uints of one line or
1030 * one page. If the wheel event scrolls a page, returns the page width and
1031 * height. Otherwise, returns line height for both its width and height.
1033 * @param aScrollContainerFrame A frame which will be scrolled by the event.
1034 * The result of
1035 * ComputeScrollTargetAndMayAdjustWheelEvent() is
1036 * expected for this value.
1037 * This can be nullptr if there is no scrollable
1038 * frame. Then, this method uses root frame's
1039 * line height or visible area's width and
1040 * height.
1042 nsSize GetScrollAmount(nsPresContext* aPresContext, WidgetWheelEvent* aEvent,
1043 ScrollContainerFrame* aScrollContainerFrame);
1046 * DoScrollText() scrolls the scroll container frame for aEvent.
1048 void DoScrollText(ScrollContainerFrame* aScrollContainerFrame,
1049 WidgetWheelEvent* aEvent);
1051 void DoScrollHistory(int32_t direction);
1052 void DoScrollZoom(nsIFrame* aTargetFrame, int32_t adjustment);
1053 void ChangeZoom(bool aIncrease);
1056 * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll
1057 * event. If wheel events are caused by pixel scroll only devices or
1058 * the delta values are customized by prefs, this class stores the delta
1059 * values and set lineOrPageDelta values.
1061 class DeltaAccumulator {
1062 public:
1063 static DeltaAccumulator* GetInstance() {
1064 if (!sInstance) {
1065 sInstance = new DeltaAccumulator;
1067 return sInstance;
1070 static void Shutdown() {
1071 delete sInstance;
1072 sInstance = nullptr;
1075 bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; }
1078 * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents
1079 * which are caused if it's needed. And if the accumulated delta becomes a
1080 * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
1082 void InitLineOrPageDelta(nsIFrame* aTargetFrame, EventStateManager* aESM,
1083 WidgetWheelEvent* aEvent);
1086 * Reset() resets all members.
1088 void Reset();
1091 * ComputeScrollAmountForDefaultAction() computes the default action's
1092 * scroll amount in device pixels with mPendingScrollAmount*.
1094 nsIntPoint ComputeScrollAmountForDefaultAction(
1095 WidgetWheelEvent* aEvent, const nsIntSize& aScrollAmountInDevPixels);
1097 private:
1098 DeltaAccumulator()
1099 : mX(0.0),
1100 mY(0.0),
1101 mPendingScrollAmountX(0.0),
1102 mPendingScrollAmountY(0.0),
1103 mHandlingDeltaMode(UINT32_MAX),
1104 mIsNoLineOrPageDeltaDevice(false) {}
1106 double mX;
1107 double mY;
1109 // When default action of a wheel event is scroll but some delta values
1110 // are ignored because the computed amount values are not integer, the
1111 // fractional values are saved by these members.
1112 double mPendingScrollAmountX;
1113 double mPendingScrollAmountY;
1115 TimeStamp mLastTime;
1117 uint32_t mHandlingDeltaMode;
1118 bool mIsNoLineOrPageDeltaDevice;
1120 static DeltaAccumulator* sInstance;
1123 // end mousewheel functions
1126 * When a touch gesture is about to start, this function determines what
1127 * kind of gesture interaction we will want to use, based on what is
1128 * underneath the initial touch point.
1129 * Currently it decides between panning (finger scrolling) or dragging
1130 * the target element, as well as the orientation to trigger panning and
1131 * display visual boundary feedback. The decision is stored back in aEvent.
1133 void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent,
1134 nsIFrame* targetFrame);
1136 // routines for the d&d gesture tracking state machine
1137 void BeginTrackingDragGesture(nsPresContext* aPresContext,
1138 WidgetMouseEvent* aDownEvent,
1139 nsIFrame* aDownFrame);
1141 void SetGestureDownPoint(WidgetGUIEvent* aEvent);
1143 LayoutDeviceIntPoint GetEventRefPoint(WidgetEvent* aEvent) const;
1145 friend class mozilla::dom::BrowserParent;
1146 void BeginTrackingRemoteDragGesture(nsIContent* aContent,
1147 dom::RemoteDragStartData* aDragStartData);
1149 MOZ_CAN_RUN_SCRIPT
1150 void GenerateDragGesture(nsPresContext* aPresContext,
1151 WidgetInputEvent* aEvent);
1154 * When starting a dnd session, UA must fire a pointercancel event and stop
1155 * firing the subsequent pointer events.
1157 MOZ_CAN_RUN_SCRIPT
1158 void MaybeFirePointerCancel(WidgetInputEvent* aEvent);
1161 * Determine which node the drag should be targeted at.
1162 * This is either the node clicked when there is a selection, or, for HTML,
1163 * the element with a draggable property set to true.
1165 * aSelectionTarget - target to check for selection
1166 * aDataTransfer - data transfer object that will contain the data to drag
1167 * aAllowEmptyDataTransfer - [out] set to true, if dnd operation can be
1168 * started even if DataTransfer is empty
1169 * aSelection - [out] set to the selection to be dragged
1170 * aTargetNode - [out] the draggable node, or null if there isn't one
1171 * aPrincipal - [out] set to the triggering principal of the drag, or null
1172 * if it's from browser chrome or OS
1173 * aCookieJarSettings - [out] set to the cookieJarSettings of the drag, or
1174 * null if it's from browser chrome or OS.
1176 void DetermineDragTargetAndDefaultData(
1177 nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget,
1178 dom::DataTransfer* aDataTransfer, bool* aAllowEmptyDataTransfer,
1179 dom::Selection** aSelection,
1180 dom::RemoteDragStartData** aRemoteDragStartData, nsIContent** aTargetNode,
1181 nsIPrincipal** aPrincipal, nsIContentSecurityPolicy** aCsp,
1182 nsICookieJarSettings** aCookieJarSettings);
1185 * Perform the default handling for the dragstart event and set up a
1186 * drag for aDataTransfer if it contains any data. Returns true if a drag has
1187 * started.
1189 * aDragEvent - the dragstart event
1190 * aDataTransfer - the data transfer that holds the data to be dragged
1191 * aAllowEmptyDataTransfer - if true, dnd can be started even if there is no
1192 * data to drag
1193 * aDragTarget - the target of the drag
1194 * aSelection - the selection to be dragged
1195 * aData - information pertaining to a drag started in a child process
1196 * aPrincipal - the triggering principal of the drag, or null if it's from
1197 * browser chrome or OS
1198 * aCookieJarSettings - the cookieJarSettings of the drag. or null if it's
1199 * from browser chrome or OS.
1201 MOZ_CAN_RUN_SCRIPT
1202 bool DoDefaultDragStart(
1203 nsPresContext* aPresContext, WidgetDragEvent* aDragEvent,
1204 dom::DataTransfer* aDataTransfer, bool aAllowEmptyDataTransfer,
1205 nsIContent* aDragTarget, dom::Selection* aSelection,
1206 dom::RemoteDragStartData* aDragStartData, nsIPrincipal* aPrincipal,
1207 nsIContentSecurityPolicy* aCsp, nsICookieJarSettings* aCookieJarSettings);
1209 bool IsTrackingDragGesture() const { return mGestureDownContent != nullptr; }
1211 * Set the fields of aEvent to reflect the mouse position and modifier keys
1212 * that were set when the user first pressed the mouse button (stored by
1213 * BeginTrackingDragGesture). aEvent->mWidget must be
1214 * mCurrentTarget->GetNearestWidget().
1216 void FillInEventFromGestureDown(WidgetMouseEvent* aEvent);
1218 MOZ_CAN_RUN_SCRIPT
1219 nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent);
1220 MOZ_CAN_RUN_SCRIPT
1221 nsresult DoContentCommandInsertTextEvent(WidgetContentCommandEvent* aEvent);
1222 nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent);
1224 dom::BrowserParent* GetCrossProcessTarget();
1225 bool IsTargetCrossProcess(WidgetGUIEvent* aEvent);
1228 * DispatchCrossProcessEvent() try to post aEvent to target remote process.
1229 * If you need to check if the event is posted to a remote process, you
1230 * can use aEvent->HasBeenPostedToRemoteProcess().
1232 void DispatchCrossProcessEvent(WidgetEvent* aEvent,
1233 dom::BrowserParent* aRemoteTarget,
1234 nsEventStatus* aStatus);
1236 * HandleCrossProcessEvent() may post aEvent to target remote processes.
1237 * When it succeeded to post the event to at least one remote process,
1238 * returns true. Otherwise, including the case not tried to dispatch to
1239 * post the event, returns false.
1240 * If you need to check if the event is posted to at least one remote
1241 * process, you can use aEvent->HasBeenPostedToRemoteProcess().
1243 bool HandleCrossProcessEvent(WidgetEvent* aEvent, nsEventStatus* aStatus);
1245 void ReleaseCurrentIMEContentObserver();
1247 MOZ_CAN_RUN_SCRIPT void HandleQueryContentEvent(
1248 WidgetQueryContentEvent* aEvent);
1250 private:
1251 // Removes a node from the :hover / :active chain if needed, notifying if the
1252 // node is not a NAC subtree.
1254 // Only meant to be called from ContentRemoved and
1255 // NativeAnonymousContentRemoved.
1256 void RemoveNodeFromChainIfNeeded(ElementState aState,
1257 nsIContent* aContentRemoved, bool aNotify);
1259 bool IsEventOutsideDragThreshold(WidgetInputEvent* aEvent) const;
1261 static inline void DoStateChange(dom::Element* aElement, ElementState aState,
1262 bool aAddState);
1263 static inline void DoStateChange(nsIContent* aContent, ElementState aState,
1264 bool aAddState);
1265 static void UpdateAncestorState(nsIContent* aStartNode,
1266 nsIContent* aStopBefore, ElementState aState,
1267 bool aAddState);
1270 * Update the attribute mLastRefPoint of the mouse event. It should be
1271 * the center of the window while the pointer is locked.
1272 * the same value as mRefPoint while there is no known last ref point.
1273 * the same value as the last known mRefPoint.
1275 static void UpdateLastRefPointOfMouseEvent(WidgetMouseEvent* aMouseEvent);
1277 static void ResetPointerToWindowCenterWhilePointerLocked(
1278 WidgetMouseEvent* aMouseEvent);
1280 // Update the last known ref point to the current event's mRefPoint.
1281 static void UpdateLastPointerPosition(WidgetMouseEvent* aMouseEvent);
1284 * Notify target when user has been interaction with some speicific user
1285 * gestures which are eKeyUp, eMouseUp, eTouchEnd.
1287 void NotifyTargetUserActivation(WidgetEvent* aEvent,
1288 nsIContent* aTargetContent);
1291 * https://html.spec.whatwg.org/multipage/popover.html#light-dismiss-open-popovers.
1293 MOZ_CAN_RUN_SCRIPT void LightDismissOpenPopovers(WidgetEvent* aEvent,
1294 nsIContent* aTargetContent);
1296 already_AddRefed<EventStateManager> ESMFromContentOrThis(
1297 nsIContent* aContent);
1299 struct LastMouseDownInfo {
1300 nsCOMPtr<nsIContent> mLastMouseDownContent;
1301 Maybe<FormControlType> mLastMouseDownInputControlType;
1302 uint32_t mClickCount = 0;
1305 LastMouseDownInfo& GetLastMouseDownInfo(int16_t aButton);
1307 // These variables are only relevant if we're the cursor-setting manager.
1308 StyleCursorKind mLockCursor;
1309 bool mHidingCursorWhileTyping = false;
1311 // Last mouse event screen point (in device pixel) when mouse was locked, used
1312 // to restore mouse position after unlocking.
1313 static LayoutDeviceIntPoint sPreLockScreenPoint;
1315 // Stores the mRefPoint of the last synthetic mouse move we dispatched
1316 // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
1317 // means we've not recently dispatched a centering event. We use this to
1318 // detect when we receive the synth event, so we can cancel and not send it
1319 // to content.
1320 static LayoutDeviceIntPoint sSynthCenteringPoint;
1322 WeakFrame mCurrentTarget;
1323 nsCOMPtr<nsIContent> mCurrentTargetContent;
1324 static AutoWeakFrame sLastDragOverFrame;
1326 // Stores the mRefPoint (the offset from the widget's origin in device
1327 // pixels) of the last mouse event.
1328 static LayoutDeviceIntPoint sLastRefPoint;
1330 // member variables for the d&d gesture state machine
1331 LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates
1332 // The content to use as target if we start a d&d (what we drag).
1333 RefPtr<nsIContent> mGestureDownContent;
1334 // The content of the frame where the mouse-down event occurred. It's the same
1335 // as the target in most cases but not always - for example when dragging
1336 // an <area> of an image map this is the image. (bug 289667)
1337 nsCOMPtr<nsIContent> mGestureDownFrameOwner;
1338 // Data associated with a drag started in a content process.
1339 RefPtr<dom::RemoteDragStartData> mGestureDownDragStartData;
1340 // State of keys when the original gesture-down happened
1341 Modifiers mGestureModifiers;
1342 uint16_t mGestureDownButtons;
1343 int16_t mGestureDownButton;
1345 LastMouseDownInfo mLastLeftMouseDownInfo;
1346 LastMouseDownInfo mLastMiddleMouseDownInfo;
1347 LastMouseDownInfo mLastRightMouseDownInfo;
1349 nsCOMPtr<nsIContent> mActiveContent;
1350 nsCOMPtr<nsIContent> mHoverContent;
1351 static nsCOMPtr<nsIContent> sDragOverContent;
1352 nsCOMPtr<nsIContent> mURLTargetContent;
1353 nsCOMPtr<nsINode> mPopoverPointerDownTarget;
1355 nsPresContext* mPresContext; // Not refcnted
1356 RefPtr<dom::Document> mDocument; // Doesn't necessarily need to be owner
1358 RefPtr<IMEContentObserver> mIMEContentObserver;
1360 bool mShouldAlwaysUseLineDeltas : 1;
1361 bool mShouldAlwaysUseLineDeltasInitialized : 1;
1363 bool mGestureDownInTextControl : 1;
1365 bool mInTouchDrag;
1367 bool m_haveShutdown;
1369 RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
1370 nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper>
1371 mPointersEnterLeaveHelper;
1373 // Array for accesskey support
1374 nsCOMArray<dom::Element> mAccessKeys;
1376 bool ShouldAlwaysUseLineDeltas();
1378 public:
1379 static nsresult UpdateUserActivityTimer(void);
1381 static bool sNormalLMouseEventInProcess;
1382 static int16_t sCurrentMouseBtn;
1384 static EventStateManager* sActiveESM;
1386 static void ClearGlobalActiveContent(EventStateManager* aClearer);
1388 // Functions used for click hold context menus
1389 nsCOMPtr<nsITimer> mClickHoldTimer;
1390 void CreateClickHoldTimer(nsPresContext* aPresContext, nsIFrame* aDownFrame,
1391 WidgetGUIEvent* aMouseDownEvent);
1392 void KillClickHoldTimer();
1393 MOZ_CAN_RUN_SCRIPT_BOUNDARY void FireContextClick();
1395 MOZ_CAN_RUN_SCRIPT static void SetPointerLock(nsIWidget* aWidget,
1396 nsPresContext* aPresContext);
1397 static void sClickHoldCallback(nsITimer* aTimer, void* aESM);
1400 } // namespace mozilla
1402 // Click and double-click events need to be handled even for content that
1403 // has no frame. This is required for Web compatibility.
1404 #define NS_EVENT_NEEDS_FRAME(event) \
1405 ((event)->mMessage != ePointerClick && \
1406 (event)->mMessage != eMouseDoubleClick && \
1407 (event)->mMessage != ePointerAuxClick)
1409 #endif // mozilla_EventStateManager_h_