EventStateManager.h (62748B)
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 "Units.h" 11 #include "WheelHandlingHelper.h" // for WheelDeltaAdjustmentStrategy 12 #include "mozilla/Attributes.h" 13 #include "mozilla/EventForwards.h" 14 #include "mozilla/TimeStamp.h" 15 #include "mozilla/dom/Record.h" 16 #include "mozilla/layers/APZPublicUtils.h" 17 #include "nsCOMArray.h" 18 #include "nsCOMPtr.h" 19 #include "nsCycleCollectionParticipant.h" 20 #include "nsIObserver.h" 21 #include "nsIWeakReferenceUtils.h" 22 #include "nsRefPtrHashtable.h" 23 #include "nsWeakReference.h" 24 25 class nsFrameLoader; 26 class nsIContent; 27 class nsICookieJarSettings; 28 class nsIDocShell; 29 class nsIDocShellTreeItem; 30 class nsIFrame; 31 class imgIContainer; 32 class nsIDocumentViewer; 33 class nsITimer; 34 class nsIWidget; 35 class nsPresContext; 36 37 enum class FormControlType : uint8_t; 38 39 namespace mozilla { 40 41 class EditorBase; 42 class EnterLeaveDispatcher; 43 class IMEContentObserver; 44 class LazyLogModule; 45 class ScrollbarsForWheel; 46 class ScrollContainerFrame; 47 class TextControlElement; 48 class WheelTransaction; 49 50 namespace dom { 51 class DataTransfer; 52 class Document; 53 class Element; 54 class Selection; 55 class BrowserParent; 56 class RemoteDragStartData; 57 58 } // namespace dom 59 60 class OverOutElementsWrapper final : public nsISupports { 61 ~OverOutElementsWrapper() = default; 62 63 public: 64 enum class BoundaryEventType : bool { Mouse, Pointer }; 65 explicit OverOutElementsWrapper(BoundaryEventType aType) : mType(aType) {} 66 67 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 68 NS_DECL_CYCLE_COLLECTION_CLASS(OverOutElementsWrapper) 69 70 already_AddRefed<nsIWidget> GetLastOverWidget() const; 71 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; 82 } 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; 88 } 89 void DidDispatchOutAndOrLeaveEvent() { 90 StoreOverEventTargetAndDeepestEnterEventTarget(nullptr); 91 mDispatchingOutOrDeepestLeaveEventTarget = nullptr; 92 } 93 [[nodiscard]] bool IsDispatchingOutEventOnLastOverEventTarget() const { 94 return mDispatchingOutOrDeepestLeaveEventTarget && 95 mDispatchingOutOrDeepestLeaveEventTarget == mDeepestEnterEventTarget; 96 } 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; 103 } 104 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; 109 } 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; 119 } 120 121 /** 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. 131 * 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. 135 */ 136 void TryToRestorePendingRemovedOverTarget(const WidgetEvent* aEvent); 137 138 /** 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. 142 */ 143 [[nodiscard]] bool MaybeHasPendingRemovingOverEventTarget() const { 144 return mPendingRemovingOverEventTarget; 145 } 146 147 private: 148 /** 149 * Whether the last "over" event target is the target of "out" event if you 150 * dispatch "out" event. 151 */ 152 [[nodiscard]] bool LastOverEventTargetIsOutEventTarget() const { 153 MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget, 154 mDeepestEnterEventTarget); 155 MOZ_ASSERT_IF(mDeepestEnterEventTargetIsOverEventTarget, 156 !MaybeHasPendingRemovingOverEventTarget()); 157 return mDeepestEnterEventTargetIsOverEventTarget; 158 } 159 160 void StoreOverEventTargetAndDeepestEnterEventTarget( 161 nsIContent* aOverEventTargetAndDeepestEnterEventTarget); 162 void UpdateDeepestEnterEventTarget(nsIContent* aDeepestEnterEventTarget); 163 164 nsCOMPtr<nsIContent> GetPendingRemovingOverEventTarget() const { 165 nsCOMPtr<nsIContent> pendingRemovingOverEventTarget = 166 do_QueryReferent(mPendingRemovingOverEventTarget); 167 return pendingRemovingOverEventTarget.forget(); 168 } 169 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; 175 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; 186 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; 191 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; 196 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; 201 202 const BoundaryEventType mType; 203 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; 209 }; 210 211 class EventStateManager : public nsSupportsWeakReference, public nsIObserver { 212 friend class mozilla::EnterLeaveDispatcher; 213 friend class mozilla::ScrollbarsForWheel; 214 friend class mozilla::WheelTransaction; 215 216 using ElementState = dom::ElementState; 217 218 virtual ~EventStateManager(); 219 220 public: 221 EventStateManager(); 222 223 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 224 NS_DECL_NSIOBSERVER 225 226 nsresult Init(); 227 nsresult Shutdown(); 228 229 static LazyLogModule& MouseCursorUpdateLogRef(); 230 231 /* The PreHandleEvent method is called before event dispatch to either 232 * the DOM or frames. Any processing which must not be prevented or 233 * cancelled should occur here. Any processing which is intended to 234 * be conditional based on either DOM or frame processing should occur in 235 * PostHandleEvent. Any centralized event processing which must occur before 236 * DOM or frame event handling should occur here as well. 237 * 238 * aOverrideClickTarget can be used to indicate which element should be 239 * used as the *up target when deciding whether to send click event. 240 * This is used when releasing pointer capture. Otherwise null. 241 */ 242 MOZ_CAN_RUN_SCRIPT 243 nsresult PreHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent, 244 nsIFrame* aTargetFrame, nsIContent* aTargetContent, 245 nsEventStatus* aStatus, 246 nsIContent* aOverrideClickTarget); 247 248 /* The PostHandleEvent method should contain all system processing which 249 * should occur conditionally based on DOM or frame processing. It should 250 * also contain any centralized event processing which must occur after 251 * DOM and frame processing. 252 */ 253 MOZ_CAN_RUN_SCRIPT 254 nsresult PostHandleEvent(nsPresContext* aPresContext, WidgetEvent* aEvent, 255 nsIFrame* aTargetFrame, nsEventStatus* aStatus, 256 nsIContent* aOverrideClickTarget); 257 258 MOZ_CAN_RUN_SCRIPT void PostHandleKeyboardEvent( 259 WidgetKeyboardEvent* aKeyboardEvent, nsIFrame* aTargetFrame, 260 nsEventStatus& aStatus); 261 262 /** 263 * DispatchLegacyMouseScrollEvents() dispatches eLegacyMouseLineOrPageScroll 264 * event and eLegacyMousePixelScroll event for compatibility with old Gecko. 265 */ 266 MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchLegacyMouseScrollEvents( 267 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, nsEventStatus* aStatus); 268 269 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyDestroyPresContext( 270 nsPresContext* aPresContext); 271 272 void ResetHoverState(); 273 274 void SetPresContext(nsPresContext* aPresContext); 275 void ClearFrameRefs(nsIFrame* aFrame); 276 277 nsIFrame* GetEventTarget(); 278 already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent); 279 280 // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET 281 static bool ManagesState(ElementState aState) { 282 return aState == ElementState::ACTIVE || aState == ElementState::HOVER || 283 aState == ElementState::DRAGOVER || 284 aState == ElementState::URLTARGET; 285 } 286 287 /** 288 * Notify that the given ElementState::* bit has changed for this content. 289 * @param aContent Content which has changed states 290 * @param aState Corresponding state flags such as ElementState::FOCUS 291 * @return Whether the content was able to change all states. Returns false 292 * if a resulting DOM event causes the content node passed in 293 * to not change states. Note, the frame for the content may 294 * change as a result of the content state change, because of 295 * frame reconstructions that may occur, but this does not 296 * affect the return value. 297 */ 298 bool SetContentState(nsIContent* aContent, ElementState aState); 299 300 nsIContent* GetActiveContent() const { return mActiveContent; } 301 302 void NativeAnonymousContentRemoved(nsIContent* aAnonContent); 303 void ContentInserted(nsIContent* aChild, const ContentInsertInfo& aInfo); 304 void ContentAppended(nsIContent* aFirstNewContent, 305 const ContentAppendInfo& aInfo); 306 MOZ_CAN_RUN_SCRIPT_BOUNDARY void ContentRemoved( 307 dom::Document* aDocument, nsIContent* aContent, 308 const ContentRemoveInfo& aInfo); 309 310 /** 311 * Called when a native anonymous <div> element which is root element of 312 * text editor will be removed. 313 */ 314 void TextControlRootWillBeRemoved(TextControlElement& aTextControlElement); 315 316 /** 317 * Called when a native anonymous <div> element which is root element of 318 * text editor is created. 319 */ 320 void TextControlRootAdded(dom::Element& aAnonymousDivElement, 321 TextControlElement& aTextControlElement); 322 323 bool EventStatusOK(WidgetGUIEvent* aEvent); 324 325 /** 326 * EventStateManager stores IMEContentObserver while it's observing contents. 327 * Following mehtods are called by IMEContentObserver when it starts to 328 * observe or stops observing the content. 329 */ 330 void OnStartToObserveContent(IMEContentObserver* aIMEContentObserver); 331 void OnStopObservingContent(IMEContentObserver* aIMEContentObserver); 332 333 /** 334 * TryToFlushPendingNotificationsToIME() suggests flushing pending 335 * notifications to IME to IMEContentObserver. 336 * Doesn't do anything in child processes where flushing happens 337 * asynchronously. 338 */ 339 void TryToFlushPendingNotificationsToIME(); 340 341 static bool IsKeyboardEventUserActivity(WidgetEvent* aEvent); 342 343 /** 344 * Register accesskey on the given element. When accesskey is activated then 345 * the element will be notified via Element::PerformAccesskey() method. 346 * 347 * @param aElement the given element 348 * @param aKey accesskey 349 */ 350 void RegisterAccessKey(dom::Element* aElement, uint32_t aKey); 351 352 /** 353 * Unregister accesskey for the given element. 354 * 355 * @param aElement the given element 356 * @param aKey accesskey 357 */ 358 void UnregisterAccessKey(dom::Element* aElement, uint32_t aKey); 359 360 /** 361 * Get accesskey registered on the given element or 0 if there is none. 362 * 363 * @param aElement the given element (must not be null) 364 * @return registered accesskey 365 */ 366 uint32_t GetRegisteredAccessKey(dom::Element* aContent); 367 368 static void GetAccessKeyLabelPrefix(dom::Element* aElement, 369 nsAString& aPrefix); 370 371 /** 372 * HandleAccessKey() looks for access keys which matches with aEvent and 373 * execute when it matches with a chrome access key or some content access 374 * keys. 375 * If the event may match chrome access keys, this handles the access key 376 * synchronously (if there are nested ESMs, their HandleAccessKey() are 377 * also called recursively). 378 * If the event may match content access keys and focused target is a remote 379 * process, this does nothing for the content because when this is called, 380 * it should already have been handled in the remote process. 381 * If the event may match content access keys and focused target is not in 382 * remote process but there are some remote children, this will post 383 * HandleAccessKey messages to all remote children. 384 * 385 * @return true if there is accesskey which aEvent and 386 * aAccessCharCodes match with. Otherwise, false. 387 * I.e., when this returns true, a target is executed 388 * or focused. 389 * Note that even if this returns false, a target in 390 * remote process may be executed or focused 391 * asynchronously. 392 */ 393 bool HandleAccessKey(WidgetKeyboardEvent* aEvent, nsPresContext* aPresContext, 394 nsTArray<uint32_t>& aAccessCharCodes) { 395 return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, aAccessCharCodes, 396 nullptr, eAccessKeyProcessingNormal, 397 true); 398 } 399 400 /** 401 * CheckIfEventMatchesAccessKey() looks for access key which matches with 402 * aEvent in the process but won't execute it. 403 * 404 * @return true if there is accesskey which aEvent matches with 405 * in this process. Otherwise, false. 406 */ 407 bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent, 408 nsPresContext* aPresContext); 409 410 nsresult SetCursor(StyleCursorKind, imgIContainer*, const ImageResolution&, 411 const Maybe<gfx::IntPoint>& aHotspot, nsIWidget* aWidget, 412 bool aLockCursor); 413 414 void StartHidingCursorWhileTyping(nsIWidget*); 415 416 /** 417 * Checks if the current mouse over element matches the given 418 * Element (which has a remote frame), and if so, notifies 419 * the BrowserParent of the mouse enter. 420 * Called when we reconstruct the BrowserParent and need to 421 * recompute state on the new object. 422 */ 423 void RecomputeMouseEnterStateForRemoteFrame(dom::Element& aElement); 424 425 nsPresContext* GetPresContext() const { return mPresContext; } 426 427 PresShell* GetPresShell() const { 428 return mPresContext ? mPresContext->GetPresShell() : nullptr; 429 } 430 431 /** 432 * Return the in-process root PresShell which is associated with the root 433 * nsPresContext of mPresContext. 434 */ 435 PresShell* GetRootPresShell() const; 436 437 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, nsIObserver) 438 439 // The manager in this process that is setting the cursor. In the parent 440 // process it might be null if a remote process is setting the cursor. 441 static EventStateManager* sCursorSettingManager; 442 static void ClearCursorSettingManager() { sCursorSettingManager = nullptr; } 443 444 // Checks if the manager in this process has a locked cursor 445 static bool CursorSettingManagerHasLockedCursor(); 446 447 static EventStateManager* GetActiveEventStateManager() { return sActiveESM; } 448 449 // Sets aNewESM to be the active event state manager, and 450 // if aContent is non-null, marks the object as active. 451 static void SetActiveManager(EventStateManager* aNewESM, 452 nsIContent* aContent); 453 454 static bool IsRemoteTarget(nsIContent* target); 455 456 static bool IsTopLevelRemoteTarget(nsIContent* aTarget); 457 458 // Returns the kind of APZ action the given WidgetWheelEvent will perform. 459 static Maybe<layers::APZWheelAction> APZWheelActionFor( 460 const WidgetWheelEvent* aEvent); 461 462 // For some kinds of scrollings, the delta values of WidgetWheelEvent are 463 // possbile to be adjusted. This function is used to detect such scrollings 464 // and returns a wheel delta adjustment strategy to use, which is corresponded 465 // to the kind of the scrolling. 466 // It returns WheelDeltaAdjustmentStrategy::eAutoDir if the current default 467 // action is auto-dir scrolling which honours the scrolling target(The 468 // comments in WheelDeltaAdjustmentStrategy describes the concept in detail). 469 // It returns WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour if the 470 // current action is auto-dir scrolling which honours the root element in the 471 // document where the scrolling target is(The comments in 472 // WheelDeltaAdjustmentStrategy describes the concept in detail). 473 // It returns WheelDeltaAdjustmentStrategy::eHorizontalize if the current 474 // default action is horizontalized scrolling. 475 // It returns WheelDeltaAdjustmentStrategy::eNone to mean no delta adjustment 476 // strategy should be used if the scrolling is just a tranditional scrolling 477 // whose delta values are never possible to be adjusted. 478 static WheelDeltaAdjustmentStrategy GetWheelDeltaAdjustmentStrategy( 479 const WidgetWheelEvent& aEvent); 480 481 // Returns user-set multipliers for a wheel event. 482 static void GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent, 483 double* aOutMultiplierX, 484 double* aOutMultiplierY); 485 486 // Holds the point in screen coords that a mouse event was dispatched to, 487 // before we went into pointer lock mode. This is constantly updated while 488 // the pointer is not locked, but we don't update it while the pointer is 489 // locked. This is used by dom::Event::GetScreenCoords() to make mouse 490 // events' screen coord appear frozen at the last mouse position while 491 // the pointer is locked. 492 static CSSIntPoint sLastScreenPoint; 493 494 // Holds the point in client coords of the last mouse event. Used by 495 // dom::Event::GetClientCoords() to make mouse events' client coords appear 496 // frozen at the last mouse position while the pointer is locked. 497 static CSSIntPoint sLastClientPoint; 498 499 /** 500 * If the absolute values of mMultiplierX and/or mMultiplierY are equal or 501 * larger than this value, the computed scroll amount isn't rounded down to 502 * the page width or height. 503 */ 504 static constexpr double MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 505 1000.0; 506 507 /** 508 * HandleMiddleClickPaste() handles middle mouse button event as pasting 509 * clipboard text. Note that if aEditorBase is nullptr, this only 510 * dispatches ePaste event because it's necessary for some web apps which 511 * want to implement their own editor and supports middle click paste. 512 * 513 * @param aPresShell The PresShell for the ESM. This lifetime 514 * should be guaranteed by the caller. 515 * @param aMouseEvent The ePointerClick event which caused the 516 * paste. 517 * @param aStatus The event status of aMouseEvent. 518 * @param aEditorBase EditorBase which may be pasted the 519 * clipboard text by the middle click. 520 * If there is no editor for aMouseEvent, 521 * set nullptr. 522 */ 523 MOZ_CAN_RUN_SCRIPT 524 nsresult HandleMiddleClickPaste(PresShell* aPresShell, 525 WidgetMouseEvent* aMouseEvent, 526 nsEventStatus* aStatus, 527 EditorBase* aEditorBase); 528 529 static void ConsumeInteractionData( 530 dom::Record<nsString, dom::InteractionData>& aInteractions); 531 532 // Stop tracking a possible drag. If aClearInChildProcesses is true, send 533 // a notification to any child processes that are in the drag service that 534 // tried to start a drag. 535 void StopTrackingDragGesture(bool aClearInChildProcesses); 536 537 /** 538 * Return the last "mouseover" (or next "mouseout"), the last deepest 539 * "mouseenter" (or next deepest "mouseleave") targets. 540 */ 541 const OverOutElementsWrapper* GetExtantMouseBoundaryEventTarget() const { 542 return mMouseEnterLeaveHelper; 543 } 544 545 nsIContent* GetTrackingDragGestureContent() const { 546 return mGestureDownContent; 547 } 548 549 // Update the tracked gesture content to the parent of its frame when it's 550 // removed, so that the gesture can be continued. 551 void NotifyContentWillBeRemovedForGesture(nsIContent& aContent); 552 553 bool IsTrackingDragGesture() const { return mGestureDownContent != nullptr; } 554 555 protected: 556 /* 557 * If aTargetFrame's widget has a cached cursor value, resets the cursor 558 * such that the next call to SetCursor on the widget will force an update 559 * of the native cursor. For use in getting puppet widget to update its 560 * cursor between mouse exit / enter transitions. This call basically wraps 561 * nsIWidget ClearCachedCursor. 562 */ 563 void ClearCachedWidgetCursor(nsIFrame* aTargetFrame); 564 565 void UpdateCursor(nsPresContext*, WidgetMouseEvent*, nsIFrame* aTargetFrame, 566 nsEventStatus* aStatus); 567 /** 568 * Turn a GUI mouse/pointer event into a mouse/pointer event targeted at the 569 * specified content. 570 * 571 * @return widget which is the nearest widget from the event target frame. 572 */ 573 [[nodiscard]] MOZ_CAN_RUN_SCRIPT already_AddRefed<nsIWidget> 574 DispatchMouseOrPointerBoundaryEvent(WidgetMouseEvent* aMouseEvent, 575 EventMessage aMessage, 576 nsIContent* aTargetContent, 577 nsIContent* aRelatedContent); 578 /** 579 * Synthesize DOM pointerover and pointerout events 580 */ 581 void GeneratePointerEnterExit(EventMessage aMessage, 582 WidgetMouseEvent* aEvent); 583 /** 584 * Synthesize DOM and frame mouseover and mouseout events from this 585 * MOUSE_MOVE or MOUSE_EXIT event. 586 */ 587 void GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent); 588 /** 589 * Tell this ESM and ESMs in parent documents that the mouse is 590 * over some content in this document. 591 */ 592 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOver( 593 WidgetMouseEvent* aMouseEvent, nsIContent* aContent); 594 /** 595 * Tell this ESM and ESMs in affected child documents that the mouse 596 * has exited this document's currently hovered content. 597 * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) 598 * 599 * @param aMouseEvent the event that triggered the mouseout 600 * @param aMovingInto the content node we've moved into. This is used to set 601 * the relatedTarget for mouseout events. Also, if it's non-null 602 * NotifyMouseOut will NOT change the current hover content to null; 603 * in that case the caller is responsible for updating hover state. 604 */ 605 MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyMouseOut(WidgetMouseEvent* aMouseEvent, 606 nsIContent* aMovingInto); 607 MOZ_CAN_RUN_SCRIPT void GenerateDragDropEnterExit( 608 nsPresContext* aPresContext, WidgetDragEvent* aDragEvent); 609 610 /** 611 * Return mMouseEnterLeaveHelper or relevant mPointersEnterLeaveHelper 612 * elements wrapper. If mPointersEnterLeaveHelper does not contain wrapper for 613 * pointerId it create new one 614 */ 615 OverOutElementsWrapper* GetWrapperByEventID(WidgetMouseEvent* aMouseEvent); 616 617 /** 618 * Fire the dragenter and dragexit/dragleave events when the mouse moves to a 619 * new target. 620 * 621 * @param aRelatedTarget relatedTarget to set for the event 622 * @param aTargetContent target to set for the event 623 * @param aTargetFrame target frame for the event 624 */ 625 MOZ_CAN_RUN_SCRIPT void FireDragEnterOrExit(nsPresContext* aPresContext, 626 WidgetDragEvent* aDragEvent, 627 EventMessage aMessage, 628 nsIContent* aRelatedTarget, 629 nsIContent* aTargetContent, 630 AutoWeakFrame& aTargetFrame); 631 /** 632 * Update the initial drag session data transfer with any changes that occur 633 * on cloned data transfer objects used for events. 634 */ 635 void UpdateDragDataTransfer(WidgetDragEvent* dragEvent); 636 637 /** 638 * InitAndDispatchClickEvent() dispatches a click event. 639 * 640 * @param aMouseUpEvent eMouseUp event which causes the click event. 641 * EventCausesClickEvents() must return true 642 * if this event is set to it. 643 * @param aStatus Returns the result of click event. 644 * If the status indicates consumed, the 645 * value won't be overwritten with 646 * nsEventStatus_eIgnore. 647 * @param aMessage Should be ePointerClick, eMouseDoubleClick 648 * or ePointerAuxClick. 649 * @param aPresShell The PresShell. 650 * @param aMouseUpContent The event target of aMouseUpEvent. 651 * @param aCurrentTarget Current target of the caller. 652 * @param aNoContentDispatch true if the event shouldn't be exposed to 653 * web contents (although will be fired on 654 * document and window). 655 * @param aOverrideClickTarget Preferred click event target. If this is 656 * not nullptr, aMouseUpContent and 657 * aCurrentTarget are ignored. 658 */ 659 MOZ_CAN_RUN_SCRIPT 660 static nsresult InitAndDispatchClickEvent( 661 WidgetMouseEvent* aMouseUpEvent, nsEventStatus* aStatus, 662 EventMessage aMessage, PresShell* aPresShell, nsIContent* aMouseUpContent, 663 AutoWeakFrame aCurrentTarget, bool aNoContentDispatch, 664 nsIContent* aOverrideClickTarget); 665 666 /** 667 * Prepare aEvent and corresponding LastMouseDownInfo for dispatching 668 * ePointerClick, ePointerAuxClick or eContextMenu later. 669 */ 670 void PrepareForFollowingClickEvent( 671 WidgetMouseEvent& aEvent, nsIContent* aOverrideClickTarget = nullptr); 672 673 /** 674 * EventCausesClickEvents() returns true when aMouseEvent is an eMouseUp 675 * event and it should cause ePointerClick, eMouseDoubleClick and/or 676 * ePointerAuxClick events. Note that this method assumes that 677 * aMouseEvent.mClickCount has already been initialized with SetClickCount(). 678 */ 679 static bool EventCausesClickEvents(const WidgetMouseEvent& aMouseEvent); 680 681 /** 682 * PostHandleMouseUp() handles default actions of eMouseUp event. 683 * 684 * @param aMouseUpEvent eMouseUp event which causes the click event. 685 * EventCausesClickEvents() must return true 686 * if this event is set to it. 687 * @param aStatus Returns the result of event status. 688 * If one of dispatching event is consumed or 689 * this does something as default action, 690 * returns nsEventStatus_eConsumeNoDefault. 691 * @param aOverrideClickTarget Preferred click event target. If nullptr, 692 * aMouseUpEvent target and current target 693 * are used. 694 */ 695 MOZ_CAN_RUN_SCRIPT 696 nsresult PostHandleMouseUp(WidgetMouseEvent* aMouseUpEvent, 697 nsEventStatus* aStatus, 698 nsIContent* aOverrideClickTarget); 699 700 /** 701 * DispatchClickEvents() dispatches ePointerClick, eMouseDoubleClick and 702 * ePointerAuxClick events for aMouseUpEvent. aMouseUpEvent should cause 703 * click event. 704 * 705 * @param aPresShell The PresShell. 706 * @param aMouseUpEvent eMouseUp event which causes the click event. 707 * EventCausesClickEvents() must return true 708 * if this event is set to it. 709 * @param aStatus Returns the result of event status. 710 * If one of dispatching click event is 711 * consumed, returns 712 * nsEventStatus_eConsumeNoDefault. 713 * @param aMouseUpContent The event target of aMouseUpEvent. 714 * @param aOverrideClickTarget Preferred click event target. If this is 715 * not nullptr, aMouseUpContent and 716 * current target frame of the ESM are ignored. 717 */ 718 MOZ_CAN_RUN_SCRIPT 719 nsresult DispatchClickEvents(PresShell* aPresShell, 720 WidgetMouseEvent* aMouseUpEvent, 721 nsEventStatus* aStatus, 722 nsIContent* aMouseUpContent, 723 nsIContent* aOverrideClickTarget); 724 725 void EnsureDocument(nsPresContext* aPresContext); 726 MOZ_CAN_RUN_SCRIPT_BOUNDARY 727 void FlushLayout(nsPresContext* aPresContext); 728 729 /** 730 * The phases of WalkESMTreeToHandleAccessKey processing. See below. 731 */ 732 enum ProcessingAccessKeyState { 733 eAccessKeyProcessingNormal = 0, 734 eAccessKeyProcessingUp, 735 eAccessKeyProcessingDown 736 }; 737 738 /** 739 * Walk EMS to look for access key and execute found access key when aExecute 740 * is true. 741 * If there is registered element for the accesskey given by the key event 742 * and modifier mask then call element.PerformAccesskey(), otherwise call 743 * WalkESMTreeToHandleAccessKey() recursively, on descendant docshells first, 744 * then on the ancestor (with |aBubbledFrom| set to the docshell associated 745 * with |this|), until something matches. 746 * 747 * @param aEvent the keyboard event triggering the acccess key 748 * @param aPresContext the presentation context 749 * @param aAccessCharCodes list of charcode candidates 750 * @param aBubbledFrom is used by an ancestor to avoid calling 751 * WalkESMTreeToHandleAccessKey() on the child the call originally 752 * came from, i.e. this is the child that recursively called us in 753 * its Up phase. The initial caller passes |nullptr| here. This is to 754 * avoid an infinite loop. 755 * @param aAccessKeyState Normal, Down or Up processing phase (see enums 756 * above). The initial event receiver uses 'normal', then 'down' when 757 * processing children and Up when recursively calling its ancestor. 758 * @param aExecute is true, execute an accesskey if it's found. Otherwise, 759 * found accesskey won't be executed. 760 * 761 * @return true if there is a target which aEvent and 762 * aAccessCharCodes match with in this process. 763 * Otherwise, false. I.e., when this returns true and 764 * aExecute is true, a target is executed or focused. 765 * Note that even if this returns false, a target in 766 * remote process may be executed or focused 767 * asynchronously. 768 */ 769 bool WalkESMTreeToHandleAccessKey(WidgetKeyboardEvent* aEvent, 770 nsPresContext* aPresContext, 771 nsTArray<uint32_t>& aAccessCharCodes, 772 nsIDocShellTreeItem* aBubbledFrom, 773 ProcessingAccessKeyState aAccessKeyState, 774 bool aExecute); 775 776 /** 777 * Look for access key and execute found access key if aExecute is true in 778 * the instance. 779 * 780 * @return true if there is a target which matches with 781 * aAccessCharCodes and aIsTrustedEvent. Otherwise, 782 * false. I.e., when this returns true and aExecute 783 * is true, a target is executed or focused. 784 */ 785 MOZ_CAN_RUN_SCRIPT_BOUNDARY bool LookForAccessKeyAndExecute( 786 nsTArray<uint32_t>& aAccessCharCodes, bool aIsTrustedEvent, 787 bool aIsRepeat, bool aExecute); 788 789 //--------------------------------------------- 790 // DocShell Focus Traversal Methods 791 //--------------------------------------------- 792 793 dom::Element* GetFocusedElement(); 794 bool IsShellVisible(nsIDocShell* aShell); 795 796 // These functions are for mousewheel and pixel scrolling 797 798 class WheelPrefs { 799 public: 800 static WheelPrefs* GetInstance(); 801 static void Shutdown(); 802 803 /** 804 * ApplyUserPrefsToDelta() overrides the wheel event's delta values with 805 * user prefs. 806 */ 807 void ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent); 808 809 /** 810 * Returns whether or not ApplyUserPrefsToDelta() would change the delta 811 * values of an event. 812 */ 813 void GetUserPrefsForEvent(const WidgetWheelEvent* aEvent, 814 double* aOutMultiplierX, double* aOutMultiplierY); 815 816 /** 817 * If ApplyUserPrefsToDelta() changed the delta values with customized 818 * prefs, the overflowDelta values would be inflated. 819 * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation. 820 */ 821 void CancelApplyingUserPrefsFromOverflowDelta(WidgetWheelEvent* aEvent); 822 823 /** 824 * Computes the default action for the aEvent with the prefs. 825 */ 826 enum Action : uint8_t { 827 ACTION_NONE = 0, 828 ACTION_SCROLL, 829 ACTION_HISTORY, 830 ACTION_ZOOM, 831 // Horizontalized scrolling means treating vertical wheel scrolling as 832 // horizontal scrolling during the process of its default action and 833 // plugins handling scrolling. Note that delta values as the event object 834 // in a DOM event listener won't be affected, and will be still the 835 // original values. For more details, refer to 836 // mozilla::WheelDeltaAdjustmentStrategy::eHorizontalize 837 ACTION_HORIZONTALIZED_SCROLL, 838 ACTION_PINCH_ZOOM, 839 ACTION_LAST = ACTION_PINCH_ZOOM, 840 // Following actions are used only by internal processing. So, cannot 841 // specified by prefs. 842 ACTION_SEND_TO_PLUGIN, 843 }; 844 Action ComputeActionFor(const WidgetWheelEvent* aEvent); 845 846 /** 847 * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be 848 * computed the lineOrPageDelta values. 849 */ 850 bool NeedToComputeLineOrPageDelta(const WidgetWheelEvent* aEvent); 851 852 /** 853 * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should 854 * be rounded down to the page width/height (false) or not (true). 855 */ 856 bool IsOverOnePageScrollAllowedX(const WidgetWheelEvent* aEvent); 857 bool IsOverOnePageScrollAllowedY(const WidgetWheelEvent* aEvent); 858 859 private: 860 WheelPrefs(); 861 ~WheelPrefs(); 862 863 static void OnPrefChanged(const char* aPrefName, void* aClosure); 864 865 enum Index { 866 INDEX_DEFAULT = 0, 867 INDEX_ALT, 868 INDEX_CONTROL, 869 INDEX_META, 870 INDEX_SHIFT, 871 COUNT_OF_MULTIPLIERS 872 }; 873 874 /** 875 * GetIndexFor() returns the index of the members which should be used for 876 * the aEvent. When only one modifier key of MODIFIER_ALT, 877 * MODIFIER_CONTROL, MODIFIER_META or MODIFIER_SHIFT is pressed, returns the 878 * index for the modifier. Otherwise, this return the default index which 879 * is used at either no modifier key is pressed or two or modifier keys are 880 * pressed. 881 */ 882 Index GetIndexFor(const WidgetWheelEvent* aEvent); 883 884 /** 885 * GetPrefNameBase() returns the base pref name for aEvent. 886 * It's decided by GetModifierForPref() which modifier should be used for 887 * the aEvent. 888 * 889 * @param aBasePrefName The result, must be "mousewheel.with_*." or 890 * "mousewheel.default.". 891 */ 892 void GetBasePrefName(Index aIndex, nsACString& aBasePrefName); 893 894 void Init(Index aIndex); 895 896 void Reset(); 897 898 /** 899 * Retrieve multiplier for aEvent->mDeltaX and aEvent->mDeltaY. 900 * 901 * Note that if the default action is ACTION_HORIZONTALIZED_SCROLL and the 902 * delta values have been adjusted by WheelDeltaHorizontalizer() before this 903 * function is called, this function will swap the X and Y multipliers. By 904 * doing this, multipliers will still apply to the delta values they 905 * originally corresponded to. 906 * 907 * @param aEvent The event which is being handled. 908 * @param aIndex The index of mMultiplierX and mMultiplierY. 909 * Should be result of GetIndexFor(aEvent). 910 * @param aMultiplierForDeltaX Will be set to multiplier for 911 * aEvent->mDeltaX. 912 * @param aMultiplierForDeltaY Will be set to multiplier for 913 * aEvent->mDeltaY. 914 */ 915 void GetMultiplierForDeltaXAndY(const WidgetWheelEvent* aEvent, 916 Index aIndex, double* aMultiplierForDeltaX, 917 double* aMultiplierForDeltaY); 918 919 bool mInit[COUNT_OF_MULTIPLIERS]; 920 double mMultiplierX[COUNT_OF_MULTIPLIERS]; 921 double mMultiplierY[COUNT_OF_MULTIPLIERS]; 922 double mMultiplierZ[COUNT_OF_MULTIPLIERS]; 923 Action mActions[COUNT_OF_MULTIPLIERS]; 924 /** 925 * action values overridden by .override_x pref. 926 * If an .override_x value is -1, same as the 927 * corresponding mActions value. 928 */ 929 Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS]; 930 931 static WheelPrefs* sInstance; 932 }; 933 934 /** 935 * DeltaDirection is used for specifying whether the called method should 936 * handle vertical delta or horizontal delta. 937 * This is clearer than using bool. 938 */ 939 enum DeltaDirection { DELTA_DIRECTION_X = 0, DELTA_DIRECTION_Y }; 940 941 struct MOZ_STACK_CLASS EventState { 942 bool mDefaultPrevented; 943 bool mDefaultPreventedByContent; 944 945 EventState() 946 : mDefaultPrevented(false), mDefaultPreventedByContent(false) {} 947 }; 948 949 /** 950 * SendLineScrollEvent() dispatches a DOMMouseScroll event for the 951 * WidgetWheelEvent. This method shouldn't be called for non-trusted 952 * wheel event because it's not necessary for compatiblity. 953 * 954 * @param aTargetFrame The event target of wheel event. 955 * @param aEvent The original Wheel event. 956 * @param aState The event which should be set to the dispatching 957 * event. This also returns the dispatched event 958 * state. 959 * @param aDelta The delta value of the event. 960 * @param aDeltaDirection The X/Y direction of dispatching event. 961 */ 962 MOZ_CAN_RUN_SCRIPT void SendLineScrollEvent(nsIFrame* aTargetFrame, 963 WidgetWheelEvent* aEvent, 964 EventState& aState, 965 int32_t aDelta, 966 DeltaDirection aDeltaDirection); 967 968 /** 969 * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the 970 * WidgetWheelEvent. This method shouldn't be called for non-trusted 971 * wheel event because it's not necessary for compatiblity. 972 * 973 * @param aTargetFrame The event target of wheel event. 974 * @param aEvent The original Wheel event. 975 * @param aState The event which should be set to the dispatching 976 * event. This also returns the dispatched event 977 * state. 978 * @param aPixelDelta The delta value of the event. 979 * @param aDeltaDirection The X/Y direction of dispatching event. 980 */ 981 MOZ_CAN_RUN_SCRIPT void SendPixelScrollEvent(nsIFrame* aTargetFrame, 982 WidgetWheelEvent* aEvent, 983 EventState& aState, 984 int32_t aPixelDelta, 985 DeltaDirection aDeltaDirection); 986 987 /** 988 * ComputeScrollTargetAndMayAdjustWheelEvent() returns the scrollable frame 989 * which should be scrolled. 990 * 991 * @param aTargetFrame The event target of the wheel event. 992 * @param aEvent The handling mouse wheel event. 993 * @param aOptions The options for finding the scroll target. 994 * Callers should use COMPUTE_*. 995 * @return The scrollable frame which should be scrolled. 996 */ 997 // These flags are used in ComputeScrollTargetAndMayAdjustWheelEvent(). 998 // Callers should use COMPUTE_*. 999 enum { 1000 PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001, 1001 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002, 1002 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004, 1003 START_FROM_PARENT = 0x00000008, 1004 INCLUDE_PLUGIN_AS_TARGET = 0x00000010, 1005 // Indicates the wheel scroll event being computed is an auto-dir scroll, so 1006 // its delta may be adjusted after being computed. 1007 MAY_BE_ADJUSTED_BY_AUTO_DIR = 0x00000020, 1008 }; 1009 enum ComputeScrollTargetOptions { 1010 // At computing scroll target for legacy mouse events, we should return 1011 // first scrollable element even when it's not scrollable to the direction. 1012 COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0, 1013 // Default action prefers the scrolled element immediately before if it's 1014 // still under the mouse cursor. Otherwise, it prefers the nearest 1015 // scrollable ancestor which will be scrolled actually. 1016 COMPUTE_DEFAULT_ACTION_TARGET = 1017 (PREFER_MOUSE_WHEEL_TRANSACTION | 1018 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | 1019 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS), 1020 // Compute the default action target without considering the current wheel 1021 // transaction. 1022 COMPUTE_DEFAULT_ACTION_TARGET_WITHOUT_WHEEL_TRANSACTION = 1023 (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | 1024 PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS), 1025 COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR = 1026 (COMPUTE_DEFAULT_ACTION_TARGET | MAY_BE_ADJUSTED_BY_AUTO_DIR), 1027 // Look for the nearest scrollable ancestor which can be scrollable with 1028 // aEvent. 1029 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS = 1030 (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT), 1031 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS = 1032 (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT), 1033 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR = 1034 (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS | 1035 MAY_BE_ADJUSTED_BY_AUTO_DIR), 1036 COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR = 1037 (COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS | 1038 MAY_BE_ADJUSTED_BY_AUTO_DIR), 1039 }; 1040 1041 // Compute the scroll target. 1042 // The delta values in the wheel event may be changed if the event is for 1043 // auto-dir scrolling. For information on auto-dir, 1044 // @see mozilla::WheelDeltaAdjustmentStrategy 1045 ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent( 1046 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, 1047 ComputeScrollTargetOptions aOptions); 1048 1049 ScrollContainerFrame* ComputeScrollTargetAndMayAdjustWheelEvent( 1050 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY, 1051 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions); 1052 1053 ScrollContainerFrame* ComputeScrollTarget( 1054 nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent, 1055 ComputeScrollTargetOptions aOptions) { 1056 MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR), 1057 "aEvent may be modified by auto-dir"); 1058 return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, aEvent, 1059 aOptions); 1060 } 1061 1062 ScrollContainerFrame* ComputeScrollTarget( 1063 nsIFrame* aTargetFrame, double aDirectionX, double aDirectionY, 1064 WidgetWheelEvent* aEvent, ComputeScrollTargetOptions aOptions) { 1065 MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR), 1066 "aEvent may be modified by auto-dir"); 1067 return ComputeScrollTargetAndMayAdjustWheelEvent( 1068 aTargetFrame, aDirectionX, aDirectionY, aEvent, aOptions); 1069 } 1070 1071 /** 1072 * GetScrollAmount() returns the scroll amount in app uints of one line or 1073 * one page. If the wheel event scrolls a page, returns the page width and 1074 * height. Otherwise, returns line height for both its width and height. 1075 * 1076 * @param aScrollContainerFrame A frame which will be scrolled by the event. 1077 * The result of 1078 * ComputeScrollTargetAndMayAdjustWheelEvent() is 1079 * expected for this value. 1080 * This can be nullptr if there is no scrollable 1081 * frame. Then, this method uses root frame's 1082 * line height or visible area's width and 1083 * height. 1084 */ 1085 nsSize GetScrollAmount(nsPresContext* aPresContext, WidgetWheelEvent* aEvent, 1086 ScrollContainerFrame* aScrollContainerFrame); 1087 1088 /** 1089 * DoScrollText() scrolls the scroll container frame for aEvent. 1090 */ 1091 void DoScrollText(ScrollContainerFrame* aScrollContainerFrame, 1092 WidgetWheelEvent* aEvent); 1093 1094 MOZ_CAN_RUN_SCRIPT 1095 void DoScrollHistory(int32_t direction); 1096 void DoScrollZoom(nsIFrame* aTargetFrame, int32_t adjustment); 1097 void ChangeZoom(bool aIncrease); 1098 1099 /** 1100 * DeltaAccumulator class manages delta values for dispatching DOMMouseScroll 1101 * event. If wheel events are caused by pixel scroll only devices or 1102 * the delta values are customized by prefs, this class stores the delta 1103 * values and set lineOrPageDelta values. 1104 */ 1105 class DeltaAccumulator { 1106 public: 1107 static DeltaAccumulator* GetInstance() { 1108 if (!sInstance) { 1109 sInstance = new DeltaAccumulator; 1110 } 1111 return sInstance; 1112 } 1113 1114 static void Shutdown() { 1115 delete sInstance; 1116 sInstance = nullptr; 1117 } 1118 1119 bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; } 1120 1121 /** 1122 * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents 1123 * which are caused if it's needed. And if the accumulated delta becomes a 1124 * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically. 1125 */ 1126 void InitLineOrPageDelta(nsIFrame* aTargetFrame, EventStateManager* aESM, 1127 WidgetWheelEvent* aEvent); 1128 1129 /** 1130 * Reset() resets all members. 1131 */ 1132 void Reset(); 1133 1134 /** 1135 * ComputeScrollAmountForDefaultAction() computes the default action's 1136 * scroll amount in device pixels with mPendingScrollAmount*. 1137 */ 1138 nsIntPoint ComputeScrollAmountForDefaultAction( 1139 WidgetWheelEvent* aEvent, const nsIntSize& aScrollAmountInDevPixels); 1140 1141 private: 1142 DeltaAccumulator() 1143 : mX(0.0), 1144 mY(0.0), 1145 mPendingScrollAmountX(0.0), 1146 mPendingScrollAmountY(0.0), 1147 mHandlingDeltaMode(UINT32_MAX), 1148 mIsNoLineOrPageDeltaDevice(false) {} 1149 1150 double mX; 1151 double mY; 1152 1153 // When default action of a wheel event is scroll but some delta values 1154 // are ignored because the computed amount values are not integer, the 1155 // fractional values are saved by these members. 1156 double mPendingScrollAmountX; 1157 double mPendingScrollAmountY; 1158 1159 TimeStamp mLastTime; 1160 1161 uint32_t mHandlingDeltaMode; 1162 bool mIsNoLineOrPageDeltaDevice; 1163 1164 static DeltaAccumulator* sInstance; 1165 }; 1166 1167 // end mousewheel functions 1168 1169 /* 1170 * When a touch gesture is about to start, this function determines what 1171 * kind of gesture interaction we will want to use, based on what is 1172 * underneath the initial touch point. 1173 * Currently it decides between panning (finger scrolling) or dragging 1174 * the target element, as well as the orientation to trigger panning and 1175 * display visual boundary feedback. The decision is stored back in aEvent. 1176 */ 1177 void DecideGestureEvent(WidgetGestureNotifyEvent* aEvent, 1178 nsIFrame* targetFrame); 1179 1180 // routines for the d&d gesture tracking state machine 1181 void BeginTrackingDragGesture(nsPresContext* aPresContext, 1182 WidgetMouseEvent* aDownEvent, 1183 nsIFrame* aDownFrame); 1184 1185 void SetGestureDownPoint(WidgetGUIEvent* aEvent); 1186 1187 LayoutDeviceIntPoint GetEventRefPoint(WidgetEvent* aEvent) const; 1188 1189 friend class mozilla::dom::BrowserParent; 1190 void BeginTrackingRemoteDragGesture(nsIContent* aContent, 1191 dom::RemoteDragStartData* aDragStartData); 1192 1193 MOZ_CAN_RUN_SCRIPT 1194 void GenerateDragGesture(nsPresContext* aPresContext, 1195 WidgetInputEvent* aEvent); 1196 1197 /** 1198 * Try to dispatch ePointerCancel for aSourceEvent to aTargetContent. 1199 */ 1200 MOZ_CAN_RUN_SCRIPT void MaybeDispatchPointerCancel( 1201 const WidgetInputEvent& aSourceEvent, nsIContent& aTargetContent); 1202 1203 /** 1204 * Determine which node the drag should be targeted at. 1205 * This is either the node clicked when there is a selection, or, for HTML, 1206 * the element with a draggable property set to true. 1207 * 1208 * aSelectionTarget - target to check for selection 1209 * aDataTransfer - data transfer object that will contain the data to drag 1210 * aAllowEmptyDataTransfer - [out] set to true, if dnd operation can be 1211 * started even if DataTransfer is empty 1212 * aSelection - [out] set to the selection to be dragged 1213 * aTargetNode - [out] the draggable node, or null if there isn't one 1214 * aPrincipal - [out] set to the triggering principal of the drag, or null 1215 * if it's from browser chrome or OS 1216 * aCookieJarSettings - [out] set to the cookieJarSettings of the drag, or 1217 * null if it's from browser chrome or OS. 1218 */ 1219 void DetermineDragTargetAndDefaultData( 1220 nsPIDOMWindowOuter* aWindow, nsIContent* aSelectionTarget, 1221 dom::DataTransfer* aDataTransfer, bool* aAllowEmptyDataTransfer, 1222 dom::Selection** aSelection, 1223 dom::RemoteDragStartData** aRemoteDragStartData, nsIContent** aTargetNode, 1224 nsIPrincipal** aPrincipal, nsIPolicyContainer** aPolicyContainer, 1225 nsICookieJarSettings** aCookieJarSettings); 1226 1227 /* 1228 * Perform the default handling for the dragstart event and set up a 1229 * drag for aDataTransfer if it contains any data. Returns true if a drag has 1230 * started. 1231 * 1232 * aDragEvent - the dragstart event 1233 * aDataTransfer - the data transfer that holds the data to be dragged 1234 * aAllowEmptyDataTransfer - if true, dnd can be started even if there is no 1235 * data to drag 1236 * aDragTarget - the target of the drag 1237 * aSelection - the selection to be dragged 1238 * aData - information pertaining to a drag started in a child process 1239 * aPrincipal - the triggering principal of the drag, or null if it's from 1240 * browser chrome or OS 1241 * aCookieJarSettings - the cookieJarSettings of the drag. or null if it's 1242 * from browser chrome or OS. 1243 */ 1244 MOZ_CAN_RUN_SCRIPT 1245 bool DoDefaultDragStart(nsPresContext* aPresContext, 1246 WidgetDragEvent* aDragEvent, 1247 dom::DataTransfer* aDataTransfer, 1248 bool aAllowEmptyDataTransfer, nsIContent* aDragTarget, 1249 dom::Selection* aSelection, 1250 dom::RemoteDragStartData* aDragStartData, 1251 nsIPrincipal* aPrincipal, 1252 nsIPolicyContainer* aPolicyContainer, 1253 nsICookieJarSettings* aCookieJarSettings); 1254 1255 /** 1256 * Set the fields of aEvent to reflect the mouse position and modifier keys 1257 * that were set when the user first pressed the mouse button (stored by 1258 * BeginTrackingDragGesture). aEvent->mWidget must be 1259 * mCurrentTarget->GetNearestWidget(). 1260 */ 1261 void FillInEventFromGestureDown(WidgetMouseEvent* aEvent); 1262 1263 MOZ_CAN_RUN_SCRIPT 1264 nsresult DoContentCommandEvent(WidgetContentCommandEvent* aEvent); 1265 MOZ_CAN_RUN_SCRIPT 1266 nsresult DoContentCommandInsertTextEvent(WidgetContentCommandEvent* aEvent); 1267 MOZ_CAN_RUN_SCRIPT 1268 nsresult DoContentCommandReplaceTextEvent(WidgetContentCommandEvent* aEvent); 1269 nsresult DoContentCommandScrollEvent(WidgetContentCommandEvent* aEvent); 1270 1271 dom::BrowserParent* GetCrossProcessTarget(); 1272 bool IsTargetCrossProcess(WidgetGUIEvent* aEvent); 1273 1274 /** 1275 * DispatchCrossProcessEvent() try to post aEvent to target remote process. 1276 * If you need to check if the event is posted to a remote process, you 1277 * can use aEvent->HasBeenPostedToRemoteProcess(). 1278 */ 1279 void DispatchCrossProcessEvent(WidgetEvent* aEvent, 1280 dom::BrowserParent* aRemoteTarget, 1281 nsEventStatus* aStatus); 1282 /** 1283 * HandleCrossProcessEvent() may post aEvent to target remote processes. 1284 * When it succeeded to post the event to at least one remote process, 1285 * returns true. Otherwise, including the case not tried to dispatch to 1286 * post the event, returns false. 1287 * If you need to check if the event is posted to at least one remote 1288 * process, you can use aEvent->HasBeenPostedToRemoteProcess(). 1289 */ 1290 bool HandleCrossProcessEvent(WidgetEvent* aEvent, nsEventStatus* aStatus); 1291 1292 void ReleaseCurrentIMEContentObserver(); 1293 1294 MOZ_CAN_RUN_SCRIPT void HandleQueryContentEvent( 1295 WidgetQueryContentEvent* aEvent); 1296 1297 private: 1298 // Removes a node from the :hover / :active chain if needed, notifying if the 1299 // node is not a NAC subtree. 1300 // 1301 // Only meant to be called from ContentRemoved and 1302 // NativeAnonymousContentRemoved. 1303 void RemoveNodeFromChainIfNeeded(ElementState aState, 1304 nsIContent* aContentRemoved, bool aNotify); 1305 1306 bool IsEventOutsideDragThreshold(WidgetInputEvent* aEvent) const; 1307 1308 static inline void DoStateChange(dom::Element* aElement, ElementState aState, 1309 bool aAddState); 1310 static inline void DoStateChange(nsIContent* aContent, ElementState aState, 1311 bool aAddState); 1312 static void UpdateAncestorState(nsIContent* aStartNode, 1313 nsIContent* aStopBefore, ElementState aState, 1314 bool aAddState); 1315 1316 /** 1317 * Update the attribute mLastRefPoint of the mouse event. It should be 1318 * the center of the window while the pointer is locked. 1319 * the same value as mRefPoint while there is no known last ref point. 1320 * the same value as the last known mRefPoint. 1321 */ 1322 static void UpdateLastRefPointOfMouseEvent(WidgetMouseEvent* aMouseEvent); 1323 1324 static void ResetPointerToWindowCenterWhilePointerLocked( 1325 WidgetMouseEvent* aMouseEvent); 1326 1327 // Update the last known ref point to the current event's mRefPoint. 1328 static void UpdateLastPointerPosition(WidgetMouseEvent* aMouseEvent); 1329 1330 void UpdateGestureContent(nsIContent* aContent); 1331 1332 /** 1333 * Notify target when user has been interaction with some speicific user 1334 * gestures which are eKeyUp, eMouseUp, eTouchEnd. 1335 */ 1336 void NotifyTargetUserActivation(WidgetEvent* aEvent, 1337 nsIContent* aTargetContent); 1338 1339 /** 1340 * https://html.spec.whatwg.org/multipage/popover.html#light-dismiss-open-popovers. 1341 */ 1342 MOZ_CAN_RUN_SCRIPT void LightDismissOpenPopovers(WidgetEvent* aEvent, 1343 nsIContent* aTargetContent); 1344 1345 /** 1346 * https://html.spec.whatwg.org/multipage/interactive-elements.html#light-dismiss-open-dialogs 1347 */ 1348 MOZ_CAN_RUN_SCRIPT void LightDismissOpenDialogs(WidgetEvent* aEvent, 1349 nsIContent* aTargetContent); 1350 1351 already_AddRefed<EventStateManager> ESMFromContentOrThis( 1352 nsIContent* aContent); 1353 1354 struct LastMouseDownInfo { 1355 nsCOMPtr<nsIContent> mLastMouseDownContent; 1356 Maybe<FormControlType> mLastMouseDownInputControlType; 1357 uint32_t mClickCount = 0; 1358 }; 1359 1360 LastMouseDownInfo& GetLastMouseDownInfo(int16_t aButton); 1361 1362 // These variables are only relevant if we're the cursor-setting manager. 1363 StyleCursorKind mLockCursor; 1364 bool mHidingCursorWhileTyping = false; 1365 1366 // Last mouse event screen point (in device pixel) when mouse was locked, used 1367 // to restore mouse position after unlocking. 1368 static LayoutDeviceIntPoint sPreLockScreenPoint; 1369 1370 // Stores the mRefPoint of the last synthetic mouse move we dispatched 1371 // to re-center the mouse when we were pointer locked. If this is (-1,-1) it 1372 // means we've not recently dispatched a centering event. We use this to 1373 // detect when we receive the synth event, so we can cancel and not send it 1374 // to content. 1375 static LayoutDeviceIntPoint sSynthCenteringPoint; 1376 1377 WeakFrame mCurrentTarget; 1378 nsCOMPtr<nsIContent> mCurrentTargetContent; 1379 static AutoWeakFrame sLastDragOverFrame; 1380 1381 // Stores the mRefPoint (the offset from the widget's origin in device 1382 // pixels) of the last mouse event. 1383 static LayoutDeviceIntPoint sLastRefPoint; 1384 static LayoutDeviceIntPoint sLastRefPointOfRawUpdate; 1385 1386 // member variables for the d&d gesture state machine 1387 LayoutDeviceIntPoint mGestureDownPoint; // screen coordinates 1388 // The content to use as target if we start a d&d (what we drag). 1389 RefPtr<nsIContent> mGestureDownContent; 1390 // The content of the frame where the mouse-down event occurred. It's the same 1391 // as the target in most cases but not always - for example when dragging 1392 // an <area> of an image map this is the image. (bug 289667) 1393 nsCOMPtr<nsIContent> mGestureDownFrameOwner; 1394 // Data associated with a drag started in a content process. 1395 RefPtr<dom::RemoteDragStartData> mGestureDownDragStartData; 1396 // State of keys when the original gesture-down happened 1397 Modifiers mGestureModifiers; 1398 uint16_t mGestureDownButtons; 1399 int16_t mGestureDownButton; 1400 1401 LastMouseDownInfo mLastLeftMouseDownInfo; 1402 LastMouseDownInfo mLastMiddleMouseDownInfo; 1403 LastMouseDownInfo mLastRightMouseDownInfo; 1404 1405 nsCOMPtr<nsIContent> mActiveContent; 1406 nsCOMPtr<nsIContent> mHoverContent; 1407 static nsCOMPtr<nsIContent> sDragOverContent; 1408 nsCOMPtr<nsIContent> mURLTargetContent; 1409 nsCOMPtr<nsINode> mPopoverPointerDownTarget; 1410 1411 nsPresContext* mPresContext; // Not refcnted 1412 RefPtr<dom::Document> mDocument; // Doesn't necessarily need to be owner 1413 1414 RefPtr<IMEContentObserver> mIMEContentObserver; 1415 1416 bool mShouldAlwaysUseLineDeltas : 1; 1417 bool mShouldAlwaysUseLineDeltasInitialized : 1; 1418 1419 bool mGestureDownInTextControl : 1; 1420 1421 bool mInTouchDrag; 1422 1423 bool m_haveShutdown; 1424 1425 RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper; 1426 nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> 1427 mPointersEnterLeaveHelper; 1428 1429 // Array for accesskey support 1430 nsCOMArray<dom::Element> mAccessKeys; 1431 1432 bool ShouldAlwaysUseLineDeltas(); 1433 1434 public: 1435 static nsresult UpdateUserActivityTimer(void); 1436 1437 static bool sNormalLMouseEventInProcess; 1438 static int16_t sCurrentMouseBtn; 1439 1440 static EventStateManager* sActiveESM; 1441 1442 static void ClearGlobalActiveContent(EventStateManager* aClearer); 1443 1444 // Functions used for click hold context menus 1445 nsCOMPtr<nsITimer> mClickHoldTimer; 1446 void CreateClickHoldTimer(nsPresContext* aPresContext, nsIFrame* aDownFrame, 1447 WidgetGUIEvent* aMouseDownEvent); 1448 void KillClickHoldTimer(); 1449 MOZ_CAN_RUN_SCRIPT_BOUNDARY void FireContextClick(); 1450 1451 MOZ_CAN_RUN_SCRIPT static void SetPointerLock(nsIWidget* aWidget, 1452 nsPresContext* aPresContext); 1453 static void sClickHoldCallback(nsITimer* aTimer, void* aESM); 1454 }; 1455 1456 } // namespace mozilla 1457 1458 // Click and double-click events need to be handled even for content that 1459 // has no frame. This is required for Web compatibility. 1460 #define NS_EVENT_NEEDS_FRAME(event) \ 1461 ((event)->mMessage != ePointerClick && \ 1462 (event)->mMessage != eMouseDoubleClick && \ 1463 (event)->mMessage != ePointerAuxClick) 1464 1465 #endif // mozilla_EventStateManager_h_